Passed
Push — 1.0.0-dev ( b68981...00dab9 )
by nguereza
05:23
created

DatabaseQueryRunner::setLogger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 1
eloc 2
c 1
b 1
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
  /**
4
   * TNH Framework
5
   *
6
   * A simple PHP framework using HMVC architecture
7
   *
8
   * This content is released under the GNU GPL License (GPL)
9
   *
10
   * Copyright (C) 2017 Tony NGUEREZA
11
   *
12
   * This program is free software; you can redistribute it and/or
13
   * modify it under the terms of the GNU General Public License
14
   * as published by the Free Software Foundation; either version 3
15
   * of the License, or (at your option) any later version.
16
   *
17
   * This program is distributed in the hope that it will be useful,
18
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   * GNU General Public License for more details.
21
   *
22
   * You should have received a copy of the GNU General Public License
23
   * along with this program; if not, write to the Free Software
24
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25
  */
26
  class DatabaseQueryRunner{
27
      
28
    /**
29
	* The logger instance
30
	* @var object
31
	*/
32
    private $logger            = null;
33
    
34
  	/**
35
  	 * The last query result
36
  	 * @var object
37
  	*/
38
  	private $queryResult       = null;
39
  	
40
  	/**
41
    * The benchmark instance
42
    * @var object
43
    */
44
    private $benchmarkInstance = null;
45
    
46
    /**
47
	 * The SQL query statment to execute
48
	 * @var string
49
	*/
50
    private $query             = null;
51
    
52
    /**
53
	 * Indicate if we need return result as list (boolean) 
54
     * or the data used to replace the placeholder (array)
55
	 * @var array|boolean
56
	 */
57
     private $returnAsList     = true;
58
     
59
     
60
     /**
61
	   * Indicate if we need return result as array or not
62
     * @var boolean
63
	   */
64
     private $returnAsArray     = true;
65
     
66
     /**
67
     * The last PDOStatment instance
68
     * @var object
69
     */
70
     private $pdoStatment       = null;
71
     
72
     /**
73
  	 * The error returned for the last query
74
  	 * @var string
75
  	 */
76
     private $error             = null;
77
	
78
    /**
79
     * The PDO instance
80
     * @var object
81
    */
82
    private $pdo                = null;
83
  
84
    /**
85
     * The database driver name used
86
     * @var string
87
    */
88
    private $driver             = null;
89
90
91
	
92
    /**
93
     * Construct new DatabaseQueryRunner
94
     * @param object $pdo the PDO object
95
     * @param string $query the SQL query to be executed
96
     * @param boolean $returnAsList if need return as list or just one row
97
     * @param boolean $returnAsArray whether to return the result as array or not
98
     */
99
    public function __construct(PDO $pdo = null, $query = null, $returnAsList = true, $returnAsArray = false){
100
        if (is_object($pdo)){
101
          $this->pdo = $pdo;
102
        }
103
        $this->query         = $query;
104
        $this->returnAsList  = $returnAsList;
105
        $this->returnAsArray = $returnAsArray;
106
        $this->setLoggerFromParamOrCreateNewInstance(null);
107
    }
108
    
109
    /**
110
     * Run the database SQL query and return the DatabaseQueryResult object
111
     * @see Database::query
112
     * 
113
     * @return object|void
114
     */
115
    public function execute(){
116
        //reset instance
117
        $this->reset();
118
       
119
       //for database query execution time
120
        $benchmarkMarkerKey = $this->getBenchmarkKey();
121
        if (! is_object($this->benchmarkInstance)){
122
          $this->benchmarkInstance = & class_loader('Benchmark');
123
        }
124
        
125
        $this->logger->info('Execute SQL query [' . $this->query . ']');
126
127
        $this->benchmarkInstance->mark('DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')');                
128
        //Now execute the query
129
        $this->pdoStatment = $this->pdo->query($this->query);
130
        
131
        //get response time for this query
132
        $responseTime = $this->benchmarkInstance->elapsedTime(
133
                                                                'DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')', 
134
                                                                'DATABASE_QUERY_END(' . $benchmarkMarkerKey . ')'
135
                                                              );
136
		    //TODO use the configuration value for the high response time currently is 1 second
137
        if ($responseTime >= 1 ){
138
            $this->logger->warning(
139
                                    'High response time while processing database query [' . $this->query . ']. 
140
                                     The response time is [' .$responseTime. '] sec.'
141
                                  );
142
        }
143
		
144
        if ($this->pdoStatment !== false){
145
          $isSqlSELECTQuery = stristr($this->query, 'SELECT') !== false;
146
          if($isSqlSELECTQuery){
147
              $this->setResultForSelect();              
148
          }
149
          else{
150
              $this->setResultForNonSelect();
151
          }
152
          return $this->queryResult;
153
        }
154
        $this->setQueryRunnerError();
155
    }
156
	
157
   /**
158
   * Return the result for SELECT query
159
   * @see DatabaseQueryRunner::execute
160
   */
161
    protected function setResultForSelect(){
162
      //if need return all result like list of record
163
      $result = null;
164
      $numRows = 0;
165
      $fetchMode = PDO::FETCH_OBJ;
166
      if($this->returnAsArray){
167
        $fetchMode = PDO::FETCH_ASSOC;
168
      }
169
      if ($this->returnAsList){
170
          $result = $this->pdoStatment->fetchAll($fetchMode);
171
      }
172
      else{
173
          $result = $this->pdoStatment->fetch($fetchMode);
174
      }
175
      //Sqlite and pgsql always return 0 when using rowCount()
176
      if (in_array($this->driver, array('sqlite', 'pgsql'))){
177
        $numRows = count($result);  
178
      }
179
      else{
180
        $numRows = $this->pdoStatment->rowCount(); 
181
      }
182
      if(! is_object($this->queryResult)){
183
          $this->queryResult = & class_loader('DatabaseQueryResult', 'classes/database');
184
      }
185
      $this->queryResult->setResult($result);
186
      $this->queryResult->setNumRows($numRows);
187
    }
188
189
    /**
190
   * Return the result for non SELECT query
191
   * @see DatabaseQueryRunner::execute
192
   */
193
    protected function setResultForNonSelect(){
194
      //Sqlite and pgsql always return 0 when using rowCount()
195
      $result = false;
196
      $numRows = 0;
197
      if (in_array($this->driver, array('sqlite', 'pgsql'))){
198
        $result = true; //to test the result for the query like UPDATE, INSERT, DELETE
199
        $numRows = 1; //TODO use the correct method to get the exact affected row
200
      }
201
      else{
202
          //to test the result for the query like UPDATE, INSERT, DELETE
203
          $result  = $this->pdoStatment->rowCount() >= 0; 
204
          $numRows = $this->pdoStatment->rowCount(); 
205
      }
206
      if(! is_object($this->queryResult)){
207
          $this->queryResult = & class_loader('DatabaseQueryResult', 'classes/database');
208
      }
209
      $this->queryResult->setResult($result);
210
      $this->queryResult->setNumRows($numRows);
211
    }
212
213
214
	/**
215
     * Return the benchmark instance
216
     * @return Benchmark
217
     */
218
    public function getBenchmark(){
219
      return $this->benchmarkInstance;
220
    }
221
222
    /**
223
     * Set the benchmark instance
224
     * @param Benchmark $benchmark the benchmark object
225
	 * @return object DatabaseQueryRunner
226
     */
227
    public function setBenchmark($benchmark){
228
      $this->benchmarkInstance = $benchmark;
229
      return $this;
230
    }
231
    
232
    /**
233
     * Return the database query result
234
     *
235
     * @return object DatabaseQueryResult
236
     */
237
    public function getQueryResult(){
238
      return $this->queryResult;
239
    }
240
241
    /**
242
     * Set the database query result instance
243
     * @param object $queryResult the query result
244
     *
245
	 * @return object DatabaseQueryRunner
246
     */
247
    public function setQueryResult(DatabaseQueryResult $queryResult){
248
      $this->queryResult = $queryResult;
249
      return $this;
250
    }
251
    
252
    /**
253
     * Return the Log instance
254
     * @return Log
255
     */
256
    public function getLogger(){
257
      return $this->logger;
258
    }
259
260
    /**
261
     * Set the log instance
262
     * @param Log $logger the log object
263
	 * @return object DatabaseQueryRunner
264
     */
265
    public function setLogger($logger){
266
      $this->logger = $logger;
267
      return $this;
268
    }
269
    
270
    /**
271
     * Return the current query SQL string
272
     * @return string
273
     */
274
    public function getQuery(){
275
      return $this->query;
276
    }
277
    
278
    /**
279
     * Set the query SQL string
280
     * @param string $query the SQL query to set
281
     * @return object DatabaseQueryRunner
282
     */
283
    public function setQuery($query){
284
       $this->query = $query;
285
       return $this;
286
    }
287
    
288
    /**
289
     * Set the query return type as list or not
290
     * @param boolean $returnType
291
     * @return object DatabaseQueryRunner
292
     */
293
    public function setReturnType($returnType){
294
       $this->returnAsList = $returnType;
295
       return $this;
296
    }
297
    
298
    /**
299
     * Set the return as array or not
300
     * @param boolean $status the status if true will return as array
301
     * @return object DatabaseQueryRunner
302
     */
303
    public function setReturnAsArray($status = true){
304
       $this->returnAsArray = $status;
305
       return $this;
306
    }
307
    
308
    /**
309
     * Return the error for last query execution
310
     * @return string
311
     */
312
    public function getQueryError(){
313
      return $this->error;
314
    }
315
316
    /**
317
     * Return the PDO instance
318
     * @return object
319
     */
320
    public function getPdo(){
321
      return $this->pdo;
322
    }
323
324
    /**
325
     * Set the PDO instance
326
     * @param PDO $pdo the pdo object
327
     * @return object DatabaseQueryRunner
328
     */
329
    public function setPdo(PDO $pdo = null){
330
      $this->pdo = $pdo;
331
      return $this;
332
    }
333
  
334
     /**
335
     * Return the database driver
336
     * @return string
337
     */
338
    public function getDriver(){
339
      return $this->driver;
340
    }
341
342
    /**
343
     * Set the database driver
344
     * @param string $driver the new driver
345
     * @return object DatabaseQueryRunner
346
     */
347
    public function setDriver($driver){
348
      $this->driver = $driver;
349
      return $this;
350
    }
351
    
352
    /**
353
     * Return the benchmark key for the current query
354
     * 
355
     *  @return string
356
     */
357
    protected function getBenchmarkKey(){
358
      return md5($this->query . $this->returnAsList . $this->returnAsArray);
0 ignored issues
show
Bug introduced by
Are you sure $this->returnAsList of type array|boolean can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

358
      return md5($this->query . /** @scrutinizer ignore-type */ $this->returnAsList . $this->returnAsArray);
Loading history...
359
    }
360
    
361
    /**
362
     * Set error for database query execution
363
     */
364
    protected function setQueryRunnerError(){
365
      $error = $this->pdo->errorInfo();
366
      $this->error = isset($error[2]) ? $error[2] : '';
367
      $this->logger->error('The database query execution got an error: ' . stringfy_vars($error));
368
	  //show error message
369
      show_error('Query: "' . $this->query . '" Error: ' . $this->error, 'Database Error');
370
    }
371
    
372
    /**
373
     * Set the Log instance using argument or create new instance
374
     * @param object $logger the Log instance if not null
375
     */
376
    protected function setLoggerFromParamOrCreateNewInstance(Log $logger = null){
377
      if ($logger !== null){
378
        $this->logger = $logger;
379
      }
380
      else{
381
          $this->logger =& class_loader('Log', 'classes');
382
          $this->logger->setLogger('Library::DatabaseQueryRunner');
383
      }
384
    }
385
    
386
    
387
    /**
388
    * Reset the instance before run each query
389
    */
390
    private function reset(){
391
        $this->error = null;
392
        $this->pdoStatment = null;
393
    }
394
395
}
396