Completed
Push — master ( 7297ae...24cab6 )
by SignpostMarv
02:24
created

RecallDaftObjectFromData()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6.0045

Importance

Changes 0
Metric Value
cc 6
eloc 20
nc 12
nop 1
dl 0
loc 39
rs 8.439
c 0
b 0
f 0
ccs 19
cts 20
cp 0.95
crap 6.0045
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 10
    protected function __construct(string $type, EasyDB $db)
21
    {
22 10
        parent::__construct($type);
23 10
        $this->db = $db;
24 10
    }
25
26 18
    public static function DaftObjectRepositoryByType(
27
        string $type,
28
        ? EasyDB $db = null
29
    ) : DaftObjectRepository {
30 18
        $a = is_a($type, DaftObjectCreatedByArray::class, true);
31
        if (
32 18
            false === $a ||
33 18
            false === is_a($type, DefinesOwnIdPropertiesInterface::class, true)
34
        ) {
35 6
            throw new DaftObjectRepositoryTypeByClassMethodAndTypeException(
36 6
                1,
37 6
                static::class,
38 6
                __FUNCTION__,
39 6
                ($a ? DefinesOwnIdPropertiesInterface::class : DaftObjectCreatedByArray::class),
40 6
                $type
41
            );
42 12
        } elseif (false === ($db instanceof EasyDB)) {
43 2
            throw new DatabaseConnectionNotSpecifiedException(
44 2
                2,
45 2
                static::class,
46 2
                __FUNCTION__,
47 2
                EasyDB::class,
48 2
                'null'
49
            );
50
        }
51
52 10
        return new static($type, $db);
53
    }
54
55 10
    public static function DaftObjectRepositoryByDaftObject(
56
        DefinesOwnIdPropertiesInterface $object,
57
        ? EasyDB $db = null
58
    ) : DaftObjectRepository {
59 10
        return static::DaftObjectRepositoryByType(get_class($object), $db);
60
    }
61
62
    /**
63
    * @param mixed $id
64
    */
65 4
    public function RemoveDaftObjectById($id) : void
66
    {
67 4
        $id = array_values(is_array($id) ? $id : [$id]);
68
69
        /**
70
        * @var DefinesOwnIdPropertiesInterface $type
71
        */
72 4
        $type = $this->type;
73 4
        $idkv = [];
74
75 4
        foreach (array_values($type::DaftObjectIdProperties()) as $i => $prop) {
76 4
            $idkv[$prop] = $id[$i];
77
        }
78
79 4
        $this->db->delete($this->DaftObjectDatabaseTable(), $idkv);
80
81 4
        $this->ForgetDaftObjectById($id);
82 4
    }
83
84
    abstract protected function DaftObjectDatabaseTable() : string;
85
86
    /**
87
    * @return string[]
88
    */
89 4
    protected function RememberDaftObjectDataCols(DaftObject $object, bool $exists) : array {
90 4
        $cols = $object::DaftObjectExportableProperties();
91 4
        if ($exists) {
92 4
            $changed = $object->ChangedProperties();
93 4
            $cols = array_filter(
94 4
                $cols,
95 4
                function (string $prop) use ($changed) : bool {
96 4
                    return in_array($prop, $changed, true);
97 4
                }
98
            );
99
        }
100
101 4
        return $cols;
102
    }
103
104
    /**
105
    * @return array<string, mixed>
106
    */
107 4
    protected function RememberDaftObjectDataValues(DaftObject $object, bool $exists) : array
108
    {
109 4
        $values = [];
110 4
        $cols = $this->RememberDaftObjectDataCols($object, $exists);
111 4
        foreach ($cols as $col) {
112 4
            $values[$col] = $object->$col;
113
        }
114
115 4
        return $values;
116
    }
117
118 4
    protected function RememberDaftObjectDataUpdate(bool $exists, array $id, array $values) : void
119
    {
120 4
        if (count($values) > 0) {
121 4
            if (false === $exists) {
122 4
                $this->db->insert($this->DaftObjectDatabaseTable(), $values);
123
            } else {
124 4
                $this->db->update($this->DaftObjectDatabaseTable(), $values, $id);
125
            }
126
        }
127 4
    }
128
129 4
    protected function RememberDaftObjectData(DefinesOwnIdPropertiesInterface $object) : void
130
    {
131 4
        $id = [];
132
133 4
        foreach ($object::DaftObjectIdProperties() as $prop) {
134 4
            $id[$prop] = $object->$prop;
135
        }
136
137 4
        $this->db->tryFlatTransaction(function () use ($id, $object) : void {
138 4
            $exists = $this->DaftObjectExistsInDatabase($id);
139 4
            $values = $this->RememberDaftObjectDataValues($object, $exists);
140 4
            $this->RememberDaftObjectDataUpdate($exists, $id, $values);
141 4
        });
142 4
    }
143
144
    /**
145
    * @param mixed $id
146
    */
147 4
    protected function RecallDaftObjectFromData($id) : ? DaftObject
148
    {
149 4
        $type = $this->type;
150 4
        $idkv = [];
151
152 4
        if (is_scalar($id) && 1 === count($type::DaftObjectIdProperties())) {
153
            $id = [$id];
154
        }
155
156 4
        foreach (array_values($type::DaftObjectIdProperties()) as $i => $prop) {
157 4
            $idkv[$prop] = $id[$i];
158
        }
159
160 4
        if (true === $this->DaftObjectExistsInDatabase($idkv)) {
161 4
            $where = [];
162 4
            foreach (array_keys($idkv) as $col) {
163 4
                $where[] = $this->db->escapeIdentifier($col) . ' = ?';
164
            }
165
166 4
            $data = $this->db->safeQuery(
167
                (
168
                    'SELECT * FROM ' .
169 4
                    $this->db->escapeIdentifier($this->DaftObjectDatabaseTable()) .
170 4
                    ' WHERE ' .
171 4
                    implode(' AND ', $where) .
172 4
                    ' LIMIT 1'
173
                ),
174 4
                array_values($idkv)
175
            );
176
177
            /**
178
            * @var DefinesOwnIdPropertiesInterface $out
179
            */
180 4
            $out = new $type($data[0]);
181
182 4
            return $out;
183
        }
184
185 4
        return null;
186
    }
187
188 4
    private function DaftObjectExistsInDatabase(array $id) : bool
189
    {
190 4
        $where = [];
191 4
        foreach (array_keys($id) as $col) {
192 4
            $where[] = $this->db->escapeIdentifier($col) . ' = ?';
193
        }
194
195
        return
196 4
            (int) $this->db->single(
197
                (
198
                    'SELECT COUNT(*) FROM ' .
199 4
                    $this->db->escapeIdentifier($this->DaftObjectDatabaseTable()) .
200 4
                    ' WHERE ' .
201 4
                    implode(' AND ', $where)
202
                ),
203 4
                array_values($id)
204 4
            ) >= 1;
205
    }
206
}
207