Entity::alteredToArray()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace Zortje\MVC\Model\Table\Entity;
5
6
use Ramsey\Uuid\Uuid;
7
use Zortje\MVC\Model\Table\Entity\Exception\InvalidEntityPropertyException;
8
use Zortje\MVC\Model\Table\Entity\Exception\InvalidValueTypeForEntityPropertyException;
9
10
/**
11
 * Class Entity
12
 *
13
 * @package Zortje\MVC\Model\Table\Entity
14
 */
15
abstract class Entity
16
{
17
18
    /**
19
     * @var array Columns
20
     */
21
    protected static $columns = [];
22
23
    /**
24
     * @var array Internal entity properties
25
     */
26
    protected $properties = [];
27
28
    /**
29
     * @var array Internal altered columns
30
     */
31
    protected $alteredColumns = [];
32
33
    /**
34
     * @param string|null $id       Entity ID
35
     * @param \DateTime   $modified Datetime of last modification
36
     * @param \DateTime   $created  Datetime of creation
37
     */
38 2
    public function __construct($id, \DateTime $modified, \DateTime $created)
39
    {
40 2
        $this->set('id', $id ?: Uuid::uuid1()->toString());
41 2
        $this->set('modified', $modified);
42 2
        $this->set('created', $created);
43 2
    }
44
45
    /**
46
     * Get entity columns
47
     *
48
     * @return array Entity columns
49
     */
50 1
    public static function getColumns(): array
51
    {
52 1
        $columns = array_merge([
53
            'id' => EntityProperty::UUID
54 1
        ], static::$columns);
55
56 1
        $columns = array_merge($columns, [
57 1
            'modified' => EntityProperty::DATETIME,
58
            'created'  => EntityProperty::DATETIME
59
        ]);
60
61 1
        return $columns;
62
    }
63
64
    /**
65
     * Set entity property
66
     *
67
     * @param string                                      $key   Entity property name
68
     * @param object|int|double|string|array|boolean|null $value Entity property value
69
     *
70
     * @throws InvalidEntityPropertyException If entity does not have that property
71
     * @throws InvalidValueTypeForEntityPropertyException If value is of the wrong type
72
     */
73 2
    public function set(string $key, $value)
74
    {
75 2 View Code Duplication
        if (isset(self::getColumns()[$key]) === false) {
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...
76 1
            throw new InvalidEntityPropertyException([get_class($this), $key]);
77
        }
78
79 2
        $entityProperty = new EntityProperty(self::getColumns()[$key]);
80
81 2
        if ($entityProperty->validateValue($value)) {
82 2
            if (!isset($this->properties[$key]) || $this->properties[$key] !== $value) {
83
                /**
84
                 * Set internal property
85
                 */
86 2
                $this->properties[$key] = $value;
87
88
                /**
89
                 * Set altered column
90
                 */
91 2
                $this->alteredColumns[$key] = true;
92
            }
93
        }
94 2
    }
95
96
    /**
97
     * Get entity property
98
     *
99
     * @param string $key Entity property
100
     *
101
     * @return object|int|double|string|array|boolean|null Entity property value for given key
102
     *
103
     * @throws InvalidEntityPropertyException If entity does not have that property
104
     */
105 2
    public function get(string $key)
106
    {
107 2 View Code Duplication
        if (!isset(self::getColumns()[$key])) {
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...
108 1
            throw new InvalidEntityPropertyException([get_class($this), $key]);
109
        }
110
111 1
        return $this->properties[$key];
112
    }
113
114
    /**
115
     * Check if entity has been altered
116
     *
117
     * @return bool True if altered, otherwise false
118
     */
119 1
    public function isAltered(): bool
120
    {
121 1
        return count($this->alteredColumns) > 0;
122
    }
123
124
    /**
125
     * Marks the entity as unaltered
126
     */
127 1
    public function setUnaltered()
128
    {
129 1
        $this->alteredColumns = [];
130 1
    }
131
132
    /**
133
     * Get altered columns
134
     *
135
     * @return array
136
     */
137 1
    public function getAlteredColumns(): array
138
    {
139 1
        return $this->alteredColumns;
140
    }
141
142
    /**
143
     * Return table structure for saving
144
     * Example: `[':{table_field_name}' => $this->fieldName]`
145
     *
146
     * @return array
147
     */
148 1
    public function toArray(): array
149
    {
150 1
        $columns = self::getColumns();
151
152 1
        return $this->toArrayFromColumns($columns);
153
    }
154
155
    /**
156
     * Return table structure for saving just altered columns
157
     *
158
     * @param bool $includeId Should the ID column be included
159
     *
160
     * @return array
161
     */
162 2
    public function alteredToArray(bool $includeId): array
163
    {
164 2
        $alteredColumns = $this->alteredColumns;
165
166 2
        if ($includeId) {
167 1
            $alteredColumns['id'] = true;
168
        }
169
170 2
        return $this->toArrayFromColumns(array_intersect_key(self::getColumns(), $alteredColumns));
171
    }
172
173
    /**
174
     * Return columns in structure for saving
175
     *
176
     * @param array $columns Columns to include
177
     *
178
     * @return array
179
     */
180 1
    protected function toArrayFromColumns(array $columns): array
181
    {
182 1
        $array = [];
183
184 1
        foreach ($columns as $column => $type) {
185 1
            $property = new EntityProperty($type);
186
187 1
            $value = $this->get($column);
188 1
            $value = $property->formatValueForDatabase($value);
189
190 1
            $array[":$column"] = $value;
191
        }
192
193 1
        return $array;
194
    }
195
}
196