Completed
Push — master ( 1bb9ae...807fec )
by James Ekow Abaka
03:08
created

RecordWrapper::fetchRelatedFields()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 14
ccs 6
cts 6
cp 1
rs 9.4285
cc 3
eloc 10
nc 4
nop 2
crap 3
1
<?php
2
/*
3
 * The MIT License
4
 *
5
 * Copyright 2015 ekow.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
26
namespace ntentan\nibii;
27
28
use ntentan\utils\Utils;
29
use ntentan\kaikai\Cache;
30
use ntentan\panie\InjectionContainer;
31
use ntentan\utils\Text;
32
33
class RecordWrapper implements \ArrayAccess, \Countable, \Iterator
34
{
35
    use \ntentan\panie\ComponentContainerTrait;
36
    
37
    protected $hasMany = [];
38
    protected $belongsTo = [];
39
    protected $manyHaveMany = [];
40
    protected $behaviours = [];
41
    protected $table;
42
    private $modelData = [];
43
    private $invalidFields;
44
    private $dynamicOperations;
45
    private $index = 0;
46
    private $dataSet = false;
47
    protected $adapter;
48
49 36
    public function __construct(DriverAdapter $adapter)
50
    {
51 36
        $this->table = Nibii::getModelTable($this);
52 36
        $this->adapter = $adapter;
53 36
        foreach($this->behaviours as $behaviour) {
54
            $behaviourInstance = $this->getComponentInstance($behaviour);
55
            $behaviourInstance->setModel($this);
56
        }
57 36
    }
58
59
    /**
60
     * 
61
     * @return ModelDescription
62
     */
63 28
    public function getDescription()
64
    {
65 28
        return Cache::read(
66 28
            (new \ReflectionClass($this))->getName() . '::desc',
67 28
            function() 
68
            {
69 28
                return new ModelDescription($this);
70 28
            }
71
        );
72
    }
73
    
74 10
    public function count()
75
    {
76 10
        if ($this->dataSet) {
77 10
            return count($this->getData());
78
        } else {
79
            return $this->__call('count', []);
0 ignored issues
show
Documentation introduced by
'count' is of type string, but the function expects a object<ntentan\nibii\type>.

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...
Documentation introduced by
array() is of type array, but the function expects a object<ntentan\nibii\type>.

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...
80
        }
81
    }
82
83 12
    private function retrieveItem($key)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
84
    {
85 12
        $relationships = $this->getDescription()->getRelationships();
86 12
        if(isset($relationships[$key])) {
87 4
            return $this->fetchRelatedFields($relationships[$key]);
88
        } else {
89 8
            return isset($this->modelData[$key]) ? $this->modelData[$key] : null;
90
        }
91
    }
92
93
    /**
94
     * Create a new instance of this Model
95
     * @return \ntentan\nibii\RecordWrapper
96
     */
97 34
    public static function createNew()
98
    {
99 34
        $class = get_called_class();
100 34
        return InjectionContainer::resolve($class);
101
    }
102
103
    /**
104
     * @method
105
     * @param type $name
106
     * @param type $arguments
107
     * @return type
108
     */
109 34
    public function __call($name, $arguments)
110
    {
111 34
        if($this->dynamicOperations === null) {
112 34
            $this->dynamicOperations = new Operations(
113 34
                $this, $this->adapter
114
            );
115
        }
116 34
        return $this->dynamicOperations->perform($name, $arguments);
117
    }
118
119 26
    public static function __callStatic($name, $arguments)
120
    {
121 26
        return call_user_func_array([self::createNew(), $name], $arguments);
122
    }
123
124 8
    public function __set($name, $value)
125
    {
126 8
        $this->dataSet = true;
127 8
        $this->modelData[Text::deCamelize($name)] = $value;
128 8
    }
129
130 12
    public function __get($name)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
131
    {
132 12
        return $this->retrieveItem(Text::deCamelize($name));
133
    }
134
135 36
    public function getTable()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
136
    {
137 36
        return $this->table;
138
    }
139
    
140 4
    private function expandArrayValue($array, $relationships, $depth, $index = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
141
    {
142 4
        foreach($relationships as $name => $relationship) {
143 4
            $array[$name] = $this->fetchRelatedFields($relationship, $index)->toArray($depth);
144
        }
145 4
        return $array;
146
    }
147
148 12
    public function toArray($depth = 0)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
149
    {
150 12
        $relationships = $this->getDescription()->getRelationships();
151 12
        $array = $this->modelData;
152 12
        if($depth > 0) {
153 4
            if($this->hasMultipleData()) {
154
                foreach($array as $i => $value) {
155
                    $array[$i] = $this->expandArrayValue($value, $relationships, $depth - 1, $i);
156
                }
157
            } else {
158 4
                $array = $this->expandArrayValue($array, $relationships, $depth - 1);
159
            }
160
        }
161 12
        return $array;
162
    }
163
    
164 10
    public function save()
165
    {
166 10
        $return = $this->__call('save', [$this->hasMultipleData()]);
0 ignored issues
show
Documentation introduced by
'save' is of type string, but the function expects a object<ntentan\nibii\type>.

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...
Documentation introduced by
array($this->hasMultipleData()) is of type array<integer,boolean,{"0":"boolean"}>, but the function expects a object<ntentan\nibii\type>.

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...
167 10
        $this->invalidFields = $this->dynamicOperations->getInvalidFields();
168 10
        return $return;
169
    }
170
171 18
    private function hasMultipleData()
172
    {
173 18
        if(count($this->modelData) > 0) {
174 16
            return is_numeric(array_keys($this->modelData)[0]);
175
        } else {
176 2
            return false;
177
        }
178
    }
179
180 14
    public function getData()
181
    {
182 14
        $data = [];
183
                
184 14
        if(count($this->modelData) == 0) {
185 6
            $data = $this->modelData;
186 12
        } else if($this->hasMultipleData()) {
187 2
            $data = $this->modelData;
188 12
        } else if(count($this->modelData) > 0) {
189 12
            $data[] = $this->modelData;
190
        }
191
        
192 14
        return $data;
193
    }
194
195 26
    public function setData($data)
196
    {
197 26
        $this->dataSet = true;
198 26
        $this->modelData = $data;
199 26
    }
200
    
201
    public function mergeData($data)
202
    {
203
        foreach($data as $key => $value) {
204
            $this->modelData[$key] = $value;
205
        }
206
        $this->dataSet = true;
207
    }
208
209 2
    public function offsetExists($offset)
210
    {
211 2
        return isset($this->modelData[$offset]);
212
    }
213
214 2
    public function offsetGet($offset)
215
    {
216 2
        if (is_numeric($offset)) {
217 2
            return $this->wrap($offset);
218
        } else {
219 2
            return $this->retrieveItem($offset);
220
        }
221
    }
222
223 2
    public function offsetSet($offset, $value)
224
    {
225 2
        $this->dataSet = true;
226 2
        $this->modelData[$offset] = $value;
227 2
    }
228
229
    public function offsetUnset($offset)
230
    {
231
        unset($this->modelData[$offset]);
232
    }
233
234 6
    private function wrap($offset)
235
    {
236 6
        if(isset($this->modelData[$offset])) {
237 6
            $newInstance = $this->createNew();
238 6
            $newInstance->setData($this->modelData[$offset]);
239 6
            return $newInstance;
240
        } else {
241
            return null;
242
        }
243
    }
244
245 4
    public function getInvalidFields()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
246
    {
247 4
        return $this->invalidFields;
248
    }
249
250
    public function getHasMany()
251
    {
252
        return $this->hasMany;
253
    }
254
255
    public function getBelongsTo()
256
    {
257
        return $this->belongsTo;
258
    }
259
260 4
    public function current()
261
    {
262 4
        return $this->wrap($this->index);
263
    }
264
265
    public function key()
266
    {
267
        return $this->index;
268
    }
269
270 2
    public function next()
271
    {
272 2
        $this->index++;
273 2
    }
274
275 4
    public function rewind()
276
    {
277 4
        $this->index = 0;
278 4
    }
279
280 4
    public function valid()
281
    {
282 4
        return isset($this->modelData[$this->index]);
283
    }
284
    
285 6
    public function onValidate()
286
    {
287 6
        return true;
288
    }
289
290 8
    private function fetchRelatedFields($relationship, $index = null)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
291
    {
292 8
        if($index === null) {
293 8
            $data = $this->modelData;
294
        } else {
295
            $data = $this->modelData[$index];
296
        }
297 8
        $model = $relationship->getModelInstance();
298 8
        if(empty($data)) {
299
            return $model;
300
        } else {
301 8
            return $model->fetch($relationship->getQuery($data));
302
        }
303
    }
304
305 28
    public function getRelationships()
306
    {
307
        return [
308 28
            'HasMany' => $this->hasMany,
309 28
            'BelongsTo' => $this->belongsTo,
310 28
            'ManyHaveMany' => $this->manyHaveMany
311
        ];
312
    }
313
    
314
    public function usetField($field)
315
    {
316
        unset($this->modelData[$field]);
317
    }
318
    
319 8
    public function preSaveCallback()
320
    {
321
        
322 8
    }
323
    
324 4
    public function postSaveCallback($id)
0 ignored issues
show
Unused Code introduced by
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
325
    {
326
        
327 4
    }
328
    
329 2
    public function preUpdateCallback()
330
    {
331
        
332 2
    }
333
    
334 2
    public function postUpdateCallback()
335
    {
336
        
337 2
    }
338
    
339 10
    public function getBehaviours()
340
    {
341 10
        return $this->loadedComponents;
342
    }
343
}
344