TReadDatabase::getReadDialect()   A
last analyzed

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