Passed
Push — master ( 00b45f...505b3b )
by SignpostMarv
01:41
created

RememberDaftObjectData()   F

Complexity

Conditions 12
Paths 320

Size

Total Lines 95
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 52
CRAP Score 12.0524

Importance

Changes 0
Metric Value
dl 0
loc 95
ccs 52
cts 56
cp 0.9286
rs 3.7956
c 0
b 0
f 0
cc 12
eloc 63
nc 320
nop 1
crap 12.0524

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
use RuntimeException;
13
use Throwable;
14
15
abstract class AbstractDaftObjectEasyDBRepository extends DaftObjectMemoryRepository
16
{
17
    /**
18
    * @var EasyDB
19
    */
20
    protected $db;
21
22 6
    protected function __construct(string $type, EasyDB $db)
23
    {
24 6
        parent::__construct($type);
25 6
        $this->db = $db;
26 6
    }
27
28 6
    public static function DaftObjectRepositoryByType(
29
        string $type,
30
        ? EasyDB $db = null
31
    ) : DaftObjectRepository {
32 6
        if (class_exists($type) === false) {
33 1
            throw new DaftObjectRepositoryTypeException(
34
                'Argument 1 passed to ' .
0 ignored issues
show
Unused Code introduced by
The call to DaftObjectRepositoryTypeException::__construct() has too many arguments starting with 'Argument 1 passed to ' ..., ' . $type . ' given.'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
35 1
                static::class .
36
                '::' .
37
                __FUNCTION__ .
38
                '() must be an implementation of ' .
39
                DefinesOwnIdPropertiesInterface::class .
40 1
                ', ' .
41 1
                $type .
42 1
                ' given.'
43
            );
44 6
        } elseif (($db instanceof EasyDB) === false) {
45
            throw new RuntimeException('Database connection not specified!');
46
        }
47
48 6
        return new static($type, $db);
49
    }
50
51 5
    public static function DaftObjectRepositoryByDaftObject(
52
        DefinesOwnIdPropertiesInterface $object,
53
        ? EasyDB $db = null
54
    ) : DaftObjectRepository {
55 5
        if (($db instanceof EasyDB) === true) {
56 5
            return static::DaftObjectRepositoryByType(get_class($object), $db);
57
        }
58
59
        throw new RuntimeException('Database connection not specified!');
60
    }
61
62
    /**
63
    * @param mixed $id
64
    */
65 2
    public function RemoveDaftObjectById($id) : void
66
    {
67 2
        $id = array_values(is_array($id) ? $id : [$id]);
68 2
        $type = $this->type;
69 2
        $idkv = [];
70
71
        foreach (
72 2
            array_values($type::DaftObjectIdProperties()) as $i => $prop
73
        ) {
74 2
            $idkv[$prop] = $id[$i];
75
        }
76
77 2
        $where = [];
78 2
        foreach (array_keys($idkv) as $col) {
79 2
            $where[] = $this->db->escapeIdentifier($col) . ' = ?';
80
        }
81
82
        $query = (
83
            'DELETE FROM ' .
84 2
            $this->db->escapeIdentifier(
85 2
                $this->DaftObjectDatabaseTable()
86
            ) .
87 2
            ' WHERE ' .
88 2
            implode(' AND ', $where)
89
        );
90
91 2
        $this->db->safeQuery($query, array_values($idkv));
92
93 2
        $this->ForgetDaftObjectById($id);
94 2
    }
95
96
    abstract protected function DaftObjectDatabaseTable() : string;
97
98 2
    protected function RememberDaftObjectData(
99
        DefinesOwnIdPropertiesInterface $object
100
    ) : void {
101 2
        $id = [];
102
103 2
        foreach ($object::DaftObjectIdProperties() as $prop) {
104 2
            $id[$prop] = $object->$prop;
105
        }
106
107 2
        $autoStartTransaction = ($this->db->inTransaction() === false);
108
109 2
        if ($autoStartTransaction === true) {
110 2
            $this->db->beginTransaction();
111
        }
112
113
        try {
114 2
            $exists = $this->DaftObjectExistsInDatabase($id);
115 2
            if ($exists === false) {
116 2
                $cols = [];
117 2
                $values = [];
118
119 2
                foreach ($object::DaftObjectProperties() as $col) {
120
                    if (
121 2
                        method_exists(
122 2
                            $object,
123 2
                            'Get' . ucfirst($col)
124 2
                        ) === false
125
                    ) {
126 2
                        continue;
127
                    }
128 2
                    $cols[] = $this->db->escapeIdentifier($col);
129 2
                    $values[] = $object->$col;
130
                }
131
132 2
                $this->db->safeQuery(
133
                    (
134
                        'INSERT INTO ' .
135 2
                        $this->db->escapeIdentifier(
136 2
                            $this->DaftObjectDatabaseTable()
137
                        ) .
138 2
                        ' (' .
139 2
                        implode(', ', $cols) .
140 2
                        ') VALUES (' .
141 2
                        implode(', ', array_fill(0, count($cols), '?')) .
142 2
                        ')'
143
                    ),
144 2
                    $values
145
                );
146
            } else {
147 2
                $changed = $object->ChangedProperties();
148 2
                if (count($changed) > 0) {
149 2
                    $cols = [];
150 2
                    $values = [];
151
152 2
                    foreach ($changed as $col) {
153 2
                        $values[] = $object->$col;
154 2
                        $cols[] =
155 2
                            $this->db->escapeIdentifier($col) .
156 2
                            ' = ?';
157
                    }
158
159
                    $query =
160
                        'UPDATE ' .
161 2
                        $this->db->escapeIdentifier(
162 2
                            $this->DaftObjectDatabaseTable()
163
                        ) .
164 2
                        ' SET ' .
165 2
                        implode(', ', $cols);
166
167 2
                    $cols = [];
168
169 2
                    foreach ($id as $col => $value) {
170 2
                        $values[] = $value;
171 2
                        $cols[] =
172 2
                            $this->db->escapeIdentifier($col) .
173 2
                            ' = ?';
174
                    }
175
176 2
                    $query .= ' WHERE ' . implode(' AND ', $cols);
177
178 2
                    $this->db->safeQuery($query, $values);
179
                }
180
            }
181
182 2
            if ($autoStartTransaction === true) {
183 2
                $this->db->commit();
184
            }
185
        } catch (Throwable $e) {
186
            if ($autoStartTransaction === true) {
187
                $this->db->rollBack();
188
            }
189
190
            throw $e;
191
        }
192 2
    }
193
194
    /**
195
    * @param mixed $id
196
    */
197 2
    protected function RecallDaftObjectFromData($id) : ? DaftObject
198
    {
199 2
        $type = $this->type;
200 2
        $idkv = [];
201
202
        foreach (
203 2
            array_values($type::DaftObjectIdProperties()) as $i => $prop
204
        ) {
205 2
            $idkv[$prop] = $id[$i];
206
        }
207
208 2
        if ($this->DaftObjectExistsInDatabase($idkv) === true) {
209 2
            $where = [];
210 2
            foreach (array_keys($idkv) as $col) {
211 2
                $where[] = $this->db->escapeIdentifier($col) . ' = ?';
212
            }
213
214 2
            $data = $this->db->safeQuery(
215
                (
216
                    'SELECT * FROM ' .
217 2
                    $this->db->escapeIdentifier(
218 2
                        $this->DaftObjectDatabaseTable()
219
                    ) .
220 2
                    ' WHERE ' .
221 2
                    implode(' AND ', $where) .
222 2
                    ' LIMIT 1'
223
                ),
224 2
                array_values($idkv)
225
            );
226
227 2
            return new $type($data[0]);
228
        }
229
230 2
        return null;
231
    }
232
233 2
    private function DaftObjectExistsInDatabase(array $id) : bool
234
    {
235 2
        $where = [];
236 2
        foreach (array_keys($id) as $col) {
237 2
            $where[] = $this->db->escapeIdentifier($col) . ' = ?';
238
        }
239
240
        return
241 2
            (int) $this->db->single(
242
                (
243
                    'SELECT COUNT(*) FROM ' .
244 2
                    $this->db->escapeIdentifier(
245 2
                        $this->DaftObjectDatabaseTable()
246
                    ) .
247 2
                    ' WHERE ' .
248 2
                    implode(' AND ', $where)
249
                ),
250 2
                array_values($id)
251 2
            ) >= 1;
252
    }
253
}
254