Completed
Push — master ( 20edd5...7d7f4e )
by smiley
02:32
created

DBResult::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Class DBResult
4
 *
5
 * @filesource   DBResult.php
6
 * @created      23.05.2017
7
 * @package      chillerlan\Database
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database;
14
15
use ArrayAccess, Countable, Iterator;
16
use chillerlan\Database\Traits\{Enumerable, Magic};
17
18
/**
19
 * @property int $length
20
 *
21
 * each($func [, $fieldname)
22
 */
23
class DBResult implements Iterator, ArrayAccess, Countable{
24
	use Enumerable, Magic;
25
26
	/**
27
	 * @var \chillerlan\Database\DBResultRow[]
28
	 */
29
	protected $array = [];
30
31
	/**
32
	 * @var int
33
	 */
34
	protected $offset = 0;
35
	protected $sourceEncoding;
36
	protected $destEncoding;
37
38
	/**
39
	 * DBResult constructor.
40
	 *
41
	 * @param \Traversable|\stdClass|array|null $data
42
	 * @param string|null                       $sourceEncoding
43
	 * @param string                            $destEncoding
44
	 *
45
	 * @throws \chillerlan\Database\DBException
46
	 */
47
	public function __construct($data = null, $sourceEncoding = null, $destEncoding = 'UTF-8'){
48
		$this->sourceEncoding = $sourceEncoding;
49
		$this->destEncoding   = $destEncoding;
50
51
		if(is_null($data)){
52
			$data = [];
53
		}
54
		else if($data instanceof \Traversable){
55
			$data = iterator_to_array($data);
56
		}
57
		else if(!$data instanceof \stdClass && !is_array($data)){
58
			throw new DBException('invalid data');
59
		}
60
61
		foreach($data as $k => $v){
0 ignored issues
show
Bug introduced by
The expression $data of type object<stdClass>|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
62
			$this->offsetSet($k, $v);
63
		}
64
65
		$this->offset = 0;
66
	}
67
68
	/**
69
	 * @param \chillerlan\Database\DBResult $DBResult
70
	 *
71
	 * @return \chillerlan\Database\DBResult
72
	 */
73
	public function __merge(DBResult $DBResult){
74
		$arr = [];
75
76
		foreach($DBResult as $row){
77
			$arr[] = $row;
78
		}
79
80
		$this->array = array_merge($this->array, $arr);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->array, $arr) of type array is incompatible with the declared type array<integer,object<chi...\Database\DBResultRow>> of property $array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
81
82
		return $this;
83
	}
84
85
	/**
86
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/toArray/
87
	 *
88
	 * @return array
89
	 */
90
	public function __toArray():array {
91
		$arr = [];
92
93
		foreach($this->array as $item){
94
			$arr[] = $item->__toArray();
95
		}
96
97
		return $arr;
98
	}
99
100
101
	/*********
102
	 * magic *
103
	 *********/
104
105
	/**
106
	 * @return int
107
	 */
108
	protected function magic_get_length():int{
109
		return $this->count();
110
	}
111
112
113
	/***************
114
	 * ArrayAccess *
115
	 ***************/
116
117
	/**
118
	 * @param int|string $offset
119
	 *
120
	 * @return bool
121
	 */
122
	public function offsetExists($offset):bool{
123
		return isset($this->array[$offset]);
124
	}
125
126
	/**
127
	 * @param int|string $offset
128
	 *
129
	 * @return \chillerlan\Database\DBResultRow|mixed|null
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use DBResultRow|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
130
	 */
131
	public function offsetGet($offset){
132
		return $this->array[$offset] ?? null;
133
	}
134
135
	/**
136
	 * @param int|string   $offset
137
	 * @param array        $value
138
	 *
139
	 * @return void
140
	 */
141
	public function offsetSet($offset, $value){
142
143
		if(is_null($offset)){
144
			$this->array[] = new DBResultRow($value, $this->sourceEncoding, $this->destEncoding);
145
		}
146
		else{
147
			$this->array[$offset] = new DBResultRow($value, $this->sourceEncoding, $this->destEncoding);
148
		}
149
150
	}
151
152
	/**
153
	 * @param int|string $offset
154
	 *
155
	 * @return void
156
	 */
157
	public function offsetUnset($offset){
158
		unset($this->array[$offset]);
159
	}
160
161
162
	/*************
163
	 * Countable *
164
	 *************/
165
166
	/**
167
	 * @return int
168
	 */
169
	public function count():int{
170
		return count($this->array);
171
	}
172
173
174
	/************
175
	 * Iterator *
176
	 ************/
177
178
	/**
179
	 * @return \chillerlan\Database\DBResultRow|mixed
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use DBResultRow|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
180
	 */
181
	public function current(){
182
		return $this->offsetGet($this->offset);
183
	}
184
185
	/**
186
	 * @return int
187
	 */
188
	public function key():int{
189
		return $this->offset;
190
	}
191
192
	/**
193
	 * @return bool
194
	 */
195
	public function valid():bool{
196
		return $this->offsetExists($this->offset);
197
	}
198
199
	/**
200
	 *  @return void
201
	 */
202
	public function next(){
203
		$this->offset++;
204
	}
205
206
	/**
207
	 * @return void
208
	 */
209
	public function rewind(){
210
		$this->offset = 0;
211
	}
212
213
}
214