Completed
Push — master ( df1cf3...847e27 )
by SignpostMarv
03:02
created

AbstractDaftObjectEasyDBRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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