Completed
Push — master ( 870f46...9343b3 )
by Adam
01:55
created

Database::where()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 8
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 8
nc 3
nop 1
crap 30
1
<?php
2
namespace DBAL;
3
4
use PDO;
5
use DBAL\Modifiers\SafeString;
6
use DBAL\Modifiers\Operators;
7
8
/**
9
 * PDO Database connection class
10
 *
11
 * @author Adam Binnersley <[email protected]>
12
 * @version PDO Database Class
13
 */
14
final class Database implements DBInterface{
15
    protected $db;
16
    protected $sql;
17
    private $key;
18
    
19
    protected $logLocation;
20
    public $logErrors = true;
21
    public $logQueries = false;
22
    public $displayErrors = false;
23
    
24
    protected $database;
25
    protected $cacheEnabled = false;
26
    protected $cacheObj;
27
    protected $cacheValue;
28
    protected $modified = false;
29
30
    private $query;
31
    private $values = [];
32
    private $prepare = [];
33
    
34
    private static $connectors = array(
35
        'cubrid' => 'cubrid:host=%s;port=%d;dbname=%s',
36
        'dblib' => 'dblib:host=%s:%d;dbname=%s',
37
        'mssql' => 'sqlsrv:Server=%s,%d;Database=%s',
38
        'mysql' => 'mysql:host=%s;port=%d;dbname=%s',
39
        'pgsql' => 'pgsql:host=%s;port=%d;dbname=%s',
40
        'sqlite' => 'sqlite::memory:'
41
    );
42
43
    /**
44
     * Connect to database using PDO connection
45
     * @param string $hostname This should be the host of the database e.g. 'localhost'
46
     * @param string $username This should be the username for the chosen database
47
     * @param string $password This should be the password for the chosen database 
48
     * @param string $database This should be the database that you wish to connect to
49
     * @param string|false $backuphost If you have a replication server set up put the hostname or IP address incase the primary server goes down
50
     * @param object|false $cache If you want to cache the queries with Memcache(d)/Redis/APC/Xcache This should be the object else set to false
51
     * @param boolean $persistent If you want a persistent database connection set to true
52
     * @param string $type The type of connection that you wish to make can be 'mysql', 'cubrid', 'dblib', 'mssql', 'odbc', 'pgsql, or 'sqlite'
53
     * @param int $port This should be the port number of the MySQL database connection
54
     */
55
    public function __construct($hostname, $username, $password, $database, $backuphost = false, $cache = false, $persistent = false, $type = 'mysql', $port = 3306){
56
        $this->setLogLocation();
57
        try{
58
            $this->connectToServer($username, $password, $database, $hostname, $persistent, $type, $port);
59
        }
60
        catch(\Exception $e){
61
            if($backuphost !== false){
62
                $this->connectToServer($username, $password, $database, $backuphost, $persistent, $type, $port);
63
            }
64
            $this->error($e);
65
        }
66
        if(is_object($cache)){
67
            $this->setCaching($cache);
68
        }
69
    }
70
    
71
    /**
72
     * Closes the PDO database connection when Database object unset
73
     */
74
    public function __destruct(){
75
        $this->closeDatabase();
76
    }
77
    
78
    /**
79
     * Connect to the database using PDO connection
80
     * @param string $username This should be the username for the chosen database
81
     * @param string $password This should be the password for the chosen database 
82
     * @param string $database This should be the database that you wish to connect to
83
     * @param string $hostname The hostname for the database
84
     * @param boolean $persistent If you want a persistent database connection set to true
85
     * @param string $type The type of connection that you wish to make can be 'mysql', 'cubrid', 'dblib', 'mssql', 'pgsql, or 'sqlite'
86
     * @param int $port The port number to connect to the MySQL server
87
     */
88
    protected function connectToServer($username, $password, $database, $hostname, $persistent = false, $type = 'mysql', $port = 3306){
89
        if(!$this->db){
90
            $this->database = $database;
91
            $this->db = new PDO(sprintf(self::$connectors[$type], $hostname, $port, $database), $username, $password,
92
                array_merge(
93
                    array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
94
                    ($persistent !== false ? array(PDO::ATTR_PERSISTENT => true) : array()),
95
                    ($type === 'mysql' ? array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, PDO::ATTR_EMULATE_PREPARES => true) : array())
96
                )
97
            );
98
        }
99
    }
100
    
101
    /**
102
     * Enables the caching and set the caching object to the one provided
103
     * @param object $caching This should be class of the type of caching you are using
104
     */
105
    public function setCaching($caching){
106
        if(is_object($caching)){
107
            $this->cacheObj = $caching;
108
            $this->cacheEnabled = true;
109
        }
110
        return $this;
111
    }
112
    
113
    /**
114
     * This query function is used for more advanced SQL queries for which non of the other methods fit
115
     * @param string $sql This should be the SQL query which you wish to run
116
     * @return array Returns array of results for the query that has just been run
117
     */
118
    public function query($sql, $variables = array(), $cache = true){
119
        try{
120
            $this->sql = $sql;
121
            $this->query = $this->db->prepare($this->sql);
122
            $this->query->execute($variables);
123
            if(strpos($this->sql, 'SELECT') !== false){
124
                return $this->query->fetchAll(PDO::FETCH_ASSOC);
125
            }
126
        }
127
        catch(\Exception $e){
128
            $this->error($e);
129
        }
130
    }
131
    
132
    /**
133
     * Returns a single record for a select query for the chosen table
134
     * @param string $table This should be the table you wish to select the values from
135
     * @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
136
     * @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
137
     * @param array|string $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC')
138
     * @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
139
     * @return array Returns a single table record as the standard array when running SQL queries
140
     */
141
    public function select($table, $where = array(), $fields = '*', $order = array(), $cache = true){
142
        return $this->selectAll($table, $where, $fields, $order, 1, $cache);
143
    }
144
    
145
    /**
146
     * Returns a multidimensional array of the results from the selected table given the given parameters
147
     * @param string $table This should be the table you wish to select the values from
148
     * @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
149
     * @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
150
     * @param array|string $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC')
151
     * @param integer|array $limit The number of results you want to return 0 is default and returns all results, else should be formated either as a standard integer or as an array as the start and end values e.g. array(0 => 150)
152
     * @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
153
     * @return array Returns a multidimensional array with the chosen fields from the table
154
     */
155
    public function selectAll($table, $where = array(), $fields = '*', $order = array(), $limit = 0, $cache = true){        
156
        $this->buildSelectQuery(SafeString::makeSafe($table), $where, $fields, $order, $limit);
0 ignored issues
show
Bug introduced by
It seems like $order defined by parameter $order on line 155 can also be of type string; however, DBAL\Database::buildSelectQuery() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
157
        $result = $this->executeQuery($cache);
158
        if(!$result){
159
            if($limit === 1){$result = $this->query->fetch(PDO::FETCH_ASSOC);} // Reduce the memory usage if only one record and increase performance
160
            else{$result = $this->query->fetchAll(PDO::FETCH_ASSOC);}
161
            if($cache && $this->cacheEnabled){$this->setCache($this->key, $result);}
162
        }
163
        return $result ? $result : false;
164
    }
165
    
166
    /**
167
     * Returns a single column value for a given query
168
     * @param string $table This should be the table you wish to select the values from
169
     * @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
170
     * @param array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
171
     * @param int $colNum This should be the column number you wish to get (starts at 0)
172
     * @param array $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC') so it can be done in both directions
173
     * @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
174
     * @return mixed If a result is found will return the value of the colum given else will return false
175
     */
176
    public function fetchColumn($table, $where = array(), $fields = '*', $colNum = 0, $order = array(), $cache = true){
177
        $this->buildSelectQuery(SafeString::makeSafe($table), $where, $fields, $order, 1);
178
        $result = $this->executeQuery($cache);
179
        if(!$result){
180
            $result = $this->query->fetchColumn(intval($colNum));
181
            if($cache && $this->cacheEnabled){$this->setCache($this->key, $result);}
182
        }
183
        return $result;
184
    }
185
    
186
    /**
187
     * Inserts into database using the prepared PDO statements 
188
     * @param string $table This should be the table you wish to insert the values into
189
     * @param array $records This should be the field names and values in the format of array('fieldname' => 'value', 'fieldname2' => 'value2', etc.)
190
     * @return boolean If data is inserted returns true else returns false
191
     */
192
    public function insert($table, $records){
193
        unset($this->prepare);
194
        
195
        $this->sql = sprintf("INSERT INTO `%s` (%s) VALUES (%s);", SafeString::makeSafe($table), $this->fields($records, true), implode(', ', $this->prepare));
196
        $this->executeQuery(false);
197
        return $this->numRows() ? true : false;
198
    }
199
    
200
    /**
201
     * Updates values in a database using the provide variables
202
     * @param string $table This should be the table you wish to update the values for
203
     * @param array $records This should be the field names and new values in the format of array('fieldname' => 'newvalue', 'fieldname2' => 'newvalue2', etc.)
204
     * @param array $where Should be the field names and values you wish to update in the form of an array e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
205
     * @param int $limit The number of results you want to return 0 is default and will update all results that match the query, else should be formated as a standard integer
206
     * @return boolean Returns true if update is successful else returns false
207
     */
208
    public function update($table, $records, $where = array(), $limit = 0){
209
        $this->sql = sprintf("UPDATE `%s` SET %s %s%s;", SafeString::makeSafe($table), $this->fields($records), $this->where($where), $this->limit($limit));
210
        $this->executeQuery(false);
211
        return $this->numRows() ? true : false;
212
    }
213
    
214
    /**
215
     * Deletes records from the given table based on the variables given
216
     * @param string $table This should be the table you wish to delete the records from
217
     * @param array $where This should be an array of for the where statement
218
     * @param int $limit The number of results you want to return 0 is default and will delete all results that match the query, else should be formated as a standard integer
219
     */
220
    public function delete($table, $where, $limit = 0){
221
        $this->sql = sprintf("DELETE FROM `%s` %s%s;", SafeString::makeSafe($table), $this->where($where), $this->limit($limit));
222
        $this->executeQuery(false);
223
        return $this->numRows() ? true : false;
224
    }
225
    
226
    /**
227
     * Count the number of return results 
228
     * @param string $table The table you wish to count the result of 
229
     * @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
230
     * @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
231
     * @return int Returns the number of results
232
     */
233
    public function count($table, $where = array(), $cache = true){
234
        $this->sql = sprintf("SELECT count(*) FROM `%s`%s;", SafeString::makeSafe($table), $this->where($where));
235
        $this->key = md5($this->database.$this->sql.serialize($this->values));
236
        
237
        $result = $this->executeQuery($cache);
238
        if(!$result){
239
            $result = $this->query->fetchColumn();
240
            if($cache && $this->cacheEnabled){$this->setCache($this->key, $result);}
241
        }
242
        return $result;
243
    }
244
    
245
    /**
246
     * Truncates a given table from the selected database so there are no values in the table
247
     * @param string $table This should be the table you wish to truncate
248
     * @return boolean If the table is emptied returns true else returns false
249
     */
250
    public function truncate($table){
251
        try{
252
            $this->sql = sprintf("TRUNCATE TABLE `%s`", SafeString::makeSafe($table));
253
            $this->query = $this->db->exec($this->sql);
254
        }
255
        catch(\Exception $e){
256
            $this->error($e);
257
        }
258
        return $this->query ? true : false;
259
    }
260
    
261
    /**
262
     * Returns the number of rows for the last query sent
263
     * @return int Returns the number of rows for the last query
264
     */
265
    public function numRows(){
266
        if(isset($this->query)){
267
            return $this->query->rowCount();
268
        }
269
        return 0;
270
    }
271
    
272
    /**
273
     * Returns the number of rows for the last query sent (Looks a the numRows() function just added incase of habbit)
274
     * @return int Returns the number of rows for the last query
275
     */
276
    public function rowCount(){
277
        return $this->numRows();
278
    }
279
    
280
    /**
281
     * Returns the ID of the last record last inserted 
282
     * @param string $name This should be the name of the sequence object you wish to retrieve
283
     * @return int|string Returns the last inserted ID of the last insert item if $name is null else returns string with sequenced object
284
     */
285
    public function lastInsertId($name = null) {
286
        return $this->db->lastInsertId($name);
287
    }
288
    
289
    /**
290
     * Returns the index of the given table or tables within the database
291
     * @param string|array $table Table can wither be a standard string with a single table name or an array with multiple table names
292
     * @return array Returns the table index for the selected table as an array 
293
     */
294
    public function fulltextIndex($table){
295
        $fieldlist = array();
296
        if(is_array($table)){
297
            foreach($table as $name){
298
                $fieldlist[$name] = $this->fulltextIndex($name);
299
            }
300
        }else{
301
            try{
302
                $this->query = $this->db->prepare("SHOW INDEX FROM ?;");
303
                $this->query->execute($table);
304
            }
305
            catch(\Exception $e){
306
                $this->error($e);
307
            }
308
            
309
            while($index = $this->query->fetchAll(PDO::FETCH_ASSOC)){
310
                if($index['Index_type'] == 'FULLTEXT' && $index['Key_name'] == 'fulltext'){
311
                    $fieldlist[] = $index['Column_name'];
312
                }
313
            }
314
        }
315
        return $fieldlist;
316
    }
317
    
318
    /**
319
     * Checks to see if a connection has been made to the server
320
     * @return boolean
321
     */
322
    public function isConnected(){
323
        return is_object($this->db) ? true : false;
324
    }
325
    
326
    /**
327
     * Returns the server version information
328
     */
329
    public function serverVersion(){
330
        return $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
331
    }
332
    
333
    /**
334
     * Sets the location of the log files
335
     * @param string $location This should be where you wish the logs to be stored
336
     * @return $this
337
     */
338
    public function setLogLocation($location = false){
339
        if($location === false){
340
            $location = dirname(__FILE__).DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR;
341
        }
342
        $this->logLocation = $location;
343
        if (!file_exists($location)) {
344
            mkdir($location, 0777, true);
345
        }
346
        return $this;
347
    }
348
    
349
    /**
350
     * Displays the error massage which occurs
351
     * @param \Exception $error This should be an instance of Exception
352
     */
353
    private function error($error){
354
        if($this->logErrors){
355
            $file = $this->logLocation.'db-errors.txt';
356
            $current = file_get_contents($file);
357
            $current .= date('d/m/Y H:i:s')." ERROR: ".$error->getMessage()." on ".$this->sql."\n";
358
            file_put_contents($file, $current);
359
        }
360
        if($this->displayErrors){
361
            die('ERROR: '.$error->getMessage().' on '.$this->sql);
362
        }
363
    }
364
    
365
    /**
366
     * Writes all queries to a log file
367
     */
368
    public function writeQueryToLog(){
369
        $file = $this->logLocation.'queries.txt';
370
        $current = file_get_contents($file);
371
        $current .= "SQL: ".$this->sql.":".serialize($this->values)."\n";
372
        file_put_contents($file, $current);
373
    }
374
    
375
    /**
376
     * Closes the PDO database connection by setting the connection to NULL 
377
     */
378
    public function closeDatabase(){
379
        $this->db = null;
380
    }
381
    
382
    /**
383
     * Build the SQL query but doesn't execute it
384
     * @param string $table This should be the table you wish to select the values from
385
     * @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
386
     * @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
387
     * @param array $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC') so it can be done in both directions
388
     * @param integer|array $limit The number of results you want to return 0 is default and returns all results, else should be formated either as a standard integer or as an array as the start and end values e.g. array(0 => 150)
389
     */
390
    protected function buildSelectQuery($table, $where = array(), $fields = '*', $order = array(), $limit = 0){
391
        if(is_array($fields)){
392
            $selectfields = array();
393
            foreach($fields as $field => $value){
394
                $selectfields[] = sprintf("`%s`", SafeString::makeSafe($value));
395
            }
396
            $fieldList = implode(', ', $selectfields);
397
        }
398
        else{$fieldList = '*';}
399
        
400
        $this->sql = sprintf("SELECT %s FROM `%s`%s%s%s;", $fieldList, SafeString::makeSafe($table), $this->where($where), $this->orderBy($order), $this->limit($limit));
401
        $this->key = md5($this->database.$this->sql.serialize($this->values));
402
    }
403
    
404
    /**
405
     * Execute the current query if no cache value is available
406
     * @param boolean $cache If the cache should be checked for the checked for the values of the query set to true else set to false 
407
     * @return mixed If a cached value exists will be returned else if cache is not checked and query is executed will not return anything
408
     */
409
    protected function executeQuery($cache = true){
410
        if($this->logQueries){$this->writeQueryToLog();}
411
        if($cache && $this->cacheEnabled && $this->getCache($this->key)){
412
            return $this->cacheValue;
413
        }
414
        try{
415
            $this->query = $this->db->prepare($this->sql);
416
            $this->query->execute($this->values);
417
            unset($this->values);
418
            $this->values = [];
419
        }
420
        catch(\Exception $e){
421
            $this->error($e);
422
        }
423
}
424
	
425
    /**
426
     * This outputs the SQL where query based on a given array
427
     * @param array $where This should be an array that you wish to create the where query for in the for array('field1' => 'test') or array('field1' => array('>=', 0))
428
     * @return string|false If the where query is an array will return the where string and set the values else returns false if no array sent
429
     */
430
    private function where($where){
431
        if(is_array($where) && !empty($where)){
432
            $wherefields = array();
433
            foreach($where as $field => $value){
434
                $where[] = $this->formatValues($field, $value);
435
            }
436
            if(!empty($wherefields)){
437
                return " WHERE ".implode(' AND ', $wherefields);
438
            }
439
        }
440
        return false;
441
    }
442
    
443
    /**
444
     * Sets the order sting for the SQL query based on an array or string
445
     * @param array|string $order This should be either set to array('fieldname' => 'ASC/DESC') or RAND()
446
     * @return string|false If the SQL query has an valid order by will return a string else returns false
447
     */
448
    private function orderBy($order){
449
        if(is_array($order) && !empty(array_filter($order))){
450
            foreach($order as $fieldorder => $fieldvalue){
451
                if(!empty($fieldorder) && !empty($fieldvalue)){
452
                    $string[] = sprintf("`%s` %s", SafeString::makeSafe($fieldorder), strtoupper(SafeString::makeSafe($fieldvalue)));
0 ignored issues
show
Coding Style Comprehensibility introduced by
$string was never initialized. Although not strictly required by PHP, it is generally a good practice to add $string = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
453
                }
454
                elseif($fieldvalue === 'RAND()'){
455
                    $string[] = $fieldvalue;
0 ignored issues
show
Bug introduced by
The variable $string does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
456
                }
457
            }
458
            return sprintf(" ORDER BY %s", implode(", ", $string));
459
        }
460
        elseif($order == 'RAND()'){
461
            return " ORDER BY RAND()";
462
        }
463
        return false;
464
    }
465
    
466
    /**
467
     * Build the field list for the query
468
     * @param array $records This should be an array listing all of the fields
469
     * @param boolean $insert If this is an insert statement should be set to true to create the correct amount of queries for the prepared statement
470
     * @return string The fields list will be returned as a string to insert into the SQL query
471
     */
472
    private function fields($records, $insert = false){
473
        $fields = array();
474
        
475
        foreach($records as $field => $value){
476
            if($insert === true){
477
                $fields[] = sprintf("`%s`", SafeString::makeSafe($field));
478
                $this->prepare[] = '?';
479
            }
480
            else{
481
                $fields[] = sprintf("`%s` = ?", SafeString::makeSafe($field));
482
            }
483
            $this->values[] = $value;
484
        }
485
        return implode(', ', $fields);
486
    }
487
    
488
    /**
489
     * Returns the limit SQL for the current query as a string
490
     * @param integer|array $limit This should either be set as an integer or should be set as an array with a start and end value  
491
     * @return string|false Will return the LIMIT string for the current query if it is valid else returns false
492
     */
493
    private function limit($limit = 0){
494
        if(is_array($limit) && !empty(array_filter($limit))){
495
            foreach($limit as $start => $end){
496
                 return " LIMIT ".intval($start).", ".intval($end);
497
            }
498
        }
499
        elseif((int)$limit > 0){
500
            return " LIMIT ".intval($limit);
501
        }
502
        return false;
503
    }
504
    
505
    
506
    /**
507
     * Set the cache with a key and value
508
     * @param string $key The unique key to store the value against
509
     * @param mixed $value The value of the MYSQL query 
510
     */
511
    public function setCache($key, $value){
512
        if($this->cacheEnabled){
513
            $this->cacheObj->save($key, $value);
514
        }
515
    }
516
    
517
    /**
518
     * Get the results for a given key
519
     * @param string $key The unique key to check for stored variables
520
     * @return mixed Returned the cached results from
521
     */
522
    public function getCache($key){
523
        if($this->modified === true || !$this->cacheEnabled){return false;}
524
        else{
525
            $this->cacheValue = $this->cacheObj->fetch($key);
526
            return $this->cacheValue;
527
        }
528
    }
529
    
530
    /**
531
     * Clears the cache
532
     */
533
    public function flushDB(){
534
        $this->cacheObj->deleteAll();
535
    }
536
    
537
    /**
538
     * Format the where queries and set the prepared values
539
     * @param string $field This should be the field name in the database
540
     * @param mixed $value This should be the value which should either be a string or an array if it contains an operator
541
     * @return string This should be the string to add to the SQL query
542
     */
543
    protected function formatValues($field, $value){
544
        if(Operators::isOperatorValid($value) && !Operators::isOperatorPrepared($value)){
545
            return sprintf("`%s` %s", SafeString::makeSafe($field), Operators::getOperatorFormat($value));
546
        }
547
        elseif(is_array($value)){
548
            if(!is_array(array_values($value)[0])){
549
                $this->values[] = (isset($value[1]) ? $value[1] : array_values($value)[0]);
550
                $operator = (isset($value[0]) ? $value[0] : key($value));
551
            }
552
            else{
553
                foreach(array_values($value)[0] as $op => $array_value){
554
                    $this->values[] = $array_value;
555
                }
556
                $operator = key($value);
557
            }
558
            return sprintf("`%s` %s", SafeString::makeSafe($field), Operators::getOperatorFormat($operator));
559
            
560
        }
561
        $this->values[] = $value;
562
        return sprintf("`%s` = ?", SafeString::makeSafe($field));
563
    }
564
}
565