Completed
Push — master ( 9060a9...8d9a79 )
by Gabriel
02:31 queued 11s
created

RecordManager   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 439
Duplicated Lines 0 %

Test Coverage

Coverage 66.23%

Importance

Changes 0
Metric Value
eloc 124
dl 0
loc 439
ccs 100
cts 151
cp 0.6623
rs 4.5599
c 0
b 0
f 0
wmc 58

33 Methods

Rating   Name   Duplication   Size   Complexity  
A getAll() 0 7 2
A getCollectionClass() 0 7 2
A setController() 0 3 1
A getRequest() 0 3 1
A initCollectionClass() 0 3 1
A hasField() 0 8 3
A generateModelClass() 0 18 4
A initController() 0 8 2
A setCollectionClass() 0 3 1
A initModelNamespacePath() 0 9 2
A getModelNamespace() 0 3 1
A getRegistry() 0 7 2
A getModelNamespacePath() 0 7 2
A getNewRecord() 0 9 1
A inflectModel() 0 4 1
A inflect() 0 3 1
A newCollection() 0 8 1
A getNewRecordFromDB() 0 6 1
A generateControllerNamespaced() 0 6 1
A getController() 0 7 2
A getHelper() 0 3 1
A getUrlPK() 0 7 2
A setModel() 0 3 1
A getRootNamespace() 0 6 2
A getNew() 0 14 4
A getQueryModelData() 0 12 3
A __wakeup() 0 3 1
A generateModelNamespacePathFromClassName() 0 10 1
A generateControllerGeneric() 0 5 1
A getModel() 0 7 2
A generateCollectionClass() 0 3 1
A getFullTextFields() 0 11 3
A __call() 0 19 4

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
namespace Nip\Records\AbstractModels;
4
5
use Nip\Collections\Registry;
6
use Nip\Database\Query\Insert as InsertQuery;
7
use Nip\HelperBroker;
8
use Nip\Records\Collections\Collection as RecordCollection;
9
use Nip\Records\Traits\ActiveRecord\ActiveRecordsTrait;
10
use Nip\Records\Traits\HasUrl\HasUrlRecordManagerTrait;
11
use Nip\Utility\Traits\NameWorksTrait;
12
13
/**
14
 * Class Table
15
 * @package Nip\Records\_Abstract
16
 *
17
 * @method \Nip_Helper_Url Url()
18
 */
19
abstract class RecordManager
20
{
21
    use NameWorksTrait;
22
    use ActiveRecordsTrait;
23
    use HasUrlRecordManagerTrait;
24
25
    /**
26
     * Collection class for current record manager
27
     *
28
     * @var string
29
     */
30
    protected $collectionClass = null;
31
32
    protected $helpers = [];
33
34
    /**
35
     * @var null|string
36
     */
37
    protected $urlPK = null;
38
39
    /**
40
     * Model class name
41
     * @var null|string
42
     */
43
    protected $model = null;
44
45
    /**
46
     * @var null|string
47
     */
48
    protected $controller = null;
49
50
    /**
51
     * @var null|string
52
     */
53
    protected $modelNamespacePath = null;
54
55
    protected $registry = null;
56
57
    /**
58
     * Overloads findByRecord, findByField, deleteByRecord, deleteByField, countByRecord, countByField
59
     *
60
     * @example findByCategory(Category $item)
61
     * @example deleteByProduct(Product $item)
62
     * @example findByIdUser(2)
63
     * @example deleteByTitle(array('Lorem ipsum', 'like'))
64
     * @example countByIdCategory(1)
65
     *
66
     * @param string $name
67
     * @param array $arguments
68
     *
69
     * @return mixed
70
     */
71 1
    public function __call($name, $arguments)
72
    {
73 1
        $return = $this->isCallDatabaseOperation($name, $arguments);
74 1
        if ($return !== false) {
75
            return $return;
76
        }
77
78
        /** @noinspection PhpAssignmentInConditionInspection */
79 1
        if ($return = $this->isCallUrl($name, $arguments)) {
80
            return $return;
81
        }
82
83 1
        if ($name === ucfirst($name)) {
84 1
            return $this->getHelper($name);
85
        }
86
87
        trigger_error("Call to undefined method $name", E_USER_ERROR);
88
89
        return $this;
90
    }
91
92
    /**
93
     * @return string
94
     */
95 13
    public function getController()
96
    {
97 13
        if ($this->controller === null) {
98 13
            $this->initController();
99
        }
100
101 13
        return $this->controller;
102
    }
103
104
    /**
105
     * @param null|string $controller
106
     */
107 13
    public function setController($controller)
108
    {
109 13
        $this->controller = $controller;
110 13
    }
111
112 13
    protected function initController()
113
    {
114 13
        if ($this->isNamespaced()) {
115 8
            $controller = $this->generateControllerNamespaced();
116
        } else {
117 5
            $controller = $this->generateControllerGeneric();
118
        }
119 13
        $this->setController($controller);
120 13
    }
121
122
    /**
123
     * @return string
124
     */
125 8
    protected function generateControllerNamespaced()
126
    {
127 8
        $class = $this->getModelNamespacePath();
128 8
        $class = trim($class, '\\');
129
130 8
        return inflector()->unclassify($class);
131
    }
132
133
    /**
134
     * @return string
135
     */
136 8
    public function getModelNamespacePath()
137
    {
138 8
        if ($this->modelNamespacePath == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->modelNamespacePath of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
139 8
            $this->initModelNamespacePath();
140
        }
141
142 8
        return $this->modelNamespacePath;
143
    }
144
145 8
    public function initModelNamespacePath()
146
    {
147 8
        if ($this->isNamespaced()) {
148 8
            $path = $this->generateModelNamespacePathFromClassName() . '\\';
149
        } else {
150
            $controller = $this->generateControllerGeneric();
151
            $path = inflector()->classify($controller) . '\\';
152
        }
153 8
        $this->modelNamespacePath = $path;
154 8
    }
155
156
    /**
157
     * @return string
158
     */
159 8
    protected function generateModelNamespacePathFromClassName()
160
    {
161 8
        $className = $this->getClassName();
162 8
        $rootNamespace = $this->getRootNamespace();
163 8
        $path = str_replace($rootNamespace, '', $className);
164
165 8
        $nsParts = explode('\\', $path);
166 8
        array_pop($nsParts);
167
168 8
        return implode($nsParts, '\\');
0 ignored issues
show
Bug introduced by
'\' of type string is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

168
        return implode($nsParts, /** @scrutinizer ignore-type */ '\\');
Loading history...
169
    }
170
171
    /**
172
     * @return string
173
     */
174 8
    public function getRootNamespace()
175
    {
176 8
        if (function_exists('app')) {
177
            return app('app')->getRootNamespace() . 'Models\\';
178
        }
179 8
        return 'App\\Models\\';
180
    }
181
182
    /**
183
     * @return string
184
     */
185 5
    protected function generateControllerGeneric()
186
    {
187 5
        $class = $this->getClassName();
188
189 5
        return inflector()->unclassify($class);
190
    }
191
192
    /**
193
     * @param string $name
194
     * @return \Nip\Helpers\AbstractHelper
195
     */
196 1
    public function getHelper($name)
197
    {
198 1
        return HelperBroker::get($name);
199
    }
200
201
    /**
202
     * @return string
203
     */
204
    public function getModelNamespace()
205
    {
206
        return $this->getRootNamespace() . $this->getModelNamespacePath();
207
    }
208
209
    /**
210
     * @return RecordCollection
211
     */
212 1
    public function newCollection()
213
    {
214 1
        $class = $this->getCollectionClass();
215
        /** @var RecordCollection $collection */
216 1
        $collection = new $class();
217 1
        $collection->setManager($this);
218
219 1
        return $collection;
220
    }
221
222
    /**
223
     * @return string
224
     */
225 2
    public function getCollectionClass()
226
    {
227 2
        if ($this->collectionClass === null) {
228 2
            $this->initCollectionClass();
229
        }
230
231 2
        return $this->collectionClass;
232
    }
233
234
    /**
235
     * @param string $collectionClass
236
     */
237 2
    public function setCollectionClass($collectionClass)
238
    {
239 2
        $this->collectionClass = $collectionClass;
240 2
    }
241
242 2
    protected function initCollectionClass()
243
    {
244 2
        $this->setCollectionClass($this->generateCollectionClass());
245 2
    }
246
247
    /**
248
     * @return string
249
     */
250 2
    protected function generateCollectionClass()
251
    {
252 2
        return RecordCollection::class;
253
    }
254
255
    /**
256
     * @return \Nip\Collections\Registry
257
     */
258
    public function getRegistry()
259
    {
260
        if (!$this->registry) {
261
            $this->registry = new Registry();
262
        }
263
264
        return $this->registry;
265
    }
266
267
    /**
268
     * Factory
269
     *
270
     * @param array $data [optional]
271
     * @return Record
272
     */
273 3
    public function getNew($data = [])
274
    {
275 3
        $pk = $this->getPrimaryKey();
276 3
        if (is_string($pk) && isset($data[$pk]) && $this->getRegistry()->has($data[$pk])) {
277
            $return = $this->getRegistry()->get($data[$pk]);
278
            $return->writeData($data);
279
            $return->writeDBData($data);
280
281
            return $return;
282
        }
283
284 3
        $record = $this->getNewRecordFromDB($data);
285
286 3
        return $record;
287
    }
288
289
    /**
290
     * @param array $data
291
     * @return Record
292
     */
293 3
    public function getNewRecordFromDB($data = [])
294
    {
295 3
        $record = $this->getNewRecord($data);
296 3
        $record->writeDBData($data);
297
298 3
        return $record;
299
    }
300
301
    /**
302
     * @param array $data
303
     * @return Record
304
     */
305 3
    public function getNewRecord($data = [])
306
    {
307 3
        $model = $this->getModel();
308
        /** @var Record $record */
309 3
        $record = new $model();
310 3
        $record->setManager($this);
311 3
        $record->writeData($data);
312
313 3
        return $record;
314
    }
315
316
    /**
317
     * @return string
318
     */
319 4
    public function getModel()
320
    {
321 4
        if ($this->model == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->model of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
322 1
            $this->inflectModel();
323
        }
324
325 4
        return $this->model;
326
    }
327
328
    /**
329
     * @param null $model
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $model is correct as it would always require null to be passed?
Loading history...
330
     */
331 1
    public function setModel($model)
332
    {
333 1
        $this->model = $model;
334 1
    }
335
336 1
    protected function inflectModel()
337
    {
338 1
        $class = $this->getClassName();
339 1
        $this->model = $this->generateModelClass($class);
340 1
    }
341
342
    /**
343
     * @param string $class
344
     * @return string
345
     */
346 2
    public function generateModelClass($class = null)
347
    {
348 2
        $class = $class ? $class : get_class($this);
349
350 2
        if (strpos($class, '\\')) {
351 2
            $nsParts = explode('\\', $class);
352 2
            $class = array_pop($nsParts);
353
354 2
            if ($class == 'Table') {
355 1
                $class = 'Row';
356
            } else {
357 1
                $class = ucfirst(inflector()->singularize($class));
358
            }
359
360 2
            return implode($nsParts, '\\') . '\\' . $class;
0 ignored issues
show
Bug introduced by
'\' of type string is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

360
            return implode($nsParts, /** @scrutinizer ignore-type */ '\\') . '\\' . $class;
Loading history...
361
        }
362
363 1
        return ucfirst(inflector()->singularize($class));
364
    }
365
366
    /**
367
     * @return \Nip\Request
368
     */
369
    public function getRequest()
370
    {
371
        return request();
0 ignored issues
show
Bug introduced by
The function request was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

371
        return /** @scrutinizer ignore-call */ request();
Loading history...
372
    }
373
374
    public function __wakeup()
375
    {
376
        $this->initDB();
377
    }
378
379
    /**
380
     * @return RecordCollection
381
     */
382
    public function getAll()
383
    {
384
        if (!$this->getRegistry()->has("all")) {
385
            $this->getRegistry()->set("all", $this->findAll());
386
        }
387
388
        return $this->getRegistry()->get("all");
389
    }
390
391
    /**
392
     * @param Record $model
393
     * @return array
394
     */
395
    public function getQueryModelData($model)
396
    {
397
        $data = [];
398
399
        $fields = $this->getFields();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fields is correct as $this->getFields() targeting Nip\Records\AbstractMode...ordManager::getFields() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
400
        foreach ($fields as $field) {
0 ignored issues
show
Bug introduced by
The expression $fields of type null is not traversable.
Loading history...
401
            if (isset($model->{$field})) {
402
                $data[$field] = $model->{$field};
403
            }
404
        }
405
406
        return $data;
407
    }
408
409
    /**
410
     * The name of the field used as a foreign key in other tables
411
     * @return string
412
     */
413
    public function getUrlPK()
414
    {
415
        if ($this->urlPK == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->urlPK of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
416
            $this->urlPK = $this->getPrimaryKey();
417
        }
418
419
        return $this->urlPK;
420
    }
421
422
    /**
423
     * @param $name
424
     * @return bool
425
     */
426
    public function hasField($name)
427
    {
428
        $fields = $this->getFields();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $fields is correct as $this->getFields() targeting Nip\Records\AbstractMode...ordManager::getFields() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
429
        if (is_array($fields) && in_array($name, $fields)) {
0 ignored issues
show
introduced by
The condition is_array($fields) is always false.
Loading history...
430
            return true;
431
        }
432
433
        return false;
434
    }
435
436
    /**
437
     * @return array
438
     */
439
    public function getFullTextFields()
440
    {
441
        $return = [];
442
        $structure = $this->getTableStructure();
443
        foreach ($structure['indexes'] as $name => $index) {
444
            if ($index['fulltext']) {
445
                $return[$name] = $index['fields'];
446
            }
447
        }
448
449
        return $return;
450
    }
451
452
    /**
453
     * Sets model and database table from the class name
454
     */
455
    protected function inflect()
456
    {
457
        $this->initController();
458
    }
459
}
460