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 | namespace Bedd\Doctrine\Dbal; |
||
3 | |||
4 | use \Doctrine\DBAL\Schema; |
||
5 | use \Doctrine\DBAL\Query\QueryBuilder; |
||
6 | |||
7 | /** |
||
8 | * Model |
||
9 | */ |
||
10 | class Model |
||
11 | { |
||
12 | /** |
||
13 | * The DBAL connection |
||
14 | * |
||
15 | * @var \Doctrine\DBAL\Connection |
||
16 | */ |
||
17 | protected $conn = null; |
||
18 | |||
19 | /** |
||
20 | * Shortcut for the return of getSchemaManager() |
||
21 | * |
||
22 | * @var \Doctrine\DBAL\Schema\AbstractSchemaManager |
||
23 | */ |
||
24 | protected $sm = null; |
||
25 | |||
26 | /** |
||
27 | * Table-Name |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $table_name = ''; |
||
32 | |||
33 | /** |
||
34 | * Quoted Table-Name |
||
35 | * |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $quoted_table_name = ''; |
||
39 | |||
40 | /** |
||
41 | * Array with the Columns |
||
42 | * |
||
43 | * @var \Doctrine\DBAL\Schema\Column[] |
||
44 | */ |
||
45 | protected $columns = []; |
||
46 | |||
47 | /** |
||
48 | * Shortcut with Column-Types |
||
49 | * |
||
50 | * @var array |
||
51 | */ |
||
52 | protected $column_types = []; |
||
53 | |||
54 | /** |
||
55 | * Caching variable if the table has an auto increment column |
||
56 | * |
||
57 | * @var bool |
||
58 | */ |
||
59 | protected $has_autoincrement = null; |
||
60 | |||
61 | /** |
||
62 | * Original return type for the read-method |
||
63 | * |
||
64 | * @var string |
||
65 | */ |
||
66 | const READ_RETURN_ORIGINAL = 'original'; |
||
67 | |||
68 | /** |
||
69 | * Simple return type for the read-method |
||
70 | * |
||
71 | * @var string |
||
72 | */ |
||
73 | const READ_RETURN_SIMPLE = 'simple'; |
||
74 | |||
75 | /** |
||
76 | * Complex return type for the read-method |
||
77 | * |
||
78 | * @var string |
||
79 | */ |
||
80 | const READ_RETURN_COMPLEX = 'complex'; |
||
81 | |||
82 | /** |
||
83 | * constructor |
||
84 | * |
||
85 | * @param string $table_name |
||
86 | * @param Connection $conn |
||
87 | */ |
||
88 | public function __construct($table_name, \Doctrine\DBAL\Connection $conn) |
||
89 | { |
||
90 | $this->conn = $conn; |
||
91 | $this->table_name = $table_name; |
||
92 | $this->quoted_table_name = $this->conn->quoteIdentifier($this->table_name); |
||
93 | $this->sm = $this->conn->getSchemaManager(); |
||
94 | if (!$this->sm->tablesExist([$table_name])) { |
||
95 | throw Schema\SchemaException::tableDoesNotExist($table_name); |
||
96 | } |
||
97 | foreach ($this->sm->listTableColumns($this->table_name) as $colum) { |
||
98 | $this->columns[$colum->getName()] = $colum; |
||
99 | $this->column_types[$colum->getName()] = $colum->getType()->getName(); |
||
100 | } |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Tells of the table has an auto increment column |
||
105 | * |
||
106 | * @return boolean |
||
107 | */ |
||
108 | public function hasAutoIncrement() |
||
109 | { |
||
110 | if ($this->has_autoincrement === null) { |
||
111 | $this->has_autoincrement = false; |
||
112 | foreach ($this->columns as $column) { |
||
113 | if ($column->getAutoincrement()) { |
||
114 | $this->has_autoincrement = true; |
||
115 | break; |
||
116 | } |
||
117 | } |
||
118 | } |
||
119 | return $this->has_autoincrement; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Returns the Column with $column_name |
||
124 | * |
||
125 | * @param string $column_name |
||
126 | * |
||
127 | * @return \Doctrine\DBAL\Schema\Column or null if the Column doesn't exist |
||
128 | */ |
||
129 | protected function getColumn($column_name) |
||
130 | { |
||
131 | return isset($this->columns[$column_name]) ? $this->columns[$column_name] : null; |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Creates a new datarow |
||
136 | * |
||
137 | * @param array $data |
||
138 | * |
||
139 | * @return boolean|string false on error, true on success or an string with the last insert id if the table has an auto increment column |
||
140 | */ |
||
141 | public function create(array $data) |
||
142 | { |
||
143 | $return = false; |
||
0 ignored issues
–
show
|
|||
144 | $qb = $this->conn->createQueryBuilder()->insert($this->quoted_table_name); |
||
145 | View Code Duplication | foreach ($data as $column => $value) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
146 | if ($this->getColumn($column) === null) { |
||
147 | throw Schema\SchemaException::columnDoesNotExist($column, $this->table_name); |
||
148 | } |
||
149 | $qb->setValue($this->conn->quoteIdentifier($column), $qb->createNamedParameter($value)); |
||
150 | } |
||
151 | $return = (bool) $qb->execute(); |
||
152 | if ($this->hasAutoIncrement()) { |
||
153 | $return = $this->conn->lastInsertId(); |
||
154 | } |
||
155 | return $return; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * read $columns from $table_name |
||
160 | * |
||
161 | * @param array $columns |
||
162 | * @param array $filters |
||
163 | * @param array $limit |
||
164 | * @param array $order_by |
||
165 | * @param string $return_type |
||
166 | * |
||
167 | * @return array |
||
168 | */ |
||
169 | public function read(array $columns = [], array $filters = [], array $limit = [], array $order_by = [], $return_type = self::READ_RETURN_COMPLEX) |
||
170 | { |
||
171 | $return = []; |
||
0 ignored issues
–
show
$return 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 ![]() |
|||
172 | $alias_mapping = []; |
||
173 | $qb = $this->conn->createQueryBuilder(); |
||
174 | if (empty($columns)) { |
||
175 | $columns = $this->getColumnNames(); |
||
176 | } |
||
177 | foreach ($columns as $column) { |
||
178 | $column_name = null; |
||
179 | $alias = null; |
||
180 | $expr = []; |
||
181 | if (is_string($column)) { |
||
182 | $column_name = $alias = $column; |
||
183 | View Code Duplication | if (strpos($alias, ':') !== false) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
184 | $alias = explode(':', $alias); |
||
185 | $alias = array_pop($alias); |
||
186 | } |
||
187 | } elseif (is_array($column)) { |
||
188 | list($column_name, $alias) = $column; |
||
189 | } |
||
190 | View Code Duplication | if (strpos($column_name, ':') !== false) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
191 | $expr = explode(':', $column_name); |
||
192 | $column_name = array_pop($expr); |
||
193 | } |
||
194 | $alias_mapping[$alias] = $column_name; |
||
195 | if ($this->getColumn($column_name) === null) { |
||
196 | throw Schema\SchemaException::columnDoesNotExist($column_name, $this->table_name); |
||
197 | } |
||
198 | $column_expr = $this->conn->quoteIdentifier($column_name); |
||
199 | $expr = array_reverse($expr); |
||
200 | foreach ($expr as $ex) { |
||
201 | if (in_array($ex, ['max', 'min', 'avg', 'count', 'sum', 'lower', 'upper'])) { |
||
202 | $column_expr = call_user_func([$this->conn->getDatabasePlatform(), 'get'.ucfirst($ex).'Expression'], $column_expr); |
||
203 | } else { |
||
204 | throw QueryBuilderException::expressionTypeDoesNotExist($ex); |
||
205 | } |
||
206 | } |
||
207 | if ($column_name !== $alias || !empty($expr)) { |
||
208 | $column_expr .= ' AS '.$this->conn->quoteIdentifier($alias); |
||
209 | } |
||
210 | $qb->addSelect($column_expr); |
||
211 | } |
||
212 | $qb->from($this->quoted_table_name); |
||
213 | $this |
||
214 | ->buildWhere($qb, $filters) |
||
215 | ->buildOrderBy($qb, $order_by) |
||
216 | ->buildLimit($qb, $limit) |
||
217 | ; |
||
218 | $res = $qb->execute(); |
||
219 | $return = $res->fetchAll(\PDO::FETCH_ASSOC); |
||
220 | if (in_array($return_type, [self::READ_RETURN_SIMPLE, self::READ_RETURN_COMPLEX])) { |
||
221 | foreach ($return as $index => $row) { |
||
222 | foreach ($row as $column => $value) { |
||
223 | if ($return_type === self::READ_RETURN_SIMPLE && !$this->isSimpleType($alias_mapping[$column])) { |
||
224 | continue; |
||
225 | } |
||
226 | $return[$index][$column] = $this->conn->convertToPHPValue($value, $this->column_types[$alias_mapping[$column]]); |
||
227 | } |
||
228 | } |
||
229 | } |
||
230 | return $return; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Update table rows |
||
235 | * |
||
236 | * @param array $data |
||
237 | * @param array $filters |
||
238 | * |
||
239 | * @return integer The number of rows |
||
240 | */ |
||
241 | public function update(array $data, array $filters = []) |
||
242 | { |
||
243 | $qb = $this->conn->createQueryBuilder()->update($this->quoted_table_name); |
||
244 | View Code Duplication | foreach ($data as $column => $value) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
245 | if ($this->getColumn($column) === null) { |
||
246 | throw Schema\SchemaException::columnDoesNotExist($column, $this->table_name); |
||
247 | } |
||
248 | $qb->set($this->conn->quoteIdentifier($column), $qb->createNamedParameter($value)); |
||
249 | } |
||
250 | $this->buildWhere($qb, $filters); |
||
251 | return $qb->execute(); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Delete rows |
||
256 | * |
||
257 | * @param array $filters |
||
258 | * |
||
259 | * @return integer The number of rows |
||
260 | */ |
||
261 | public function delete(array $filters = []) |
||
262 | { |
||
263 | $qb = $this->conn->createQueryBuilder()->delete($this->quoted_table_name); |
||
264 | $this->buildWhere($qb, $filters); |
||
265 | return $qb->execute(); |
||
266 | } |
||
267 | |||
268 | /** |
||
269 | * copy some records and maybe change some values |
||
270 | * |
||
271 | * @param array $filters |
||
272 | * @param array $limit |
||
273 | * @param array $order_by |
||
274 | * @param array $changes |
||
275 | * |
||
276 | * @return array the result of each $this->create() |
||
277 | */ |
||
278 | public function copy(array $filters = [], array $limit = [], array $order_by = [], array $changes = []) |
||
279 | { |
||
280 | $return = []; |
||
281 | //read |
||
282 | $data = $this->read($this->getColumnNames(), $filters, $limit, $order_by, self::READ_RETURN_SIMPLE); |
||
283 | foreach ($data as $row) { |
||
284 | foreach ($row as $column_name => $value) { |
||
285 | $column = $this->getColumn($column_name); |
||
286 | //changes |
||
287 | if (isset($changes[$column_name])) { |
||
288 | $row[$column_name] = $changes[$column_name]; |
||
289 | } |
||
290 | //remove autoincrements |
||
291 | if ($column->getAutoincrement()) { |
||
292 | unset($row[$column_name]); |
||
293 | } |
||
294 | } |
||
295 | $return[] = $this->create($row); |
||
296 | } |
||
297 | return $return; |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Builds the WHERE clause from $filter |
||
302 | * |
||
303 | * @param QueryBuilder $qb |
||
304 | * @param array $filters should be an array with arrays wich contains 3 datas |
||
305 | * [ |
||
306 | * ['column_name', 'expr_type', 'value'], |
||
307 | * [], |
||
308 | * ... |
||
309 | * ] |
||
310 | * expr_types: 'eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'like', 'in', 'notIn', 'notLike' |
||
311 | * |
||
312 | * @return self |
||
313 | */ |
||
314 | protected function buildWhere(QueryBuilder $qb, array $filters = []) |
||
315 | { |
||
316 | if (!empty($filters)) { |
||
317 | $expr = $qb->expr()->andX(); |
||
318 | foreach ($filters as $f) { |
||
319 | $column = $f[0]; |
||
320 | $expr_type = $f[1]; |
||
321 | $value = isset($f[2]) ? $f[2] : null; |
||
322 | $type = \PDO::PARAM_STR; |
||
323 | if ($this->getColumn($column) === null) { |
||
324 | throw Schema\SchemaException::columnDoesNotExist($column, $this->table_name); |
||
325 | } |
||
326 | if (!in_array($expr_type, $this->getExpressionTypes())) { |
||
327 | throw QueryBuilderException::expressionTypeDoesNotExist($expr_type); |
||
328 | } |
||
329 | if (in_array($expr_type, ['in', 'notIn']) && is_array($value)) { |
||
330 | switch ($this->column_types[$column]) { |
||
331 | case 'integer': |
||
332 | $type = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY; |
||
333 | break; |
||
334 | case 'string': |
||
335 | $type = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY; |
||
336 | break; |
||
337 | } |
||
338 | } |
||
339 | $expr->add($qb->expr()->$expr_type($this->conn->quoteIdentifier($column), $qb->createNamedParameter($value, $type))); |
||
340 | } |
||
341 | $qb->where($expr); |
||
342 | } |
||
343 | return $this; |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * Build up dynamilcy the LIMIT part |
||
348 | * |
||
349 | * @param QueryBuilder $qb |
||
350 | * @param array $limit |
||
351 | * |
||
352 | * @return self |
||
353 | */ |
||
354 | protected function buildLimit(QueryBuilder $qb, array $limit = []) |
||
355 | { |
||
356 | switch (count($limit)) { |
||
357 | case 2: |
||
358 | $qb->setFirstResult((int) $limit[0]); |
||
359 | $qb->setMaxResults((int) $limit[1]); |
||
360 | break; |
||
361 | case 1: |
||
362 | $qb->setMaxResults((int) $limit[0]); |
||
363 | break; |
||
364 | } |
||
365 | return $this; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Builds the ORDER BY part |
||
370 | * |
||
371 | * @param QueryBuilder $qb |
||
372 | * @param array $order_by |
||
373 | * |
||
374 | * @return self |
||
375 | */ |
||
376 | protected function buildOrderBy(QueryBuilder $qb, array $order_by = []) |
||
377 | { |
||
378 | foreach ($order_by as $order) { |
||
379 | $column = null; |
||
380 | $direction = 'ASC'; |
||
381 | if (is_string($order)) { |
||
382 | $column = $order; |
||
383 | } elseif (is_array($order) && count($order) === 2) { |
||
384 | list($column, $direction) = $order; |
||
385 | } |
||
386 | if ($column === null || $this->getColumn($column) === null) { |
||
387 | throw Schema\SchemaException::columnDoesNotExist($column, $this->table_name); |
||
388 | } |
||
389 | if (!in_array($direction, ['ASC', 'DESC'])) { |
||
390 | throw QueryBuilderException::orderByDirectionDoesNotExist($direction); |
||
391 | } |
||
392 | $qb->addOrderBy($this->conn->quoteIdentifier($column), $direction); |
||
393 | } |
||
394 | return $this; |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * Returns the table-Name |
||
399 | * |
||
400 | * @return string |
||
401 | */ |
||
402 | public function getTableName() |
||
403 | { |
||
404 | return $this->table_name; |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * List all possible expression types |
||
409 | * |
||
410 | * @return string[] |
||
411 | */ |
||
412 | public function getExpressionTypes() |
||
413 | { |
||
414 | return ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'like', 'in', 'notIn', 'notLike', 'isNull', 'isNotNull']; |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * List all possible column names |
||
419 | * @return string[] |
||
420 | */ |
||
421 | public function getColumnNames() |
||
422 | { |
||
423 | return array_keys($this->columns); |
||
424 | } |
||
425 | |||
426 | /** |
||
427 | * return true if the column type of $column_name is a simple type like string, integer, ... |
||
428 | * @param string $column_name |
||
429 | * @return boolean |
||
430 | */ |
||
431 | public function isSimpleType($column_name) |
||
432 | { |
||
433 | return in_array($this->column_types[$column_name], ['string', 'integer']); |
||
434 | } |
||
435 | } |
||
436 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.