Passed
Push — master ( c90fcd...a1da5a )
by Petr
09:07
created

AConnector::getBasicRecord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace kalanis\kw_mapper\Search\Connector;
4
5
6
use kalanis\kw_mapper\Interfaces\IQueryBuilder;
7
use kalanis\kw_mapper\MapperException;
8
use kalanis\kw_mapper\Mappers\Shared\ForeignKey;
9
use kalanis\kw_mapper\Records\ARecord;
10
use kalanis\kw_mapper\Storage;
11
12
13
/**
14
 * Class AConnector
15
 * @package kalanis\kw_mapper\Search
16
 * Connect real sources into search engine
17
 */
18
abstract class AConnector
19
{
20
    use Database\TRecordsInJoins;
21
22
    protected ARecord $basicRecord;
23
    protected Storage\Shared\QueryBuilder $queryBuilder;
24
25
    /**
26
     * @param string $table
27
     * @param string $column
28
     * @param string|float|int $value
29
     * @throws MapperException
30
     * @return $this
31
     */
32 1
    public function notExact(string $table, string $column, $value): self
33
    {
34 1
        $aTable = $this->correctTable($table);
35 1
        $this->getQueryBuilder()->addCondition(
36 1
            $aTable,
37 1
            $this->correctColumn($aTable, $column),
38 1
            IQueryBuilder::OPERATION_NEQ,
39
            $value
40
        );
41 1
        return $this;
42
    }
43
44
    /**
45
     * @param string $table
46
     * @param string $column
47
     * @param string|float|int $value
48
     * @throws MapperException
49
     * @return $this
50
     */
51 8
    public function exact(string $table, string $column, $value): self
52
    {
53 8
        $aTable = $this->correctTable($table);
54 8
        $this->getQueryBuilder()->addCondition(
55 8
            $aTable,
56 8
            $this->correctColumn($aTable, $column),
57 7
            IQueryBuilder::OPERATION_EQ,
58
            $value
59
        );
60 7
        return $this;
61
    }
62
63
    /**
64
     * @param string $table
65
     * @param string $column
66
     * @param string|float|int $value
67
     * @param bool $equals
68
     * @throws MapperException
69
     * @return $this
70
     */
71 1
    public function from(string $table, string $column, $value, bool $equals = true): self
72
    {
73 1
        $aTable = $this->correctTable($table);
74 1
        $this->getQueryBuilder()->addCondition(
75 1
            $aTable,
76 1
            $this->correctColumn($aTable, $column),
77 1
            $equals ? IQueryBuilder::OPERATION_GTE : IQueryBuilder::OPERATION_GT,
78
            $value
79
        );
80 1
        return $this;
81
    }
82
83
    /**
84
     * @param string $table
85
     * @param string $column
86
     * @param string|float|int $value
87
     * @param bool $equals
88
     * @throws MapperException
89
     * @return $this
90
     */
91 1
    public function to(string $table, string $column, $value, bool $equals = true): self
92
    {
93 1
        $aTable = $this->correctTable($table);
94 1
        $this->getQueryBuilder()->addCondition(
95 1
            $aTable,
96 1
            $this->correctColumn($aTable, $column),
97 1
            $equals ? IQueryBuilder::OPERATION_LTE : IQueryBuilder::OPERATION_LT,
98
            $value
99
        );
100 1
        return $this;
101
    }
102
103
    /**
104
     * @param string $table
105
     * @param string $column
106
     * @param string $value
107
     * @throws MapperException
108
     * @return $this
109
     */
110 7
    public function like(string $table, string $column, $value): self
111
    {
112 7
        $aTable = $this->correctTable($table);
113 7
        $this->getQueryBuilder()->addCondition(
114 7
            $aTable,
115 7
            $this->correctColumn($aTable, $column),
116 6
            IQueryBuilder::OPERATION_LIKE,
117
            $value
118
        );
119 6
        return $this;
120
    }
121
122
    /**
123
     * @param string $table
124
     * @param string $column
125
     * @param string $value
126
     * @throws MapperException
127
     * @return $this
128
     */
129 2
    public function notLike(string $table, string $column, $value): self
130
    {
131 2
        $aTable = $this->correctTable($table);
132 2
        $this->getQueryBuilder()->addCondition(
133 2
            $aTable,
134 2
            $this->correctColumn($aTable, $column),
135 2
            IQueryBuilder::OPERATION_NLIKE,
136
            $value
137
        );
138 2
        return $this;
139
    }
140
141
    /**
142
     * @param string $table
143
     * @param string $column
144
     * @param string $pattern
145
     * @throws MapperException
146
     * @return $this
147
     */
148 1
    public function regexp(string $table, string $column, string $pattern): self
149
    {
150 1
        $aTable = $this->correctTable($table);
151 1
        $this->getQueryBuilder()->addCondition(
152 1
            $aTable,
153 1
            $this->correctColumn($aTable, $column),
154 1
            IQueryBuilder::OPERATION_REXP,
155
            $pattern
156
        );
157 1
        return $this;
158
    }
159
160
    /**
161
     * @param string $table
162
     * @param string $column
163
     * @param string $min
164
     * @param string $max
165
     * @throws MapperException
166
     * @return $this
167
     */
168 1
    public function between(string $table, string $column, $min, $max): self
169
    {
170 1
        $aTable = $this->correctTable($table);
171 1
        $this->getQueryBuilder()->addCondition($aTable, $this->correctColumn($aTable, $column), IQueryBuilder::OPERATION_GTE, $min);
172 1
        $this->getQueryBuilder()->addCondition($aTable, $this->correctColumn($aTable, $column), IQueryBuilder::OPERATION_LTE, $max);
173 1
        return $this;
174
    }
175
176
    /**
177
     * @param string $table
178
     * @param string $column
179
     * @throws MapperException
180
     * @return $this
181
     */
182 1
    public function null(string $table, string $column): self
183
    {
184 1
        $aTable = $this->correctTable($table);
185 1
        $this->getQueryBuilder()->addCondition(
186 1
            $aTable,
187 1
            $this->correctColumn($aTable, $column),
188 1
            IQueryBuilder::OPERATION_NULL
189
        );
190 1
        return $this;
191
    }
192
193
    /**
194
     * @param string $table
195
     * @param string $column
196
     * @throws MapperException
197
     * @return $this
198
     */
199 1
    public function notNull(string $table, string $column): self
200
    {
201 1
        $aTable = $this->correctTable($table);
202 1
        $this->getQueryBuilder()->addCondition(
203 1
            $aTable,
204 1
            $this->correctColumn($aTable, $column),
205 1
            IQueryBuilder::OPERATION_NNULL
206
        );
207 1
        return $this;
208
    }
209
210
    /**
211
     * @param string $table
212
     * @param string $column
213
     * @param array<string|int|float> $values
214
     * @throws MapperException
215
     * @return $this
216
     */
217 1
    public function in(string $table, string $column, array $values): self
218
    {
219 1
        $aTable = $this->correctTable($table);
220 1
        $this->getQueryBuilder()->addCondition(
221 1
            $aTable,
222 1
            $this->correctColumn($aTable, $column),
223 1
            IQueryBuilder::OPERATION_IN,
224
            $values
225
        );
226 1
        return $this;
227
    }
228
229
    /**
230
     * @param string $table
231
     * @param string $column
232
     * @param array<string|int|float> $values
233
     * @throws MapperException
234
     * @return $this
235
     */
236 1
    public function notIn(string $table, string $column, array $values): self
237
    {
238 1
        $aTable = $this->correctTable($table);
239 1
        $this->getQueryBuilder()->addCondition(
240 1
            $aTable,
241 1
            $this->correctColumn($aTable, $column),
242 1
            IQueryBuilder::OPERATION_NIN,
243
            $values
244
        );
245 1
        return $this;
246
    }
247
248 1
    public function useAnd(): self
249
    {
250 1
        $this->getQueryBuilder()->setRelations(IQueryBuilder::RELATION_AND);
251 1
        return $this;
252
    }
253
254 1
    public function useOr(): self
255
    {
256 1
        $this->getQueryBuilder()->setRelations(IQueryBuilder::RELATION_OR);
257 1
        return $this;
258
    }
259
260 1
    public function limit(?int $limit): self
261
    {
262 1
        $this->getQueryBuilder()->setLimit($limit);
263 1
        return $this;
264
    }
265
266 1
    public function offset(?int $offset): self
267
    {
268 1
        $this->getQueryBuilder()->setOffset($offset);
269 1
        return $this;
270
    }
271
272
    /**
273
     * Add ordering by
274
     * @param string $table
275
     * @param string $column
276
     * @param string $direction
277
     * @throws MapperException
278
     * @return $this
279
     */
280 1
    public function orderBy(string $table, string $column, string $direction = IQueryBuilder::ORDER_ASC): self
281
    {
282 1
        $aTable = $this->correctTable($table);
283 1
        $this->getQueryBuilder()->addOrderBy($aTable, $this->correctColumn($aTable, $column), $direction);
284 1
        return $this;
285
    }
286
287
    /**
288
     * Add grouping by
289
     * @param string $table
290
     * @param string $column
291
     * @throws MapperException
292
     * @return $this
293
     */
294 1
    public function groupBy(string $table, string $column): self
295
    {
296 1
        $aTable = $this->correctTable($table);
297 1
        $this->getQueryBuilder()->addGroupBy($aTable, $this->correctColumn($aTable, $column));
298 1
        return $this;
299
    }
300
301
    /**
302
     * Add child which will be mounted to results
303
     * @param string $childAlias
304
     * @param string $joinType
305
     * @param string $parentAlias
306
     * @param string $customAlias
307
     * @throws MapperException
308
     * @return $this
309
     */
310 9
    public function child(string $childAlias, string $joinType = IQueryBuilder::JOIN_LEFT, string $parentAlias = '', string $customAlias = ''): self
311
    {
312
        // from mapper - children's mapper then there table name
313 9
        if (!empty($parentAlias)) {
314 3
            $parentLookup = $this->recordLookup($parentAlias);
315 3
            if ($parentLookup && $parentLookup->getRecord()) {
316 3
                $parentRecord = $parentLookup->getRecord();
317
            }
318
        } else {
319 8
            $parentRecord = $this->getBasicRecord();
320 8
            $parentAlias = $parentRecord->getMapper()->getAlias();
321
        }
322 9
        if (empty($parentRecord)) {
323 1
            throw new MapperException(sprintf('Unknown record for parent alias *%s*', $parentAlias));
324
        }
325
326
        /** @var array<string|int, ForeignKey> $parentKeys */
327 8
        $parentKeys = $parentRecord->getMapper()->getForeignKeys();
328 8
        if (!isset($parentKeys[$childAlias])) {
329 1
            throw new MapperException(sprintf('Unknown alias *%s* in mapper for parent *%s*', $childAlias, $parentAlias));
330
        }
331
332 8
        $parentKey = $parentKeys[$childAlias];
333 8
        $parentRelations = $parentRecord->getMapper()->getRelations();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parentRecord does not seem to be defined for all execution paths leading up to this point.
Loading history...
334 8
        if (empty($parentRelations[$parentKey->getLocalEntryKey()])) {
335 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for parent *%s*', $parentKey->getLocalEntryKey(), $parentAlias));
336
        }
337
338 7
        $childTableAlias = empty($customAlias) ? $childAlias : $customAlias;
339 7
        $childLookup = $this->recordLookup($childTableAlias, $childAlias);
340 7
        if (empty($childLookup) || empty($childLookup->getRecord())) {
341
            // might never happens - part already checked, so it must exists
342
            // @codeCoverageIgnoreStart
343
            throw new MapperException(sprintf('Unknown record for child alias *%s*', $childAlias));
344
        }
345
        // @codeCoverageIgnoreEnd
346
347 7
        $childRecord = $childLookup->getRecord();
348 7
        $childRelations = $childRecord->getMapper()->getRelations();
349 7
        if (empty($childRelations[$parentKey->getRemoteEntryKey()])) {
350 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for child *%s*', $parentKey->getRemoteEntryKey(), $childAlias));
351
        }
352
353 6
        if ($parentRecord->getMapper()->getSource() != $childRecord->getMapper()->getSource()) {
354 1
            throw new MapperException(sprintf('Parent *%s* and child *%s* must both have the same source', $parentAlias, $childAlias));
355
        }
356
357 5
        $this->getQueryBuilder()->addJoin(
358 5
            $childAlias,
359 5
            $childRecord->getMapper()->getAlias(),
360 5
            $childRelations[$parentKey->getRemoteEntryKey()],
361
            $parentAlias,
362 5
            $parentRelations[$parentKey->getLocalEntryKey()],
363
            $joinType,
364
            $childTableAlias
365
        );
366
367 4
        return $this;
368
    }
369
370
    /**
371
     * That child is not set for chosen parent
372
     * @param string $childAlias
373
     * @param string $table
374
     * @param string $column
375
     * @param string $parentAlias
376
     * @throws MapperException
377
     * @return $this
378
     */
379 2
    public function childNotExist(string $childAlias, string $table, string $column, string $parentAlias = ''): self
380
    {
381 2
        $this->child($childAlias, IQueryBuilder::JOIN_LEFT_OUTER, $parentAlias);
382 1
        $aTable = $this->correctTable($table);
383 1
        $this->getQueryBuilder()->addCondition(
384 1
            $aTable,
385 1
            $this->correctColumn($aTable, $column),
386 1
            IQueryBuilder::OPERATION_NULL
387
        );
388 1
        return $this;
389
    }
390
391
    /**
392
     * Return count of all records selected by params
393
     * @throws MapperException
394
     * @return int
395
     */
396
    abstract public function getCount(): int;
397
398
    /**
399
     * Return records
400
     * @throws MapperException
401
     * @return ARecord[]
402
     */
403
    abstract public function getResults(): array;
404
405
    /**
406
     * @param string $table
407
     * @throws MapperException
408
     * @return string
409
     */
410 8
    protected function correctTable(string $table): string
411
    {
412 8
        return empty($table) ? $this->getBasicRecord()->getMapper()->getAlias() : $table ;
413
    }
414
415
    /**
416
     * @param string $table
417
     * @param string $column
418
     * @throws MapperException
419
     * @return string|int
420
     */
421 8
    protected function correctColumn(string $table, string $column)
422
    {
423 8
        $record = !empty($table) ? $this->recordLookup($table)->getRecord() : $this->getBasicRecord() ;
424 8
        if (empty($record)) {
425
            // @codeCoverageIgnoreStart
426
            throw new MapperException(sprintf('Unknown relation table *%s*', $table));
427
        }
428
        // @codeCoverageIgnoreEnd
429 8
        $relations = $record->getMapper()->getRelations();
430 8
        if (empty($relations[$column])) {
431 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for table *%s*', $column, $table));
432
        }
433 7
        return $relations[$column];
434
    }
435
436 28
    private function getQueryBuilder(): Storage\Shared\QueryBuilder
437
    {
438 28
        return $this->queryBuilder;
439
    }
440
441 13
    private function getBasicRecord(): ARecord
442
    {
443 13
        return $this->basicRecord;
444
    }
445
}
446