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 ( f500e6...8bb85a )
by Andreas
02:52
created

AbstractDbEntity::getDbPropertyNames()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
crap 2
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
     * Database fields that has had their value modified since init/load.
92
     *
93
     * @var array
94
     */
95
    private $modifiedDbProperties = [];
96
97
    /**
98
     * @var bool
99
     */
100
    private $deleteFromDbOnSave = false;
101
102
    /**
103
     * @var bool
104
     */
105
    private $deleted = false;
106
107
    /**
108
     * @var bool
109
     */
110
    private $forceDbInsertOnSave = false;
111
112
    /**
113
     * Constructor.
114
     *
115
     * @param mixed $primaryDbValueOrRowData
116
     */
117 67
    public function __construct($primaryDbValueOrRowData = null)
118
    {
119 67
        self::checkStaticProperties();
120
121
        // Set default values
122 66
        $this->dbData = $this->getDefaultDbData();
123
124
        // Override default values with provided values
125 66
        if ($primaryDbValueOrRowData !== null) {
126 13
            $this->setPrimaryDbValueOrRowData($primaryDbValueOrRowData);
127 13
        }
128 66
    }
129
130
    /**
131
     * Make sure that class has all necessary static properties set.
132
     */
133 67
    private static function checkStaticProperties()
134
    {
135 67
        static $checkedClasses = [];
136 67
        if (!in_array(static::class, $checkedClasses)) {
137 8
            if (empty(static::$dbTableName)
138 7
                || empty(static::$dbProperties)
139 7
                || empty(static::$primaryDbPropertyKey)
140 7
                || (is_scalar(static::$primaryDbPropertyKey)
141 7
                    && !isset(static::$dbProperties[static::$primaryDbPropertyKey]['type']))
142 7
                || (is_array(static::$primaryDbPropertyKey)
143 7
                    && !Arr::allIn(static::$primaryDbPropertyKey, array_keys(static::$dbProperties)))
144 8
            ) {
145 1
                throw new \LogicException("All db entity's static properties not set");
146
            }
147 7
            $checkedClasses[] = static::class;
148 7
        }
149 66
    }
150
151
    /**
152
     * @param mixed $primaryDbValueOrRowData
153
     */
154 13
    public function setPrimaryDbValueOrRowData($primaryDbValueOrRowData = null)
155
    {
156
        // Row data would ba an associative array (not sequential, that would indicate a multi column primary key)
157 13
        if (is_array($primaryDbValueOrRowData) && !isset($primaryDbValueOrRowData[0])) {
158 1
            $this->setDbDataFromRow($primaryDbValueOrRowData);
159 1
        } else {
160 12
            $this->setPrimaryDbValue($primaryDbValueOrRowData);
161
        }
162 13
    }
163
164
    /**
165
     * Get all default database values.
166
     *
167
     * @return array
168
     */
169 66
    public function getDefaultDbData()
170
    {
171 66
        $class = get_called_class();
172 66
        if (!isset(self::$cachedDefaultDbData[$class])) {
173 7
            self::$cachedDefaultDbData[$class] = [];
174 7
            foreach (array_keys(static::$dbProperties) as $propertyName) {
175 7
                self::$cachedDefaultDbData[$class][$propertyName] = $this->getDefaultDbPropertyValue($propertyName);
176 7
            }
177 7
        }
178
179 66
        return self::$cachedDefaultDbData[$class];
180
    }
181
182
    /**
183
     * Get default db value (can be overridden if non static default values need to be used).
184
     *
185
     * @param string $propertyName
186
     * @return mixed
187
     */
188 7
    public function getDefaultDbPropertyValue($propertyName)
189
    {
190
        // A default value is set
191 7
        if (array_key_exists('default', static::$dbProperties[$propertyName])) {
192 5
            $defaultValue = static::$dbProperties[$propertyName]['default'];
193
        // No default value set, use default for type
194 5
        } else {
195 7
            $defaultValue = self::$typeDefaults[static::$dbProperties[$propertyName]['type']];
196
        }
197
198 7
        return $defaultValue;
199
    }
200
201
    /**
202
     * @return mixed
203
     */
204 22
    public function getPrimaryDbValue()
205
    {
206 22
        if (is_array(static::$primaryDbPropertyKey)) {
207 3
            $primaryValues = [];
208 3
            foreach (static::$primaryDbPropertyKey as $keyPart) {
209 3
                $primaryValues[] = $this->dbData[$keyPart];
210 3
            }
211
212 3
            return $primaryValues;
213
        }
214
215 19
        return $this->dbData[static::$primaryDbPropertyKey];
216
    }
217
218
    /**
219
     * @param mixed $primaryDbValue
220
     */
221 17
    public function setPrimaryDbValue($primaryDbValue)
222
    {
223 17
        if (is_array(static::$primaryDbPropertyKey)) {
224 3
            if (!is_array($primaryDbValue)) {
225 1
                throw new \InvalidArgumentException("Primary db value should be an array");
226
            }
227
228 2
            reset($primaryDbValue);
229 2
            foreach (static::$primaryDbPropertyKey as $keyPart) {
230 2
                $this->dbData[$keyPart] = current($primaryDbValue);
231 2
                next($primaryDbValue);
232 2
            }
233 2
        } else {
234 14
            $this->dbData[static::$primaryDbPropertyKey] = $primaryDbValue;
235
        }
236 16
    }
237
238
    /**
239
     * @return bool
240
     */
241 10
    public function isNewDbEntity()
242
    {
243 10
        if (is_array(static::$primaryDbPropertyKey)) {
244
            // Multiple column keys have to use explicit force insert because we have no way
245
            // to detect if it's a new entity (can't leave more than one primary field empty on insert because
246
            // db can't have two auto increment columns)
247 1
            throw new \LogicException("Can't detect if multi column primary key is a new entity");
248
        }
249
250 9
        return !$this->getPrimaryDbValue();
251
    }
252
253
    /**
254
     * @return bool
255
     */
256 9
    public function shouldInsertOnDbSave()
257
    {
258 9
        return (!is_array(static::$primaryDbPropertyKey) && $this->isNewDbEntity())
259 9
            || $this->shouldForceDbInsertOnSave();
260
    }
261
262
    /**
263
     * Set a row field value.
264
     *
265
     * @param string $property
266
     * @param mixed  $value
267
     * @param bool   $setAsModified
268
     * @param bool   $force
269
     */
270 26
    protected function setDbValue($property, $value, $setAsModified = true, $force = false)
271
    {
272 26
        if (!isset(static::$dbProperties[$property])) {
273 1
            throw new \InvalidArgumentException("No database entity property[{$property}] exists");
274
        }
275
276
        // Don't set type if value is null and allowed (allowed currently indicated by default => null)
277 25
        $nullIsAllowed = (array_key_exists('default', static::$dbProperties[$property])
278 25
            && static::$dbProperties[$property]['default'] === null);
279 25
        if (!($value === null && $nullIsAllowed)) {
280 24
            $type = static::$dbProperties[$property]['type'];
281
            // Set null when empty and default is null
282 24
            if ($value === '' && $nullIsAllowed) {
283 1
                 $value = null;
284 24
            } elseif ($type === 'dateTime') {
285 1
                if (!($value instanceof \DateTimeInterface)) {
286 1
                    $value = $this->createDateTimeDbValue($value);
287 1
                }
288 1
            } else {
289 23
                settype($value, $type);
290
            }
291 24
        }
292
293 25
        if ($this->dbData[$property] !== $value || $force) {
294 22
            $this->dbData[$property] = $value;
295
296 22
            if ($setAsModified && !$this->isDbPropertyModified($property)) {
297 15
                $this->modifiedDbProperties[] = $property;
298 15
            }
299 22
        }
300 25
    }
301
302
    /**
303
     * @param string $value
304
     * @return \DateTime|\Carbon\Carbon|null
305
     */
306 1
    protected function createDateTimeDbValue($value)
307
    {
308 1
        static $carbonExists = null;
309
        if ($carbonExists === true
310 1
            || ($carbonExists === null && ($carbonExists = class_exists(\Carbon\Carbon::class)))
311 1
        ) {
312 1
            return new \Carbon\Carbon($value);
313
        }
314
315
        return new \DateTime($value);
316
    }
317
318
    /**
319
     * Get a database field value.
320
     *
321
     * @param string $property
322
     * @return mixed
323
     */
324 7
    protected function getDbValue($property)
325
    {
326 7
        return $this->dbData[$property];
327
    }
328
329
    /**
330
     * Get raw (with underscore as word separator as it is formatted in database)
331
     * field name from a object field property name (camelcased).
332
     *
333
     * @param string $propertyName
334
     * @return string
335
     */
336 18
    public static function getDbFieldName($propertyName)
337
    {
338 18
        if (!isset(self::$cachedDbFieldNames[$propertyName])) {
339 6
            self::$cachedDbFieldNames[$propertyName] = Str::camelToSeparator($propertyName);
340 6
        }
341
342 18
        return self::$cachedDbFieldNames[$propertyName];
343
    }
344
345
    /**
346
     * Get object field property name (camelCased) from database field name (underscore separated).
347
     *
348
     * @param string $dbFieldName
349
     * @return string
350
     */
351 7
    public static function getDbPropertyName($dbFieldName)
352
    {
353 7
        if (!isset(self::$cachedDbPropertyNames[$dbFieldName])) {
354 2
            self::$cachedDbPropertyNames[$dbFieldName] = Str::separatorToCamel($dbFieldName);
355 2
        }
356
357 7
        return self::$cachedDbPropertyNames[$dbFieldName];
358
    }
359
360
    /**
361
     * @return bool
362
     */
363 5
    public function hasModifiedDbProperties()
364
    {
365 5
        return !empty($this->modifiedDbProperties);
366
    }
367
368
    /**
369
     * @param string $property
370
     * @return bool
371
     */
372 16
    public function isDbPropertyModified($property)
373
    {
374 16
        return in_array($property, $this->modifiedDbProperties);
375
    }
376
377
    /**
378
     * @return array
379
     */
380 6
    public function getModifiedDbData()
381
    {
382 6
        return array_intersect_key($this->dbData, array_flip($this->modifiedDbProperties));
383
    }
384
385
    /**
386
     * @param string $property
387
     */
388
    public function clearModifiedDbProperty($property)
389
    {
390
        if (($key = array_search($property, $this->modifiedDbProperties))) {
391
            unset($this->modifiedDbProperties[$key]);
392
        }
393
    }
394
395 4
    public function clearModifiedDbProperties()
396
    {
397 4
        $this->modifiedDbProperties = [];
398 4
    }
399
400 1
    public function setAllDbPropertiesAsModified()
401
    {
402 1
        $this->modifiedDbProperties = array_keys(static::$dbProperties);
403 1
    }
404
405
    /**
406
     * Magic method used to automate getters & setters for row data.
407
     *
408
     * @param string $name
409
     * @param array  $arguments
410
     * @return mixed
411
     */
412 19
    public function __call($name, array $arguments = [])
413
    {
414 19
        $propertyName = lcfirst(substr($name, 3));
415
416 19
        if (strpos($name, 'get') === 0 && isset(static::$dbProperties[$propertyName])) {
417 5
            return $this->getDbValue($propertyName);
418 17
        } elseif (strpos($name, 'set') === 0 && isset(static::$dbProperties[$propertyName])) {
419 16
            $argumentCount = count($arguments);
420 16
            if ($argumentCount >= 1 && $argumentCount <= 3) {
421 15
                return $this->setDbValue($propertyName, ...$arguments);
422
            } else {
423 1
                throw new \BadMethodCallException("Invalid argument count[{$argumentCount}] for {$name}()");
424
            }
425
        } else {
426 1
            throw new \BadMethodCallException("No method named {$name}()");
427
        }
428
    }
429
430
    /**
431
     * Set database fields' data.
432
     *
433
     * @param array $data
434
     */
435 2
    public function setDbData(array $data)
436
    {
437 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...
438 2
            if (array_key_exists($propertyName, $data)) {
439 2
                $this->setDbValue($propertyName, $data[$propertyName], true);
440 2
            }
441 2
        }
442 2
    }
443
444
    /**
445
     * Set db data from raw database row data with field names in database format.
446
     *
447
     * @param array $rowData
448
     */
449 7
    public function setDbDataFromRow(array $rowData)
450
    {
451
        // If there are less row data than properties, use rows as starting point (optimization)
452 7
        if (count($rowData) < count(static::$dbProperties)) {
453 6
            foreach ($rowData as $dbFieldName => $value) {
454 6
                $propertyName = static::getDbPropertyName($dbFieldName);
455 6
                if (isset(static::$dbProperties[$propertyName])) {
456 6
                    $this->setDbValue($propertyName, $value, false);
457 6
                }
458 6
            }
459
        // If there are more row data than properties, use properties as starting point
460 6
        } else {
461 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...
462 2
                $fieldName = static::getDbFieldName($propertyName);
463 2
                if (array_key_exists($fieldName, $rowData)) {
464 2
                    $this->setDbValue($propertyName, $rowData[$fieldName], false);
465 2
                }
466 2
            }
467
        }
468 7
    }
469
470
    /**
471
     * @return array
472
     */
473 10
    public function getDbData()
474
    {
475 10
        return $this->dbData;
476
    }
477
478
    /**
479
     * @return array
480
     */
481 2
    public function getDbDataWithoutPrimary()
482
    {
483 2
        $dbDataWithoutPrimary = $this->dbData;
484
485 2
        if (is_array(static::$primaryDbPropertyKey)) {
486 1
            foreach (static::$primaryDbPropertyKey as $keyPart) {
487 1
                unset($dbDataWithoutPrimary[$keyPart]);
488 1
            }
489 1
        } else {
490 1
            unset($dbDataWithoutPrimary[static::$primaryDbPropertyKey]);
491
        }
492
493 2
        return $dbDataWithoutPrimary;
494
    }
495
496
    /**
497
     * @param bool $deleteFromDbOnSave
498
     */
499 3
    public function setDeleteFromDbOnSave($deleteFromDbOnSave = true)
500
    {
501 3
        $this->deleteFromDbOnSave = $deleteFromDbOnSave;
502 3
    }
503
504
    /**
505
     * @return bool
506
     */
507 11
    public function shouldBeDeletedFromDbOnSave()
508
    {
509 11
        return $this->deleteFromDbOnSave;
510
    }
511
512
    /**
513
     * @return bool
514
     */
515 1
    public function isDeleted()
516
    {
517 1
        return $this->deleted;
518
    }
519
520
    /**
521
     * @param bool $deleted
522
     */
523 3
    public function setDeleted($deleted = true)
524
    {
525 3
        $this->deleted = $deleted;
526 3
    }
527
528
    /**
529
     * @param bool $forceDbInsertOnSave
530
     */
531 5
    public function setForceDbInsertOnSave($forceDbInsertOnSave)
532
    {
533 5
        $this->forceDbInsertOnSave = $forceDbInsertOnSave;
534 5
    }
535
536
    /**
537
     * @return bool
538
     */
539 10
    public function shouldForceDbInsertOnSave()
540
    {
541 10
        return $this->forceDbInsertOnSave;
542
    }
543
544
    /**
545
     * @return array
546
     */
547 1
    public static function getDbProperties()
548
    {
549 1
        return static::$dbProperties;
550
    }
551
552
    /**
553
     * @param string $propertyName
554
     * @return int|null
555
     */
556 6
    public static function getDbPropertyMaxLength($propertyName)
557
    {
558 6
        return isset(static::$dbProperties[$propertyName]['maxLength'])
559 6
            ? static::$dbProperties[$propertyName]['maxLength']
560 6
            : null;
561
    }
562
563
    /**
564
     * @param string $propertyName
565
     * @return bool
566
     */
567 3
    public static function getDbPropertyRequired($propertyName)
568
    {
569 3
        return isset(static::$dbProperties[$propertyName]['required'])
570 3
            ? static::$dbProperties[$propertyName]['required']
571 3
            : false;
572
    }
573
574
    /**
575
     * @param string $propertyName
576
     * @return bool
577
     */
578 4
    public static function getDbPropertyNonEmpty($propertyName)
579
    {
580 4
        return isset(static::$dbProperties[$propertyName]['nonEmpty'])
581 4
            ? static::$dbProperties[$propertyName]['nonEmpty']
582 4
            : false;
583
    }
584
585
    /**
586
     * @return string|array
587
     */
588 18
    public static function getPrimaryDbPropertyKey()
589
    {
590 18
        return static::$primaryDbPropertyKey;
591
    }
592
593
    /**
594
     * @return string|array
595
     */
596 10
    public static function getPrimaryDbFieldKey()
597
    {
598 10
        $primaryDbPropertyKey = static::getPrimaryDbPropertyKey();
599
600 10
        if (is_array($primaryDbPropertyKey)) {
601 3
            $primaryDbFieldKey = [];
602 3
            foreach ($primaryDbPropertyKey as $propertyName) {
603 3
                $primaryDbFieldKey[] = static::getDbFieldName($propertyName);
604 3
            }
605
606 3
            return $primaryDbFieldKey;
607
        } else {
608 7
            return static::getDbFieldName($primaryDbPropertyKey);
609
        }
610
    }
611
612
    /**
613
     * Return array with db property names.
614
     *
615
     * @param array $exclude
616
     * @return array
617
     */
618 1
    public static function getDbPropertyNames(array $exclude = [])
619
    {
620 1
        $dbPropertyNames = array_keys(static::$dbProperties);
621
622 1
        return $exclude ? array_diff($dbPropertyNames, $exclude) : $dbPropertyNames;
623
    }
624
625
    /**
626
     * Return array with raw db field names.
627
     *
628
     * @param array $exclude
629
     * @return array
630
     */
631 3
    public static function getDbFieldNames(array $exclude = [])
632
    {
633 3
        $fieldNames = [];
634 3
        foreach (array_keys(static::$dbProperties) as $propertyName) {
635 3
            $fieldNames[] = static::getDbFieldName($propertyName);
636 3
        }
637
638 3
        return $exclude ? array_diff($fieldNames, $exclude) : $fieldNames;
639
    }
640
641
642
    /**
643
     * Get raw database field names prefixed (id, name becomes t.id, t.name etc.).
644
     *
645
     * @param string $dbTableAlias
646
     * @param array  $exclude
647
     * @return array
648
     */
649 1
    public static function getPrefixedDbFieldNames($dbTableAlias, array $exclude = [])
650
    {
651 1
        return Arr::valuesWithPrefix(static::getDbFieldNames($exclude), $dbTableAlias . '.');
652
    }
653
654
    /**
655
     * Get database columns transformed from e.g. "productId, date" to "p.product_id AS p_product_id, p.date AS p_date".
656
     *
657
     * @param string $dbTableAlias
658
     * @param array  $exclude
659
     * @return array
660
     */
661 1
    public static function getAliasedDbFieldNames($dbTableAlias, array $exclude = [])
662
    {
663 1
        $newArray = [];
664 1
        foreach (static::getDbFieldNames($exclude) as $dbFieldName) {
665 1
            $fromCol = $dbTableAlias . '.' . $dbFieldName;
666 1
            $toCol = $dbTableAlias . '_' . $dbFieldName;
667 1
            $newArray[] = $fromCol . ' AS ' . $toCol;
668 1
        }
669
670 1
        return $newArray;
671
    }
672
673
    /**
674
     * Filters a full db item array by it's table alias and the strips the table alias.
675
     *
676
     * @param array  $rowData
677
     * @param string $dbTableAlias
678
     * @param bool   $skipStrip For cases when you want to filter only (no stripping)
679
     * @return array
680
     */
681 1
    public static function filterStripDbRowData(array $rowData, $dbTableAlias, $skipStrip = false)
682
    {
683 1
        $columnPrefix = $dbTableAlias . '_';
684
685 1
        $filteredAndStrippedRowData = [];
686 1
        foreach ($rowData as $key => $val) {
687 1
            if (strpos($key, $columnPrefix) === 0) {
688 1
                $strippedKey = $skipStrip ? $key : Str::stripLeft($key, $columnPrefix);
689 1
                $filteredAndStrippedRowData[$strippedKey] = $val;
690 1
            }
691 1
        }
692
693 1
        return $filteredAndStrippedRowData;
694
    }
695
696
    /**
697
     * @return string
698
     */
699 8
    public static function getDbTableName()
700
    {
701 8
        return static::$dbTableName;
702
    }
703
704
    /**
705
     * Method to handle the serialization of this object.
706
     *
707
     * Implementation of Serializable interface. If descendant private properties
708
     * should be serialized, they need to be visible to this parent (i.e. not private).
709
     *
710
     * @return string
711
     */
712 2
    public function serialize()
713
    {
714 2
        return serialize(get_object_vars($this));
715
    }
716
717
    /**
718
     * Method to handle the unserialization of this object.
719
     *
720
     * Implementation of Serializable interface. If descendant private properties
721
     * should be unserialized, they need to be visible to this parent (i.e. not private).
722
     *
723
     * @param string $serializedObject
724
     */
725 1
    public function unserialize($serializedObject)
726
    {
727 1
        $objectVars = unserialize($serializedObject);
728
729 1
        foreach ($objectVars as $key => $value) {
730 1
            $this->{$key} = $value;
731 1
        }
732 1
    }
733
734
    /**
735
     * Merges other object's modified database data into this object.
736
     *
737
     * @param AbstractDbEntity $otherEntity
738
     */
739 1
    public function mergeWith(AbstractDbEntity $otherEntity)
740
    {
741 1
        $dataToMerge = $otherEntity->getModifiedDbData();
742 1
        $this->setDbData($dataToMerge);
743 1
    }
744
}
745