This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Fwk |
||
4 | * |
||
5 | * Copyright (c) 2011-2012, Julien Ballestracci <[email protected]>. |
||
6 | * All rights reserved. |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | * |
||
11 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
12 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
13 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
14 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||
15 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||
17 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
18 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||
19 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
20 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||
21 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
22 | * POSSIBILITY OF SUCH DAMAGE. |
||
23 | * |
||
24 | * PHP Version 5.3 |
||
25 | * |
||
26 | * @category Database |
||
27 | * @package Fwk\Db |
||
28 | * @author Julien Ballestracci <[email protected]> |
||
29 | * @copyright 2011-2012 Julien Ballestracci <[email protected]> |
||
30 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
||
31 | * @link http://www.phpfwk.com |
||
32 | */ |
||
33 | namespace Fwk\Db; |
||
34 | |||
35 | use Fwk\Db\Registry\RegistryState; |
||
36 | use Fwk\Db\Relations\AbstractManyRelation; |
||
37 | use Fwk\Db\Relations\One2Many; |
||
38 | use Fwk\Db\Relations\One2One; |
||
39 | |||
40 | /** |
||
41 | * This class transforms a resultset from a query into a set of corresponding |
||
42 | * entities. |
||
43 | * |
||
44 | * @category Utilities |
||
45 | * @package Fwk\Db |
||
46 | * @author Julien Ballestracci <[email protected]> |
||
47 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
||
48 | * @link http://www.phpfwk.com |
||
49 | */ |
||
50 | class Hydrator |
||
51 | { |
||
52 | /** |
||
53 | * The query |
||
54 | * |
||
55 | * @var Query |
||
56 | */ |
||
57 | protected $query; |
||
58 | |||
59 | /** |
||
60 | * The Connection |
||
61 | * |
||
62 | * @var Connection |
||
63 | */ |
||
64 | protected $connection; |
||
65 | |||
66 | /** |
||
67 | * Columns description |
||
68 | * |
||
69 | * @var array |
||
70 | */ |
||
71 | protected $columns; |
||
72 | |||
73 | /** |
||
74 | * Parsing stack informations |
||
75 | * |
||
76 | * @var array |
||
77 | */ |
||
78 | protected $stack; |
||
79 | |||
80 | /** |
||
81 | * Entities that need to be marked as fresh in registry |
||
82 | * |
||
83 | * @var array |
||
84 | */ |
||
85 | protected $markAsFresh; |
||
86 | |||
87 | /** |
||
88 | * Constructor |
||
89 | * |
||
90 | * @param Query $query Executed query |
||
91 | * @param Connection $connection Database Connection |
||
92 | * @param array $columns Columns description |
||
93 | * |
||
94 | * @return void |
||
0 ignored issues
–
show
|
|||
95 | */ |
||
96 | public function __construct(Query $query, Connection $connection, array $columns) |
||
97 | { |
||
98 | $this->query = $query; |
||
99 | $this->columns = $columns; |
||
100 | $this->connection = $connection; |
||
101 | |||
102 | $joins = (array) $query['joins']; |
||
103 | $tables = array(); |
||
104 | $itx = 0; |
||
105 | |||
106 | foreach ($columns as $column => $infos) { |
||
107 | $itx++; |
||
108 | $table = $infos['table']; |
||
109 | |||
110 | if (isset($tables[$table])) { |
||
111 | $tables[$table]['columns'][$column] = $infos['column']; |
||
112 | continue; |
||
113 | } |
||
114 | |||
115 | $skipped = false; |
||
116 | $jointure = false; |
||
117 | $joinOpt = false; |
||
118 | |||
119 | foreach ($joins as $join) { |
||
120 | $jointure = false; |
||
121 | $skipped = false; |
||
122 | |||
123 | if (\strpos($join['table'], ' ') !== false) { |
||
124 | list($joinTable, $alias) = explode(' ', $join['table']); |
||
0 ignored issues
–
show
The assignment to
$alias is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
125 | } else { |
||
126 | $joinTable = $join['table']; |
||
127 | $alias = null; |
||
0 ignored issues
–
show
$alias is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
128 | } |
||
129 | |||
130 | if ($joinTable == $table) { |
||
131 | if ($join['options']['skipped'] == true) { |
||
132 | $skipped = true; |
||
133 | } |
||
134 | |||
135 | $jointure = true; |
||
136 | $joinOpt = $join; |
||
137 | break; |
||
138 | } |
||
139 | } |
||
140 | |||
141 | if ($skipped && $jointure) { |
||
142 | continue; |
||
143 | } |
||
144 | |||
145 | $tables[$table]['columns'] = array(); |
||
146 | if ($jointure) { |
||
147 | $tables[$table]['join'] = $joinOpt; |
||
148 | $tables[$table]['entity'] = $joinOpt['options']['entity']; |
||
149 | $tables[$table]['entityListeners'] |
||
150 | = $joinOpt['options']['entityListeners']; |
||
151 | } else { |
||
152 | $tables[$table]['entity'] |
||
153 | = ($itx == 1 ? $query['entity'] : $this->connection->table($table)->getDefaultEntity()); |
||
154 | $tables[$table]['entityListeners'] |
||
155 | = (count($query['entityListeners']) ? |
||
156 | $query['entityListeners'] : |
||
157 | $this->connection->table($table)->getDefaultEntityListeners() |
||
158 | ); |
||
159 | } |
||
160 | $tables[$table]['columns'][$column] = $infos['column']; |
||
161 | } |
||
162 | |||
163 | $this->stack = $tables; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Transform raw results from database into ORM-style entities |
||
168 | * |
||
169 | * @param array $results Raw PDO results |
||
170 | * |
||
171 | * @return array |
||
172 | */ |
||
173 | public function hydrate(array $results) |
||
174 | { |
||
175 | $final = array(); |
||
176 | $joinData = array(); |
||
177 | |||
178 | foreach ($results as $result) { |
||
179 | $mainObj = null; |
||
180 | $mainObjRefs = null; |
||
181 | $mainObjTable = null; |
||
182 | |||
183 | foreach ($this->stack as $tableName => $infos) { |
||
184 | $columns = $infos['columns']; |
||
185 | $isJoin = (isset($infos['join']) ? true : false); |
||
186 | $entityClass= $infos['entity']; |
||
187 | $ids = $this->getIdentifiers($tableName, $result); |
||
188 | $obj = $this->loadEntityClass( |
||
189 | $tableName, |
||
190 | $ids, |
||
191 | $entityClass, |
||
192 | $infos['entityListeners'] |
||
193 | ); |
||
194 | $access = new Accessor($obj); |
||
195 | $values = $this->getValuesFromSet($columns, $result); |
||
196 | $access->setValues($values); |
||
197 | $mainObjRefs = $ids; |
||
198 | |||
199 | foreach ($access->getRelations() as $relation) { |
||
200 | $relation->setConnection($this->connection); |
||
201 | $relation->setParentRefs($access->get($relation->getLocal())); |
||
0 ignored issues
–
show
The method
setParentRefs() does not exist on Fwk\Db\RelationInterface . Did you maybe mean setParent() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
202 | } |
||
203 | |||
204 | if (!$isJoin) { |
||
205 | $mainObj = $obj; |
||
206 | $mainObjTable = $tableName; |
||
207 | unset($access, $values, $isJoin, $columns); |
||
208 | if (!in_array($mainObj, $final, true)) { |
||
209 | array_push($final, $mainObj); |
||
210 | } |
||
211 | continue; |
||
212 | } |
||
213 | |||
214 | $idsHash = $tableName . implode(':', $ids); |
||
215 | $access = new Accessor($mainObj); |
||
216 | $columnName = $infos['join']['options']['column']; |
||
217 | |||
218 | $current = (isset($joinData[$idsHash . $columnName]) ? |
||
219 | $joinData[$idsHash . $columnName] : |
||
220 | $this->getRelationObject( |
||
221 | $mainObj, |
||
222 | $columnName, |
||
223 | $infos['join'], |
||
224 | $entityClass |
||
225 | ) |
||
226 | ); |
||
227 | |||
228 | $joinData[$idsHash . $columnName] = $current; |
||
229 | $current->add($obj, $ids); |
||
230 | $current->setFetched(true); |
||
231 | $current->setParentRefs($mainObjRefs); |
||
232 | |||
233 | $tableObj = $this->connection->table($mainObjTable); |
||
234 | $current->setParent( |
||
235 | $mainObj, |
||
236 | $tableObj->getRegistry()->getEventDispatcher($mainObj) |
||
237 | ); |
||
238 | |||
239 | $access->set($columnName, $current); |
||
240 | |||
241 | unset($access, $values, $isJoin, $columns, $current); |
||
242 | } |
||
243 | |||
244 | $access = new Accessor($mainObj); |
||
245 | $relations = $access->getRelations(); |
||
246 | foreach ($relations as $relation) { |
||
247 | $tableObj = $this->connection->table($mainObjTable); |
||
248 | $relation->setParent( |
||
249 | $mainObj, |
||
250 | $tableObj->getRegistry()->getEventDispatcher($mainObj) |
||
251 | ); |
||
252 | } |
||
253 | |||
254 | unset($mainObj, $mainObjRefs); |
||
255 | } |
||
256 | |||
257 | $this->markAsFresh(); |
||
258 | |||
259 | return $final; |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Return RelationInterface object of an entity |
||
264 | * |
||
265 | * @param mixed $object The entity |
||
266 | * @param string $columnName RelationInterface's column name |
||
267 | * @param array $join Join descriptor (array) |
||
268 | * @param string $entityClass RelationInterface's entity class name |
||
0 ignored issues
–
show
Should the type for parameter
$entityClass not be string|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
269 | * |
||
270 | * @return RelationInterface |
||
271 | */ |
||
272 | public function getRelationObject($object, $columnName, array $join, |
||
273 | $entityClass = null |
||
274 | ) { |
||
275 | $access = new Accessor($object); |
||
276 | $test = $access->get($columnName); |
||
277 | |||
278 | if (strpos($join['table'], ' ') !== false) { |
||
279 | list($table, ) = explode(' ', $join['table']); |
||
280 | } else { |
||
281 | $table = $join['table']; |
||
282 | } |
||
283 | |||
284 | if ($test instanceof \Fwk\Db\RelationInterface && $entityClass == $test->getEntity()) { |
||
285 | if ($test instanceof One2One) { |
||
286 | return $test; |
||
287 | } elseif ($test instanceof AbstractManyRelation && $join['options']['reference'] == $test->getReference()) { |
||
288 | return $test; |
||
289 | } |
||
290 | } |
||
291 | |||
292 | if (strpos($join['table'], ' ') !== false) { |
||
293 | list($table, ) = explode(' ', $join['table']); |
||
294 | } else { |
||
295 | $table = $join['table']; |
||
296 | } |
||
297 | |||
298 | $ref = new One2Many( |
||
299 | $join['local'], |
||
300 | $join['foreign'], |
||
301 | $table, |
||
302 | $entityClass, |
||
303 | $join['options']['entityListeners'] |
||
304 | ); |
||
305 | |||
306 | if (!empty($join['options']['reference'])) { |
||
307 | $ref->setReference($join['options']['reference']); |
||
308 | } |
||
309 | |||
310 | // $ref->setRegistry($this->connection->table($table)->getRegistry()); |
||
311 | $ref->setConnection($this->connection); |
||
312 | |||
313 | return $ref; |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * Transforms aliased results into results with real columns names |
||
318 | * |
||
319 | * @param array $columns Columns description |
||
320 | * @param array $resultSet Result set |
||
321 | * |
||
322 | * @return array |
||
323 | */ |
||
324 | public function getValuesFromSet(array $columns, array $resultSet) |
||
325 | { |
||
326 | $final = array(); |
||
327 | foreach ($columns as $alias => $realName) { |
||
328 | $final[$realName] = $resultSet[$alias]; |
||
329 | } |
||
330 | |||
331 | return $final; |
||
332 | } |
||
333 | |||
334 | /** |
||
335 | * Loads an entity |
||
336 | * |
||
337 | * @param string $tableName Table's name |
||
338 | * @param array $identifiers Entity identifiers |
||
339 | * @param string $entityClass Entity class name |
||
0 ignored issues
–
show
Should the type for parameter
$entityClass not be string|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
340 | * @param array $listeners Entity's listeners |
||
341 | * |
||
342 | * @return mixed |
||
0 ignored issues
–
show
|
|||
343 | */ |
||
344 | protected function loadEntityClass($tableName, array $identifiers, |
||
345 | $entityClass = null, array $listeners = array() |
||
346 | ) { |
||
347 | $tableObj = $this->connection->table($tableName); |
||
348 | $registry = $tableObj->getRegistry(); |
||
349 | |||
350 | if ($entityClass === null) { |
||
351 | $entityClass = $tableObj->getDefaultEntity(); |
||
352 | } |
||
353 | |||
354 | $obj = $registry->get($identifiers, $entityClass); |
||
355 | |||
356 | if (null === $obj) { |
||
357 | $obj = new $entityClass; |
||
358 | $registry->store( |
||
359 | $obj, $identifiers, RegistryState::FRESH, array( |
||
360 | 'listeners' => $listeners |
||
361 | ) |
||
362 | ); |
||
363 | $this->markAsFresh[] = array( |
||
364 | 'registry' => $registry, |
||
365 | 'entity' => $obj, |
||
366 | 'table' => $tableObj |
||
367 | ); |
||
368 | } |
||
369 | |||
370 | return $obj; |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Mark freshly built entities as fresh (aka "just fetched") |
||
375 | * |
||
376 | * @return void |
||
377 | */ |
||
378 | protected function markAsFresh() |
||
379 | { |
||
380 | if (!is_array($this->markAsFresh) || !count($this->markAsFresh)) { |
||
381 | return; |
||
382 | } |
||
383 | |||
384 | foreach ($this->markAsFresh as $infos) { |
||
385 | $infos['registry']->defineInitialValues( |
||
386 | $infos['entity'], |
||
387 | $this->connection, |
||
388 | $infos['table'] |
||
389 | ); |
||
390 | } |
||
391 | |||
392 | unset($this->markAsFresh); |
||
393 | } |
||
394 | |||
395 | /** |
||
396 | * Returns an array of identifiers for the given table |
||
397 | * |
||
398 | * @param string $tableName Table's name |
||
399 | * @param array $results Raw PDO results |
||
400 | * |
||
401 | * @return array |
||
402 | */ |
||
403 | protected function getIdentifiers($tableName, array $results) |
||
404 | { |
||
405 | $tableObj = $this->connection->table($tableName); |
||
406 | $tableIds = $tableObj->getIdentifiersKeys(); |
||
407 | |||
408 | if (!count($tableIds)) { |
||
409 | return array(); |
||
410 | } |
||
411 | |||
412 | $final = array(); |
||
413 | foreach ((array) $this->columns as $colName => $infos) { |
||
414 | if ($infos['table'] == $tableName |
||
415 | && in_array($infos['column'], $tableIds) |
||
416 | ) { |
||
417 | $final[$infos['column']] = $results[$colName]; |
||
418 | } |
||
419 | } |
||
420 | |||
421 | return $final; |
||
422 | } |
||
423 | } |
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.