Completed
Push — master ( e7a385...9fb364 )
by SignpostMarv
02:50
created

AbstractDaftObjectEasyDBRepository   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 247
Duplicated Lines 0 %

Test Coverage

Coverage 99.12%

Importance

Changes 0
Metric Value
dl 0
loc 247
rs 10
c 0
b 0
f 0
ccs 112
cts 113
cp 0.9912
wmc 27

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A RememberDaftObjectDataValues() 0 11 2
B DaftObjectRepositoryByType() 0 45 5
A RememberDaftObjectDataUpdate() 0 16 3
A DaftObjectRepositoryByDaftObject() 0 5 1
A RememberDaftObjectDataCols() 0 16 2
A DaftObjectExistsInDatabase() 0 19 2
B RecallDaftObjectFromData() 0 53 6
A RememberDaftObjectData() 0 13 2
A RemoveDaftObjectById() 0 22 3
1
<?php
2
/**
3
* Base daft objects.
4
*
5
* @author SignpostMarv
6
*/
7
declare(strict_types=1);
8
9
namespace SignpostMarv\DaftObject;
10
11
use ParagonIE\EasyDB\EasyDB;
12
13
abstract class AbstractDaftObjectEasyDBRepository extends DaftObjectMemoryRepository
14
{
15
    /**
16
    * @var EasyDB
17
    */
18
    protected $db;
19
20 5
    protected function __construct(string $type, EasyDB $db)
21
    {
22 5
        parent::__construct($type);
23 5
        $this->db = $db;
24 5
    }
25
26 9
    public static function DaftObjectRepositoryByType(
27
        string $type,
28
        ? EasyDB $db = null
29
    ) : DaftObjectRepository {
30
        if (
31
            false === (
32 9
                $a = is_a(
33 9
                $type,
34 9
                DaftObjectCreatedByArray::class,
35 9
                true
36
                )
37
            ) ||
38 7
            false === is_a(
39 7
                $type,
40 7
                DefinesOwnIdPropertiesInterface::class,
41 7
                true
42
            )
43
        ) {
44 3
            throw new DaftObjectRepositoryTypeByClassMethodAndTypeException(
45 3
                1,
46 3
                static::class,
47 3
                __FUNCTION__,
48
                (
49 3
                    $a
50 1
                        ? DefinesOwnIdPropertiesInterface::class
51 3
                        : DaftObjectCreatedByArray::class
52
                ),
53 3
                $type
54
            );
55 6
        } elseif (false === ($db instanceof EasyDB)) {
56 1
            throw new DatabaseConnectionNotSpecifiedException(
57 1
                2,
58 1
                static::class,
59 1
                __FUNCTION__,
60 1
                EasyDB::class,
61 1
                'null'
62
            );
63
        }
64
65
        /**
66
        * @var EasyDB $db
67
        */
68 5
        $db = $db;
69
70 5
        return new static($type, $db);
71
    }
72
73 5
    public static function DaftObjectRepositoryByDaftObject(
74
        DefinesOwnIdPropertiesInterface $object,
75
        ? EasyDB $db = null
76
    ) : DaftObjectRepository {
77 5
        return static::DaftObjectRepositoryByType(get_class($object), $db);
78
    }
79
80
    /**
81
    * @param mixed $id
82
    */
83 2
    public function RemoveDaftObjectById($id) : void
84
    {
85 2
        $id = array_values(is_array($id) ? $id : [$id]);
86
87
        /**
88
        * @var DefinesOwnIdPropertiesInterface $type
89
        */
90 2
        $type = $this->type;
91 2
        $idkv = [];
92
93
        foreach (
94 2
            array_values($type::DaftObjectIdProperties()) as $i => $prop
95
        ) {
96 2
            $idkv[$prop] = $id[$i];
97
        }
98
99 2
        $this->db->delete(
100 2
            $this->DaftObjectDatabaseTable(),
101 2
            $idkv
102
        );
103
104 2
        $this->ForgetDaftObjectById($id);
105 2
    }
106
107
    abstract protected function DaftObjectDatabaseTable() : string;
108
109
    /**
110
    * @return string[]
111
    */
112 2
    protected function RememberDaftObjectDataCols(
113
        DaftObject $object,
114
        bool $exists
115
    ) : array {
116 2
        $cols = $object::DaftObjectExportableProperties();
117 2
        if ($exists) {
118 2
            $changed = $object->ChangedProperties();
119 2
            $cols = array_filter(
120 2
                $cols,
121 2
                function (string $prop) use ($changed) : bool {
122 2
                    return in_array($prop, $changed, true);
123 2
                }
124
            );
125
        }
126
127 2
        return $cols;
128
    }
129
130
    /**
131
    * @return mixed[]
132
    */
133 2
    protected function RememberDaftObjectDataValues(
134
        DaftObject $object,
135
        bool $exists
136
    ) : array {
137 2
        $values = [];
138 2
        $cols = $this->RememberDaftObjectDataCols($object, $exists);
139 2
        foreach ($cols as $col) {
140 2
            $values[$col] = $object->$col;
141
        }
142
143 2
        return $values;
144
    }
145
146 2
    protected function RememberDaftObjectDataUpdate(
147
        bool $exists,
148
        array $id,
149
        array $values
150
    ) : void {
151 2
        if (count($values) > 0) {
152 2
            if (false === $exists) {
153 2
                $this->db->insert(
154 2
                    $this->DaftObjectDatabaseTable(),
155 2
                    $values
156
                );
157
            } else {
158 2
                $this->db->update(
159 2
                    $this->DaftObjectDatabaseTable(),
160 2
                    $values,
161 2
                    $id
162
                );
163
            }
164
        }
165 2
    }
166
167 2
    protected function RememberDaftObjectData(
168
        DefinesOwnIdPropertiesInterface $object
169
    ) : void {
170 2
        $id = [];
171
172 2
        foreach ($object::DaftObjectIdProperties() as $prop) {
173 2
            $id[$prop] = $object->$prop;
174
        }
175
176 2
        $this->db->tryFlatTransaction(function () use ($id, $object) : void {
177 2
            $exists = $this->DaftObjectExistsInDatabase($id);
178 2
            $values = $this->RememberDaftObjectDataValues($object, $exists);
179 2
            $this->RememberDaftObjectDataUpdate($exists, $id, $values);
180 2
        });
181 2
    }
182
183
    /**
184
    * @param mixed $id
185
    */
186 2
    protected function RecallDaftObjectFromData($id) : ? DaftObject
187
    {
188
        /**
189
        * @var DefinesOwnIdPropertiesInterface $type
190
        */
191 2
        $type = $this->type;
192 2
        $idkv = [];
193
194 2
        if (is_scalar($id) && 1 === count($type::DaftObjectIdProperties())) {
195
            $id = [
196
                $id,
197
            ];
198
        }
199
200
        foreach (
201 2
            array_values($type::DaftObjectIdProperties()) as $i => $prop
202
        ) {
203 2
            $idkv[$prop] = $id[$i];
204
        }
205
206 2
        if (true === $this->DaftObjectExistsInDatabase($idkv)) {
207 2
            $where = [];
208 2
            foreach (array_keys($idkv) as $col) {
209 2
                $where[] = $this->db->escapeIdentifier($col) . ' = ?';
210
            }
211
212 2
            $data = $this->db->safeQuery(
213
                (
214
                    'SELECT * FROM ' .
215 2
                    $this->db->escapeIdentifier(
216 2
                        $this->DaftObjectDatabaseTable()
217
                    ) .
218 2
                    ' WHERE ' .
219 2
                    implode(' AND ', $where) .
220 2
                    ' LIMIT 1'
221
                ),
222 2
                array_values($idkv)
223
            );
224
225
            /**
226
            * @var \SignpostMarv\DaftObject\DaftObjectCreatedByArray $type
227
            */
228 2
            $type = $type;
229
230
            /**
231
            * @var DefinesOwnIdPropertiesInterface $out
232
            */
233 2
            $out = new $type($data[0]);
234
235 2
            return $out;
236
        }
237
238 2
        return null;
239
    }
240
241 2
    private function DaftObjectExistsInDatabase(array $id) : bool
242
    {
243 2
        $where = [];
244 2
        foreach (array_keys($id) as $col) {
245 2
            $where[] = $this->db->escapeIdentifier($col) . ' = ?';
246
        }
247
248
        return
249 2
            (int) $this->db->single(
250
                (
251
                    'SELECT COUNT(*) FROM ' .
252 2
                    $this->db->escapeIdentifier(
253 2
                        $this->DaftObjectDatabaseTable()
254
                    ) .
255 2
                    ' WHERE ' .
256 2
                    implode(' AND ', $where)
257
                ),
258 2
                array_values($id)
259 2
            ) >= 1;
260
    }
261
}
262