ALdap   C
last analyzed

Complexity

Total Complexity 53

Size/Duplication

Total Lines 259
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 130
c 1
b 0
f 1
dl 0
loc 259
rs 6.96
wmc 53

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getAlias() 0 3 1
A multiple() 0 11 3
A loadRecord() 0 16 5
A getPk() 0 6 2
A readItem() 0 3 4
A deleteRecord() 0 10 3
B updateRecord() 0 41 9
A authorize() 0 23 5
A loadMultiple() 0 22 6
A countRecord() 0 8 3
B insertRecord() 0 29 7
A fillConditions() 0 13 4

How to fix   Complexity   

Complex Class

Complex classes like ALdap 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 ALdap, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace kalanis\kw_mapper\Mappers\Database;
4
5
6
use kalanis\kw_mapper\Interfaces\ICanFill;
7
use kalanis\kw_mapper\Interfaces\IQueryBuilder;
8
use kalanis\kw_mapper\MapperException;
9
use kalanis\kw_mapper\Mappers\AMapper;
10
use kalanis\kw_mapper\Mappers\Shared\TEntityChanged;
11
use kalanis\kw_mapper\Records\ARecord;
12
use kalanis\kw_mapper\Records\TFill;
13
use kalanis\kw_mapper\Storage;
14
15
16
/**
17
 * Class ALdap
18
 * @package kalanis\kw_mapper\Mappers\Database
19
 * @codeCoverageIgnore for now - external source
20
 */
21
abstract class ALdap extends AMapper
22
{
23
    use TEntityChanged;
24
    use TFill;
25
    use TTable;
26
27
    /** @var Storage\Database\Raw\Ldap */
28
    protected Storage\Database\Raw\Ldap $database;
29
    protected Storage\Shared\QueryBuilder $queryBuilder;
30
    protected Storage\Database\Dialects\LdapQueries $dialect;
31
32
    /**
33
     * @throws MapperException
34
     */
35
    public function __construct()
36
    {
37
        parent::__construct();
38
        $config = Storage\Database\ConfigStorage::getInstance()->getConfig($this->getSource());
39
        $this->database = Storage\Database\DatabaseSingleton::getInstance()->getDatabase($config);
40
        $this->dialect = new Storage\Database\Dialects\LdapQueries();
41
        $this->queryBuilder = new Storage\Shared\QueryBuilder();
42
    }
43
44
    public function getAlias(): string
45
    {
46
        return $this->getTable();
47
    }
48
49
    protected function insertRecord(ARecord $record): bool
50
    {
51
        $this->queryBuilder->clear();
52
        $this->queryBuilder->setBaseTable($record->getMapper()->getAlias());
53
        $relations = $record->getMapper()->getRelations();
54
55
        foreach ($record as $key => $item) {
56
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
57
                $this->queryBuilder->addProperty(
58
                    $record->getMapper()->getAlias(),
59
                    $relations[$key],
60
                    $item
61
                );
62
            }
63
        }
64
65
        if (empty($this->queryBuilder->getProperties())) {
66
            return false;
67
        }
68
69
        $this->database->connect();
70
        $connect = $this->database->getConnection();
71
        if (!(is_resource($connect) || is_object($connect))) {
72
            return false;
73
        }
74
75
        return $this->database->add(
76
            $this->dialect->domainDn($this->database->getDomain()),
77
            $this->dialect->changed($this->queryBuilder)
78
        );
79
    }
80
81
    protected function updateRecord(ARecord $record): bool
82
    {
83
        $this->queryBuilder->clear();
84
        $this->queryBuilder->setBaseTable($record->getMapper()->getAlias());
85
        $relations = $record->getMapper()->getRelations();
86
87
        foreach ($record as $key => $item) {
88
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
89
                if ($record->getEntry($key)->isFromStorage()) {
90
                    $this->queryBuilder->addCondition(
91
                        $record->getMapper()->getAlias(),
92
                        $relations[$key],
93
                        IQueryBuilder::OPERATION_EQ,
94
                        $item
95
                    );
96
                } else {
97
                    $this->queryBuilder->addProperty(
98
                        $record->getMapper()->getAlias(),
99
                        $relations[$key],
100
                        $item
101
                    );
102
                }
103
            }
104
        }
105
106
        if (empty($this->queryBuilder->getConditions())) { /// this one is questionable - I really want to update everything?
107
            return false;
108
        }
109
        if (empty($this->queryBuilder->getProperties())) {
110
            return false;
111
        }
112
113
        $this->database->connect();
114
        $connect = $this->database->getConnection();
115
        if (!(is_resource($connect) || is_object($connect))) {
116
            return false;
117
        }
118
119
        return $this->database->replace(
120
            $this->dialect->userDn($this->database->getDomain(), $this->getPk($record)),
121
            $this->dialect->changed($this->queryBuilder)
122
        );
123
    }
124
125
    protected function deleteRecord(ARecord $record): bool
126
    {
127
        $this->database->connect();
128
        $connect = $this->database->getConnection();
129
        if (!(is_resource($connect) || is_object($connect))) {
130
            return false;
131
        }
132
133
        return $this->database->delete(
134
            $this->dialect->userDn($this->database->getDomain(), $this->getPk($record))
135
        );
136
    }
137
138
    /**
139
     * @param ARecord $record
140
     * @throws MapperException
141
     * @return string
142
     */
143
    protected function getPk(ARecord $record)
144
    {
145
        $pks = $record->getMapper()->getPrimaryKeys();
146
        $pk = reset($pks);
147
        $off = $record->offsetGet($pk);
148
        return ($off instanceof ICanFill) ? strval($off->dumpData()) : strval($off);
149
    }
150
151
    protected function loadRecord(ARecord $record): bool
152
    {
153
        $this->fillConditions($record);
154
        $lines = $this->multiple();
155
        if (empty($lines) || empty($lines[0]) || !is_iterable($lines[0])) { // nothing found
156
            return false;
157
        }
158
159
        // fill entries in record
160
        $relations = $record->getMapper()->getRelations();
161
        $relationMap = array_flip($relations);
162
        foreach ($lines[0] as $index => $item) {
163
            $entry = $record->getEntry($relationMap[$index]);
164
            $entry->setData($this->typedFillSelection($entry, $this->readItem($item)), true);
165
        }
166
        return true;
167
    }
168
169
    public function countRecord(ARecord $record): int
170
    {
171
        $this->fillConditions($record);
172
        $entries = $this->multiple();
173
        if (empty($entries) || empty($entries['count'])) {
174
            return 0;
175
        }
176
        return intval($entries['count']);
177
    }
178
179
    public function loadMultiple(ARecord $record): array
180
    {
181
        $this->fillConditions($record);
182
        $lines = $this->multiple();
183
        if (empty($lines)) {
184
            return [];
185
        }
186
187
        $result = [];
188
        $relations = $record->getMapper()->getRelations();
189
        $relationMap = array_flip($relations);
190
        foreach ($lines as $key => $line) {
191
            if (is_numeric($key) && is_iterable($line)) {
192
                $rec = clone $record;
193
                foreach ($line as $index => $item) {
194
                    $entry = $rec->getEntry($relationMap[$index]);
195
                    $entry->setData($this->typedFillSelection($entry, $this->readItem($item)), true);
196
                }
197
                $result[] = $rec;
198
            }
199
        }
200
        return $result;
201
    }
202
203
    /**
204
     * @param mixed $item
205
     * @return string
206
     */
207
    protected function readItem($item)
208
    {
209
        return (empty($item) || empty($item[0]) || ('NULL' == $item[0])) ? '' : $item[0];
210
    }
211
212
    /**
213
     * @param ARecord $record
214
     * @throws MapperException
215
     */
216
    protected function fillConditions(ARecord $record): void
217
    {
218
        $this->queryBuilder->clear();
219
        $this->queryBuilder->setBaseTable($record->getMapper()->getAlias());
220
        $relations = $record->getMapper()->getRelations();
221
222
        foreach ($record as $key => $item) {
223
            if (isset($relations[$key]) && $this->ifEntryChanged($record->getEntry($key))) {
224
                $this->queryBuilder->addCondition(
225
                    $record->getMapper()->getAlias(),
226
                    $relations[$key],
227
                    IQueryBuilder::OPERATION_EQ,
228
                    $item
229
                );
230
            }
231
        }
232
    }
233
234
    /**
235
     * @throws MapperException
236
     * @return array<string|int, string|int|float|array<string|int|float>>
237
     */
238
    protected function multiple(): array
239
    {
240
        $this->database->connect();
241
        $connect = $this->database->getConnection();
242
        if (!(is_resource($connect) || is_object($connect))) {
243
            return [];
244
        }
245
246
        return $this->database->search(
247
            $this->dialect->domainDn($this->database->getDomain()),
248
            $this->dialect->filter($this->queryBuilder)
249
        );
250
    }
251
252
    /**
253
     * @param string[] $params
254
     * @throws MapperException
255
     * @return bool
256
     */
257
    public function authorize(array $params): bool
258
    {
259
        if (empty($params['user'])) {
260
            throw new MapperException('Cannot determine user!');
261
        }
262
        if (empty($params['password'])) {
263
            throw new MapperException('Password not set!');
264
        }
265
266
        $this->database->disconnect();
267
        $this->database->connect(false);
268
        $connect = $this->database->getConnection();
269
        if (!(is_resource($connect) || is_object($connect))) {
270
            return false;
271
        }
272
273
        $result = $this->database->bindUser(
274
            $this->dialect->userDn($this->database->getDomain(), $params['user']),
275
            $params['password']
276
        );
277
        $this->database->disconnect();
278
279
        return $result;
280
    }
281
}
282