Passed
Push — master ( 6139d1...678a4c )
by Petr
13:22 queued 10:27
created

AConnector   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 414
Duplicated Lines 0 %

Test Coverage

Coverage 98.68%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 147
c 1
b 0
f 0
dl 0
loc 414
ccs 150
cts 152
cp 0.9868
rs 9.28
wmc 39

22 Methods

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