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 | namespace JamesMoss\Flywheel; |
||
4 | |||
5 | /** |
||
6 | * Query |
||
7 | * |
||
8 | * Builds an executes a query whichs searches and sorts documents from a |
||
9 | * repository. |
||
10 | */ |
||
11 | class QueryExecuter |
||
12 | { |
||
13 | protected $repo; |
||
14 | protected $predicate; |
||
15 | protected $limit; |
||
16 | protected $orderBy; |
||
17 | |||
18 | /** |
||
19 | * Constructor |
||
20 | * |
||
21 | * @param Repository $repo The repo to execute against |
||
22 | * @param Predicate $pred The predicate to use. |
||
23 | * @param array $limit The count and offset. |
||
24 | * @param array $orderBy An array of field names to order by |
||
25 | */ |
||
26 | 13 | public function __construct(Repository $repo, Predicate $pred, array $limit, array $orderBy) |
|
27 | { |
||
28 | 13 | $this->repo = $repo; |
|
29 | 13 | $this->predicate = $pred; |
|
30 | 13 | $this->limit = $limit; |
|
31 | 13 | $this->orderBy = $orderBy; |
|
32 | 13 | } |
|
33 | |||
34 | /** |
||
35 | * Runs the query. |
||
36 | * |
||
37 | * @return Result The documents returned from this query. |
||
38 | */ |
||
39 | 13 | public function run() |
|
40 | { |
||
41 | 13 | $documents = $this->repo->findAll(); |
|
42 | |||
43 | 13 | if ($predicates = $this->predicate->getAll()) { |
|
44 | 10 | $documents = $this->filter($documents, $predicates); |
|
45 | 10 | } |
|
46 | |||
47 | 13 | if ($this->orderBy) { |
|
0 ignored issues
–
show
|
|||
48 | 4 | $sorts = array(); |
|
49 | 4 | foreach ($this->orderBy as $order) { |
|
50 | 4 | $parts = explode(' ', $order, 2); |
|
51 | // TODO - validate parts |
||
52 | 4 | $sorts[] = array( |
|
53 | 4 | $parts[0], |
|
54 | 4 | isset($parts[1]) && $parts[1] == 'DESC' ? SORT_DESC : SORT_ASC |
|
55 | 4 | ); |
|
56 | 4 | } |
|
57 | |||
58 | 4 | $documents = $this->sort($documents, $sorts); |
|
59 | 4 | } |
|
60 | |||
61 | 13 | $totalCount = count($documents); |
|
62 | |||
63 | 13 | if ($this->limit) { |
|
0 ignored issues
–
show
The expression
$this->limit of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
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 ![]() |
|||
64 | list($count, $offset) = $this->limit; |
||
65 | $documents = array_slice($documents, $offset, $count); |
||
66 | } |
||
67 | |||
68 | 13 | return new Result(array_values($documents), $totalCount); |
|
69 | } |
||
70 | |||
71 | 11 | public function getFieldValue($doc, $field, &$found = false) |
|
72 | { |
||
73 | 11 | $found = false; |
|
74 | |||
75 | 11 | if ($field === '__id') { |
|
76 | 1 | $found = true; |
|
77 | |||
78 | 1 | return $doc->getId(); |
|
79 | } |
||
80 | |||
81 | 10 | if (false !== strpos($field, '.')) { |
|
82 | 5 | return $doc->getNestedProperty($field, $found); |
|
83 | } |
||
84 | |||
85 | 7 | if (!property_exists($doc, $field)) { |
|
86 | 1 | return false; |
|
87 | } |
||
88 | |||
89 | 6 | $found = true; |
|
90 | |||
91 | 6 | return $doc->{$field}; |
|
92 | } |
||
93 | |||
94 | 10 | public function matchDocument($doc, $field, $operator, $value) |
|
95 | { |
||
96 | 10 | $docVal = $this->getFieldValue($doc, $field, $found); |
|
97 | |||
98 | 10 | if (!$found) { |
|
99 | 3 | return false; |
|
100 | } |
||
101 | |||
102 | 9 | switch (true) { |
|
103 | 9 | case ($operator === '==' && $docVal == $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
104 | 9 | case ($operator === '===' && $docVal === $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
105 | 9 | case ($operator === '!=' && $docVal != $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
106 | 9 | case ($operator === '!==' && $docVal !== $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
107 | 9 | case ($operator === '>' && $docVal > $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
108 | 9 | case ($operator === '>=' && $docVal >= $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
109 | 9 | case ($operator === '<' && $docVal < $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
110 | 9 | case ($operator === '>=' && $docVal >= $value): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
111 | 9 | case ($operator === 'IN' && in_array($docVal, (array)$value)): return true; |
|
0 ignored issues
–
show
The case body in a switch statement must start on the line following the statement.
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement. switch ($expr) {
case "A":
doSomething(); //right
break;
case "B":
doSomethingElse(); //wrong
break;
} To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() Terminating statement must be on a line by itself
As per the PSR-2 coding standard, the switch ($expr) {
case "A":
doSomething();
break; //wrong
case "B":
doSomething();
break; //right
case "C:":
doSomething();
return true; //right
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig. ![]() |
|||
112 | } |
||
113 | |||
114 | 9 | return false; |
|
115 | } |
||
116 | |||
117 | 10 | protected function filter($documents, $predicates) |
|
118 | { |
||
119 | 10 | $result = array(); |
|
120 | 10 | $originalDocs = $documents; |
|
121 | |||
122 | 10 | $andPredicates = array_filter($predicates, function($pred) { |
|
123 | 10 | return $pred[0] !== Predicate::LOGICAL_OR; |
|
124 | 10 | }); |
|
125 | |||
126 | 10 | $orPredicates = array_filter($predicates, function($pred) { |
|
127 | 10 | return $pred[0] === Predicate::LOGICAL_OR; |
|
128 | 10 | }); |
|
129 | |||
130 | // 5.3 hack for accessing $this inside closure. |
||
131 | 10 | $self = $this; |
|
132 | |||
133 | 10 | foreach($andPredicates as $predicate) { |
|
134 | 10 | if (is_array($predicate[1])) { |
|
135 | 1 | $documents = $this->filter($documents, $predicate[1]); |
|
136 | 1 | } else { |
|
137 | 10 | list($type, $field, $operator, $value) = $predicate; |
|
0 ignored issues
–
show
The assignment to
$type 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();
![]() |
|||
138 | |||
139 | |||
140 | $documents = array_values(array_filter($documents, function ($doc) use ($self, $field, $operator, $value) { |
||
141 | 10 | return $self->matchDocument($doc, $field, $operator, $value); |
|
142 | 10 | })); |
|
143 | } |
||
144 | |||
145 | 10 | $result = $documents; |
|
146 | 10 | } |
|
147 | |||
148 | 10 | foreach($orPredicates as $predicate) { |
|
149 | 2 | if (is_array($predicate[1])) { |
|
150 | $documents = $this->filter($originalDocs, $predicate[1]); |
||
151 | } else { |
||
152 | 2 | list($type, $field, $operator, $value) = $predicate; |
|
0 ignored issues
–
show
The assignment to
$type 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();
![]() |
|||
153 | |||
154 | $documents = array_values(array_filter($originalDocs, function ($doc) use ($self, $field, $operator, $value) { |
||
155 | 2 | return $self->matchDocument($doc, $field, $operator, $value); |
|
156 | 2 | })); |
|
157 | } |
||
158 | |||
159 | 2 | $result = array_unique(array_merge($result, $documents), SORT_REGULAR); |
|
160 | 10 | } |
|
161 | |||
162 | 10 | return $result; |
|
163 | } |
||
164 | |||
165 | /** |
||
166 | * Sorts an array of documents by multiple fields if needed. |
||
167 | * |
||
168 | * @param array $array An array of Documents. |
||
169 | * @param array $args The fields to sort by. |
||
170 | * |
||
171 | * @return array The sorted array of documents. |
||
172 | */ |
||
173 | 4 | protected function sort(array $array, array $args) |
|
174 | { |
||
175 | 4 | $c = count($args); |
|
176 | |||
177 | // PHP 5.3 hack |
||
178 | 4 | $self = $this; |
|
179 | |||
180 | usort($array, function ($a, $b) use ($self, $args, $c) { |
||
181 | 4 | $i = 0; |
|
182 | 4 | $cmp = 0; |
|
183 | 4 | while ($cmp == 0 && $i < $c) { |
|
184 | 4 | $keyName = $args[$i][0]; |
|
185 | 4 | if($keyName == 'id' || $keyName == '__id') { |
|
186 | 1 | $valueA = $a->getId(); |
|
187 | 1 | $valueB = $b->getId(); |
|
188 | 1 | } else { |
|
189 | 3 | $valueA = $self->getFieldValue($a, $keyName, $found); |
|
190 | 3 | if ($found === false) { |
|
191 | $valueA = null; |
||
192 | } |
||
193 | 3 | $valueB = $self->getFieldValue($b, $keyName, $found); |
|
194 | 3 | if ($found === false) { |
|
195 | $valueB = null; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | 4 | if (is_string($valueA)) { |
|
200 | 3 | $cmp = strcmp($valueA, $valueB); |
|
201 | 4 | } elseif (is_bool($valueA)) { |
|
202 | $cmp = $valueA - $valueB; |
||
203 | } else { |
||
204 | 1 | $cmp = ($valueA == $valueB) ? 0 : (($valueA < $valueB) ? -1 : 1); |
|
205 | } |
||
206 | |||
207 | 4 | if ($args[$i][1] === SORT_DESC) { |
|
208 | 4 | $cmp *= -1; |
|
209 | 4 | } |
|
210 | 4 | $i++; |
|
211 | 4 | } |
|
212 | |||
213 | 4 | return $cmp; |
|
214 | 4 | }); |
|
215 | |||
216 | 4 | return $array; |
|
217 | } |
||
218 | } |
||
219 |
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.