Store::fieldCheck()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
namespace Fabrica\Tools;
4
5
use Exception;
6
use PDO;
7
use PHPCensor\Exception\InvalidArgumentException;
8
use RuntimeException;
9
10
abstract class Store
11
{
12
    /**
13
     * @var string
14
     */
15
    protected $modelName = null;
16
17
    /**
18
     * @var string
19
     */
20
    protected $tableName = '';
21
22
    /**
23
     * @var string
24
     */
25
    protected $primaryKey = null;
26
27
    /**
28
     * @param string $key
29
     * @param string $useConnection
30
     *
31
     * @return Model|null
32
     */
33
    abstract public function getByPrimaryKey($key, $useConnection = 'read');
34
35
    /**
36
     * @throws RuntimeException
37
     */
38
    public function __construct()
39
    {
40
        if (empty($this->primaryKey)) {
41
            throw new RuntimeException('Save not implemented for this store.');
42
        }
43
    }
44
45
    /**
46
     * @param array  $where
47
     * @param int    $limit
48
     * @param int    $offset
49
     * @param array  $order
50
     * @param string $whereType
51
     *
52
     * @return array
53
     *
54
     * @throws InvalidArgumentException
55
     */
56
    public function getWhere(
57
        $where = [],
58
        $limit = 25,
59
        $offset = 0,
60
        $order = [],
61
        $whereType = 'AND'
62
    ) {
63
        $query      = 'SELECT * FROM {{' . $this->tableName . '}}';
64
        $countQuery = 'SELECT COUNT(*) AS {{count}} FROM {{' . $this->tableName . '}}';
65
66
        $wheres = [];
67
        $params = [];
68
        foreach ($where as $key => $value) {
69
            $key = $this->fieldCheck($key);
70
71
            if (!is_array($value)) {
72
                $params[] = $value;
73
                $wheres[] = $key . ' = ?';
74
            }
75
        }
76
77
        if (count($wheres)) {
78
            $query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
79
            $countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
80
        }
81
82
        if (count($order)) {
83
            $orders = [];
84
            foreach ($order as $key => $value) {
85
                $orders[] = $this->fieldCheck($key) . ' ' . $value;
86
            }
87
88
            $query .= ' ORDER BY ' . implode(', ', $orders);
89
        }
90
91
        if ($limit) {
92
            $query .= ' LIMIT ' . $limit;
93
        }
94
95
        if ($offset) {
96
            $query .= ' OFFSET ' . $offset;
97
        }
98
99
        $stmt = Database::getConnection('read')->prepareCommon($countQuery);
100
        $stmt->execute($params);
101
        $res = $stmt->fetch(PDO::FETCH_ASSOC);
102
        $count = (int)$res['count'];
103
104
        $stmt = Database::getConnection('read')->prepareCommon($query);
105
        $stmt->execute($params);
106
        $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
107
        $rtn = [];
108
109
        foreach ($res as $data) {
110
            $rtn[] = new $this->modelName($data);
111
        }
112
113
        return ['items' => $rtn, 'count' => $count];
114
    }
115
116
    /**
117
     * @param Model $obj
118
     * @param bool  $saveAllColumns
119
     *
120
     * @throws InvalidArgumentException
121
     *
122
     * @return Model|null
123
     */
124
    public function save(Model $obj, $saveAllColumns = false)
125
    {
126
        if (!($obj instanceof $this->modelName)) {
127
            throw new InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
128
        }
129
130
        $data = $obj->getDataArray();
131
132
        if (isset($data[$this->primaryKey])) {
133
            $rtn = $this->saveByUpdate($obj, $saveAllColumns);
134
        } else {
135
            $rtn = $this->saveByInsert($obj, $saveAllColumns);
136
        }
137
138
        return $rtn;
139
    }
140
141
    /**
142
     * @param Model $obj
143
     * @param bool  $saveAllColumns
144
     *
145
     * @return Model|null
146
     *
147
     * @throws Exception
148
     */
149
    public function saveByUpdate(Model $obj, $saveAllColumns = false)
150
    {
151
        $rtn = null;
0 ignored issues
show
Unused Code introduced by
$rtn is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
152
        $data = $obj->getDataArray();
153
        $modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
154
155
        $updates      = [];
156
        $updateParams = [];
157
        foreach ($modified as $key) {
158
            $updates[]      = $key . ' = :' . $key;
159
            $updateParams[] = [$key, $data[$key]];
160
        }
161
162
        if (count($updates)) {
163
            $qs = sprintf(
164
                'UPDATE {{%s}} SET %s WHERE {{%s}} = :primaryKey',
165
                $this->tableName,
166
                implode(', ', $updates),
167
                $this->primaryKey
168
            );
169
            $q  = Database::getConnection('write')->prepareCommon($qs);
170
171
            foreach ($updateParams as $updateParam) {
172
                $q->bindValue(':' . $updateParam[0], $updateParam[1]);
173
            }
174
175
            $q->bindValue(':primaryKey', $data[$this->primaryKey]);
176
            $q->execute();
177
178
            $rtn = $this->getByPrimaryKey($data[$this->primaryKey], 'write');
179
        } else {
180
            $rtn = $obj;
181
        }
182
183
        return $rtn;
184
    }
185
186
    /**
187
     * @param Model $obj
188
     * @param bool  $saveAllColumns
189
     *
190
     * @return Model|null
191
     *
192
     * @throws Exception
193
     */
194
    public function saveByInsert(Model $obj, $saveAllColumns = false)
195
    {
196
        $rtn      = null;
197
        $data     = $obj->getDataArray();
198
        $modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
199
200
        $cols    = [];
201
        $values  = [];
202
        $qParams = [];
203
        foreach ($modified as $key) {
204
            $cols[]              = $key;
205
            $values[]            = ':' . $key;
206
            $qParams[':' . $key] = $data[$key];
207
        }
208
209
        if (count($cols)) {
210
            $qs = sprintf(
211
                'INSERT INTO {{%s}} (%s) VALUES (%s)',
212
                $this->tableName,
213
                implode(', ', $cols),
214
                implode(', ', $values)
215
            );
216
            $q = Database::getConnection('write')->prepareCommon($qs);
217
218
            if ($q->execute($qParams)) {
219
                $id  = Database::getConnection('write')->lastInsertIdExtended($this->tableName);
220
                $rtn = $this->getByPrimaryKey($id, 'write');
221
            }
222
        }
223
224
        return $rtn;
225
    }
226
227
    /**
228
     * @param Model $obj
229
     *
230
     * @return bool
231
     *
232
     * @throws InvalidArgumentException
233
     */
234
    public function delete(Model $obj)
235
    {
236
        if (!($obj instanceof $this->modelName)) {
237
            throw new InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
238
        }
239
240
        $data = $obj->getDataArray();
241
242
        $q = Database::getConnection('write')
243
            ->prepareCommon(
244
                sprintf(
245
                    'DELETE FROM {{%s}} WHERE {{%s}} = :primaryKey',
246
                    $this->tableName,
247
                    $this->primaryKey
248
                )
249
            );
250
        $q->bindValue(':primaryKey', $data[$this->primaryKey]);
251
        $q->execute();
252
253
        return true;
254
    }
255
256
    /**
257
     * @param string $field
258
     *
259
     * @return string
260
     *
261
     * @throws InvalidArgumentException
262
     */
263
    protected function fieldCheck($field)
264
    {
265
        if (empty($field)) {
266
            throw new InvalidArgumentException('You cannot have an empty field name.');
267
        }
268
269
        if (strpos($field, '.') === false) {
270
            return '{{' . $this->tableName . '}}.{{' . $field . '}}';
271
        }
272
273
        return $field;
274
    }
275
}
276