Issues (4)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Source/QueryBuilder.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @author Rémy M. Böhler <[email protected]>
4
 */
5
namespace Rorm;
6
7
use PDO;
8
9
/**
10
 * Class QueryBuilder
11
 * @package Rorm
12
 */
13
class QueryBuilder extends Query
14
{
15
    /** @var callable */
16
    protected $quoteIdentifier;
17
18
    /** @var string */
19
    protected $table;
20
21
    /** @var array */
22
    protected $idColumn;
23
24
    // query
25
    protected $distinct = false;
26
27
    /** @var array */
28
    protected $select = array();
29
30
    /** @var array */
31
    protected $where = array();
32
33
    /** @var array */
34
    protected $buildParams = array();
35
36
    /** @var array */
37
    protected $order = array();
38
39
    /** @var int */
40
    protected $limit;
41
42
    /** @var int */
43
    protected $offset;
44
45
    /**
46
     * @param string $table
47
     * @param string|array $idColumn
48
     * @param string $class
49
     * @param \PDO|null $dbh
50
     */
51 24
    public function __construct($table, $idColumn, $class = 'stdClass', PDO $dbh = null)
52
    {
53 24
        parent::__construct($class, $dbh);
54
55 24
        $this->table = $table;
56 24
        $this->idColumn = is_array($idColumn) ? $idColumn : array($idColumn);
57 24
        $this->quoteIdentifier = Rorm::getIdentifierQuoter($this->dbh);
58 24
    }
59
60
    /**
61
     * @param string $identifier
62
     * @return string
63
     */
64 21
    public function quoteIdentifier($identifier)
65
    {
66
        // TODO there must be an easier way to do this without an extra variable!
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
67 21
        $func = $this->quoteIdentifier;
68 21
        return $func($identifier);
69
    }
70
71
    /**
72
     * @return string
73
     */
74 1
    public function getTable()
75
    {
76 1
        return $this->table;
77
    }
78
79
    // select
80
    /**
81
     * @return $this
82
     */
83 2
    public function distinct()
84
    {
85 2
        $this->distinct = true;
86 2
        return $this;
87
    }
88
89
    /**
90
     * @return $this
91
     */
92 4
    public function selectAll()
93
    {
94 4
        $this->select[] = '*';
95 4
        return $this;
96
    }
97
98
    /**
99
     * @param string $column
100
     * @param string|null $as
101
     * @return $this
102
     */
103 5
    public function select($column, $as = null)
104
    {
105 5
        return $this->selectExpr($this->quoteIdentifier($column), $as);
106
    }
107
108
    /**
109
     * @param string $expression
110
     * @param string|null $as
111
     * @return $this
112
     */
113 5
    public function selectExpr($expression, $as = null)
114
    {
115 5
        $select = $expression;
116 5
        if ($as !== null) {
117 4
            $select .= ' AS ' . $this->quoteIdentifier($as);
118 4
        }
119 5
        $this->select[] = $select;
120
121 5
        return $this;
122
    }
123
124
125
    // where
126
    /**
127
     * @param string $column
128
     * @param mixed $value
129
     * @return $this
130
     */
131 12
    public function where($column, $value)
132
    {
133 12
        $this->where[] = $this->quoteIdentifier($column) . ' = ?';
134 12
        $this->buildParams[] = $value;
135 12
        return $this;
136
    }
137
138
    /**
139
     * @param string $column
140
     * @param mixed $value
141
     * @return $this
142
     */
143 2
    public function whereNot($column, $value)
144
    {
145 2
        $this->where[] = $this->quoteIdentifier($column) . ' != ?';
146 2
        $this->buildParams[] = $value;
147 2
        return $this;
148
    }
149
150
    /**
151
     * @param mixed $id , ...
152
     * @return $this
153
     *
154
     * @throws QueryBuilderException
155
     */
156 8
    public function whereId($id)
0 ignored issues
show
The parameter $id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
157
    {
158 8
        $args = func_get_args();
159 8
        if (count($args) !== count($this->idColumn)) {
160 1
            throw new QueryBuilderException('number of id parameters must match');
161
        }
162
163 7
        $keys = array_combine($this->idColumn, $args);
164 7
        foreach ($keys as $column => $value) {
165 7
            $this->where($column, $value);
166 7
        }
167
168 7
        return $this;
169
    }
170
171
    /**
172
     * check: could be extended with optional $params
173
     *
174
     * @param string $column
175
     * @param string $expression
176
     * @return $this
177
     */
178 4
    public function whereExpr($column, $expression)
179
    {
180 4
        $this->where[] = $this->quoteIdentifier($column) . ' = ' . $expression;
181 4
        return $this;
182
    }
183
184
    /**
185
     * @param string $where
186
     * @param array $params
187
     * @return $this
188
     */
189 4
    public function whereRaw($where, array $params = array())
190
    {
191 4
        $this->where[] = $where;
192 4
        foreach ($params as $param) {
193 4
            $this->buildParams[] = $param;
194 4
        }
195 4
        return $this;
196
    }
197
198
    /**
199
     * Take care, the $values gets quoted!
200
     *
201
     * @param string $column
202
     * @param int|float|string $value
203
     * @return $this
204
     */
205 4
    public function whereLt($column, $value)
206
    {
207 4
        $this->where[] = $this->quoteIdentifier($column) . ' < ?';
208 4
        $this->buildParams[] = $value;
209 4
        return $this;
210
    }
211
212
    /**
213
     * Take care, the $values gets quoted!
214
     *
215
     * @param string $column
216
     * @param int|float|string $value
217
     * @return $this
218
     */
219 4
    public function whereLte($column, $value)
220
    {
221 4
        $this->where[] = $this->quoteIdentifier($column) . ' <= ?';
222 4
        $this->buildParams[] = $value;
223 4
        return $this;
224
    }
225
226
    /**
227
     * Take care, the $values gets quoted!
228
     *
229
     * @param string $column
230
     * @param int|float|string $value
231
     * @return $this
232
     */
233 6
    public function whereGt($column, $value)
234
    {
235 6
        $this->where[] = $this->quoteIdentifier($column) . ' > ?';
236 6
        $this->buildParams[] = $value;
237 6
        return $this;
238
    }
239
240
    /**
241
     * Take care, the $values gets quoted!
242
     *
243
     * @param string $column
244
     * @param int|float|string $value
245
     * @return $this
246
     */
247 4
    public function whereGte($column, $value)
248
    {
249 4
        $this->where[] = $this->quoteIdentifier($column) . ' >= ?';
250 4
        $this->buildParams[] = $value;
251 4
        return $this;
252
    }
253
254
    /**
255
     * @param string $column
256
     * @return $this
257
     */
258 4
    public function whereNotNull($column)
259
    {
260 4
        $this->where[] = $this->quoteIdentifier($column) . ' IS NOT NULL';
261 4
        return $this;
262
    }
263
264
    /**
265
     * @param string $column
266
     * @return $this
267
     */
268 2
    public function whereNull($column)
269
    {
270 2
        $this->where[] = $this->quoteIdentifier($column) . ' IS NULL';
271 2
        return $this;
272
    }
273
274
    /**
275
     * @param string $column
276
     * @param array $data
277
     * @return $this
278
     */
279 3
    public function whereIn($column, array $data)
280
    {
281 3
        $this->where[] = $this->quoteIdentifier($column) . ' IN (' .
282 3
            substr(str_repeat('?, ', count($data)), 0, -2) .
283 3
            ')';
284 3
        $this->buildParams = array_merge($this->buildParams, $data);
285 3
        return $this;
286
    }
287
288
    // order by
289
    /**
290
     * @param string $column
291
     * @return $this
292
     */
293 7
    public function orderByAsc($column)
294
    {
295 7
        $this->order[] = $this->quoteIdentifier($column) . ' ASC';
296 7
        return $this;
297
    }
298
299
    /**
300
     * @param string $column
301
     * @return $this
302
     */
303 4
    public function orderByDesc($column)
304
    {
305 4
        $this->order[] = $this->quoteIdentifier($column) . ' DESC';
306 4
        return $this;
307
    }
308
309
    /**
310
     * @param string $expression
311
     * @param array $params
312
     * @return $this
313
     */
314 1
    public function orderByExpr($expression, array $params = array())
315
    {
316 1
        $this->order[] = $expression;
317 1
        $this->buildParams = array_merge($this->buildParams, $params);
318 1
        return $this;
319
    }
320
321
    // limit
322
    /**
323
     * @param int $limit
324
     * @return $this
325
     */
326 12
    public function limit($limit)
327
    {
328 12
        $this->limit = $limit;
329 12
        return $this;
330
    }
331
332
    /**
333
     * @param int $offset
334
     * @return $this
335
     */
336 4
    public function offset($offset)
337
    {
338 4
        $this->offset = $offset;
339 4
        return $this;
340
    }
341
342
343
    // execute
344
    /**
345
     * @return $this
346
     */
347 18
    public function build()
348
    {
349 18
        $params = array();
350 18
        $query = 'SELECT ';
351
352 18
        if ($this->distinct) {
353 1
            $query .= 'DISTINCT ';
354 1
        }
355
356
        // select
357 18
        if (!empty($this->select)) {
358 5
            $query .= implode(', ', $this->select);
359 5
        } else {
360
            // select everything
361 14
            $query .= '*';
362
        }
363
364
        // from
365 18
        $query .= ' FROM ' . $this->quoteIdentifier($this->table);
366
367
        // where
368 18
        if (!empty($this->where)) {
369 11
            $query .= ' WHERE ' . implode(' AND ', $this->where);
370
371
            // params (CAUTION, we override the array, faster and not used before!)
372 11
            $params = $this->buildParams;
373 11
        }
374
375
        // order
376 18
        if (!empty($this->order)) {
377 7
            $query .= ' ORDER BY ' . implode(', ', $this->order);
378 7
        }
379
380
        // limit
381 18
        if ($this->limit !== null) {
382 11
            $query .= ' LIMIT ' . (int)$this->limit;
383
384
            // offset
385 11
            if ($this->offset !== null) {
386 3
                $query .= ' OFFSET ' . (int)$this->offset;
387 3
            }
388 11
        }
389
390 18
        $this->query = $query;
391 18
        $this->params = $params;
392
393 18
        return $this;
394
    }
395
396
    /**
397
     * @return string|null
398
     */
399 3
    public function findColumn()
400
    {
401 3
        $this->limit(1);
402 3
        $this->build();
403 3
        return parent::findColumn();
404
    }
405
406
    /**
407
     * @return object|null
408
     */
409 8
    public function findOne()
410
    {
411 8
        $this->limit(1);
412 8
        $this->build();
413 8
        return parent::findOne();
414
    }
415
416
    /**
417
     * @return QueryIterator
418
     */
419 4
    public function findMany()
420
    {
421 4
        $this->build();
422 4
        return parent::findMany();
423
    }
424
425
    /**
426
     * @return array
427
     */
428 2
    public function findAll()
429
    {
430 2
        $this->build();
431 2
        return parent::findAll();
432
    }
433
434
    /**
435
     * Count found rows
436
     * this method executes a COUNT(*) query
437
     *
438
     * @return int
439
     */
440 1
    public function count()
441
    {
442 1
        $select = $this->select;
443 1
        $this->select = array('COUNT(*)');
444 1
        $count = $this->findColumn();
445 1
        $this->select = $select;
446
447 1
        return $count === null ? null : (int)$count;
448
    }
449
}
450