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
Pull Request — master (#10)
by Andreas
02:22
created

AbstractDbEntity::setDbDataPrimaryValue()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 1
crap 3
1
<?php
2
/**
3
 * Starlit Db.
4
 *
5
 * @copyright Copyright (c) 2016 Starweb AB
6
 * @license   BSD 3-Clause
7
 */
8
9
namespace Starlit\Db;
10
11
use Starlit\Utils\Str;
12
use Starlit\Utils\Arr;
13
14
/**
15
 * Abstract class to model a single database row into an object.
16
 *
17
 * @author Andreas Nilsson <http://github.com/jandreasn>
18
 */
19
abstract class AbstractDbEntity implements \Serializable
20
{
21
    /**
22
     * The database table name (meant to be overridden).
23
     *
24
     * @var string
25
     */
26
    protected static $dbTableName;
27
28
    /**
29
     * Entity's database properties and their attributes (meant to be overridden).
30
     * Example format:
31
     *
32
     * $dbProperties = [
33
     *     'productId' => ['type' => 'int'],
34
     *     'otherId'   => ['type' => 'int', 'required' => true,],
35
     *     'name'      => ['type' => 'string', 'maxLength' => 10, 'required' => true, 'default' => 'Some name'],
36
     * ];
37
     *
38
     * 'type' => 'int'     Corresponding PHP type (required).
39
     * 'required' => true  The value have to be set (not '', null, false)
40
     * 'nonEmpty' => true  The value should not be empty ('', 0, null)
41
     *
42
     * Properties correspond to database table's columns but words are
43
     * camel cased instead of separated with underscore (_) as in the database.
44
     *
45
     * @var array
46
     */
47
    protected static $dbProperties = [];
48
49
    /**
50
     * Object database field name that is used for primary key (meant to be overridden).
51
     * Should be camel cased as it maps to the dbFields array.
52
     *
53
     * @var string|array
54
     */
55
    protected static $primaryDbPropertyKey;
56
57
    /**
58
     * @var array
59
     */
60
    private static $cachedDefaultDbData = [];
61
62
    /**
63
     * @var array
64
     */
65
    private static $cachedDbPropertyNames;
66
67
    /**
68
     * @var array
69
     */
70
    private static $cachedDbFieldNames;
71
72
    /**
73
     * @var array
74
     */
75
    private static $typeDefaults = [
76
        'string'   => '',
77
        'int'      => 0,
78
        'float'    => 0.0,
79
        'bool'     => false,
80
        'dateTime' => null,
81
    ];
82
83
    /**
84
     * Database row data with field names and their values.
85
     *
86
     * @var array
87
     */
88
    private $dbData = [];
89
90
    /**
91
     * The primary key value currently set in database. This
92
     * can be different from the value in $dbData if the primary value
93
     * is changed.
94
     *
95
     * @var mixed
96
     */
97
    private $primaryDbValue;
98
99
    /**
100
     * Database fields that has had their value modified since init/load.
101
     *
102
     * @var array
103
     */
104
    private $modifiedDbProperties = [];
105
106
    /**
107
     * @var bool
108
     */
109
    private $deleteFromDbOnSave = false;
110
111
    /**
112
     * @var bool
113
     */
114
    private $deleted = false;
115
116
    /**
117
     * @var bool
118
     */
119
    private $forceDbInsertOnSave = false;
120
121
    /**
122
     * Constructor.
123
     *
124
     * @param mixed $primaryDbValueOrRowData
125
     */
126 68
    public function __construct($primaryDbValueOrRowData = null)
127
    {
128 68
        self::checkStaticProperties();
129
130
        // Set default values
131 67
        $this->dbData = $this->getDefaultDbData();
132
133
        // Override default values with provided values
134 67
        if ($primaryDbValueOrRowData !== null) {
135 13
            $this->setPrimaryDbValueOrRowData($primaryDbValueOrRowData);
136
        }
137 67
    }
138
139
    /**
140
     * Make sure that class has all necessary static properties set.
141
     */
142 68
    private static function checkStaticProperties()
143
    {
144 68
        static $checkedClasses = [];
145 68
        if (!in_array(static::class, $checkedClasses)) {
146 8
            if (empty(static::$dbTableName)
147
                || empty(static::$dbProperties)
148
                || empty(static::$primaryDbPropertyKey)
149 7
                || (is_scalar(static::$primaryDbPropertyKey)
150 4
                    && !isset(static::$dbProperties[static::$primaryDbPropertyKey]['type']))
151 7
                || (is_array(static::$primaryDbPropertyKey)
152 3
                    && !Arr::allIn(static::$primaryDbPropertyKey, array_keys(static::$dbProperties)))
153
            ) {
154 1
                throw new \LogicException("All db entity's static properties not set");
155
            }
156 7
            $checkedClasses[] = static::class;
157
        }
158 67
    }
159
160
    /**
161
     * @param mixed $primaryDbValueOrRowData
162
     */
163 13
    public function setPrimaryDbValueOrRowData($primaryDbValueOrRowData = null)
164
    {
165
        // Row data would be an associative array (i.e. not sequential, that would
166
        // indicate a multi column primary key)
167 13
        if (is_array($primaryDbValueOrRowData) && !isset($primaryDbValueOrRowData[0])) {
168 1
            $this->setDbDataFromRow($primaryDbValueOrRowData);
169
        } else {
170 12
            $this->setPrimaryDbValue($primaryDbValueOrRowData);
171
        }
172 13
    }
173
174
    /**
175
     * Get all default database values.
176
     *
177
     * @return array
178
     */
179 67
    public function getDefaultDbData()
180
    {
181 67
        $class = get_called_class();
182 67
        if (!isset(self::$cachedDefaultDbData[$class])) {
183 7
            self::$cachedDefaultDbData[$class] = [];
184 7
            foreach (array_keys(static::$dbProperties) as $propertyName) {
185 7
                self::$cachedDefaultDbData[$class][$propertyName] = $this->getDefaultDbPropertyValue($propertyName);
186
            }
187
        }
188
189 67
        return self::$cachedDefaultDbData[$class];
190
    }
191
192
    /**
193
     * Get default db value (can be overridden if non static default values need to be used).
194
     *
195
     * @param string $propertyName
196
     * @return mixed
197
     */
198 7
    public function getDefaultDbPropertyValue($propertyName)
199
    {
200
        // A default value is set
201 7
        if (array_key_exists('default', static::$dbProperties[$propertyName])) {
202 5
            $defaultValue = static::$dbProperties[$propertyName]['default'];
203
        // No default value set, use default for type
204
        } else {
205 7
            $defaultValue = self::$typeDefaults[static::$dbProperties[$propertyName]['type']];
206
        }
207
208 7
        return $defaultValue;
209
    }
210
211
    /**
212
     * The primary key value currently set in database.
213
     *
214
     * This can be different from the value/values in $dbData
215
     * if a primary value is changed.
216
     *
217
     * @return mixed
218
     */
219 24
    public function getPrimaryDbValue()
220
    {
221 24
        return $this->primaryDbValue;
222
    }
223
224
    /**
225
     * @param mixed $primaryDbValue
226
     */
227 23
    public function setPrimaryDbValue($primaryDbValue)
228
    {
229 23
        $typedPrimaryDbValue = $this->getPrimaryDbValueWithPropertyType($primaryDbValue);
230
231 22
        $this->primaryDbValue = $typedPrimaryDbValue;
232 22
        $this->setDbDataPrimaryValue($typedPrimaryDbValue);
233 22
    }
234
235
    /**
236
     * @param mixed $primaryDbValue
237
     */
238 22
    protected function setDbDataPrimaryValue($primaryDbValue)
239
    {
240 22
        if (is_array(static::$primaryDbPropertyKey)) {
241 3
            reset($primaryDbValue);
242 3
            foreach (static::$primaryDbPropertyKey as $keyPart) {
243 3
                $this->dbData[$keyPart] = current($primaryDbValue);
244 3
                next($primaryDbValue);
245
            }
246
        } else {
247 19
            $this->dbData[static::$primaryDbPropertyKey] = $primaryDbValue;
248
        }
249 22
    }
250
251
    /**
252
     * @return bool
253
     */
254 10
    public function isNewDbEntity()
255
    {
256 10
        if (is_array(static::$primaryDbPropertyKey)) {
257
            // Multiple column keys have to use explicit force insert because we have no way
258
            // to detect if it's a new entity (can't leave more than one primary field empty
259
            // on insert because db can't have two auto increment columns)
260 1
            throw new \LogicException("Can't detect if multi column primary key is a new entity");
261
        }
262
263 9
        return !$this->getPrimaryDbValue();
264
    }
265
266
    /**
267
     * @return bool
268
     */
269 9
    public function shouldInsertOnDbSave()
270
    {
271 9
        return (!is_array(static::$primaryDbPropertyKey) && $this->isNewDbEntity())
272 9
            || $this->shouldForceDbInsertOnSave();
273
    }
274
275
    /**
276
     * Set a row field value.
277
     *
278
     * @param string $property
279
     * @param mixed  $value
280
     * @param bool   $setAsModified
281
     * @param bool   $force
282
     */
283 27
    protected function setDbValue($property, $value, $setAsModified = true, $force = false)
284
    {
285 27
        $value = $this->getValueWithPropertyType($property, $value);
286
287 26
        if ($this->dbData[$property] !== $value || $force) {
288 23
            $this->dbData[$property] = $value;
289
290 23
            if ($setAsModified && !$this->isDbPropertyModified($property)) {
291 16
                $this->modifiedDbProperties[] = $property;
292
            }
293
        }
294 26
    }
295
296
    /**
297
     * @param string $property
298
     * @param mixed  $value
299
     * @return mixed
300
     */
301 39
    private function getValueWithPropertyType(string $property, $value) {
302 39
        if (!isset(static::$dbProperties[$property])) {
303 1
            throw new \InvalidArgumentException("No database entity property[{$property}] exists");
304
        }
305
306
         // Don't set type if value is null and allowed (allowed currently indicated by default => null)
307 38
        $nullIsAllowed = (array_key_exists('default', static::$dbProperties[$property])
308 38
            && static::$dbProperties[$property]['default'] === null);
309 38
        if (!($value === null && $nullIsAllowed)) {
310 37
            $type = static::$dbProperties[$property]['type'];
311
            // Set null when empty and default is null
312 37
            if ($value === '' && $nullIsAllowed) {
313 1
                 $value = null;
314 37
            } elseif ($type === 'dateTime') {
315 1
                if (!($value instanceof \DateTimeInterface)) {
316 1
                    $value = $this->createDateTimeDbValue($value);
317
                }
318
            } else {
319 36
                settype($value, $type);
320
            }
321
        }
322
323 38
        return $value;
324
    }
325
326
    /**
327
     * @param string $property
0 ignored issues
show
Bug introduced by
There is no parameter named $property. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
328
     * @param mixed $value
0 ignored issues
show
Bug introduced by
There is no parameter named $value. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
329
     * @return mixed
330
     */
331 23
    private function getPrimaryDbValueWithPropertyType($primaryDbValue) {
332 23
        if (is_array(static::$primaryDbPropertyKey)) {
333 4
            if (!is_array($primaryDbValue)
334 3
                || count(static::$primaryDbPropertyKey) !== count($primaryDbValue)
335
            ) {
336 1
                throw new \InvalidArgumentException(sprintf(
337 1
                    'Primary db value should be an array of length %d',
338 1
                    count(static::$primaryDbPropertyKey)
339
                ));
340
            }
341
342 3
            $primaryDbValueParts = [];
343 3
            reset($primaryDbValue);
344 3
            foreach (static::$primaryDbPropertyKey as $keyPart) {
345 3
                $partValue = current($primaryDbValue);
346 3
                $primaryDbValueParts[] = $this->getValueWithPropertyType($keyPart, $partValue);
347 3
                next($primaryDbValue);
348
            }
349
350 3
            return $primaryDbValueParts;
351
        }
352
353 19
        return $this->getValueWithPropertyType(
354 19
            static::$primaryDbPropertyKey,
355 19
            $primaryDbValue
356
        );
357
    }
358
359
    /**
360
     * @param string $value
361
     * @return \DateTime|\Carbon\Carbon|null
362
     */
363 1
    protected function createDateTimeDbValue($value)
364
    {
365 1
        static $carbonExists = null;
366 1
        if ($carbonExists === true
367 1
            || ($carbonExists === null && ($carbonExists = class_exists(\Carbon\Carbon::class)))
368
        ) {
369 1
            return new \Carbon\Carbon($value);
370
        }
371
372
        return new \DateTime($value);
373
    }
374
375
    /**
376
     * Get a database field value.
377
     *
378
     * @param string $property
379
     * @return mixed
380
     */
381 9
    protected function getDbValue($property)
382
    {
383 9
        return $this->dbData[$property];
384
    }
385
386
    /**
387
     * Get raw (with underscore as word separator as it is formatted in database)
388
     * field name from a object field property name (camelcased).
389
     *
390
     * @param string $propertyName
391
     * @return string
392
     */
393 24
    public static function getDbFieldName($propertyName)
394
    {
395 24
        if (!isset(self::$cachedDbFieldNames[$propertyName])) {
396 6
            self::$cachedDbFieldNames[$propertyName] = Str::camelToSeparator($propertyName);
397
        }
398
399 24
        return self::$cachedDbFieldNames[$propertyName];
400
    }
401
402
    /**
403
     * Get object field property name (camelCased) from database field name (underscore separated).
404
     *
405
     * @param string $dbFieldName
406
     * @return string
407
     */
408 7
    public static function getDbPropertyName($dbFieldName)
409
    {
410 7
        if (!isset(self::$cachedDbPropertyNames[$dbFieldName])) {
411 2
            self::$cachedDbPropertyNames[$dbFieldName] = Str::separatorToCamel($dbFieldName);
412
        }
413
414 7
        return self::$cachedDbPropertyNames[$dbFieldName];
415
    }
416
417
    /**
418
     * @return bool
419
     */
420 5
    public function hasModifiedDbProperties()
421
    {
422 5
        return !empty($this->modifiedDbProperties);
423
    }
424
425
    /**
426
     * @param string $property
427
     * @return bool
428
     */
429 17
    public function isDbPropertyModified($property)
430
    {
431 17
        return in_array($property, $this->modifiedDbProperties);
432
    }
433
434
    /**
435
     * @return array
436
     */
437 6
    public function getModifiedDbData()
438
    {
439 6
        return array_intersect_key($this->dbData, array_flip($this->modifiedDbProperties));
440
    }
441
442
    /**
443
     * @param string $property
444
     */
445
    public function clearModifiedDbProperty($property)
446
    {
447
        if (($key = array_search($property, $this->modifiedDbProperties))) {
448
            unset($this->modifiedDbProperties[$key]);
449
        }
450
    }
451
452 4
    public function clearModifiedDbProperties()
453
    {
454 4
        $this->modifiedDbProperties = [];
455 4
    }
456
457 1
    public function setAllDbPropertiesAsModified()
458
    {
459 1
        $this->modifiedDbProperties = array_keys(static::$dbProperties);
460 1
    }
461
462
    /**
463
     * Magic method used to automate getters & setters for row data.
464
     *
465
     * @param string $name
466
     * @param array  $arguments
467
     * @return mixed
468
     */
469 21
    public function __call($name, array $arguments = [])
470
    {
471 21
        $propertyName = lcfirst(substr($name, 3));
472
473 21
        if (strpos($name, 'get') === 0 && isset(static::$dbProperties[$propertyName])) {
474 7
            return $this->getDbValue($propertyName);
475 17
        } elseif (strpos($name, 'set') === 0 && isset(static::$dbProperties[$propertyName])) {
476 16
            $argumentCount = count($arguments);
477 16
            if ($argumentCount >= 1 && $argumentCount <= 3) {
478 15
                return $this->setDbValue($propertyName, ...$arguments);
479
            } else {
480 1
                throw new \BadMethodCallException("Invalid argument count[{$argumentCount}] for {$name}()");
481
            }
482
        } else {
483 1
            throw new \BadMethodCallException("No method named {$name}()");
484
        }
485
    }
486
487
    /**
488
     * Set database fields' data.
489
     *
490
     * @param array $data
491
     */
492 3
    public function setDbData(array $data)
493
    {
494 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...
495 3
            if (array_key_exists($propertyName, $data)) {
496 3
                $this->setDbValue($propertyName, $data[$propertyName], true);
497
            }
498
        }
499 3
    }
500
501
    /**
502
     * Set db data from raw database row data with field names in database format.
503
     *
504
     * @param array $rowData
505
     */
506 7
    public function setDbDataFromRow(array $rowData)
507
    {
508
        // If there are less row data than properties, use rows as starting point (optimization)
509 7
        if (count($rowData) < count(static::$dbProperties)) {
510 6
            foreach ($rowData as $dbFieldName => $value) {
511 6
                $propertyName = static::getDbPropertyName($dbFieldName);
512 6
                if (isset(static::$dbProperties[$propertyName])) {
513 6
                    $this->setDbValue($propertyName, $value, false);
514
                }
515
            }
516
        // If there are more row data than properties, use properties as starting point
517
        } else {
518 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...
519 2
                $fieldName = static::getDbFieldName($propertyName);
520 2
                if (array_key_exists($fieldName, $rowData)) {
521 2
                    $this->setDbValue($propertyName, $rowData[$fieldName], false);
522
                }
523
            }
524
        }
525
526 7
        $primaryDbValue = $this->getPrimaryDbValueFromRow($rowData);
527 7
        if (!empty($primaryDbValue)) {
528 7
            $this->setPrimaryDbValue($primaryDbValue);
529
        }
530 7
    }
531
532
    /**
533
     * @return mixed
534
     */
535 7
    protected function getPrimaryDbValueFromRow(array $rowData)
536
    {
537 7
        if (is_array(static::$primaryDbPropertyKey)) {
538 1
            $primaryValues = [];
539 1
            foreach (static::$primaryDbPropertyKey as $keyPart) {
540 1
                $fieldName = static::getDbFieldName($keyPart);
541 1
                $primaryValues[] = $rowData[$fieldName] ?? null;
542
            }
543
544 1
            return $primaryValues;
545
        }
546
547 6
        $fieldName = static::getDbFieldName(static::$primaryDbPropertyKey);
548
549 6
        return $rowData[$fieldName] ?? null;
550
    }
551
552
    /**
553
     * @return array
554
     */
555 11
    public function getDbData()
556
    {
557 11
        return $this->dbData;
558
    }
559
560
    /**
561
     * @return array
562
     */
563 1
    public function getDbRowData()
564
    {
565 1
        $rowData = [];
566 1
        foreach ($this->getDbData() as $propertyName => $value) {
567 1
            $dbFieldName = static::getDbFieldName($propertyName);
568 1
            $rowData[$dbFieldName] = $value;
569
        }
570
571 1
        return $rowData;
572
    }
573
574
    /**
575
     * @return array
576
     */
577 2
    public function getDbDataWithoutPrimary()
578
    {
579 2
        $dbDataWithoutPrimary = $this->dbData;
580
581 2
        if (is_array(static::$primaryDbPropertyKey)) {
582 1
            foreach (static::$primaryDbPropertyKey as $keyPart) {
583 1
                unset($dbDataWithoutPrimary[$keyPart]);
584
            }
585
        } else {
586 1
            unset($dbDataWithoutPrimary[static::$primaryDbPropertyKey]);
587
        }
588
589 2
        return $dbDataWithoutPrimary;
590
    }
591
592
    /**
593
     * @param bool $deleteFromDbOnSave
594
     */
595 3
    public function setDeleteFromDbOnSave($deleteFromDbOnSave = true)
596
    {
597 3
        $this->deleteFromDbOnSave = $deleteFromDbOnSave;
598 3
    }
599
600
    /**
601
     * @return bool
602
     */
603 11
    public function shouldBeDeletedFromDbOnSave()
604
    {
605 11
        return $this->deleteFromDbOnSave;
606
    }
607
608
    /**
609
     * @return bool
610
     */
611 1
    public function isDeleted()
612
    {
613 1
        return $this->deleted;
614
    }
615
616
    /**
617
     * @param bool $deleted
618
     */
619 3
    public function setDeleted($deleted = true)
620
    {
621 3
        $this->deleted = $deleted;
622 3
    }
623
624
    /**
625
     * @param bool $forceDbInsertOnSave
626
     */
627 5
    public function setForceDbInsertOnSave($forceDbInsertOnSave)
628
    {
629 5
        $this->forceDbInsertOnSave = $forceDbInsertOnSave;
630 5
    }
631
632
    /**
633
     * @return bool
634
     */
635 5
    public function shouldForceDbInsertOnSave()
636
    {
637 5
        return $this->forceDbInsertOnSave;
638
    }
639
640
    /**
641
     * @return array
642
     */
643 1
    public static function getDbProperties()
644
    {
645 1
        return static::$dbProperties;
646
    }
647
648
    /**
649
     * @param string $propertyName
650
     * @return int|null
651
     */
652 6
    public static function getDbPropertyMaxLength($propertyName)
653
    {
654 6
        return isset(static::$dbProperties[$propertyName]['maxLength'])
655 6
            ? static::$dbProperties[$propertyName]['maxLength']
656 6
            : null;
657
    }
658
659
    /**
660
     * @param string $propertyName
661
     * @return bool
662
     */
663 3
    public static function getDbPropertyRequired($propertyName)
664
    {
665 3
        return isset(static::$dbProperties[$propertyName]['required'])
666 3
            ? static::$dbProperties[$propertyName]['required']
667 3
            : false;
668
    }
669
670
    /**
671
     * @param string $propertyName
672
     * @return bool
673
     */
674 6
    public static function getDbPropertyNonEmpty($propertyName)
675
    {
676 6
        return isset(static::$dbProperties[$propertyName]['nonEmpty'])
677 2
            ? static::$dbProperties[$propertyName]['nonEmpty']
678 6
            : false;
679
    }
680
681
    /**
682
     * @return string|array
683
     */
684 14
    public static function getPrimaryDbPropertyKey()
685
    {
686 14
        return static::$primaryDbPropertyKey;
687
    }
688
689
    /**
690
     * @return string|array
691
     */
692 10
    public static function getPrimaryDbFieldKey()
693
    {
694 10
        $primaryDbPropertyKey = static::getPrimaryDbPropertyKey();
695
696 10
        if (is_array($primaryDbPropertyKey)) {
697 3
            $primaryDbFieldKey = [];
698 3
            foreach ($primaryDbPropertyKey as $propertyName) {
699 3
                $primaryDbFieldKey[] = static::getDbFieldName($propertyName);
700
            }
701
702 3
            return $primaryDbFieldKey;
703
        } else {
704 7
            return static::getDbFieldName($primaryDbPropertyKey);
705
        }
706
    }
707
708
    /**
709
     * Return array with db property names.
710
     *
711
     * @param array $exclude
712
     * @return array
713
     */
714 1
    public static function getDbPropertyNames(array $exclude = [])
715
    {
716 1
        $dbPropertyNames = array_keys(static::$dbProperties);
717
718 1
        return $exclude ? array_diff($dbPropertyNames, $exclude) : $dbPropertyNames;
719
    }
720
721
    /**
722
     * Return array with raw db field names.
723
     *
724
     * @param array $exclude
725
     * @return array
726
     */
727 3
    public static function getDbFieldNames(array $exclude = [])
728
    {
729 3
        $fieldNames = [];
730 3
        foreach (array_keys(static::$dbProperties) as $propertyName) {
731 3
            $fieldNames[] = static::getDbFieldName($propertyName);
732
        }
733
734 3
        return $exclude ? array_diff($fieldNames, $exclude) : $fieldNames;
735
    }
736
737
738
    /**
739
     * Get raw database field names prefixed (id, name becomes t.id, t.name etc.).
740
     *
741
     * @param string $dbTableAlias
742
     * @param array  $exclude
743
     * @return array
744
     */
745 1
    public static function getPrefixedDbFieldNames($dbTableAlias, array $exclude = [])
746
    {
747 1
        return Arr::valuesWithPrefix(static::getDbFieldNames($exclude), $dbTableAlias . '.');
748
    }
749
750
    /**
751
     * Get database columns transformed from e.g. "productId, date" to "p.product_id AS p_product_id, p.date AS p_date".
752
     *
753
     * @param string $dbTableAlias
754
     * @param array  $exclude
755
     * @return array
756
     */
757 1
    public static function getAliasedDbFieldNames($dbTableAlias, array $exclude = [])
758
    {
759 1
        $newArray = [];
760 1
        foreach (static::getDbFieldNames($exclude) as $dbFieldName) {
761 1
            $fromCol = $dbTableAlias . '.' . $dbFieldName;
762 1
            $toCol = $dbTableAlias . '_' . $dbFieldName;
763 1
            $newArray[] = $fromCol . ' AS ' . $toCol;
764
        }
765
766 1
        return $newArray;
767
    }
768
769
    /**
770
     * Filters a full db item array by it's table alias and the strips the table alias.
771
     *
772
     * @param array  $rowData
773
     * @param string $dbTableAlias
774
     * @param bool   $skipStrip For cases when you want to filter only (no stripping)
775
     * @return array
776
     */
777 1
    public static function filterStripDbRowData(array $rowData, $dbTableAlias, $skipStrip = false)
778
    {
779 1
        $columnPrefix = $dbTableAlias . '_';
780
781 1
        $filteredAndStrippedRowData = [];
782 1
        foreach ($rowData as $key => $val) {
783 1
            if (strpos($key, $columnPrefix) === 0) {
784 1
                $strippedKey = $skipStrip ? $key : Str::stripLeft($key, $columnPrefix);
785 1
                $filteredAndStrippedRowData[$strippedKey] = $val;
786
            }
787
        }
788
789 1
        return $filteredAndStrippedRowData;
790
    }
791
792
    /**
793
     * @return string
794
     */
795 8
    public static function getDbTableName()
796
    {
797 8
        return static::$dbTableName;
798
    }
799
800
    /**
801
     * Method to handle the serialization of this object.
802
     *
803
     * Implementation of Serializable interface. If descendant private properties
804
     * should be serialized, they need to be visible to this parent (i.e. not private).
805
     *
806
     * @return string
807
     */
808 2
    public function serialize()
809
    {
810 2
        return serialize(get_object_vars($this));
811
    }
812
813
    /**
814
     * Method to handle the unserialization of this object.
815
     *
816
     * Implementation of Serializable interface. If descendant private properties
817
     * should be unserialized, they need to be visible to this parent (i.e. not private).
818
     *
819
     * @param string $serializedObject
820
     */
821 1
    public function unserialize($serializedObject)
822
    {
823 1
        $objectVars = unserialize($serializedObject);
824
825 1
        foreach ($objectVars as $key => $value) {
826 1
            $this->{$key} = $value;
827
        }
828 1
    }
829
830
    /**
831
     * Merges other object's modified database data into this object.
832
     *
833
     * @param AbstractDbEntity $otherEntity
834
     */
835 1
    public function mergeWith(AbstractDbEntity $otherEntity)
836
    {
837 1
        $dataToMerge = $otherEntity->getModifiedDbData();
838 1
        $this->setDbData($dataToMerge);
839 1
    }
840
}
841