Completed
Push — master ( 7e591a...ced319 )
by James Ekow Abaka
02:48
created

RecordWrapper::save()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 10
Bugs 1 Features 2
Metric Value
c 10
b 1
f 2
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4286
cc 1
eloc 4
nc 1
nop 0
crap 1
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
31
class RecordWrapper implements \ArrayAccess, \Countable, \Iterator
32
{
33
    use \ntentan\utils\DependencyInjector;
34
    
35
    protected $hasMany = [];
36
    protected $belongsTo = [];
37
    protected $manyHaveMany = [];
38
    protected $behaviours = [];
39
40
    protected $table;
41
    private $modelData = [];
42
    private $invalidFields;
43
    private $dynamicOperations;
44
    private $index = 0;
45
    private $dataSet = false;
46
    private $adapter;
47
48 36
    public function __construct()
49
    {
50 36
        Utils::factory(
51 36
            $this->table,
52
            function() {
53 36
                return Nibii::getModelTable($this);
54
            }
55 36
        );
56 36
        foreach($this->behaviours as $behaviour) {
57
            $behaviourInstance = $this->loadDependency($behaviour);
58
            $behaviourInstance->setModel($this);
59 36
        }
60 36
    }
61
62
    /**
63
     *
64
     * @return \ntentan\nibii\DriverAdapter
65
     */
66 34
    protected function getDataAdapter()
67
    {
68 34
        if(!$this->adapter)
69 34
        {
70 34
            $this->adapter = DriverAdapter::getDefaultInstance();
71 34
        }
72 34
        return $this->adapter;
73
    }
74
75
    protected function getDriver()
76
    {
77
        return $this->getDataAdapter()->getDriver();
78
    }
79
80
    /**
81
     * 
82
     * @return ModelDescription
83
     */
84 28
    public function getDescription()
85
    {
86 28
        return Cache::read(
87 28
            (new \ReflectionClass($this))->getName() . '::desc',
88
            function() 
89
            {
90 8
                return new ModelDescription($this);
91
            }
92 28
        );
93
    }
94
    
95 10
    public function count()
96
    {
97 10
        if ($this->dataSet) {
98 10
            return count($this->getData());
99
        } else {
100
            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...
101
        }
102
    }
103
104 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...
105
    {
106 12
        $relationships = $this->getDescription()->getRelationships();
107 12
        if(isset($relationships[$key])) {
108 8
            return $this->fetchRelatedFields($relationships[$key]);
109
        } else {
110 4
            return isset($this->modelData[$key]) ? $this->modelData[$key] : null;
111
        }
112
    }
113
114
    /**
115
     * Create a new instance of this Model
116
     * @return \ntentan\nibii\RecordWrapper
117
     */
118 34
    public static function createNew()
119
    {
120 34
        $class = get_called_class();
121 34
        return new $class();
122
    }
123
124
    /**
125
     * @method
126
     * @param type $name
127
     * @param type $arguments
128
     * @return type
129
     */
130 34
    public function __call($name, $arguments)
131
    {
132 34
        return Utils::factory($this->dynamicOperations,
133 34
            function() {
134 34
                return new Operations($this, $this->getDataAdapter());
135
            }
136 34
        )->perform($name, $arguments);
137
    }
138
139 26
    public static function __callStatic($name, $arguments)
140
    {
141 26
        return call_user_func_array([self::createNew(), $name], $arguments);
142
    }
143
144 8
    public function __set($name, $value)
145
    {
146 8
        $this->dataSet = true;
147 8
        $this->modelData[$name] = $value;
148 8
    }
149
150 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...
151
    {
152 12
        return $this->retrieveItem($name);
153
    }
154
155 32
    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...
156
    {
157 32
        return $this->table;
158
    }
159
    
160 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...
161 2
    {
162 4
        foreach($relationships as $name => $relationship) {
163 4
            $array[$name] = $this->fetchRelatedFields($relationship, $index)->toArray($depth);
164 4
        }
165 4
        return $array;
166
    }
167
168 16
    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...
169
    {
170 16
        $relationships = $this->getDescription()->getRelationships();
171 16
        $array = $this->modelData;
172 16
        if($depth > 0) {
173 4
            if($this->hasMultipleData()) {
174
                foreach($array as $i => $value) {
175
                    $array[$i] = $this->expandArrayValue($value, $relationships, $depth - 1, $i);
176
                }
177
            } else {
178 4
                $array = $this->expandArrayValue($array, $relationships, $depth - 1);
179
            }
180 4
        }
181 16
        return $array;
182
    }
183
    
184 10
    public function save()
185
    {
186 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...
187 10
        $this->invalidFields = $this->dynamicOperations->getInvalidFields();
188 10
        return $return;
189
    }
190
191 18
    private function hasMultipleData()
192
    {
193 18
        if(count($this->modelData) > 0) {
194 16
            return is_numeric(array_keys($this->modelData)[0]);
195
        } else {
196 2
            return false;
197
        }
198
    }
199
200 14
    public function getData()
201
    {
202 14
        $data = [];
203
                
204 14
        if(count($this->modelData) == 0) {
205 6
            $data = $this->modelData;
206 14
        } else if($this->hasMultipleData()) {
207 2
            $data = $this->modelData;
208 12
        } else if(count($this->modelData) > 0) {
209 12
            $data[] = $this->modelData;
210 12
        }
211
        
212 14
        return $data;
213
    }
214
215 26
    public function setData($data)
216
    {
217 26
        $this->dataSet = true;
218 26
        $this->modelData = $data;
219 26
    }
220
    
221
    public function mergeData($data)
222
    {
223
        foreach($data as $key => $value) {
224
            $this->modelData[$key] = $value;
225
        }
226
        $this->dataSet = true;
227
    }
228
229 2
    public function offsetExists($offset)
230
    {
231 2
        return isset($this->modelData[$offset]);
232
    }
233
234 2
    public function offsetGet($offset)
235
    {
236 2
        if (is_numeric($offset)) {
237 2
            return $this->wrap($offset);
238
        } else {
239 2
            return $this->retrieveItem($offset);
240
        }
241
    }
242
243 2
    public function offsetSet($offset, $value)
244
    {
245 2
        $this->dataSet = true;
246 2
        $this->modelData[$offset] = $value;
247 2
    }
248
249
    public function offsetUnset($offset)
250
    {
251
        unset($this->modelData[$offset]);
252
    }
253
254 6
    private function wrap($offset)
255
    {
256 6
        if(isset($this->modelData[$offset])) {
257 6
            $newInstance = $this->createNew();
258 6
            $newInstance->setData($this->modelData[$offset]);
259 6
            return $newInstance;
260
        } else {
261
            return null;
262
        }
263
    }
264
265 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...
266
    {
267 4
        return $this->invalidFields;
268
    }
269
270
    public function getHasMany()
271
    {
272
        return $this->hasMany;
273
    }
274
275
    public function getBelongsTo()
276
    {
277
        return $this->belongsTo;
278
    }
279
280 4
    public function current()
281
    {
282 4
        return $this->wrap($this->index);
283
    }
284
285
    public function key()
286
    {
287
        return $this->index;
288
    }
289
290 4
    public function next()
291
    {
292 4
        $this->index++;
293 4
    }
294
295 4
    public function rewind()
296
    {
297 4
        $this->index = 0;
298 4
    }
299
300 4
    public function valid()
301
    {
302 4
        return isset($this->modelData[$this->index]);
303
    }
304
305 12
    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...
306
    {
307 12
        if($index === null) {
308 12
            $data = $this->modelData;
309 12
        } else {
310
            $data = $this->modelData[$index];
311
        }
312 12
        $model = $relationship->getModelInstance();
313 12
        if(empty($data)) {
314
            return $model;
315
        } else {
316 12
            return $model->fetch($relationship->getQuery($data));
317
        }
318
    }
319
320 8
    public function getRelationships()
321
    {
322
        return [
323 8
            'HasMany' => $this->hasMany,
324 8
            'BelongsTo' => $this->belongsTo,
325 8
            'ManyHaveMany' => $this->manyHaveMany
326 8
        ];
327
    }
328
    
329
    public function usetField($field)
330
    {
331
        unset($this->modelData[$field]);
332
    }
333
    
334 8
    public function preSaveCallback()
335
    {
336
        
337 8
    }
338
    
339 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...
340
    {
341
        
342 4
    }
343
    
344 2
    public function preUpdateCallback()
345
    {
346
        
347 2
    }
348
    
349 2
    public function postUpdateCallback()
350
    {
351
        
352 2
    }
353
    
354 10
    public function getBehaviours()
355
    {
356 10
        return $this->loadedDependencies;
357
    }
358
}
359