Passed
Push — master ( 02118d...11fb63 )
by Petr
03:00
created

TReadDatabase::loadMultiple()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 25
c 1
b 0
f 0
nc 24
nop 1
dl 0
loc 41
ccs 25
cts 25
cp 1
crap 8
rs 8.4444
1
<?php
2
3
namespace kalanis\kw_mapper\Mappers\Database;
4
5
6
use kalanis\kw_mapper\Interfaces\IQueryBuilder;
7
use kalanis\kw_mapper\MapperException;
8
use kalanis\kw_mapper\Mappers\Shared\TEntityChanged;
9
use kalanis\kw_mapper\Records\ARecord;
10
use kalanis\kw_mapper\Records\TFill;
11
use kalanis\kw_mapper\Storage\Database;
12
13
14
/**
15
 * Trait TReadDatabase
16
 * @package kalanis\kw_mapper\Mappers\Database
17
 * Separated read DB entry without need to reload mapper
18
 *
19
 * Contains only operations for reading from DB
20
 */
21
trait TReadDatabase
22
{
23
    use TEntityChanged;
24
    use TFill;
25
26
    /** @var string */
27
    protected $readSource = '';
28
    /** @var Database\ASQL */
29
    protected $readDatabase = null;
30
    /** @var Database\Dialects\ADialect */
31
    protected $readDialect = null;
32
    /** @var Database\QueryBuilder */
33
    protected $readQueryBuilder = null;
34
35
    /**
36
     * @throws MapperException
37
     */
38 16
    protected function initTReadDatabase(): void
39
    {
40 16
        $this->readDatabase = $this->getReadDatabase();
41 16
        $this->readDialect = $this->getReadDialect($this->readDatabase);
42 16
        $this->readQueryBuilder = $this->getReadQueryBuilder($this->readDialect);
43 16
    }
44
45 4
    protected function setReadSource(string $readSource): void
46
    {
47 4
        $this->readSource = $readSource;
48 4
    }
49
50 4
    protected function getReadSource(): string
51
    {
52 4
        return $this->readSource;
53
    }
54
55
    /**
56
     * @throws MapperException
57
     * @return Database\ADatabase
58
     */
59 16
    protected function getReadDatabase(): Database\ADatabase
60
    {
61 16
        return Database\DatabaseSingleton::getInstance()->getDatabase(
62 16
            Database\ConfigStorage::getInstance()->getConfig($this->getReadSource())
63
        );
64
    }
65
66
    /**
67
     * @param Database\ADatabase $database
68
     * @throws MapperException
69
     * @return Database\Dialects\ADialect
70
     */
71 16
    protected function getReadDialect(Database\ADatabase $database): Database\Dialects\ADialect
72
    {
73 16
        return Database\Dialects\Factory::getInstance()->getDialectClass($database->languageDialect());
74
    }
75
76 16
    protected function getReadQueryBuilder(Database\Dialects\ADialect $dialect): Database\QueryBuilder
77
    {
78 16
        return new Database\QueryBuilder($dialect);
79
    }
80
81
    /**
82
     * @param ARecord $record
83
     * @throws MapperException
84
     * @return bool
85
     */
86 6
    protected function loadRecord(ARecord $record): bool
87
    {
88 6
        if ($this->loadRecordByPk($record)) {
89 3
            return true;
90
        }
91
92 6
        $this->readQueryBuilder->clear();
93 6
        $this->readQueryBuilder->setBaseTable($record->getMapper()->getAlias());
94 6
        $relations = $record->getMapper()->getRelations();
95
96
        // conditions - must be equal
97 6
        foreach ($record as $key => $item) {
98 6
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
99 5
                $this->readQueryBuilder->addCondition(
100 5
                    $record->getMapper()->getAlias(),
101 5
                    $relations[$key],
102 5
                    IQueryBuilder::OPERATION_EQ,
103
                    $item
104
                );
105
            }
106
        }
107
108
        // relations - what to get
109 6
        foreach ($relations as $localAlias => $remoteColumn) {
110 6
            $this->readQueryBuilder->addColumn($record->getMapper()->getAlias(), $remoteColumn, $localAlias);
111
        }
112 6
        $this->readQueryBuilder->setLimits(0,1);
113
114
        // query itself
115 6
        $lines = $this->readDatabase->query(
116 6
            strval($this->readDialect->select($this->readQueryBuilder)),
117 6
            $this->readQueryBuilder->getParams()
118
        );
119 6
        if (empty($lines)) {
120 3
            return false;
121
        }
122
123
        // fill entries in record
124 3
        $line = reset($lines);
125 3
        foreach ($line as $index => $item) {
126 3
            $entry = $record->getEntry($index);
127 3
            $entry->setData($this->typedFillSelection($entry, $item), true);
128
        }
129 3
        return true;
130
    }
131
132
    /**
133
     * @param ARecord $record
134
     * @throws MapperException
135
     * @return bool
136
     */
137 10
    protected function loadRecordByPk(ARecord $record): bool
138
    {
139 10
        if (empty($record->getMapper()->getPrimaryKeys())) {
140 3
            return false;
141
        }
142
143 8
        $this->readQueryBuilder->clear();
144 8
        $this->readQueryBuilder->setBaseTable($record->getMapper()->getAlias());
145 8
        $relations = $record->getMapper()->getRelations();
146
147
        // conditions - everything must be equal
148 8
        foreach ($record->getMapper()->getPrimaryKeys() as $key) {
149
            try {
150 8
                if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
151 5
                    $this->readQueryBuilder->addCondition(
152 5
                        $record->getMapper()->getAlias(),
153 5
                        $relations[$key],
154 5
                        IQueryBuilder::OPERATION_EQ,
155 6
                        $record->offsetGet($key)
156
                    );
157
                }
158 3
            } catch (MapperException $ex) {
159 3
                return false;
160
            }
161
        }
162
163 6
        if (empty($this->readQueryBuilder->getConditions())) { // no conditions, nothing in PKs - back to normal system
164 3
            return false;
165
        }
166
167
        // relations - what to get
168 5
        foreach ($relations as $localAlias => $remoteColumn) {
169 5
            $this->readQueryBuilder->addColumn($record->getMapper()->getAlias(), $remoteColumn, $localAlias);
170
        }
171
172
        // query itself
173 5
        $this->readQueryBuilder->setLimits(0,1);
174 5
        $lines = $this->readDatabase->query(
175 5
            strval($this->readDialect->select($this->readQueryBuilder)),
176 5
            $this->readQueryBuilder->getParams()
177
        );
178 5
        if (empty($lines)) {
179 2
            return false;
180
        }
181
182
        // fill entries in record
183 3
        $line = reset($lines);
184 3
        foreach ($line as $index => $item) {
185 3
            $entry = $record->getEntry($index);
186 3
            $entry->setData($this->typedFillSelection($entry, $item), true);
187
        }
188 3
        return true;
189
    }
190
191
    /**
192
     * @param ARecord $record
193
     * @throws MapperException
194
     * @return int
195
     */
196 4
    public function countRecord(ARecord $record): int
197
    {
198 4
        $this->readQueryBuilder->clear();
199 4
        $this->readQueryBuilder->setBaseTable($record->getMapper()->getAlias());
200 4
        $relations = $record->getMapper()->getRelations();
201
202 4
        foreach ($record as $key => $item) {
203 4
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
204 4
                $this->readQueryBuilder->addCondition(
205 4
                    $record->getMapper()->getAlias(),
206 4
                    $relations[$key],
207 4
                    IQueryBuilder::OPERATION_EQ,
208
                    $item
209
                );
210
            }
211
        }
212
213 4
        if (empty($record->getMapper()->getPrimaryKeys())) {
214 2
            $relation = reset($relations);
215 2
            if (false !== $relation) {
216 2
                $this->readQueryBuilder->addColumn(
217 2
                    $record->getMapper()->getAlias(),
218
                    $relation,
219 2
                    'count',
220 2
                    IQueryBuilder::AGGREGATE_COUNT
221
                );
222
            }
223
        } else {
224
//            foreach ($record->getMapper()->getPrimaryKeys() as $primaryKey) {
225
//                $this->readQueryBuilder->addColumn(
226
//                    $record->getMapper()->getAlias(),
227
//                    $primaryKey,
228
//                    '',
229
//                    IQueryBuilder::AGGREGATE_COUNT
230
//                );
231
//            }
232 3
            $pks = $record->getMapper()->getPrimaryKeys();
233 3
            $key = reset($pks);
234 3
            $this->readQueryBuilder->addColumn(
235 3
                $record->getMapper()->getAlias(),
236 3
                $relations[$key],
237 3
                'count',
238 3
                IQueryBuilder::AGGREGATE_COUNT
239
            );
240
        }
241
242 4
        $lines = $this->readDatabase->query(
243 4
            strval($this->readDialect->select($this->readQueryBuilder)),
244 4
            $this->readQueryBuilder->getParams()
245
        );
246 4
        if (empty($lines) || !is_iterable($lines)) {
247
            // @codeCoverageIgnoreStart
248
            return 0;
249
        }
250
        // @codeCoverageIgnoreEnd
251 4
        $line = reset($lines);
252 4
        return intval(reset($line));
253
    }
254
255
    /**
256
     * @param ARecord $record
257
     * @throws MapperException
258
     * @return ARecord[]
259
     */
260 5
    public function loadMultiple(ARecord $record): array
261
    {
262 5
        $this->readQueryBuilder->clear();
263 5
        $this->readQueryBuilder->setBaseTable($record->getMapper()->getAlias());
264 5
        $relations = $record->getMapper()->getRelations();
265
266 5
        foreach ($record as $key => $item) {
267 5
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
268 5
                $this->readQueryBuilder->addCondition(
269 5
                    $record->getMapper()->getAlias(),
270 5
                    $relations[$key],
271 5
                    IQueryBuilder::OPERATION_EQ,
272
                    $item
273
                );
274
            }
275
        }
276
277
        // relations - what to get
278 5
        foreach ($relations as $localAlias => $remoteColumn) {
279 5
            $this->readQueryBuilder->addColumn($record->getMapper()->getAlias(), $remoteColumn, $localAlias);
280
        }
281
282
        // query itself
283 5
        $lines = $this->readDatabase->query(
284 5
            strval($this->readDialect->select($this->readQueryBuilder)),
285 5
            $this->readQueryBuilder->getParams()
286
        );
287 5
        if (empty($lines)) {
288 2
            return [];
289
        }
290
291 3
        $result = [];
292 3
        foreach ($lines as $line) {
293 3
            $rec = clone $record;
294 3
            foreach ($line as $index => $item) {
295 3
                $entry = $rec->getEntry($index);
296 3
                $entry->setData($this->typedFillSelection($entry, $item), true);
297
            }
298 3
            $result[] = $rec;
299
        }
300 3
        return $result;
301
    }
302
}
303