Completed
Push — 2.0 ( 67733d...ad1c2d )
by Vermeulen
02:14
created

SqlActions   B

Complexity

Total Complexity 37

Size/Duplication

Total Lines 374
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
wmc 37
lcom 2
cbo 1
dl 0
loc 374
rs 8.6
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getSqlConnect() 0 4 1
A setIsPreparedRequest() 0 6 1
A getPreparedRequestArgs() 0 4 1
A getPrepareDriversOptions() 0 4 1
A setPrepareDriversOptions() 0 6 1
A isAssembled() 0 8 2
assembleRequest() 0 1 ?
A assemble() 0 8 3
B executeQuery() 0 28 3
B execute() 0 22 5
A closeCursor() 0 4 1
A obtainImpactedRows() 0 13 3
A query() 0 4 1
A where() 0 10 2
A addPreparedFilters() 0 6 2
A generateWhere() 0 20 4
A addDatasForColumns() 0 18 4
A callObserver() 0 6 1
1
<?php
2
3
namespace BfwSql;
4
5
use \Exception;
6
7
/**
8
 * Abstract class used for all query writer class.
9
 * 
10
 * @package bfw-sql
11
 * @author Vermeulen Maxime <[email protected]>
12
 * @version 2.0
13
 */
14
abstract class SqlActions
15
{
16
    /**
17
     * @var \BfwSql\SqlConnect $sqlConnect SqlConnect object
18
     */
19
    protected $sqlConnect;
20
    
21
    /**
22
     * @var string $assembledRequest The request will be executed
23
     */
24
    protected $assembledRequest = '';
25
    
26
    /**
27
     * @var boolean $isPreparedRequest If is a prepared request
28
     */
29
    protected $isPreparedRequest = true;
30
    
31
    /**
32
     * @var string $tableName The main table name for request
33
     */
34
    protected $tableName = '';
35
    
36
    /**
37
     * @var array $columns List of impacted columns by the request
38
     */
39
    protected $columns = array();
40
    
41
    /**
42
     * @var string[] $where All filter use in where part of the request
43
     */
44
    protected $where = array();
45
    
46
    /**
47
     * @var string[] $preparedRequestArgs Arguments used by prepared request
48
     */
49
    protected $preparedRequestArgs = array();
50
    
51
    /**
52
     * @var array $prepareDriversOptions SGBD driver option used for
53
     *  prepared request
54
     * 
55
     * @link http://php.net/manual/en/pdo.prepare.php
56
     */
57
    protected $prepareDriversOptions = array();
58
    
59
    /**
60
     * @var boolean $noResult If request has sent no result.
61
     */
62
    protected $noResult = false;
63
    
64
    /**
65
     * @var \PDOStatement $lastRequestStatement The PDOStatement pour the
66
     *  last request executed.
67
     */
68
    protected $lastRequestStatement;
69
    
70
    /**
71
     * Constructor
72
     * 
73
     * @param \BfwSql\SqlConnect $sqlConnect Instance of SGBD connexion
74
     */
75
    public function __construct(\BfwSql\SqlConnect $sqlConnect)
76
    {
77
        $this->sqlConnect = $sqlConnect;
78
    }
79
    
80
    /**
81
     * Getter to access at sqlConnect property
82
     * 
83
     * @return \BfwSql\SqlConnect
84
     */
85
    public function getSqlConnect()
86
    {
87
        return $this->sqlConnect;
88
    }
89
    
90
    /**
91
     * Setter to enable or disable prepared request
92
     * 
93
     * @param boolean $preparedRequestStatus The new status for prepared request
94
     * 
95
     * @return \BfwSql\SqlActions
96
     */
97
    public function setIsPreparedRequest($preparedRequestStatus)
98
    {
99
        $this->isPreparedRequest = (bool) $preparedRequestStatus;
100
        
101
        return $this;
102
    }
103
    
104
    /**
105
     * Getter to access at preparedRequestArgs property
106
     * 
107
     * @return array
108
     */
109
    public function getPreparedRequestArgs()
110
    {
111
        return $this->preparedRequestArgs;
112
    }
113
    
114
    /**
115
     * Getter to access at prepareDriversOptions property
116
     * 
117
     * @return array
118
     */
119
    public function getPrepareDriversOptions()
120
    {
121
        return $this->prepareDriversOptions;
122
    }
123
    
124
    /**
125
     * Define driver options to prepared request
126
     * 
127
     * @link http://php.net/manual/fr/pdo.prepare.php
128
     * 
129
     * @param array $driverOptions Drivers options
130
     * 
131
     * @return \BfwSql\SqlActions
132
     */
133
    public function setPrepareDriversOptions($driverOptions)
134
    {
135
        $this->prepareDriversOptions = $driverOptions;
136
        
137
        return $this;
138
    }
139
    
140
    /**
141
     * Check if a request is assemble or not.
142
     * If not, run the method assembleRequest.
143
     * 
144
     * @return boolean
145
     */
146
    public function isAssembled()
147
    {
148
        if ($this->assembledRequest === '') {
149
            return false;
150
        }
151
        
152
        return true;
153
    }
154
    
155
    /**
156
     * Write the query
157
     * 
158
     * @return void
159
     */
160
    protected abstract function assembleRequest();
161
    
162
    /**
163
     * Return the assembled request
164
     * 
165
     * @param boolean $force : Force to re-assemble request
166
     * 
167
     * @return string
168
     */
169
    public function assemble($force = false)
170
    {
171
        if ($this->isAssembled() === false || $force === true) {
172
            $this->assembleRequest();
173
        }
174
        
175
        return $this->assembledRequest;
176
    }
177
    
178
    /**
179
     * Execute the assembled request
180
     * 
181
     * @return array The pdo errorInfo array
182
     */
183
    protected function executeQuery()
184
    {
185
        $pdo = $this->sqlConnect->getPDO();
186
        $this->sqlConnect->upNbQuery();
187
        $this->assemble();
188
        
189
        if ($this->isPreparedRequest) {
190
            $req = $pdo->prepare(
191
                $this->assembledRequest,
192
                $this->prepareDriversOptions
193
            );
194
            
195
            $req->execute($this->preparedRequestArgs);
196
            $error = $req->errorInfo();
197
        } else {
198
            $pdoMethodToCall = 'exec';
199
            if ($this instanceof \BfwSql\SqlSelect) {
200
                $pdoMethodToCall = 'query';
201
            }
202
            
203
            $req   = $pdo->{$pdoMethodToCall}($this->assembledRequest);
204
            $error = $pdo->errorInfo();
205
        }
206
        
207
        $this->lastRequestStatement = $req;
208
        
209
        return $error;
210
    }
211
    
212
    /**
213
     * Execute the assembled request and check if there are errors
214
     * Update property noResult
215
     * 
216
     * @throws \Exception If the request fail
217
     * 
218
     * @return \PDOStatement|integer
219
     */
220
    public function execute()
221
    {
222
        $error = $this->executeQuery();
223
        
224
        //Throw an exception if they are an error with the request
225
        if ($error[0] !== null && $error[0] !== '00000') {
226
            throw new Exception($error[2]);
227
        }
228
        
229
        if ($this->lastRequestStatement === false) {
230
            throw new Exception(
231
                'An error occurred during the execution of the request'
232
            );
233
        }
234
        
235
        $this->noResult = false;
236
        if ($this->obtainImpactedRows() === 0) {
237
            $this->noResult = true;
238
        }
239
240
        return $this->lastRequestStatement;
241
    }
242
    
243
    /**
244
     * Closes the cursor, enabling the statement to be executed again.
245
     * 
246
     * @link http://php.net/manual/fr/pdostatement.closecursor.php
247
     * 
248
     * @return void
249
     */
250
    public function closeCursor()
251
    {
252
        return $this->lastRequestStatement->closeCursor();
253
    }
254
    
255
    /**
256
     * Return the number of impacted rows by the last request
257
     * 
258
     * @return int|bool
259
     */
260
    public function obtainImpactedRows()
261
    {
262
        if (is_object($this->lastRequestStatement)) {
263
            //If pdo::query or pdo::prepare
264
            return $this->lastRequestStatement->rowCount();
265
        } elseif (is_integer($this->lastRequestStatement)) {
266
            //If pdo::exec
267
            return $this->lastRequestStatement;
268
        }
269
        
270
        //Security if call without executed a request
271
        return false;
272
    }
273
    
274
    /**
275
     * To call this own request without use query writer
276
     * 
277
     * @param string $request The user request
278
     * 
279
     * @return void
280
     */
281
    public function query($request)
282
    {
283
        $this->assembledRequest = $request;
284
    }
285
    
286
    /**
287
     * Add a filter to where part of the request
288
     * 
289
     * @param string     $filter          The filter to add
290
     * @param array|null $preparedFilters (default: null) Filters to add
291
     *  in prepared request
292
     * 
293
     * @throws \Exception If key on prepared request is already used
294
     * 
295
     * @return \BfwSql\SqlActions
296
     */
297
    public function where($filter, $preparedFilters = null)
298
    {
299
        $this->where[] = $filter;
300
        
301
        if (is_array($preparedFilters)) {
302
            $this->addPreparedFilters($preparedFilters);
303
        }
304
        
305
        return $this;
306
    }
307
    
308
    /**
309
     * Add filters to prepared requests
310
     * 
311
     * @param array $preparedFilters Filters to add in prepared request
312
     * 
313
     * @return void
314
     */
315
    protected function addPreparedFilters($preparedFilters)
316
    {
317
        foreach ($preparedFilters as $prepareKey => $prepareValue) {
318
            $this->preparedRequestArgs[$prepareKey] = $prepareValue;
319
        }
320
    }
321
    
322
    /**
323
     * Write the where part of a sql query and return it
324
     * 
325
     * @return string
326
     */
327
    protected function generateWhere()
328
    {
329
        $where = '';
330
        
331
        //check if there are filters to write
332
        if (count($this->where) > 0) {
333
            $where = ' WHERE ';
334
            
335
            foreach ($this->where as $filter) {
336
                
337
                if ($where != ' WHERE ') {
338
                    $where .= ' AND ';
339
                }
340
                
341
                $where .= $filter;
342
            } 
343
        }
344
        
345
        return $where;
346
    }
347
    
348
    /**
349
     * Add datas to insert or update for a column.
350
     * Used by UPDATE and INSERT requests
351
     * 
352
     * @param array $columns Datas to add or update
353
     *  Format : array('sqlColumnName' => 'valueForThisColumn', ...);
354
     * 
355
     * @return \BfwSql\SqlActions
356
     */
357
    public function addDatasForColumns(array $columns)
358
    {
359
        foreach ($columns as $columnName => $data) {
360
            if (
361
                isset($this->columns[$columnName])
362
                && $this->columns[$columnName] != $data
363
            ) {
364
                throw new \Exception(
365
                    'A different data is already declared for the column '
366
                    .$columnName
367
                );
368
            }
369
            
370
            $this->columns[$columnName] = $data;
371
        }
372
        
373
        return $this;
374
    }
375
    
376
    /**
377
     * Send a notify to application observers
378
     * 
379
     * @return void
380
     */
381
    protected function callObserver()
382
    {
383
        $app = \BFW\Application::getInstance();
384
        $app->setContext($this);
385
        $app->notifyAction('BfwSqlRequest');
386
    }
387
}
388