1 | <?php |
||
2 | |||
3 | namespace BfwSql\Executers; |
||
4 | |||
5 | use \Exception; |
||
6 | |||
7 | class Common |
||
8 | { |
||
9 | /** |
||
10 | * @const ERR_EXECUTE_BAD_REQUEST Exception code if a request has fail |
||
11 | * during execution |
||
12 | */ |
||
13 | const ERR_EXECUTE_BAD_REQUEST = 2201001; |
||
14 | |||
15 | /** |
||
16 | * @const ERR_EXECUTED_UNKNOWN_ERROR Exception code if a request has fail |
||
17 | * but when the error has not been returned by PDO::errorInfos() |
||
18 | */ |
||
19 | const ERR_EXECUTED_UNKNOWN_ERROR = 2201002; |
||
20 | |||
21 | /** |
||
22 | * @const ERR_CLOSE_CURSOR_NOT_PDOSTATEMENT Exception code if the method |
||
23 | * closeCursor is called for a request who have not returned a |
||
24 | * PDOStatement object. |
||
25 | */ |
||
26 | const ERR_CLOSE_CURSOR_NOT_PDOSTATEMENT = 2201003; |
||
27 | |||
28 | /** |
||
29 | * @var \BfwSql\Queries\AbstractQuery $query Query system object |
||
30 | */ |
||
31 | protected $query; |
||
32 | |||
33 | /** |
||
34 | * @var \BfwSql\SqlConnect $sqlConnect SqlConnect object |
||
35 | */ |
||
36 | protected $sqlConnect; |
||
37 | |||
38 | /** |
||
39 | * @var boolean $isPreparedRequest If is a prepared request |
||
40 | */ |
||
41 | protected $isPreparedRequest = true; |
||
42 | |||
43 | /** |
||
44 | * @var array $lastErrorInfos The PDO::errorInfos return for the last |
||
45 | * query executed. Empty if no request has been executed. |
||
46 | */ |
||
47 | protected $lastErrorInfos = []; |
||
48 | |||
49 | /** |
||
50 | * @var \PDOStatement|integer|bool $lastRequestStatement The PDOStatement |
||
51 | * for the last request executed. Or integer if the request return the number |
||
52 | * of row impacted. Or a boolean (false) if request failed. |
||
53 | */ |
||
54 | protected $lastRequestStatement; |
||
55 | |||
56 | /** |
||
57 | * @var boolean $noResult If request has sent no result. |
||
58 | */ |
||
59 | protected $noResult = false; |
||
60 | |||
61 | /** |
||
62 | * @var array $prepareDriversOptions SGBD driver option used for |
||
63 | * prepared request |
||
64 | * |
||
65 | * @link http://php.net/manual/en/pdo.prepare.php |
||
66 | */ |
||
67 | protected $prepareDriversOptions = array(); |
||
68 | |||
69 | /** |
||
70 | * Constructor |
||
71 | * |
||
72 | * @param \BfwSql\Queries\AbstractQuery $query Instance of query |
||
73 | * system |
||
74 | */ |
||
75 | public function __construct(\BfwSql\Queries\AbstractQuery $query) |
||
76 | { |
||
77 | $this->query = $query; |
||
78 | $this->sqlConnect = $query->getSqlConnect(); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * Getter to access to isPreparedRequest property |
||
83 | * |
||
84 | * @return boolean |
||
85 | */ |
||
86 | public function getIsPreparedRequest(): bool |
||
87 | { |
||
88 | return $this->isPreparedRequest; |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Setter to enable or disable prepared request |
||
93 | * |
||
94 | * @param boolean $preparedRequestStatus The new status for prepared request |
||
95 | * |
||
96 | * @return $this |
||
97 | */ |
||
98 | public function setIsPreparedRequest(bool $preparedRequestStatus): self |
||
99 | { |
||
100 | $this->isPreparedRequest = (bool) $preparedRequestStatus; |
||
101 | |||
102 | return $this; |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Getter to access to lastErrorInfos property |
||
107 | * |
||
108 | * @return array |
||
109 | */ |
||
110 | public function getLastErrorInfos(): array |
||
111 | { |
||
112 | return $this->lastErrorInfos; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Getter to access to lastRequestStatement property |
||
117 | * |
||
118 | * @return \PDOStatement|integer|bool|null |
||
119 | */ |
||
120 | public function getLastRequestStatement() |
||
121 | { |
||
122 | return $this->lastRequestStatement; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Getter to access to noResult property |
||
127 | * |
||
128 | * @return boolean |
||
129 | */ |
||
130 | public function getNoResult(): bool |
||
131 | { |
||
132 | return $this->noResult; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Getter to access at prepareDriversOptions property |
||
137 | * |
||
138 | * @return array |
||
139 | */ |
||
140 | public function getPrepareDriversOptions(): array |
||
141 | { |
||
142 | return $this->prepareDriversOptions; |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * Define driver options to prepared request |
||
147 | * |
||
148 | * @link http://php.net/manual/fr/pdo.prepare.php |
||
149 | * |
||
150 | * @param array $driverOptions Drivers options |
||
151 | * |
||
152 | * @return $this |
||
153 | */ |
||
154 | public function setPrepareDriversOptions(array $driverOptions): self |
||
155 | { |
||
156 | $this->prepareDriversOptions = $driverOptions; |
||
157 | |||
158 | return $this; |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Getter accessor to property query |
||
163 | * |
||
164 | * @return \BfwSql\Queries\AbstractQuery |
||
165 | */ |
||
166 | public function getQuery(): \BfwSql\Queries\AbstractQuery |
||
167 | { |
||
168 | return $this->query; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Getter to access at sqlConnect property |
||
173 | * |
||
174 | * @return \BfwSql\SqlConnect |
||
175 | */ |
||
176 | public function getSqlConnect(): \BfwSql\SqlConnect |
||
177 | { |
||
178 | return $this->sqlConnect; |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Execute the assembled request |
||
183 | * |
||
184 | * @return array The pdo errorInfo array |
||
185 | */ |
||
186 | protected function executeQuery(): array |
||
187 | { |
||
188 | $this->sqlConnect->upNbQuery(); |
||
189 | $this->query->assemble(); |
||
190 | |||
191 | try { |
||
192 | if ($this->isPreparedRequest) { |
||
193 | $req = $this->executePreparedQuery(); |
||
194 | } else { |
||
195 | $req = $this->executeNotPreparedQuery(); |
||
196 | } |
||
197 | |||
198 | $this->lastRequestStatement = $req; |
||
199 | } catch (\Throwable $e) { |
||
200 | \BFW\Application::getInstance() |
||
201 | ->getModuleList() |
||
202 | ->getModuleByName('bfw-sql') |
||
203 | ->monolog |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
204 | ->getLogger() |
||
205 | ->warning( |
||
206 | 'Exception while query execution : '.$e->getMessage() |
||
207 | ) |
||
208 | ; |
||
209 | |||
210 | throw new \Exception($e->getMessage(), (int) $e->getCode(), $e); |
||
211 | } finally { |
||
212 | $this->lastErrorInfos = $this->sqlConnect->getPDO()->errorInfo(); |
||
213 | $this->callObserver(); |
||
214 | } |
||
215 | |||
216 | return $this->lastErrorInfos; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Execute a prepared request |
||
221 | * |
||
222 | * @return \PDOStatement|bool |
||
223 | */ |
||
224 | protected function executePreparedQuery() |
||
225 | { |
||
226 | $pdo = $this->sqlConnect->getPDO(); |
||
227 | $req = $pdo->prepare( |
||
228 | $this->query->getAssembledRequest(), |
||
229 | $this->prepareDriversOptions |
||
230 | ); |
||
231 | |||
232 | $req->execute($this->query->getPreparedParams()); |
||
233 | |||
234 | return $req; |
||
235 | } |
||
236 | |||
237 | /** |
||
238 | * Execute a not prepared request |
||
239 | * |
||
240 | * @return \PDOStatement|integer|bool |
||
241 | */ |
||
242 | protected function executeNotPreparedQuery() |
||
243 | { |
||
244 | $pdoMethodToCall = 'exec'; |
||
245 | if ($this->query instanceof \BfwSql\Queries\Select) { |
||
246 | $pdoMethodToCall = 'query'; |
||
247 | } |
||
248 | |||
249 | $pdo = $this->sqlConnect->getPDO(); |
||
250 | return $pdo->{$pdoMethodToCall}($this->query->getAssembledRequest()); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Execute the assembled request and check if there are errors |
||
255 | * Update property noResult |
||
256 | * |
||
257 | * @throws \Exception If the request fail |
||
258 | * |
||
259 | * @return \PDOStatement|integer |
||
260 | */ |
||
261 | public function execute() |
||
262 | { |
||
263 | $error = $this->executeQuery(); |
||
264 | |||
265 | //Throw an exception if they are an error with the request |
||
266 | if ($error[0] !== null && $error[0] !== '00000') { |
||
267 | throw new Exception( |
||
268 | $error[2], |
||
269 | self::ERR_EXECUTE_BAD_REQUEST |
||
270 | ); |
||
271 | } |
||
272 | |||
273 | if ($this->lastRequestStatement === false) { |
||
274 | throw new Exception( |
||
275 | 'An error occurred during the execution of the request', |
||
276 | self::ERR_EXECUTED_UNKNOWN_ERROR |
||
277 | ); |
||
278 | } |
||
279 | |||
280 | $this->noResult = false; |
||
281 | if ($this->obtainImpactedRows() === 0) { |
||
282 | $this->noResult = true; |
||
283 | } |
||
284 | |||
285 | return $this->lastRequestStatement; |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Closes the cursor, enabling the statement to be executed again. |
||
290 | * |
||
291 | * @link http://php.net/manual/fr/pdostatement.closecursor.php |
||
292 | * |
||
293 | * @throws \Exception If the property $lastRequestStatement is not a |
||
294 | * PDOStatement object. |
||
295 | * |
||
296 | * @return bool |
||
297 | */ |
||
298 | public function closeCursor(): bool |
||
299 | { |
||
300 | if ($this->lastRequestStatement instanceof \PDOStatement === false) { |
||
301 | throw new Exception( |
||
302 | 'The cursor can\'t be close because the request ' |
||
303 | .'not have return a PDOStatement object.', |
||
304 | self::ERR_CLOSE_CURSOR_NOT_PDOSTATEMENT |
||
305 | ); |
||
306 | } |
||
307 | |||
308 | return $this->lastRequestStatement->closeCursor(); |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Return the number of impacted rows by the last request |
||
313 | * |
||
314 | * @return int|bool |
||
315 | */ |
||
316 | public function obtainImpactedRows() |
||
317 | { |
||
318 | if (is_object($this->lastRequestStatement)) { |
||
319 | //If pdo::query or pdo::prepare |
||
320 | return $this->lastRequestStatement->rowCount(); |
||
321 | } elseif (is_integer($this->lastRequestStatement)) { |
||
322 | //If pdo::exec |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
40% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
323 | return $this->lastRequestStatement; |
||
324 | } |
||
325 | |||
326 | //Security if call without executed a request |
||
327 | return false; |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * Send a notify to application observers |
||
332 | * |
||
333 | * @return void |
||
334 | */ |
||
335 | protected function callObserver() |
||
336 | { |
||
337 | $app = \BFW\Application::getInstance(); |
||
338 | $subject = $app->getSubjectList()->getSubjectByName('bfw-sql'); |
||
339 | $subject->addNotification('system query', clone $this); |
||
340 | } |
||
341 | } |
||
342 |