AConnector   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 442
Duplicated Lines 0 %

Test Coverage

Coverage 96.24%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 154
c 1
b 0
f 0
dl 0
loc 442
ccs 179
cts 186
cp 0.9624
rs 9.0399
wmc 42

25 Methods

Rating   Name   Duplication   Size   Complexity  
A between() 0 6 1
A useAnd() 0 4 1
A getBasicRecord() 0 3 1
A offset() 0 4 1
A groupBy() 0 5 1
A useOr() 0 4 1
A orderBy() 0 5 1
A getQueryBuilder() 0 3 1
A correctTable() 0 3 2
A limit() 0 4 1
A correctColumn() 0 13 4
A regexp() 0 10 1
A from() 0 10 2
A like() 0 10 1
A notExact() 0 10 1
A exact() 0 10 1
A childNotExist() 0 10 1
A raw() 0 8 1
C child() 0 58 12
A null() 0 9 1
A notNull() 0 9 1
A notLike() 0 10 1
A in() 0 10 1
A to() 0 10 2
A notIn() 0 10 1

How to fix   Complexity   

Complex Class

Complex classes like AConnector often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AConnector, and based on these observations, apply Extract Interface, too.

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 1
            $value
40 1
        );
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 8
            IQueryBuilder::OPERATION_EQ,
58 8
            $value
59 8
        );
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 1
            $value
79 1
        );
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 1
            $value
99 1
        );
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 7
            IQueryBuilder::OPERATION_LIKE,
117 7
            $value
118 7
        );
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 2
            $value
137 2
        );
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 1
            $pattern
156 1
        );
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 1
        );
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 1
        );
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 1
            $values
225 1
        );
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 1
            $values
244 1
        );
245 1
        return $this;
246
    }
247
248
    /**
249
     * @param string|string[]|callable $operation
250
     * @param string $prefix
251
     * @param mixed $value
252
     * @return $this
253
     */
254
    public function raw($operation, string $prefix = '', $value = null): self
255
    {
256
        $this->getQueryBuilder()->addRawCondition(
257
            $operation,
258
            $prefix,
259
            $value
260
        );
261
        return $this;
262
    }
263
264 1
    public function useAnd(): self
265
    {
266 1
        $this->getQueryBuilder()->setRelations(IQueryBuilder::RELATION_AND);
267 1
        return $this;
268
    }
269
270 1
    public function useOr(): self
271
    {
272 1
        $this->getQueryBuilder()->setRelations(IQueryBuilder::RELATION_OR);
273 1
        return $this;
274
    }
275
276 1
    public function limit(?int $limit): self
277
    {
278 1
        $this->getQueryBuilder()->setLimit($limit);
279 1
        return $this;
280
    }
281
282 1
    public function offset(?int $offset): self
283
    {
284 1
        $this->getQueryBuilder()->setOffset($offset);
285 1
        return $this;
286
    }
287
288
    /**
289
     * Add ordering by
290
     * @param string $table
291
     * @param string $column
292
     * @param string $direction
293
     * @throws MapperException
294
     * @return $this
295
     */
296 1
    public function orderBy(string $table, string $column, string $direction = IQueryBuilder::ORDER_ASC): self
297
    {
298 1
        $aTable = $this->correctTable($table);
299 1
        $this->getQueryBuilder()->addOrderBy($aTable, $this->correctColumn($aTable, $column), $direction);
300 1
        return $this;
301
    }
302
303
    /**
304
     * Add grouping by
305
     * @param string $table
306
     * @param string $column
307
     * @throws MapperException
308
     * @return $this
309
     */
310 1
    public function groupBy(string $table, string $column): self
311
    {
312 1
        $aTable = $this->correctTable($table);
313 1
        $this->getQueryBuilder()->addGroupBy($aTable, $this->correctColumn($aTable, $column));
314 1
        return $this;
315
    }
316
317
    /**
318
     * Add child which will be mounted to results
319
     * @param string $childAlias
320
     * @param string $joinType
321
     * @param string $parentAlias
322
     * @param string $customAlias
323
     * @throws MapperException
324
     * @return $this
325
     */
326 9
    public function child(string $childAlias, string $joinType = IQueryBuilder::JOIN_LEFT, string $parentAlias = '', string $customAlias = ''): self
327
    {
328
        // from mapper - children's mapper then there table name
329 9
        if (!empty($parentAlias)) {
330 3
            $parentLookup = $this->recordLookup($parentAlias);
331 3
            if ($parentLookup && $parentLookup->getRecord()) {
332 3
                $parentRecord = $parentLookup->getRecord();
333
            }
334
        } else {
335 8
            $parentRecord = $this->getBasicRecord();
336 8
            $parentAlias = $parentRecord->getMapper()->getAlias();
337
        }
338 9
        if (empty($parentRecord)) {
339 1
            throw new MapperException(sprintf('Unknown record for parent alias *%s*', $parentAlias));
340
        }
341
342
        /** @var array<string|int, ForeignKey> $parentKeys */
343 8
        $parentKeys = $parentRecord->getMapper()->getForeignKeys();
344 8
        if (!isset($parentKeys[$childAlias])) {
345 1
            throw new MapperException(sprintf('Unknown alias *%s* in mapper for parent *%s*', $childAlias, $parentAlias));
346
        }
347
348 8
        $parentKey = $parentKeys[$childAlias];
349 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...
350 8
        if (empty($parentRelations[$parentKey->getLocalEntryKey()])) {
351 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for parent *%s*', $parentKey->getLocalEntryKey(), $parentAlias));
352
        }
353
354 7
        $childTableAlias = empty($customAlias) ? $childAlias : $customAlias;
355 7
        $childLookup = $this->recordLookup($childTableAlias, $childAlias);
356 7
        if (empty($childLookup) || empty($childLookup->getRecord())) {
357
            // might never happens - part already checked, so it must exists
358
            // @codeCoverageIgnoreStart
359
            throw new MapperException(sprintf('Unknown record for child alias *%s*', $childAlias));
360
        }
361
        // @codeCoverageIgnoreEnd
362
363 7
        $childRecord = $childLookup->getRecord();
364 7
        $childRelations = $childRecord->getMapper()->getRelations();
365 7
        if (empty($childRelations[$parentKey->getRemoteEntryKey()])) {
366 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for child *%s*', $parentKey->getRemoteEntryKey(), $childAlias));
367
        }
368
369 6
        if ($parentRecord->getMapper()->getSource() != $childRecord->getMapper()->getSource()) {
370 1
            throw new MapperException(sprintf('Parent *%s* and child *%s* must both have the same source', $parentAlias, $childAlias));
371
        }
372
373 5
        $this->getQueryBuilder()->addJoin(
374 5
            $childAlias,
375 5
            $childRecord->getMapper()->getAlias(),
376 5
            $childRelations[$parentKey->getRemoteEntryKey()],
377 5
            $parentAlias,
378 5
            $parentRelations[$parentKey->getLocalEntryKey()],
379 5
            $joinType,
380 5
            $childTableAlias
381 5
        );
382
383 4
        return $this;
384
    }
385
386
    /**
387
     * That child is not set for chosen parent
388
     * @param string $childAlias
389
     * @param string $table
390
     * @param string $column
391
     * @param string $parentAlias
392
     * @throws MapperException
393
     * @return $this
394
     */
395 2
    public function childNotExist(string $childAlias, string $table, string $column, string $parentAlias = ''): self
396
    {
397 2
        $this->child($childAlias, IQueryBuilder::JOIN_LEFT_OUTER, $parentAlias);
398 1
        $aTable = $this->correctTable($table);
399 1
        $this->getQueryBuilder()->addCondition(
400 1
            $aTable,
401 1
            $this->correctColumn($aTable, $column),
402 1
            IQueryBuilder::OPERATION_NULL
403 1
        );
404 1
        return $this;
405
    }
406
407
    /**
408
     * Return count of all records selected by params
409
     * @throws MapperException
410
     * @return int
411
     */
412
    abstract public function getCount(): int;
413
414
    /**
415
     * Return records
416
     * @throws MapperException
417
     * @return ARecord[]
418
     */
419
    abstract public function getResults(): array;
420
421
    /**
422
     * @param string $table
423
     * @throws MapperException
424
     * @return string
425
     */
426 8
    protected function correctTable(string $table): string
427
    {
428 8
        return empty($table) ? $this->getBasicRecord()->getMapper()->getAlias() : $table ;
429
    }
430
431
    /**
432
     * @param string $table
433
     * @param string $column
434
     * @throws MapperException
435
     * @return string|int
436
     */
437 8
    protected function correctColumn(string $table, string $column)
438
    {
439 8
        $record = !empty($table) ? $this->recordLookup($table)->getRecord() : $this->getBasicRecord() ;
440 8
        if (empty($record)) {
441
            // @codeCoverageIgnoreStart
442
            throw new MapperException(sprintf('Unknown relation table *%s*', $table));
443
        }
444
        // @codeCoverageIgnoreEnd
445 8
        $relations = $record->getMapper()->getRelations();
446 8
        if (empty($relations[$column])) {
447 1
            throw new MapperException(sprintf('Unknown relation key *%s* in mapper for table *%s*', $column, $table));
448
        }
449 7
        return $relations[$column];
450
    }
451
452 28
    protected function getQueryBuilder(): Storage\Shared\QueryBuilder
453
    {
454 28
        return $this->queryBuilder;
455
    }
456
457 13
    protected function getBasicRecord(): ARecord
458
    {
459 13
        return $this->basicRecord;
460
    }
461
}
462