GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( a5b8a0...027183 )
by Andreas
02:54
created

AbstractDbEntity   D

Complexity

Total Complexity 111

Size/Duplication

Total Lines 732
Duplicated Lines 1.5 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 111
c 2
b 0
f 0
lcom 1
cbo 3
dl 11
loc 732
ccs 255
cts 255
cp 1
rs 4.4444

44 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 2
B checkStaticProperties() 0 17 9
A setPrimaryDbValueOrRowData() 0 9 3
A getDefaultDbData() 0 12 3
A getDefaultDbPropertyValue() 0 12 2
A getPrimaryDbValue() 0 13 3
A setPrimaryDbValue() 0 16 4
A isNewDbEntity() 0 11 2
A shouldInsertOnDbSave() 0 5 3
D setDbValue() 0 25 9
A getDbValue() 0 4 1
A getDbFieldName() 0 8 2
A getDbPropertyName() 0 8 2
A hasModifiedDbValues() 0 4 1
A isDbValueModified() 0 4 1
A getModifiedDbData() 0 4 1
A clearModifiedDbProperties() 0 4 1
B __call() 0 17 8
A setDbData() 5 8 3
B setDbDataFromRow() 6 20 6
A getDbData() 0 4 1
A getDbDataWithoutPrimary() 0 14 3
A setDeleteFromDbOnSave() 0 4 1
A shouldBeDeletedFromDbOnSave() 0 4 1
A isDeleted() 0 4 1
A setDeleted() 0 4 1
A setForceDbInsertOnSave() 0 4 1
A shouldForceDbInsertOnSave() 0 4 1
A getDbPropertyMaxLength() 0 6 2
A getDbPropertyRequired() 0 6 2
A getDbPropertyNonEmpty() 0 6 2
B getDbDataValidator() 0 20 6
A validateAndSetDbData() 0 15 2
A getPrimaryDbPropertyKey() 0 4 1
A getPrimaryDbFieldKey() 0 15 3
A getDbPropertyNames() 0 6 2
A getDbFieldNames() 0 9 3
A getPrefixedDbFieldNames() 0 4 1
A getAliasedDbFieldNames() 0 11 2
A filterStripDbRowData() 0 14 4
A getDbTableName() 0 4 1
A serialize() 0 4 1
A unserialize() 0 8 2
A mergeWith() 0 5 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AbstractDbEntity 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 AbstractDbEntity, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Starlit Db.
4
 *
5
 * @copyright Copyright (c) 2016 Starweb / Ehandelslogik i Lund AB
6
 * @license   BSD 3-Clause
7
 */
8
9
namespace Starlit\Db;
10
11
use Starlit\Utils\Str;
12
use Starlit\Utils\Arr;
13
use Starlit\Utils\Validation\Validator;
14
use Starlit\Utils\Validation\ValidatorTranslatorInterface;
15
use Symfony\Component\Translation\TranslatorInterface as SymfonyTranslatorInterface;
16
17
/**
18
 * Abstract class to model a single database row into an object.
19
 *
20
 * @author Andreas Nilsson <http://github.com/jandreasn>
21
 */
22
abstract class AbstractDbEntity implements \Serializable
23
{
24
    /**
25
     * The database table name (meant to be overridden).
26
     *
27
     * @var string
28
     */
29
    protected static $dbTableName;
30
31
    /**
32
     * Entity's database properties and their attributes (meant to be overridden).
33
     * Example format:
34
     *
35
     * $dbProperties = [
36
     *     'productId' => ['type' => 'int'],
37
     *     'otherId'   => ['type' => 'int', 'required' => true, 'validate' => false],
38
     *     'name'      => ['type' => 'string', 'maxLength' => 10, 'required' => true, 'default' => 'Some name'],
39
     * ];
40
     *
41
     * 'type' => 'int'     Corresponding PHP type (required).
42
     * 'validate' => false Turn off data validation, for example on required key fields that are set internally.
43
     * 'required' => true  The value have to be set (not '', null, false)
44
     * 'nonEmpty' => true  The value should not be empty ('', 0, null)
45
     *
46
     * Properties correspond to database table's columns but words are
47
     * camel cased instead of separated with underscore (_) as in the database.
48
     *
49
     * @var array
50
     */
51
    protected static $dbProperties = [];
52
53
    /**
54
     * Object database field name that is used for primary key (meant to be overridden).
55
     * Should be camel cased as it maps to the dbFields array.
56
     *
57
     * @var string|array
58
     */
59
    protected static $primaryDbPropertyKey;
60
61
    /**
62
     * @var array
63
     */
64
    private static $cachedDefaultDbData = [];
65
66
    /**
67
     * @var array
68
     */
69
    private static $cachedDbPropertyNames;
70
71
    /**
72
     * @var array
73
     */
74
    private static $cachedDbFieldNames;
75
76
    /**
77
     * @var array
78
     */
79
    private static $typeDefaults = [
80
        'string' => '',
81
        'int'    => 0,
82
        'float'  => 0.0,
83
        'bool'   => false,
84
    ];
85
86
    /**
87
     * Database row data with field names and their values.
88
     *
89
     * @var array
90
     */
91
    private $dbData = [];
92
93
    /**
94
     * Database fields that has had their value modified since init/load.
95
     *
96
     * @var array
97
     */
98
    private $modifiedDbProperties = [];
99
100
    /**
101
     * @var bool
102
     */
103
    private $deleteFromDbOnSave = false;
104
105
    /**
106
     * @var bool
107
     */
108
    private $deleted = false;
109
110
    /**
111
     * @var bool
112
     */
113
    private $forceDbInsertOnSave = false;
114
115
    /**
116
     * Constructor.
117
     *
118
     * @param mixed $primaryDbValueOrRowData
119
     */
120 64
    public function __construct($primaryDbValueOrRowData = null)
121
    {
122 64
        self::checkStaticProperties();
123
124
        // Set default values
125 63
        $this->dbData = $this->getDefaultDbData();
126
127
        // Override default values with provided values
128 63
        if ($primaryDbValueOrRowData !== null) {
129 13
            $this->setPrimaryDbValueOrRowData($primaryDbValueOrRowData);
130 13
        }
131 63
    }
132
133
    /**
134
     * Make sure that class has all necessary static properties set.
135
     */
136 64
    private static function checkStaticProperties()
137
    {
138 64
        static $checkedClasses = [];
139 64
        if (!in_array(static::class, $checkedClasses)) {
140
            if (!static::$dbTableName
141 7
                || !static::$dbProperties
0 ignored issues
show
Bug Best Practice introduced by
The expression static::$dbProperties 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...
142 6
                || !static::$primaryDbPropertyKey
143 6
                || (is_scalar(static::$primaryDbPropertyKey)
144 6
                    && !isset(static::$dbProperties[static::$primaryDbPropertyKey]['type']))
145 6
                || (is_array(static::$primaryDbPropertyKey)
146 6
                    && !Arr::allIn(static::$primaryDbPropertyKey, array_keys(static::$dbProperties)))
147 7
            ) {
148 1
                throw new \LogicException("All db entity's static properties not set");
149
            }
150 6
            $checkedClasses[] = static::class;
151 6
        }
152 63
    }
153
154
    /**
155
     * @param mixed $primaryDbValueOrRowData
156
     */
157 13
    public function setPrimaryDbValueOrRowData($primaryDbValueOrRowData = null)
158
    {
159
        // Row data would ba an associative array (not sequential, that would indicate a multi column primary key)
160 13
        if (is_array($primaryDbValueOrRowData) && !isset($primaryDbValueOrRowData[0])) {
161 1
            $this->setDbDataFromRow($primaryDbValueOrRowData);
162 1
        } else {
163 12
            $this->setPrimaryDbValue($primaryDbValueOrRowData);
164
        }
165 13
    }
166
167
    /**
168
     * Get all default database values.
169
     *
170
     * @return array
171
     */
172 63
    public function getDefaultDbData()
173
    {
174 63
        $class = get_called_class();
175 63
        if (!isset(self::$cachedDefaultDbData[$class])) {
176 6
            self::$cachedDefaultDbData[$class] = [];
177 6
            foreach (array_keys(static::$dbProperties) as $propertyName) {
178 6
                self::$cachedDefaultDbData[$class][$propertyName] = $this->getDefaultDbPropertyValue($propertyName);
179 6
            }
180 6
        }
181
182 63
        return self::$cachedDefaultDbData[$class];
183
    }
184
185
    /**
186
     * Get default db value (can be overridden if non static default values need to be used).
187
     *
188
     * @param string $propertyName
189
     * @return mixed
190
     */
191 6
    public function getDefaultDbPropertyValue($propertyName)
192
    {
193
        // A default value is set
194 6
        if (array_key_exists('default', static::$dbProperties[$propertyName])) {
195 4
            $defaultValue = static::$dbProperties[$propertyName]['default'];
196
        // No default value set, use default for type
197 4
        } else {
198 6
            $defaultValue = self::$typeDefaults[static::$dbProperties[$propertyName]['type']];
199
        }
200
201 6
        return $defaultValue;
202
    }
203
204
    /**
205
     * @return mixed
206
     */
207 21
    public function getPrimaryDbValue()
208
    {
209 21
        if (is_array(static::$primaryDbPropertyKey)) {
210 3
            $primaryValues = [];
211 3
            foreach (static::$primaryDbPropertyKey as $keyPart) {
212 3
                $primaryValues[] = $this->dbData[$keyPart];
213 3
            }
214
215 3
            return $primaryValues;
216
        }
217
218 18
        return $this->dbData[static::$primaryDbPropertyKey];
219
    }
220
221
    /**
222
     * @param mixed $primaryDbValue
223
     */
224 17
    public function setPrimaryDbValue($primaryDbValue)
225
    {
226 17
        if (is_array(static::$primaryDbPropertyKey)) {
227 3
            if (!is_array($primaryDbValue)) {
228 1
                throw new \InvalidArgumentException("Primary db value should be an array");
229
            }
230
231 2
            reset($primaryDbValue);
232 2
            foreach (static::$primaryDbPropertyKey as $keyPart) {
233 2
                $this->dbData[$keyPart] = current($primaryDbValue);
234 2
                next($primaryDbValue);
235 2
            }
236 2
        } else {
237 14
            $this->dbData[static::$primaryDbPropertyKey] = $primaryDbValue;
238
        }
239 16
    }
240
241
    /**
242
     * @return bool
243
     */
244 9
    public function isNewDbEntity()
245
    {
246 9
        if (is_array(static::$primaryDbPropertyKey)) {
247
            // Multiple column keys have to use explicit force insert because we have no way
248
            // to detect if it's a new entity (can't leave more than one primary field empty on insert because
249
            // db can't have two auto increment columns)
250 1
            throw new \LogicException("Can't detect if multi column primary key is a new entity");
251
        }
252
253 8
        return !$this->getPrimaryDbValue();
254
    }
255
256
    /**
257
     * @return bool
258
     */
259 8
    public function shouldInsertOnDbSave()
260
    {
261 8
        return (!is_array(static::$primaryDbPropertyKey) && $this->isNewDbEntity())
262 8
            || $this->shouldForceDbInsertOnSave();
263
    }
264
265
    /**
266
     * Set a row field value.
267
     *
268
     * @param string $property
269
     * @param mixed  $value
270
     * @param bool   $setAsModified
271
     */
272 23
    protected function setDbValue($property, $value, $setAsModified = true)
273
    {
274 23
        if (!isset(static::$dbProperties[$property])) {
275 1
            throw new \InvalidArgumentException("No database entity property[{$property}] exists");
276
        }
277
278
        // Don't set type if value is null and allowed (allowed currently indicated by default => null)
279 22
        $nullIsAllowed = (array_key_exists('default', static::$dbProperties[$property])
280 22
            && static::$dbProperties[$property]['default'] === null);
281 22
        if (!($value === null && $nullIsAllowed)) {
282 22
            $type = static::$dbProperties[$property]['type'];
283
            // Set null when empty and default is null
284 22
            if ($value === '' && $nullIsAllowed) {
285 1
                 $value = null;
286 1
            } else {
287 22
                settype($value, $type);
288
            }
289 22
        }
290
291 22
        $this->dbData[$property] = $value;
292
293 22
        if ($setAsModified && !$this->isDbValueModified($property)) {
294 15
            $this->modifiedDbProperties[] = $property;
295 15
        }
296 22
    }
297
298
    /**
299
     * Get a database field value.
300
     *
301
     * @param string $property
302
     * @return mixed
303
     */
304 8
    protected function getDbValue($property)
305
    {
306 8
        return $this->dbData[$property];
307
    }
308
309
    /**
310
     * Get raw (with underscore as word separator as it is formatted in database)
311
     * field name from a object field property name (camelcased).
312
     *
313
     * @param string $propertyName
314
     * @return string
315
     */
316 18
    public static function getDbFieldName($propertyName)
317
    {
318 18
        if (!isset(self::$cachedDbFieldNames[$propertyName])) {
319 5
            self::$cachedDbFieldNames[$propertyName] = Str::camelToSeparator($propertyName);
320 5
        }
321
322 18
        return self::$cachedDbFieldNames[$propertyName];
323
    }
324
325
    /**
326
     * Get object field property name (camelCased) from database field name (underscore separated).
327
     *
328
     * @param string $dbFieldName
329
     * @return string
330
     */
331 7
    public static function getDbPropertyName($dbFieldName)
332
    {
333 7
        if (!isset(self::$cachedDbPropertyNames[$dbFieldName])) {
334 2
            self::$cachedDbPropertyNames[$dbFieldName] = Str::separatorToCamel($dbFieldName);
335 2
        }
336
337 7
        return self::$cachedDbPropertyNames[$dbFieldName];
338
    }
339
340
    /**
341
     * @return bool
342
     */
343 5
    public function hasModifiedDbValues()
344
    {
345 5
        return !empty($this->modifiedDbProperties);
346
    }
347
348
    /**
349
     * @param string $property
350
     * @return bool
351
     */
352 15
    public function isDbValueModified($property)
353
    {
354 15
        return in_array($property, $this->modifiedDbProperties);
355
    }
356
357
    /**
358
     * @return array
359
     */
360 5
    public function getModifiedDbData()
361
    {
362 5
        return array_intersect_key($this->dbData, array_flip($this->modifiedDbProperties));
363
    }
364
365
    /**
366
     */
367 4
    public function clearModifiedDbProperties()
368
    {
369 4
        $this->modifiedDbProperties = [];
370 4
    }
371
372
    /**
373
     * Magic method used to automate getters & setters for row data.
374
     *
375
     * @param string $name
376
     * @param array  $arguments
377
     * @return mixed
378
     */
379 17
    public function __call($name, array $arguments = [])
380
    {
381 17
        $propertyName = lcfirst(substr($name, 3));
382
383 17
        if (strpos($name, 'get') === 0 && isset(static::$dbProperties[$propertyName])) {
384 6
            return $this->getDbValue($propertyName);
385 13
        } elseif (strpos($name, 'set') === 0 && isset(static::$dbProperties[$propertyName])) {
386 12
            $argumentCount = count($arguments);
387 12
            if ($argumentCount === 1 || $argumentCount === 2) {
388 11
                return $this->setDbValue($propertyName, $arguments[0], ($argumentCount === 2) ? $arguments[1] : true);
389
            } else {
390 1
                throw new \BadMethodCallException("Invalid argument count[{$argumentCount}] for {$name}()");
391
            }
392
        } else {
393 1
            throw new \BadMethodCallException("No method named {$name}()");
394
        }
395
    }
396
397
    /**
398
     * Set database fields' data.
399
     *
400
     * @param array $data
401
     */
402 3
    public function setDbData(array $data)
403
    {
404 3 View Code Duplication
        foreach (array_keys(static::$dbProperties) as $propertyName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
405 3
            if (array_key_exists($propertyName, $data)) {
406 3
                $this->setDbValue($propertyName, $data[$propertyName], true);
407 3
            }
408 3
        }
409 3
    }
410
411
    /**
412
     * Set db data from raw database row data with field names in database format.
413
     *
414
     * @param array $rowData
415
     */
416 7
    public function setDbDataFromRow(array $rowData)
417
    {
418
        // If there are less row data than properties, use rows as starting point (optimization)
419 7
        if (count($rowData) < count(static::$dbProperties)) {
420 6
            foreach ($rowData as $dbFieldName => $value) {
421 6
                $propertyName = static::getDbPropertyName($dbFieldName);
422 6
                if (isset(static::$dbProperties[$propertyName])) {
423 6
                    $this->setDbValue($propertyName, $value, false);
424 6
                }
425 6
            }
426
        // If there are more row data than properties, use properties as starting point
427 6
        } else {
428 2 View Code Duplication
            foreach (array_keys(static::$dbProperties) as $propertyName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
429 2
                $fieldName = static::getDbFieldName($propertyName);
430 2
                if (array_key_exists($fieldName, $rowData)) {
431 2
                    $this->setDbValue($propertyName, $rowData[$fieldName], false);
432 2
                }
433 2
            }
434
        }
435 7
    }
436
437
    /**
438
     * @return array
439
     */
440 8
    public function getDbData()
441
    {
442 8
        return $this->dbData;
443
    }
444
445
    /**
446
     * @return array
447
     */
448 2
    public function getDbDataWithoutPrimary()
449
    {
450 2
        $dbDataWithoutPrimary = $this->dbData;
451
452 2
        if (is_array(static::$primaryDbPropertyKey)) {
453 1
            foreach (static::$primaryDbPropertyKey as $keyPart) {
454 1
                unset($dbDataWithoutPrimary[$keyPart]);
455 1
            }
456 1
        } else {
457 1
            unset($dbDataWithoutPrimary[static::$primaryDbPropertyKey]);
458
        }
459
460 2
        return $dbDataWithoutPrimary;
461
    }
462
463
    /**
464
     * @param bool $deleteFromDbOnSave
465
     */
466 3
    public function setDeleteFromDbOnSave($deleteFromDbOnSave = true)
467
    {
468 3
        $this->deleteFromDbOnSave = $deleteFromDbOnSave;
469 3
    }
470
471
    /**
472
     * @return bool
473
     */
474 10
    public function shouldBeDeletedFromDbOnSave()
475
    {
476 10
        return $this->deleteFromDbOnSave;
477
    }
478
479
    /**
480
     * @return bool;
0 ignored issues
show
Documentation introduced by
The doc-type bool; could not be parsed: Expected "|" or "end of type", but got ";" at position 4. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
481
     */
482 1
    public function isDeleted()
483
    {
484 1
        return $this->deleted;
485
    }
486
487
    /**
488
     * @param bool $deleted
489
     */
490 3
    public function setDeleted($deleted = true)
491
    {
492 3
        $this->deleted = $deleted;
493 3
    }
494
495
    /**
496
     * @param bool $forceDbInsertOnSave
497
     */
498 5
    public function setForceDbInsertOnSave($forceDbInsertOnSave)
499
    {
500 5
        $this->forceDbInsertOnSave = $forceDbInsertOnSave;
501 5
    }
502
503
    /**
504
     * @return bool
505
     */
506 9
    public function shouldForceDbInsertOnSave()
507
    {
508 9
        return $this->forceDbInsertOnSave;
509
    }
510
511
    /**
512
     * @param string $propertyName
513
     * @return int|null
514
     */
515 6
    public static function getDbPropertyMaxLength($propertyName)
516
    {
517 6
        return isset(static::$dbProperties[$propertyName]['maxLength'])
518 6
            ? static::$dbProperties[$propertyName]['maxLength']
519 6
            : null;
520
    }
521
522
    /**
523
     * @param string $propertyName
524
     * @return bool
525
     */
526 2
    public static function getDbPropertyRequired($propertyName)
527
    {
528 2
        return isset(static::$dbProperties[$propertyName]['required'])
529 2
            ? static::$dbProperties[$propertyName]['required']
530 2
            : false;
531
    }
532
533
    /**
534
     * @param string $propertyName
535
     * @return bool
536
     */
537 3
    public static function getDbPropertyNonEmpty($propertyName)
538
    {
539 3
        return isset(static::$dbProperties[$propertyName]['nonEmpty'])
540 3
            ? static::$dbProperties[$propertyName]['nonEmpty']
541 3
            : false;
542
    }
543
544
    /**
545
     * Get validator for object's database data.
546
     *
547
     * @param ValidatorTranslatorInterface|SymfonyTranslatorInterface|null $translator
548
     * @return Validator
549
     */
550 3
    public function getDbDataValidator($translator = null)
551
    {
552 3
        $validRuleProperties = Validator::getValidRuleProperties();
553 3
        $fieldsRuleProperties = [];
554 3
        foreach (static::$dbProperties as $propertyName => $attributes) {
555
            // Always validate if validate is not explicitly set to false
556 3
            if (!isset($attributes['validate']) || $attributes['validate'] === true) {
557 3
                $fieldsRuleProperties[$propertyName] = [];
558 3
                foreach ($validRuleProperties as $ruleName) {
559 3
                    if (isset($attributes[$ruleName])) {
560 3
                        $fieldsRuleProperties[$propertyName][$ruleName] = $attributes[$ruleName];
561 3
                    }
562 3
                }
563 3
            }
564 3
        }
565
566 3
        $validator = new Validator($fieldsRuleProperties, $translator);
567
568 3
        return $validator;
569
    }
570
571
    /**
572
     * Validate and (if no error messages) set database data.
573
     *
574
     * @param array  $data The data (e.g. from a form post) to be validated and set
575
     * @param ValidatorTranslatorInterface|SymfonyTranslatorInterface|null $translator
576
     * @return array An array with all (if any) of error messages
577
     */
578 2
    public function validateAndSetDbData(array $data, $translator = null)
0 ignored issues
show
Unused Code introduced by
The parameter $translator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
579
    {
580
        // Get arguments this method was called with, to allow passthrough to getDbDataValidator()
581 2
        $args = array_slice(func_get_args(), 1);
582
583 2
        $validator = call_user_func_array([$this, 'getDbDataValidator'], $args);
584 2
        $errorMessages = $validator->validate($data);
585
586 2
        if (empty($errorMessages)) {
587
            // Set db data from validated data because validator normalizes data as well (like trim)
588 1
            $this->setDbData($validator->getValidatedData());
589 1
        }
590
591 2
        return $errorMessages;
592
    }
593
594
    /**
595
     * @return string|array
596
     */
597 17
    public static function getPrimaryDbPropertyKey()
598
    {
599 17
        return static::$primaryDbPropertyKey;
600
    }
601
602
    /**
603
     * @return string|array
604
     */
605 9
    public static function getPrimaryDbFieldKey()
606
    {
607 9
        $primaryDbPropertyKey = static::getPrimaryDbPropertyKey();
608
609 9
        if (is_array($primaryDbPropertyKey)) {
610 2
            $primaryDbFieldKey = [];
611 2
            foreach ($primaryDbPropertyKey as $propertyName) {
612 2
                $primaryDbFieldKey[] = static::getDbFieldName($propertyName);
613 2
            }
614
615 2
            return $primaryDbFieldKey;
616
        } else {
617 7
            return static::getDbFieldName($primaryDbPropertyKey);
618
        }
619
    }
620
621
    /**
622
     * Return array with db property names.
623
     *
624
     * @param array $exclude
625
     * @return array
626
     */
627 1
    public static function getDbPropertyNames(array $exclude = [])
628
    {
629 1
        $dbPropertyNames = array_keys(static::$dbProperties);
630
631 1
        return $exclude ? array_diff($dbPropertyNames, $exclude) : $dbPropertyNames;
632
    }
633
634
    /**
635
     * Return array with raw db field names.
636
     *
637
     * @param array $exclude
638
     * @return array
639
     */
640 3
    public static function getDbFieldNames(array $exclude = [])
641
    {
642 3
        $fieldNames = [];
643 3
        foreach (array_keys(static::$dbProperties) as $propertyName) {
644 3
            $fieldNames[] = static::getDbFieldName($propertyName);
645 3
        }
646
647 3
        return $exclude ? array_diff($fieldNames, $exclude) : $fieldNames;
648
    }
649
650
651
    /**
652
     * Get raw database field names prefixed (id, name becomes t.id, t.name etc.).
653
     *
654
     * @param string $dbTableAlias
655
     * @param array  $exclude
656
     * @return array
657
     */
658 1
    public static function getPrefixedDbFieldNames($dbTableAlias, array $exclude = [])
659
    {
660 1
        return Arr::valuesWithPrefix(static::getDbFieldNames($exclude), $dbTableAlias . '.');
0 ignored issues
show
Documentation introduced by
$dbTableAlias . '.' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
661
    }
662
663
    /**
664
     * Get database columns transformed from e.g. "productId, date" to "p.product_id AS p_product_id, p.date AS p_date".
665
     *
666
     * @param string $dbTableAlias
667
     * @param array  $exclude
668
     * @return array
669
     */
670 1
    public static function getAliasedDbFieldNames($dbTableAlias, array $exclude = [])
671
    {
672 1
        $newArray = [];
673 1
        foreach (static::getDbFieldNames($exclude) as $dbFieldName) {
674 1
            $fromCol = $dbTableAlias . '.' . $dbFieldName;
675 1
            $toCol = $dbTableAlias . '_' . $dbFieldName;
676 1
            $newArray[] = $fromCol . ' AS ' . $toCol;
677 1
        }
678
679 1
        return $newArray;
680
    }
681
682
    /**
683
     * Filters a full db item array by it's table alias and the strips the table alias.
684
     *
685
     * @param array  $rowData
686
     * @param string $dbTableAlias
687
     * @param bool   $skipStrip For cases when you want to filter only (no stripping)
688
     * @return array
689
     */
690 1
    public static function filterStripDbRowData(array $rowData, $dbTableAlias, $skipStrip = false)
691
    {
692 1
        $columnPrefix = $dbTableAlias . '_';
693
694 1
        $filteredAndStrippedRowData = [];
695 1
        foreach ($rowData as $key => $val) {
696 1
            if (strpos($key, $columnPrefix) === 0) {
697 1
                $strippedKey = $skipStrip ? $key : Str::stripLeft($key, $columnPrefix);
698 1
                $filteredAndStrippedRowData[$strippedKey] = $val;
699 1
            }
700 1
        }
701
702 1
        return $filteredAndStrippedRowData;
703
    }
704
705
    /**
706
     * @return string
707
     */
708 8
    public static function getDbTableName()
709
    {
710 8
        return static::$dbTableName;
711
    }
712
713
    /**
714
     * Method to handle the serialization of this object.
715
     *
716
     * Implementation of Serializable interface. If descendant private properties
717
     * should be serialized, they need to be visible to this parent (i.e. not private).
718
     *
719
     * @return string
720
     */
721 2
    public function serialize()
722
    {
723 2
        return serialize(get_object_vars($this));
724
    }
725
726
    /**
727
     * Method to handle the unserialization of this object.
728
     *
729
     * Implementation of Serializable interface. If descendant private properties
730
     * should be unserialized, they need to be visible to this parent (i.e. not private).
731
     *
732
     * @param string $serializedObject
733
     */
734 1
    public function unserialize($serializedObject)
735
    {
736 1
        $objectVars = unserialize($serializedObject);
737
738 1
        foreach ($objectVars as $key => $value) {
739 1
            $this->{$key} = $value;
740 1
        }
741 1
    }
742
743
    /**
744
     * Merges other object's modified database data into this object.
745
     *
746
     * @param AbstractDbEntity $otherEntity
747
     */
748 1
    public function mergeWith(AbstractDbEntity $otherEntity)
749
    {
750 1
        $dataToMerge = $otherEntity->getModifiedDbData();
751 1
        $this->setDbData($dataToMerge);
752 1
    }
753
}
754