Completed
Push — master ( 81dac7...9060a9 )
by Gabriel
02:17
created

RecordManager::compileURL()   B

Complexity

Conditions 8
Paths 128

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
eloc 19
nc 128
nop 3
dl 0
loc 31
ccs 0
cts 19
cp 0
crap 72
rs 8.2111
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A RecordManager::getModelNamespacePath() 0 7 2
A RecordManager::generateControllerNamespaced() 0 6 1
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\Utility\Traits\NameWorksTrait;
11
12
/**
13
 * Class Table
14
 * @package Nip\Records\_Abstract
15
 *
16
 * @method \Nip_Helper_Url Url()
17
 */
18
abstract class RecordManager
19
{
20
    use NameWorksTrait;
21
    use ActiveRecordsTrait;
22
23
    /**
24
     * Collection class for current record manager
25
     *
26
     * @var string
27
     */
28
    protected $collectionClass = null;
29
30
    protected $helpers = [];
31
32
    /**
33
     * @var null|string
34
     */
35
    protected $urlPK = null;
36
37
    /**
38
     * Model class name
39
     * @var null|string
40
     */
41
    protected $model = null;
42
43
    /**
44
     * @var null|string
45
     */
46
    protected $controller = null;
47
48
    /**
49
     * @var null|string
50
     */
51
    protected $modelNamespacePath = null;
52
53
    protected $registry = null;
54
55
    /**
56
     * Overloads findByRecord, findByField, deleteByRecord, deleteByField, countByRecord, countByField
57
     *
58
     * @example findByCategory(Category $item)
59
     * @example deleteByProduct(Product $item)
60
     * @example findByIdUser(2)
61
     * @example deleteByTitle(array('Lorem ipsum', 'like'))
62
     * @example countByIdCategory(1)
63
     *
64
     * @param string $name
65
     * @param array $arguments
66
     *
67
     * @return mixed
68
     */
69 1
    public function __call($name, $arguments)
70
    {
71 1
        $return = $this->isCallDatabaseOperation($name, $arguments);
72 1
        if ($return !== false) {
73
            return $return;
74
        }
75
76
        /** @noinspection PhpAssignmentInConditionInspection */
77 1
        if ($return = $this->isCallUrl($name, $arguments)) {
0 ignored issues
show
Bug introduced by
The method isCallUrl() does not exist on Nip\Records\AbstractModels\RecordManager. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

77
        if ($return = $this->/** @scrutinizer ignore-call */ isCallUrl($name, $arguments)) {
Loading history...
78
            return $return;
79
        }
80
81 1
        if ($name === ucfirst($name)) {
82 1
            return $this->getHelper($name);
83
        }
84
85
        trigger_error("Call to undefined method $name", E_USER_ERROR);
86
87
        return $this;
88
    }
89
90
    /**
91
     * @return string
92
     */
93
    public function getController()
94
    {
95 1
        if ($this->controller === null) {
96
            $this->initController();
97 1
        }
98
99
        return $this->controller;
100
    }
101
102
    /**
103
     * @param null|string $controller
104
     */
105 1
    public function setController($controller)
106
    {
107
        $this->controller = $controller;
108
    }
109
110
    protected function initController()
111
    {
112
        if ($this->isNamespaced()) {
113
            $controller = $this->generateControllerNamespaced();
114
        } else {
115
            $controller = $this->generateControllerGeneric();
116
        }
117
        $this->setController($controller);
118
    }
119
120
    /**
121
     * @return string
122
     */
123
    protected function generateControllerNamespaced()
124
    {
125
        $class = $this->getModelNamespacePath();
126
        $class = trim($class, '\\');
127
128
        return inflector()->unclassify($class);
129
    }
130
131
    /**
132
     * @return string
133
     */
134
    public function getModelNamespacePath()
135
    {
136
        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...
137
            $this->initModelNamespacePath();
138
        }
139
140
        return $this->modelNamespacePath;
141
    }
142
143
    public function initModelNamespacePath()
144
    {
145
        if ($this->isNamespaced()) {
146
            $path = $this->generateModelNamespacePathFromClassName() . '\\';
147
        } else {
148
            $controller = $this->generateControllerGeneric();
149
            $path = inflector()->classify($controller) . '\\';
150 13
        }
151
        $this->modelNamespacePath = $path;
152 13
    }
153 13
154
    /**
155
     * @return string
156 13
     */
157
    protected function generateModelNamespacePathFromClassName()
158
    {
159
        $className = $this->getClassName();
160
        $rootNamespace = $this->getRootNamespace();
161
        $path = str_replace($rootNamespace, '', $className);
162 13
163
        $nsParts = explode('\\', $path);
164 13
        array_pop($nsParts);
165 13
166
        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

166
        return implode($nsParts, /** @scrutinizer ignore-type */ '\\');
Loading history...
167 13
    }
168
169 13
    /**
170 8
     * @return string
171
     */
172 5
    public function getRootNamespace()
173
    {
174 13
        if (function_exists('app')) {
175 13
            return app('app')->getRootNamespace() . 'Models\\';
176
        }
177
        return 'App\\Models\\';
178
    }
179
180 8
    /**
181
     * @return string
182 8
     */
183 8
    protected function generateControllerGeneric()
184
    {
185 8
        $class = $this->getClassName();
186
187
        return inflector()->unclassify($class);
188
    }
189
190
    /**
191 8
     * @param string $name
192
     * @return \Nip\Helpers\AbstractHelper
193 8
     */
194 8
    public function getHelper($name)
195
    {
196
        return HelperBroker::get($name);
197 8
    }
198
199
    /**
200 8
     * @return string
201
     */
202 8
    public function getModelNamespace()
203 8
    {
204
        return $this->getRootNamespace() . $this->getModelNamespacePath();
205
    }
206
207
    /**
208 8
     * When searching by primary key, look for items in current registry before
209 8
     * fetching them from the database
210
     *
211
     * @param array $pk_list
212
     * @return RecordCollection
213
     */
214 8
    public function findByPrimary($pk_list = [])
215
    {
216 8
        $pk = $this->getPrimaryKey();
217 8
        $return = $this->newCollection();
218 8
219
        if ($pk_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $pk_list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
220 8
            $pk_list = array_unique($pk_list);
221 8
            foreach ($pk_list as $key => $value) {
222
                $item = $this->getRegistry()->get($value);
223 8
                if ($item) {
224
                    unset($pk_list[$key]);
225
                    $return[$item->{$pk}] = $item;
226
                }
227
            }
228
            if ($pk_list) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $pk_list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
229 8
                $query = $this->paramsToQuery();
230
                $query->where("$pk IN ?", $pk_list);
231 8
                $items = $this->findByQuery($query);
232
233
                if (count($items)) {
234 8
                    foreach ($items as $item) {
235
                        $this->getRegistry()->set($item->{$pk}, $item);
236
                        $return[$item->{$pk}] = $item;
237
                    }
238
                }
239
            }
240 5
        }
241
242 5
        return $return;
243
    }
244 5
245
    /**
246
     * @return RecordCollection
247
     */
248
    public function newCollection()
249
    {
250
        $class = $this->getCollectionClass();
251 1
        /** @var RecordCollection $collection */
252
        $collection = new $class();
253 1
        $collection->setManager($this);
254
255
        return $collection;
256
    }
257
258
    /**
259
     * @return string
260
     */
261
    public function getCollectionClass()
262
    {
263
        if ($this->collectionClass === null) {
264
            $this->initCollectionClass();
265
        }
266
267
        return $this->collectionClass;
268
    }
269
270
    /**
271
     * @param string $collectionClass
272
     */
273
    public function setCollectionClass($collectionClass)
274
    {
275
        $this->collectionClass = $collectionClass;
276
    }
277
278
    protected function initCollectionClass()
279
    {
280
        $this->setCollectionClass($this->generateCollectionClass());
281
    }
282
283
    /**
284
     * @return string
285
     */
286
    protected function generateCollectionClass()
287
    {
288
        return RecordCollection::class;
289
    }
290
291
    /**
292
     * @return \Nip\Collections\Registry
293
     */
294
    public function getRegistry()
295
    {
296
        if (!$this->registry) {
297
            $this->registry = new Registry();
298
        }
299
300
        return $this->registry;
301
    }
302
303
    /**
304
     * Factory
305 1
     *
306
     * @param array $data [optional]
307 1
     * @return Record
308
     */
309 1
    public function getNew($data = [])
310 1
    {
311
        $pk = $this->getPrimaryKey();
312 1
        if (is_string($pk) && isset($data[$pk]) && $this->getRegistry()->has($data[$pk])) {
313
            $return = $this->getRegistry()->get($data[$pk]);
314
            $return->writeData($data);
315
            $return->writeDBData($data);
316
317
            return $return;
318 2
        }
319
320 2
        $record = $this->getNewRecordFromDB($data);
321 2
322
        return $record;
323
    }
324 2
325
    /**
326
     * @param array $data
327
     * @return Record
328
     */
329
    public function getNewRecordFromDB($data = [])
330 2
    {
331
        $record = $this->getNewRecord($data);
332 2
        $record->writeDBData($data);
333 2
334
        return $record;
335 2
    }
336
337 2
    /**
338 2
     * @param array $data
339
     * @return Record
340
     */
341
    public function getNewRecord($data = [])
342
    {
343 2
        $model = $this->getModel();
344
        /** @var Record $record */
345 2
        $record = new $model();
346
        $record->setManager($this);
347
        $record->writeData($data);
348
349
        return $record;
350
    }
351
352
    /**
353
     * @return string
354
     */
355
    public function getModel()
356
    {
357
        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...
358
            $this->inflectModel();
359
        }
360
361
        return $this->model;
362
    }
363
364
    /**
365
     * @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...
366 3
     */
367
    public function setModel($model)
368 3
    {
369 3
        $this->model = $model;
370
    }
371
372
    protected function inflectModel()
373
    {
374
        $class = $this->getClassName();
375
        $this->model = $this->generateModelClass($class);
376
    }
377 3
378
    /**
379 3
     * @param string $class
380
     * @return string
381
     */
382
    public function generateModelClass($class = null)
383
    {
384
        $class = $class ? $class : get_class($this);
385
386 3
        if (strpos($class, '\\')) {
387
            $nsParts = explode('\\', $class);
388 3
            $class = array_pop($nsParts);
389 3
390
            if ($class == 'Table') {
391 3
                $class = 'Row';
392
            } else {
393
                $class = ucfirst(inflector()->singularize($class));
394
            }
395
396
            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

396
            return implode($nsParts, /** @scrutinizer ignore-type */ '\\') . '\\' . $class;
Loading history...
397
        }
398 3
399
        return ucfirst(inflector()->singularize($class));
400 3
    }
401
402 3
    /**
403 3
     * @return \Nip\Request
404 3
     */
405
    public function getRequest()
406 3
    {
407
        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

407
        return /** @scrutinizer ignore-call */ request();
Loading history...
408
    }
409
410
    public function __wakeup()
411
    {
412 4
        $this->initDB();
413
    }
414 4
415 1
416
    /**
417
     * Finds one Record using params array
418 4
     *
419
     * @param array $params
420
     * @return Record|null
421
     */
422
    public function findOneByParams(array $params = [])
423
    {
424 1
        $params['limit'] = 1;
425
        $records = $this->findByParams($params);
426 1
        if (count($records) > 0) {
427 1
            return $records->rewind();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $records->rewind() targeting Nip\Collections\AbstractCollection::rewind() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
Bug Best Practice introduced by
The expression return $records->rewind() returns the type void which is incompatible with the documented return type Nip\Records\AbstractModels\Record|null.
Loading history...
428
        }
429 1
430
        return null;
431 1
    }
432 1
433 1
    /**
434
     * Finds Records using params array
435
     *
436
     * @param array $params
437
     * @return RecordCollection
438
     */
439 2
    public function findByParams($params = [])
440
    {
441 2
        $query = $this->paramsToQuery($params);
442
443 2
        return $this->findByQuery($query, $params);
444 2
    }
445 2
446
    /**
447 2
     * @return RecordCollection
448 1
     */
449
    public function getAll()
450 1
    {
451
        if (!$this->getRegistry()->has("all")) {
452
            $this->getRegistry()->set("all", $this->findAll());
453 2
        }
454
455
        return $this->getRegistry()->get("all");
456 1
    }
457
458
    /**
459
     * @return RecordCollection
460
     */
461
    public function findAll()
462
    {
463
        return $this->findByParams();
464
    }
465
466
    /**
467
     * @param int $count
468
     * @return RecordCollection
469
     */
470
    public function findLast($count = 9)
471
    {
472
        return $this->findByParams([
473
            'limit' => $count,
474
        ]);
475
    }
476
477
    /**
478
     * Inserts a Record into the database
479
     * @param Record $model
480
     * @param array|bool $onDuplicate
481
     * @return integer
482
     */
483
    public function insert($model, $onDuplicate = false)
484
    {
485
        $query = $this->insertQuery($model, $onDuplicate);
486
        $query->execute();
487
488
        return $this->getDB()->lastInsertID();
489
    }
490
491
    /**
492
     * @param Record $model
493
     * @param $onDuplicate
494
     * @return InsertQuery
495
     */
496
    public function insertQuery($model, $onDuplicate)
497
    {
498
        $inserts = $this->getQueryModelData($model);
499
500
        $query = $this->newInsertQuery();
501
        $query->data($inserts);
502
503
        if ($onDuplicate !== false) {
504
            $query->onDuplicate($onDuplicate);
505
        }
506
507
        return $query;
508
    }
509
510
    /**
511
     * @param Record $model
512
     * @return array
513
     */
514
    public function getQueryModelData($model)
515
    {
516
        $data = [];
517
518
        $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...
519
        foreach ($fields as $field) {
0 ignored issues
show
Bug introduced by
The expression $fields of type null is not traversable.
Loading history...
520
            if (isset($model->{$field})) {
521
                $data[$field] = $model->{$field};
522
            }
523
        }
524
525
        return $data;
526
    }
527
528
    /**
529
     * The name of the field used as a foreign key in other tables
530
     * @return string
531
     */
532
    public function getUrlPK()
533
    {
534
        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...
535
            $this->urlPK = $this->getPrimaryKey();
536
        }
537
538
        return $this->urlPK;
539
    }
540
541
    /**
542
     * @param $name
543
     * @return bool
544
     */
545
    public function hasField($name)
546
    {
547
        $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...
548
        if (is_array($fields) && in_array($name, $fields)) {
0 ignored issues
show
introduced by
The condition is_array($fields) is always false.
Loading history...
549
            return true;
550
        }
551
552
        return false;
553
    }
554
555
    /**
556
     * @return array
557
     */
558
    public function getFullTextFields()
559
    {
560
        $return = [];
561
        $structure = $this->getTableStructure();
562
        foreach ($structure['indexes'] as $name => $index) {
563
            if ($index['fulltext']) {
564
                $return[$name] = $index['fields'];
565
            }
566
        }
567
568
        return $return;
569
    }
570
571
    /**
572
     * Sets model and database table from the class name
573
     */
574
    protected function inflect()
575
    {
576
        $this->initController();
577
    }
578
}
579