Passed
Push — master ( 39c748...16551a )
by Nate
06:42
created

ObjectRecordAccessor   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 337
Duplicated Lines 12.46 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 8
dl 42
loc 337
rs 9.6
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 10 4
A getRecordClass() 0 4 1
A getRecordQuery() 0 20 2
A createRecord() 0 22 3
A findRecordByCondition() 0 13 2
A findRecordByCriteria() 18 18 3
A getRecordByCondition() 0 12 2
A getRecordByCriteria() 0 12 2
A findAllRecords() 0 4 1
A findAllRecordsByCondition() 0 9 1
B findAllRecordsByCriteria() 24 24 3
A getAllRecords() 0 11 1
A getAllRecordsByCondition() 0 12 2
A getAllRecordsByCriteria() 0 12 2
A findRecordById() 0 9 1
A getRecordById() 0 9 1
A notFoundRecordException() 0 10 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * @link      https://craftcms.com/
4
 * @copyright Copyright (c) Pixel & Tonic, Inc.
5
 * @license   https://craftcms.com/license
6
 */
7
8
namespace flipbox\spark\behaviors;
9
10
use Craft;
11
use flipbox\spark\exceptions\RecordNotFoundException;
12
use flipbox\spark\helpers\QueryHelper;
13
use flipbox\spark\helpers\RecordHelper;
14
use flipbox\spark\records\Record;
15
use yii\base\Behavior;
16
use yii\base\InvalidConfigException;
17
use yii\db\ActiveQuery;
18
19
class ObjectRecordAccessor extends Behavior
20
{
21
22
    /**
23
     * @var string
24
     */
25
    public $record;
26
27
    /**
28
     * @var string
29
     */
30
    public $instance = Record::class;
31
32
    /**
33
     * @inheritdoc
34
     *
35
     * @throws InvalidConfigException if the behavior was not configured properly
36
     */
37
    public function init()
38
    {
39
40
        parent::init();
41
42
        if ($this->record === null || ($this->instance && $this->record instanceof $this->instance)) {
43
            throw new InvalidConfigException('Invalid record class.');
44
        }
45
46
    }
47
48
    /**
49
     * @return string
50
     */
51
    protected function getRecordClass()
52
    {
53
        return $this->record;
54
    }
55
56
    /**
57
     * @param array $config
58
     * @return \yii\db\ActiveQuery
59
     */
60
    public function getRecordQuery($config = []): ActiveQuery
61
    {
62
63
        /** @var Record $recordClass */
64
        $recordClass = $this->getRecordClass();
65
66
        $query = $recordClass::find();
67
68
        if ($config) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $config 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...
69
70
            QueryHelper::configure(
71
                $query,
72
                $config
73
            );
74
75
        }
76
77
        return $query;
78
79
    }
80
81
    /*******************************************
82
     * CREATE
83
     *******************************************/
84
85
    /**
86
     * @param array $attributes
87
     * @param string $toScenario
88
     * @return Record
89
     */
90
    public function createRecord(array $attributes = [], string $toScenario = null)
91
    {
92
93
        /** @var string $recordClass */
94
        $recordClass = $this->getRecordClass();
95
96
        /** @var Record $record */
97
        $record = new $recordClass();
98
99
        // Set scenario
100
        if ($toScenario) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $toScenario of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
101
            $record->setScenario($toScenario);
102
        }
103
104
        // Do we need to set properties too
105
        if (!empty($attributes)) {
106
            $record->setAttributes($attributes);
107
        }
108
109
        return $record;
110
111
    }
112
113
    /**
114
     * @param $condition
115
     * @param string $toScenario
116
     * @return Record|null
117
     */
118
    public function findRecordByCondition($condition, string $toScenario = null)
119
    {
120
121
        if (empty($condition)) {
122
            return null;
123
        }
124
125
        return $this->findRecordByCriteria(
126
            RecordHelper::conditionToCriteria($condition),
127
            $toScenario
128
        );
129
130
    }
131
132
    /**
133
     * @param $criteria
134
     * @param string $toScenario
135
     * @return Record
136
     */
137 View Code Duplication
    public function findRecordByCriteria($criteria, string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
138
    {
139
140
        $query = $this->getRecordQuery($criteria);
141
142
        /** @var Record $record */
143
        if ($record = $query->one()) {
0 ignored issues
show
Bug Compatibility introduced by
The expression $query->one(); of type yii\db\ActiveRecord|array|null adds the type array to the return on line 152 which is incompatible with the return type documented by flipbox\spark\behaviors\...r::findRecordByCriteria of type flipbox\spark\records\Record|null.
Loading history...
144
145
            // Set scenario
146
            if ($toScenario) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $toScenario of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
147
                $record->setScenario($toScenario);
148
            }
149
150
        }
151
152
        return $record;
153
154
    }
155
156
    /**
157
     * @param $condition
158
     * @param string $toScenario
159
     * @return Record
160
     * @throws RecordNotFoundException
161
     */
162
    public function getRecordByCondition($condition, string $toScenario = null)
163
    {
164
165
        if (!$record = $this->findRecordByCondition($condition, $toScenario)) {
166
167
            $this->notFoundRecordException();
168
169
        }
170
171
        return $record;
172
173
    }
174
175
    /**
176
     * @param $criteria
177
     * @param string $toScenario
178
     * @return Record
179
     * @throws RecordNotFoundException
180
     */
181
    public function getRecordByCriteria($criteria, string $toScenario = null)
182
    {
183
184
        if (!$record = $this->findRecordByCriteria($criteria, $toScenario)) {
185
186
            $this->notFoundRecordException();
187
188
        }
189
190
        return $record;
191
192
    }
193
194
195
    /**
196
     * @param string $toScenario
197
     * @return Record[]
198
     */
199
    public function findAllRecords(string $toScenario = null)
200
    {
201
        return $this->findAllRecordsByCondition(null, $toScenario);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
202
    }
203
204
    /**
205
     * @param array $condition
206
     * @param string $toScenario
207
     * @return Record[]
208
     */
209
    public function findAllRecordsByCondition($condition = [], string $toScenario = null)
210
    {
211
212
        return $this->findAllRecordsByCriteria(
213
            RecordHelper::conditionToCriteria($condition),
214
            $toScenario
215
        );
216
217
    }
218
219
    /**
220
     * @param array $criteria
221
     * @param string $toScenario
222
     * @return Record[]
223
     */
224 View Code Duplication
    public function findAllRecordsByCriteria($criteria = [], string $toScenario = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
225
    {
226
227
        $query = $this->getRecordQuery($criteria);
228
229
        /** @var Record[] $record s */
230
        $records = $query->all();
231
232
        // Set scenario
233
        if ($toScenario) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $toScenario of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
234
235
            /** @var Record $record */
236
            foreach ($records as $record) {
237
238
                // Set scenario
239
                $record->setScenario($toScenario);
240
241
            }
242
243
        }
244
245
        return $records;
246
247
    }
248
249
250
    /**
251
     * @deprecated
252
     * @param array $condition
253
     * @param string $toScenario
254
     * @return Record[]
255
     * @throws RecordNotFoundException
256
     */
257
    public function getAllRecords($condition = [], string $toScenario = null)
258
    {
259
260
        Craft::$app->getDeprecator()->log(
261
            __METHOD__,
262
            'Use the "getAllRecordsByCondition" method'
263
        );
264
265
        return $this->getAllRecordsByCondition($condition, $toScenario);
266
267
    }
268
269
    /**
270
     * @param array $condition
271
     * @param string $toScenario
272
     * @return Record[]
273
     * @throws RecordNotFoundException
274
     */
275
    public function getAllRecordsByCondition($condition = [], string $toScenario = null)
276
    {
277
278
        if (!$records = $this->findAllRecordsByCondition($condition, $toScenario)) {
279
280
            $this->notFoundRecordException();
281
282
        }
283
284
        return $records;
285
286
    }
287
288
    /**
289
     * @param array $criteria
290
     * @param string $toScenario
291
     * @return Record[]
292
     * @throws RecordNotFoundException
293
     */
294
    public function getAllRecordsByCriteria($criteria = [], string $toScenario = null)
295
    {
296
297
        if (!$records = $this->findAllRecordsByCriteria($criteria, $toScenario)) {
298
299
            $this->notFoundRecordException();
300
301
        }
302
303
        return $records;
304
305
    }
306
307
    /**
308
     * @param int $id
309
     * @param string $toScenario
310
     * @return Record|null
311
     */
312
    public function findRecordById(int $id, string $toScenario = null)
313
    {
314
315
        return $this->findRecordByCondition(
316
            ['id' => $id],
317
            $toScenario
318
        );
319
320
    }
321
322
    /**
323
     * @param int $id
324
     * @param string $toScenario
325
     * @return Record
326
     */
327
    public function getRecordById(int $id, string $toScenario = null): Record
328
    {
329
330
        return $this->getRecordByCondition(
331
            ['id' => $id],
332
            $toScenario
333
        );
334
335
    }
336
337
    /*******************************************
338
     * EXCEPTIONS
339
     *******************************************/
340
341
    /**
342
     * @throws RecordNotFoundException
343
     */
344
    protected function notFoundRecordException()
345
    {
346
347
        throw new RecordNotFoundException(
348
            sprintf(
349
                "Record does not exist."
350
            )
351
        );
352
353
    }
354
355
}
356