ActiveRecordsTrait::newDeleteQuery()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Nip\Records\Traits\ActiveRecord;
4
5
use Nip\Database\Query\AbstractQuery as Query;
6
use Nip\Database\Query\Delete as DeleteQuery;
7
use Nip\Database\Query\Insert as InsertQuery;
8
use Nip\Database\Query\Select as SelectQuery;
9
use Nip\Database\Query\Update as UpdateQuery;
10
use Nip\Database\Result;
11
use Nip\Records\AbstractModels\Record;
12
use Nip\Records\Collections\Collection as RecordCollection;
13
use Nip\Records\EventManager\Events\Observe;
14
use Nip\Records\Traits\HasDatabase\HasDatabaseRecordsTrait;
15
use Nip\Records\Traits\HasForeignKey\RecordsTrait as HasForeignKeyTrait;
16
use Nip\Records\Traits\HasPrimaryKey\RecordsTrait as HasPrimaryKeyTrait;
17
use Nip\Records\Traits\Searchable\SearchableRecordsTrait;
18
use Nip\Records\Traits\TableStructure\TableStructureRecordsTrait;
19
use Nip\Records\Traits\Unique\RecordsTrait as UniqueRecordsTrait;
20
21
/**
22
 * Class ActiveRecordsTrait
23
 * @package Nip\Records\Traits\ActiveRecord
24
 */
25
trait ActiveRecordsTrait
26
{
27
    use UniqueRecordsTrait;
28
    use HasForeignKeyTrait;
29
    use HasPrimaryKeyTrait;
30
    use SearchableRecordsTrait;
31
    use TableStructureRecordsTrait;
32
    use HasDatabaseRecordsTrait;
33
34
    /**
35
     * @var null|string
36
     */
37
    protected $table = null;
38
39
    /**
40
     * @return SelectQuery
41
     */
42
    public function newSelectQuery()
43
    {
44
        return $this->newQuery('select');
45
    }
46
47
    /**
48
     * Factory
49
     * @param string $type
50
     * @return Query|SelectQuery|InsertQuery|DeleteQuery|UpdateQuery
51
     */
52 6
    public function newQuery($type = 'select')
53
    {
54 6
        $query = $this->getDB()->newQuery($type);
55 6
        $query->cols("`" . $this->getTable() . "`.*");
0 ignored issues
show
Bug introduced by
'`' . $this->getTable() . '`.*' of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::cols(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        $query->cols(/** @scrutinizer ignore-type */ "`" . $this->getTable() . "`.*");
Loading history...
56 6
        $query->from($this->getFullNameTable());
0 ignored issues
show
Bug introduced by
$this->getFullNameTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

56
        $query->from(/** @scrutinizer ignore-type */ $this->getFullNameTable());
Loading history...
57 6
        $query->table($this->getTable());
0 ignored issues
show
Bug introduced by
$this->getTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::table(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
        $query->table(/** @scrutinizer ignore-type */ $this->getTable());
Loading history...
58
59 6
        return $query;
60
    }
61
62
    /**
63
     * @return string
64
     */
65 13
    public function getTable()
66
    {
67 13
        if ($this->table === null) {
68 8
            $this->initTable();
69
        }
70
71 13
        return $this->table;
72
    }
73
74
    /**
75
     * @param string $table
76
     */
77 48
    public function setTable($table)
78
    {
79 48
        $this->table = $table;
80 48
    }
81
82 8
    protected function initTable()
83
    {
84 8
        $this->setTable($this->generateTable());
85 8
    }
86
87
    /**
88
     * @return string
89
     */
90 5
    protected function generateTable()
91
    {
92 5
        return str_replace('-', '_', $this->getController());
0 ignored issues
show
Bug introduced by
It seems like getController() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

92
        return str_replace('-', '_', $this->/** @scrutinizer ignore-call */ getController());
Loading history...
93
    }
94
95
    /**
96
     * @return string
97
     */
98 8
    public function getFullNameTable()
99
    {
100 8
        $database = $this->getDB()->getDatabase();
101
102 8
        return $database ? $database . '.' . $this->getTable() : $this->getTable();
103
    }
104
105
    /**
106
     * Inserts a Record into the database
107
     * @param Record $model
108
     * @param array|bool $onDuplicate
109
     * @return integer
110
     */
111 1
    public function insert($model, $onDuplicate = false)
112
    {
113 1
        if ($this->fireModelEvent(Observe::CREATING, $model) === false) {
0 ignored issues
show
Bug introduced by
It seems like fireModelEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
        if ($this->/** @scrutinizer ignore-call */ fireModelEvent(Observe::CREATING, $model) === false) {
Loading history...
114
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
115
        }
116 1
        $query = $this->insertQuery($model, $onDuplicate);
117 1
        $return = $this->performInsert($query, $model);
118
119 1
        $this->fireModelEvent(Observe::CREATED, $model);
120 1
        return $return;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $return returns the type true which is incompatible with the documented return type integer.
Loading history...
121
    }
122
123
    /**
124
     * @param Record $model
125
     * @param $onDuplicate
126
     * @return InsertQuery
127
     */
128 1
    public function insertQuery($model, $onDuplicate)
129
    {
130 1
        $inserts = $this->getQueryModelData($model);
0 ignored issues
show
Bug introduced by
It seems like getQueryModelData() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

130
        /** @scrutinizer ignore-call */ 
131
        $inserts = $this->getQueryModelData($model);
Loading history...
131
132 1
        $query = $this->newInsertQuery();
133 1
        $query->data($inserts);
134
135 1
        if ($onDuplicate !== false) {
136
            $query->onDuplicate($onDuplicate);
137
        }
138
139 1
        return $query;
140
    }
141
142
    /**
143
     * @return InsertQuery
144
     */
145 1
    public function newInsertQuery()
146
    {
147 1
        return $this->newQuery('insert');
148
    }
149
150
    /**
151
     * @param Query $query
152
     * @param Record $record
153
     * @return bool
154
     */
155 1
    protected function performInsert(Query $query, Record $record)
156
    {
157 1
        $pk = $this->getPrimaryKey();
158 1
        $query->execute();
159 1
        $lastId = $this->getDB()->lastInsertID();
160
161 1
        if ($pk == 'id') {
162 1
            $record->{$pk} = $lastId;
163
        }
164
165 1
        return true;
166
    }
167
168
    /**
169
     * Updates a Record's database entry
170
     * @param Record $model
171
     * @return bool|Result
172
     */
173
    public function update(Record $model)
174
    {
175
        $query = $this->updateQuery($model);
176
177
        if ($query) {
178
            return $query->execute();
179
        }
180
181
        return false;
182
    }
183
184
    /**
185
     * @param Record $model
186
     * @return bool|UpdateQuery
187
     */
188
    public function updateQuery(Record $model)
189
    {
190
        $pk = $this->getPrimaryKey();
191
        if (!is_array($pk)) {
0 ignored issues
show
introduced by
The condition is_array($pk) is always false.
Loading history...
192
            $pk = [$pk];
193
        }
194
195
        $data = $this->getQueryModelData($model);
196
197
        if ($data) {
198
            $query = $this->newUpdateQuery();
199
            $query->data($data);
200
201
            foreach ($pk as $key) {
202
                $query->where("$key = ?", $model->{$key});
203
            }
204
205
            return $query;
206
        }
207
208
        return false;
209
    }
210
211
212
    /**
213
     * @return UpdateQuery
214
     */
215
    public function newUpdateQuery()
216
    {
217
        return $this->newQuery('update');
218
    }
219
220
    /**
221
     * Saves a Record's database entry
222
     * @param Record $model
223
     * @return mixed
224
     */
225
    public function save(Record $model)
226
    {
227
        if ($model->hasPrimaryKey()) {
228
            $model->update();
229
230
            return $model->getPrimaryKey();
231
        }
232
233
        /** @var Record $previous */
234
        $previous = $model->exists();
235
        if ($previous) {
0 ignored issues
show
introduced by
$previous is of type Nip\Records\AbstractModels\Record, thus it always evaluated to true.
Loading history...
236
            $data = $model->toArray();
237
238
            if ($data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
239
                $previous->writeData($model->toArray());
240
            }
241
            $previous->update();
242
243
            $model->writeData($previous->toArray());
244
245
            return $model->getPrimaryKey();
246
        }
247
248
        $model->insert();
249
        return $model->getPrimaryKey();
250
    }
251
252
    /**
253
     * Delete a Record's database entry
254
     *
255
     * @param Record $input
256
     */
257
    public function delete($input)
258
    {
259
        $pk = $this->getPrimaryKey();
260
261
        if ($input instanceof $this->model) {
262
            $primary = $input->getPrimaryKey();
263
        } else {
264
            $primary = $input;
265
        }
266
267
        $query = $this->newDeleteQuery();
268
        $query->where("$pk = ?", $primary);
269
        $query->limit(1);
270
271
        $this->getDB()->execute($query);
272
    }
273
274
    /**
275
     * @return DeleteQuery
276
     */
277
    public function newDeleteQuery()
278
    {
279
        return $this->newQuery('delete');
280
    }
281
282
    /**
283
     * Delete a Record's database entry
284
     * @param array $params
285
     * @return $this
286
     */
287
    public function deleteByParams($params = [])
288
    {
289
        extract($params);
290
291
        $query = $this->newDeleteQuery();
292
293
        if (isset($where)) {
294
            if (is_array($where)) {
295
                foreach ($where as $condition) {
296
                    $condition = (array)$condition;
297
                    $query->where($condition[0], $condition[1]);
298
                }
299
            } else {
300
                call_user_func_array([$query, 'where'], $where);
301
            }
302
        }
303
304
        if (isset($order)) {
305
            call_user_func_array([$query, 'order'], $order);
306
        }
307
308
        if (isset($limit)) {
309
            call_user_func_array([$query, 'limit'], $limit);
310
        }
311
312
        $this->getDB()->execute($query);
313
314
        return $this;
315
    }
316
317
    /**
318
     * @param array $params
319
     * @return SelectQuery
320
     */
321 3
    public function paramsToQuery($params = [])
322
    {
323 3
        $this->injectParams($params);
324
325 3
        $query = $this->newQuery('select');
326 3
        $query->addParams($params);
327
328 3
        return $query;
329
    }
330
331
    /**
332
     * @param bool|array $where
333
     * @return int
334
     */
335
    public function count($where = false)
336
    {
337
        return $this->countByParams(["where" => $where]);
338
    }
339
340
    /**
341
     * Counts all the Record entries in the database
342
     * @param array $params
343
     * @return int
344
     */
345
    public function countByParams($params = [])
346
    {
347
        $this->injectParams($params);
348
        $query = $this->newQuery('select');
349
        $query->addParams($params);
350
351
        return $this->countByQuery($query);
352
    }
353
354
    /**
355
     * Counts all the Record entries in the database
356
     * @param Query $query
357
     * @return int
358
     */
359
    public function countByQuery($query)
360
    {
361
        $queryCount = clone $query;
362
        $queryCount->setCols('count(*) as count');
0 ignored issues
show
Bug introduced by
'count(*) as count' of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::setCols(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

362
        $queryCount->setCols(/** @scrutinizer ignore-type */ 'count(*) as count');
Loading history...
363
        $result = $this->getDB()->execute($queryCount);
364
365
        if ($result->numRows()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result->numRows() of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
366
            $row = $result->fetchResult();
367
368
            return (int)$row['count'];
369
        }
370
371
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
372
    }
373
374
    /**
375
     * @param $data
376
     * @return mixed
377
     */
378
    public function cleanData($data)
379
    {
380
        return $this->getDB()->getAdapter()->cleanData($data);
381
    }
382
383
    /**
384
     * @param string $name
385
     * @param $arguments
386
     * @return RecordCollection|false
387
     */
388 1
    protected function isCallDatabaseOperation($name, $arguments)
389
    {
390 1
        $operations = ["find", "delete", "count"];
391 1
        foreach ($operations as $operation) {
392 1
            if (strpos($name, $operation . "By") !== false || strpos($name, $operation . "OneBy") !== false) {
393
                $params = [];
394
                if (count($arguments) > 1) {
395
                    $params = end($arguments);
396
                }
397
398
                $match = str_replace([$operation . "By", $operation . "OneBy"], "", $name);
399
                $field = inflector()->underscore($match);
400
401
                if ($field == $this->getPrimaryKey()) {
402
                    return $this->findByPrimary($arguments[0]);
403
                }
404
405
                $params['where'][] = ["$field " . (is_array($arguments[0]) ? "IN" : "=") . " ?", $arguments[0]];
406
407
                $operation = str_replace($match, "", $name) . "Params";
408
409
                $results = $this->$operation($params);
410
                // RETURN NULL TO DISTINCT FROM FALSE THAT MEANS NOT A DATABASE OPERATION
411
                return ($results) ? $results : null;
412
            }
413
        }
414
415 1
        return false;
416
    }
417
}
418