Completed
Push — master ( 847e27...e7a385 )
by SignpostMarv
01:32
created

AbstractDaftObjectEasyDBRepository   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 244
ccs 115
cts 115
cp 1
rs 10
c 0
b 0
f 0
wmc 24

10 Methods

Rating   Name   Duplication   Size   Complexity  
B DaftObjectRepositoryByType() 0 48 4
A __construct() 0 4 1
A DaftObjectRepositoryByDaftObject() 0 5 1
A RememberDaftObjectDataValues() 0 11 2
A RememberDaftObjectDataUpdate() 0 16 3
A RememberDaftObjectDataCols() 0 16 2
A DaftObjectExistsInDatabase() 0 19 2
B RecallDaftObjectFromData() 0 47 4
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 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
        $this->db->delete(
103 2
            $this->DaftObjectDatabaseTable(),
104 2
            $idkv
105
        );
106
107 2
        $this->ForgetDaftObjectById($id);
108 2
    }
109
110
    abstract protected function DaftObjectDatabaseTable() : string;
111
112
    /**
113
    * @return string[]
114
    */
115 2
    protected function RememberDaftObjectDataCols(
116
        DaftObject $object,
117
        bool $exists
118
    ) : array {
119 2
        $cols = $object::DaftObjectExportableProperties();
120 2
        if ($exists) {
121 2
            $changed = $object->ChangedProperties();
122 2
            $cols = array_filter(
123 2
                $cols,
124 2
                function (string $prop) use ($changed) : bool {
125 2
                    return in_array($prop, $changed, true);
126 2
                }
127
            );
128
        }
129
130 2
        return $cols;
131
    }
132
133
    /**
134
    * @return mixed[]
135
    */
136 2
    protected function RememberDaftObjectDataValues(
137
        DaftObject $object,
138
        bool $exists
139
    ) : array {
140 2
        $values = [];
141 2
        $cols = $this->RememberDaftObjectDataCols($object, $exists);
142 2
        foreach ($cols as $col) {
143 2
            $values[$col] = $object->$col;
144
        }
145
146 2
        return $values;
147
    }
148
149 2
    protected function RememberDaftObjectDataUpdate(
150
        bool $exists,
151
        array $id,
152
        array $values
153
    ) : void {
154 2
        if (count($values) > 0) {
155 2
            if (false === $exists) {
156 2
                $this->db->insert(
157 2
                    $this->DaftObjectDatabaseTable(),
158 2
                    $values
159
                );
160
            } else {
161 2
                $this->db->update(
162 2
                    $this->DaftObjectDatabaseTable(),
163 2
                    $values,
164 2
                    $id
165
                );
166
            }
167
        }
168 2
    }
169
170 2
    protected function RememberDaftObjectData(
171
        DefinesOwnIdPropertiesInterface $object
172
    ) : void {
173 2
        $id = [];
174
175 2
        foreach ($object::DaftObjectIdProperties() as $prop) {
176 2
            $id[$prop] = $object->$prop;
177
        }
178
179 2
        $this->db->tryFlatTransaction(function () use ($id, $object) : void {
180 2
            $exists = $this->DaftObjectExistsInDatabase($id);
181 2
            $values = $this->RememberDaftObjectDataValues($object, $exists);
182 2
            $this->RememberDaftObjectDataUpdate($exists, $id, $values);
183 2
        });
184 2
    }
185
186
    /**
187
    * @param mixed $id
188
    */
189 2
    protected function RecallDaftObjectFromData($id) : ? DaftObject
190
    {
191
        /**
192
        * @var DefinesOwnIdPropertiesInterface $type
193
        */
194 2
        $type = $this->type;
195 2
        $idkv = [];
196
197
        foreach (
198 2
            array_values($type::DaftObjectIdProperties()) as $i => $prop
199
        ) {
200 2
            $idkv[$prop] = $id[$i];
201
        }
202
203 2
        if (true === $this->DaftObjectExistsInDatabase($idkv)) {
204 2
            $where = [];
205 2
            foreach (array_keys($idkv) as $col) {
206 2
                $where[] = $this->db->escapeIdentifier($col) . ' = ?';
207
            }
208
209 2
            $data = $this->db->safeQuery(
210
                (
211
                    'SELECT * FROM ' .
212 2
                    $this->db->escapeIdentifier(
213 2
                        $this->DaftObjectDatabaseTable()
214
                    ) .
215 2
                    ' WHERE ' .
216 2
                    implode(' AND ', $where) .
217 2
                    ' LIMIT 1'
218
                ),
219 2
                array_values($idkv)
220
            );
221
222
            /**
223
            * @var \SignpostMarv\DaftObject\DaftObjectCreatedByArray $type
224
            */
225 2
            $type = $type;
226
227
            /**
228
            * @var DefinesOwnIdPropertiesInterface $out
229
            */
230 2
            $out = new $type($data[0]);
231
232 2
            return $out;
233
        }
234
235 2
        return null;
236
    }
237
238 2
    private function DaftObjectExistsInDatabase(array $id) : bool
239
    {
240 2
        $where = [];
241 2
        foreach (array_keys($id) as $col) {
242 2
            $where[] = $this->db->escapeIdentifier($col) . ' = ?';
243
        }
244
245
        return
246 2
            (int) $this->db->single(
247
                (
248
                    'SELECT COUNT(*) FROM ' .
249 2
                    $this->db->escapeIdentifier(
250 2
                        $this->DaftObjectDatabaseTable()
251
                    ) .
252 2
                    ' WHERE ' .
253 2
                    implode(' AND ', $where)
254
                ),
255 2
                array_values($id)
256 2
            ) >= 1;
257
    }
258
}
259