Completed
Push — 2.0 ( c11079...9c6898 )
by Vermeulen
02:10
created

SqlActions::isAssembled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
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
     * Define driver options to prepared request
106
     * 
107
     * @link http://php.net/manual/fr/pdo.prepare.php
108
     * 
109
     * @param array $driverOptions Drivers options
110
     * 
111
     * @return \BfwSql\SqlActions
112
     */
113
    public function setPrepareDriversOptions($driverOptions)
114
    {
115
        $this->prepareDriversOptions = $driverOptions;
116
        
117
        return $this;
118
    }
119
    
120
    /**
121
     * Check if a request is assemble or not.
122
     * If not, run the method assembleRequest.
123
     * 
124
     * @return boolean
125
     */
126
    public function isAssembled()
127
    {
128
        if ($this->assembledRequest === '') {
129
            return false;
130
        }
131
        
132
        return true;
133
    }
134
    
135
    /**
136
     * Write the query
137
     * 
138
     * @return void
139
     */
140
    protected abstract function assembleRequest();
141
    
142
    /**
143
     * Return the assembled request
144
     * 
145
     * @param boolean $force : Force to re-assemble request
146
     * 
147
     * @return string
148
     */
149
    public function assemble($force = false)
150
    {
151
        if ($this->isAssembled() === false || $force === true) {
152
            $this->assembleRequest();
153
        }
154
        
155
        return $this->assembledRequest;
156
    }
157
    
158
    /**
159
     * Execute the assembled request
160
     * 
161
     * @return array The pdo errorInfo array
162
     */
163
    protected function executeQuery()
164
    {
165
        $pdo = $this->sqlConnect->getPDO();
166
        $this->sqlConnect->upNbQuery();
167
        $this->assemble();
168
        
169
        if ($this->isPreparedRequest) {
170
            $req = $pdo->prepare(
171
                $this->assembledRequest,
172
                $this->prepareDriversOptions
173
            );
174
            
175
            $req->execute($this->preparedRequestArgs);
176
            $error = $req->errorInfo();
177
        } else {
178
            $pdoMethodToCall = 'exec';
179
            if ($this instanceof \BfwSql\SqlSelect) {
180
                $pdoMethodToCall = 'query';
181
            }
182
            
183
            $req   = $pdo->{$pdoMethodToCall}($this->assembledRequest);
184
            $error = $pdo->errorInfo();
185
        }
186
        
187
        $this->lastRequestStatement = $req;
188
        
189
        return $error;
190
    }
191
    
192
    /**
193
     * Execute the assembled request and check if there are errors
194
     * Update property noResult
195
     * 
196
     * @throws \Exception If the request fail
197
     * 
198
     * @return \PDOStatement|integer
199
     */
200
    public function execute()
201
    {
202
        $error = $this->executeQuery();
203
        
204
        //Throw an exception if they are an error with the request
205
        if ($error[0] !== null && $error[0] !== '00000') {
206
            throw new Exception($error[2]);
207
        }
208
        
209
        if ($this->lastRequestStatement === false) {
210
            throw new Exception(
211
                'An error occurred during the execution of the request'
212
            );
213
        }
214
        
215
        $this->noResult = false;
216
        if ($this->obtainImpactedRows() === 0) {
217
            $this->noResult = true;
218
        }
219
220
        return $this->lastRequestStatement;
221
    }
222
    
223
    /**
224
     * Closes the cursor, enabling the statement to be executed again.
225
     * 
226
     * @link http://php.net/manual/fr/pdostatement.closecursor.php
227
     * 
228
     * @return void
229
     */
230
    public function closeCursor()
231
    {
232
        return $this->lastRequestStatement->closeCursor();
233
    }
234
    
235
    /**
236
     * Return the number of impacted rows by the last request
237
     * 
238
     * @return int|bool
239
     */
240
    public function obtainImpactedRows()
241
    {
242
        if (is_object($this->lastRequestStatement)) {
243
            //If pdo::query or pdo::prepare
244
            return $this->lastRequestStatement->rowCount();
245
        } elseif (is_integer($this->lastRequestStatement)) {
246
            //If pdo::exec
247
            return $this->lastRequestStatement;
248
        }
249
        
250
        //Security if call without executed a request
251
        return false;
252
    }
253
    
254
    /**
255
     * To call this own request without use query writer
256
     * 
257
     * @param string $request The user request
258
     * 
259
     * @return void
260
     */
261
    public function query($request)
262
    {
263
        $this->assembledRequest = $request;
264
    }
265
    
266
    /**
267
     * Add a filter to where part of the request
268
     * 
269
     * @param string     $filter          The filter to add
270
     * @param array|null $preparedFilters (default: null) Filters to add
271
     *  in prepared request
272
     * 
273
     * @throws \Exception If key on prepared request is already used
274
     * 
275
     * @return \BfwSql\SqlActions
276
     */
277
    public function where($filter, $preparedFilters = null)
278
    {
279
        $this->where[] = $filter;
280
        
281
        if (is_array($preparedFilters)) {
282
            $this->addPreparedFilters($preparedFilters);
283
        }
284
        
285
        return $this;
286
    }
287
    
288
    /**
289
     * Add filters to prepared requests
290
     * 
291
     * @param array $preparedFilters Filters to add in prepared request
292
     * 
293
     * @return void
294
     */
295
    protected function addPreparedFilters($preparedFilters)
296
    {
297
        foreach ($preparedFilters as $prepareKey => $prepareValue) {
298
            $this->preparedRequestArgs[$prepareKey] = $prepareValue;
299
        }
300
    }
301
    
302
    /**
303
     * Write the where part of a sql query and return it
304
     * 
305
     * @return string
306
     */
307
    protected function generateWhere()
308
    {
309
        $where = '';
310
        
311
        //check if there are filters to write
312
        if (count($this->where) > 0) {
313
            $where = ' WHERE ';
314
            
315
            foreach ($this->where as $filter) {
316
                
317
                if ($where != ' WHERE ') {
318
                    $where .= ' AND ';
319
                }
320
                
321
                $where .= $filter;
322
            } 
323
        }
324
        
325
        return $where;
326
    }
327
    
328
    /**
329
     * Add datas to insert or update for a column.
330
     * Used by UPDATE and INSERT requests
331
     * 
332
     * @param array $columns Datas to add or update
333
     *  Format : array('sqlColumnName' => 'valueForThisColumn', ...);
334
     * 
335
     * @return \BfwSql\SqlActions
336
     */
337
    public function addDatasForColumns(array $columns)
338
    {
339
        foreach ($columns as $columnName => $data) {
340
            if (
341
                isset($this->columns[$columnName])
342
                && $this->columns[$columnName] != $data
343
            ) {
344
                throw new \Exception(
345
                    'A different data is already declared for the column '
346
                    .$columnName
347
                );
348
            }
349
            
350
            $this->columns[$columnName] = $data;
351
        }
352
        
353
        return $this;
354
    }
355
    
356
    /**
357
     * Send a notify to application observers
358
     * 
359
     * @return void
360
     */
361
    protected function callObserver()
362
    {
363
        $app = \BFW\Application::getInstance();
364
        $app->setContext($this);
365
        $app->notifyAction('BfwSqlRequest');
366
    }
367
}
368