1
|
|
|
<?php defined('SYSPATH') OR die('No direct script access.'); |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* A collection of jam models from the database. |
5
|
|
|
* |
6
|
|
|
* @package Jam |
7
|
|
|
* @category Associations |
8
|
|
|
* @author Ivan Kerin |
9
|
|
|
* @copyright (c) 2011-2012 Despark Ltd. |
10
|
|
|
* @license http://www.opensource.org/licenses/isc-license.txt |
11
|
|
|
*/ |
12
|
|
|
abstract class Kohana_Jam_Query_Builder_Collection extends Jam_Query_Builder_Select implements Countable, ArrayAccess, Iterator, Serializable { |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Create object of class Jam_Query_Builder_Collection |
16
|
|
|
* @param string $model |
17
|
|
|
* @return Jam_Query_Builder_Collection |
18
|
|
|
*/ |
19
|
|
|
public static function factory($model) |
20
|
|
|
{ |
21
|
|
|
return new Jam_Query_Builder_Collection($model); |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The result of this colleciton |
26
|
|
|
* @var Database_Result |
27
|
|
|
*/ |
28
|
|
|
protected $_result; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Result Setter / Getter |
32
|
|
|
* @param Database_Result $result |
33
|
|
|
* @return Database_Result|Jam_Query_Builder_Collection |
34
|
|
|
*/ |
35
|
81 |
|
public function result(Database_Result $result = NULL) |
36
|
|
|
{ |
37
|
81 |
|
if ($result !== NULL) |
38
|
|
|
{ |
39
|
|
|
$this->_result = $result; |
40
|
|
|
} |
41
|
|
|
|
42
|
81 |
|
if ( ! $this->_result) |
43
|
|
|
{ |
44
|
48 |
|
$this->_result = $this->execute(); |
45
|
|
|
} |
46
|
|
|
|
47
|
81 |
|
return $this->_result; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Load the info for the collection result, as if was loaded from the database |
52
|
|
|
* @param array $fields |
53
|
|
|
* @return Jam_Query_Builder_Collection |
54
|
|
|
*/ |
55
|
39 |
|
public function load_fields(array $fields) |
56
|
|
|
{ |
57
|
39 |
|
$this->_result = new Database_Result_Cached($fields, '', FALSE); |
58
|
39 |
|
return $this; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Use the Jam::build_template() to return the model for the row in the results |
63
|
|
|
* @param array $value |
64
|
|
|
* @return Jam_Model |
65
|
|
|
*/ |
66
|
57 |
|
protected function _load_model($value) |
67
|
|
|
{ |
68
|
57 |
|
if ( ! $value) |
|
|
|
|
69
|
15 |
|
return NULL; |
70
|
|
|
|
71
|
|
|
|
72
|
46 |
|
$model = clone Jam::build_template($this->meta()->model(), $value); |
73
|
46 |
|
$model = $model->load_fields($value); |
74
|
|
|
|
75
|
46 |
|
return $model; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Return all of the models in the result as an array. |
80
|
|
|
* |
81
|
|
|
* // Indexed array of all models |
82
|
|
|
* $rows = $result->as_array(); |
83
|
|
|
* |
84
|
|
|
* // Associative array of models by "id" |
85
|
|
|
* $rows = $result->as_array('id'); |
86
|
|
|
* |
87
|
|
|
* // Associative array of fields, "id" => "name" |
88
|
|
|
* $rows = $result->as_array('id', 'name'); |
89
|
|
|
* |
90
|
|
|
* @param string column for associative keys |
91
|
|
|
* @param string column for values |
92
|
|
|
* @return array |
93
|
|
|
*/ |
94
|
11 |
|
public function as_array($key = NULL, $value = NULL) |
95
|
|
|
{ |
96
|
11 |
|
$key = Jam_Query_Builder::resolve_meta_attribute($key, $this->meta()); |
97
|
11 |
|
if ($value === NULL) |
98
|
|
|
{ |
99
|
5 |
|
return array_map(array($this, '_load_model'), $this->result()->as_array($key)); |
|
|
|
|
100
|
|
|
} |
101
|
|
|
else |
102
|
|
|
{ |
103
|
7 |
|
$value = Jam_Query_Builder::resolve_meta_attribute($value, $this->meta()); |
104
|
7 |
|
return $this->result()->as_array($key, $value); |
|
|
|
|
105
|
|
|
} |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Get the ids of the models in an array |
110
|
|
|
* @return array |
111
|
|
|
*/ |
112
|
3 |
|
public function ids() |
113
|
|
|
{ |
114
|
3 |
|
return $this->as_array(NULL, ':primary_key'); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Return the first model |
119
|
|
|
* @return Jam_Model|null |
120
|
|
|
*/ |
121
|
42 |
|
public function first() |
122
|
|
|
{ |
123
|
42 |
|
return $this->_load_model($this->limit(1)->result()->rewind()->current()); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Return the first model, throw Jam_Exception_Notfound if there was no result |
128
|
|
|
* @return Jam_Model |
129
|
|
|
* @throws Jam_Exception_Notfound |
130
|
|
|
*/ |
131
|
|
|
public function first_insist() |
132
|
|
|
{ |
133
|
|
|
$result = $this->first(); |
134
|
|
|
if ( ! $result) |
135
|
|
|
throw new Jam_Exception_Notfound(":model not found", $this->meta()->model()); |
136
|
|
|
|
137
|
|
|
return $result; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Find out the primary_key of an item of the $_content |
142
|
|
|
* @param mixed $value |
143
|
|
|
* @return int |
144
|
|
|
*/ |
145
|
|
|
protected function _id($value) |
146
|
|
|
{ |
147
|
|
|
if ($value instanceof Jam_Model) |
148
|
|
|
return $value->id(); |
149
|
|
|
|
150
|
|
|
if (is_numeric($value)) |
151
|
|
|
return (int) $value; |
152
|
|
|
|
153
|
|
|
if (is_array($value) AND isset($value[$this->meta()->primary_key()])) |
154
|
|
|
return (int) $value[$this->meta()->primary_key()]; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
public function search($item) |
158
|
|
|
{ |
159
|
|
|
$search_id = $this->_id($item); |
160
|
|
|
|
161
|
|
|
if ( ! $search_id) |
162
|
|
|
return NULL; |
163
|
|
|
|
164
|
|
|
foreach ($this as $offset => $current) |
165
|
|
|
{ |
166
|
|
|
if ($this->_id($current) === $search_id) |
167
|
|
|
{ |
168
|
|
|
return (int) $offset; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
return NULL; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
public function has($item) |
176
|
|
|
{ |
177
|
|
|
return $this->search($item) !== NULL; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Implement Countable |
182
|
|
|
* @return int |
183
|
|
|
*/ |
184
|
10 |
|
public function count() |
185
|
|
|
{ |
186
|
10 |
|
return $this->result()->count(); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Implement ArrayAccess |
191
|
|
|
* |
192
|
|
|
* @param int $offset |
193
|
|
|
* @return Jam_Model |
194
|
|
|
*/ |
195
|
10 |
|
public function offsetGet($offset) |
196
|
|
|
{ |
197
|
10 |
|
$value = $this->result()->offsetGet($offset); |
198
|
10 |
|
if ( ! $value) |
199
|
1 |
|
return NULL; |
200
|
|
|
|
201
|
10 |
|
return $this->_load_model($value); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Implement ArrayAccess |
206
|
|
|
* |
207
|
|
|
* @param int $offset |
208
|
|
|
* @return boolean |
209
|
|
|
*/ |
210
|
1 |
|
public function offsetExists($offset) |
211
|
|
|
{ |
212
|
1 |
|
return $this->result()->offsetExists($offset); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Implement ArrayAccess |
217
|
|
|
*/ |
218
|
1 |
|
public function offsetSet($offset, $value) |
219
|
|
|
{ |
220
|
1 |
|
throw new Kohana_Exception('Database results are read-only'); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Implement ArrayAccess |
225
|
|
|
*/ |
226
|
1 |
|
public function offsetUnset($offset) |
227
|
|
|
{ |
228
|
1 |
|
throw new Kohana_Exception('Database results are read-only'); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Implement Iterator |
233
|
|
|
*/ |
234
|
7 |
|
public function rewind() |
235
|
|
|
{ |
236
|
7 |
|
$this->result()->rewind(); |
237
|
7 |
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Implement Iterator |
241
|
|
|
* @return Jam_Model |
242
|
|
|
*/ |
243
|
10 |
|
public function current() |
244
|
|
|
{ |
245
|
10 |
|
$value = $this->result()->current(); |
246
|
10 |
|
if ( ! $value) |
247
|
2 |
|
return NULL; |
248
|
|
|
|
249
|
8 |
|
return $this->_load_model($value); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Implement Iterator |
254
|
|
|
* @return int |
255
|
|
|
*/ |
256
|
2 |
|
public function key() |
257
|
|
|
{ |
258
|
2 |
|
return $this->result()->key(); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Implement Iterator |
263
|
|
|
*/ |
264
|
7 |
|
public function next() |
265
|
|
|
{ |
266
|
7 |
|
$this->result()->next(); |
267
|
7 |
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Implement Iterator |
271
|
|
|
* @return bool |
272
|
|
|
*/ |
273
|
7 |
|
public function valid() |
274
|
|
|
{ |
275
|
7 |
|
return $this->result()->valid(); |
276
|
|
|
} |
277
|
|
|
|
278
|
1 |
|
public function serialize() |
279
|
|
|
{ |
280
|
1 |
|
return serialize(array('fields' => $this->result()->as_array(), 'meta' => $this->meta()->model())); |
281
|
|
|
} |
282
|
|
|
|
283
|
1 |
|
public function unserialize($data) |
284
|
|
|
{ |
285
|
1 |
|
$data = unserialize($data); |
286
|
1 |
|
$this->_meta = Jam::meta($data['meta']); |
287
|
1 |
|
$this->load_fields($data['fields']); |
288
|
1 |
|
} |
289
|
|
|
} |
290
|
|
|
|
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.