| Total Complexity | 82 |
| Total Lines | 614 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like PDOSQLExecTask often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PDOSQLExecTask, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 65 | class PDOSQLExecTask extends PDOTask implements Condition |
||
| 66 | { |
||
| 67 | use FileListAware; |
||
| 68 | use FileSetAware; |
||
| 69 | |||
| 70 | public const DELIM_ROW = 'row'; |
||
| 71 | public const DELIM_NORMAL = 'normal'; |
||
| 72 | public const DELIM_NONE = 'none'; |
||
| 73 | /** |
||
| 74 | * Count of how many statements were executed successfully. |
||
| 75 | * |
||
| 76 | * @var int |
||
| 77 | */ |
||
| 78 | private $goodSql = 0; |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Count of total number of SQL statements. |
||
| 82 | * |
||
| 83 | * @var int |
||
| 84 | */ |
||
| 85 | private $totalSql = 0; |
||
| 86 | |||
| 87 | /** |
||
| 88 | * Database connection. |
||
| 89 | * |
||
| 90 | * @var PDO |
||
| 91 | */ |
||
| 92 | private $conn; |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Formatter elements. |
||
| 96 | * |
||
| 97 | * @var PDOSQLExecFormatterElement[] |
||
| 98 | */ |
||
| 99 | private $formatters = []; |
||
| 100 | |||
| 101 | /** |
||
| 102 | * SQL statement. |
||
| 103 | * |
||
| 104 | * @var PDOStatement |
||
| 105 | */ |
||
| 106 | private $statement; |
||
| 107 | |||
| 108 | /** |
||
| 109 | * SQL input file. |
||
| 110 | * |
||
| 111 | * @var File |
||
| 112 | */ |
||
| 113 | private $srcFile; |
||
| 114 | |||
| 115 | /** |
||
| 116 | * SQL input command. |
||
| 117 | * |
||
| 118 | * @var string |
||
| 119 | */ |
||
| 120 | private $sqlCommand = ''; |
||
| 121 | |||
| 122 | /** |
||
| 123 | * SQL transactions to perform. |
||
| 124 | */ |
||
| 125 | private $transactions = []; |
||
| 126 | |||
| 127 | /** |
||
| 128 | * SQL Statement delimiter (for parsing files). |
||
| 129 | * |
||
| 130 | * @var string |
||
| 131 | */ |
||
| 132 | private $delimiter = ';'; |
||
| 133 | |||
| 134 | /** |
||
| 135 | * The delimiter type indicating whether the delimiter will |
||
| 136 | * only be recognized on a line by itself. |
||
| 137 | */ |
||
| 138 | private $delimiterType = self::DELIM_NONE; |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Action to perform if an error is found. |
||
| 142 | */ |
||
| 143 | private $onError = 'abort'; |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Fetch mode for PDO select queries. |
||
| 147 | * |
||
| 148 | * @var int |
||
| 149 | */ |
||
| 150 | private $fetchMode; |
||
| 151 | |||
| 152 | /** |
||
| 153 | * The name of the property to set in the event of an error |
||
| 154 | */ |
||
| 155 | private $errorProperty; |
||
| 156 | |||
| 157 | /** |
||
| 158 | * The name of the property that receives the number of rows |
||
| 159 | * returned |
||
| 160 | */ |
||
| 161 | private $statementCountProperty; |
||
| 162 | |||
| 163 | /** |
||
| 164 | * @var bool |
||
| 165 | */ |
||
| 166 | private $keepformat = false; |
||
| 167 | |||
| 168 | /** |
||
| 169 | * @var bool |
||
| 170 | */ |
||
| 171 | private $expandProperties = true; |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Set the name of the SQL file to be run. |
||
| 175 | * Required unless statements are enclosed in the build file. |
||
| 176 | */ |
||
| 177 | public function setSrc(File $srcFile): void |
||
| 178 | { |
||
| 179 | $this->srcFile = $srcFile; |
||
| 180 | } |
||
| 181 | |||
| 182 | /** |
||
| 183 | * Set an inline SQL command to execute. |
||
| 184 | * NB: Properties are not expanded in this text. |
||
| 185 | * |
||
| 186 | * @param string $sql |
||
| 187 | */ |
||
| 188 | public function addText($sql): void |
||
| 191 | } |
||
| 192 | |||
| 193 | /** |
||
| 194 | * Creates a new PDOSQLExecFormatterElement for <formatter> element. |
||
| 195 | * |
||
| 196 | * @return PDOSQLExecFormatterElement |
||
| 197 | */ |
||
| 198 | public function createFormatter(): PDOSQLExecFormatterElement |
||
| 199 | { |
||
| 200 | $fe = new PDOSQLExecFormatterElement($this); |
||
| 201 | $this->formatters[] = $fe; |
||
| 202 | |||
| 203 | return $fe; |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * Add a SQL transaction to execute. |
||
| 208 | */ |
||
| 209 | public function createTransaction() |
||
| 210 | { |
||
| 211 | $t = new PDOSQLExecTransaction($this); |
||
| 212 | $this->transactions[] = $t; |
||
| 213 | |||
| 214 | return $t; |
||
| 215 | } |
||
| 216 | |||
| 217 | /** |
||
| 218 | * Set the statement delimiter. |
||
| 219 | * |
||
| 220 | * <p>For example, set this to "go" and delimitertype to "ROW" for |
||
| 221 | * Sybase ASE or MS SQL Server.</p> |
||
| 222 | */ |
||
| 223 | public function setDelimiter(string $delimiter): void |
||
| 224 | { |
||
| 225 | $this->delimiter = $delimiter; |
||
| 226 | } |
||
| 227 | |||
| 228 | /** |
||
| 229 | * Get the statement delimiter. |
||
| 230 | */ |
||
| 231 | public function getDelimiter(): string |
||
| 232 | { |
||
| 233 | return $this->delimiter; |
||
| 234 | } |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Set the Delimiter type for this sql task. The delimiter type takes two |
||
| 238 | * values - normal and row. Normal means that any occurrence of the delimiter |
||
| 239 | * terminate the SQL command whereas with row, only a line containing just |
||
| 240 | * the delimiter is recognized as the end of the command. |
||
| 241 | */ |
||
| 242 | public function setDelimiterType(string $delimiterType): void |
||
| 243 | { |
||
| 244 | $this->delimiterType = $delimiterType; |
||
| 245 | } |
||
| 246 | |||
| 247 | /** |
||
| 248 | * Action to perform when statement fails: continue, stop, or abort |
||
| 249 | * optional; default "abort". |
||
| 250 | * |
||
| 251 | * @param string $action continue|stop|abort |
||
| 252 | */ |
||
| 253 | public function setOnerror($action): void |
||
| 254 | { |
||
| 255 | $this->onError = $action; |
||
| 256 | } |
||
| 257 | |||
| 258 | /** |
||
| 259 | * Sets the fetch mode to use for the PDO resultset. |
||
| 260 | * |
||
| 261 | * @param mixed $mode the PDO fetchmode int or constant name |
||
| 262 | * |
||
| 263 | * @throws BuildException |
||
| 264 | */ |
||
| 265 | public function setFetchmode($mode): void |
||
| 266 | { |
||
| 267 | if (is_numeric($mode)) { |
||
| 268 | $this->fetchMode = (int) $mode; |
||
| 269 | } else { |
||
| 270 | if (defined($mode)) { |
||
| 271 | $this->fetchMode = constant($mode); |
||
| 272 | } else { |
||
| 273 | throw new BuildException('Invalid PDO fetch mode specified: ' . $mode, $this->getLocation()); |
||
| 274 | } |
||
| 275 | } |
||
| 276 | } |
||
| 277 | |||
| 278 | public function getGoodSQL() |
||
| 279 | { |
||
| 280 | return $this->goodSql; |
||
| 281 | } |
||
| 282 | |||
| 283 | /** |
||
| 284 | * Property to set to "true" if a statement throws an error. |
||
| 285 | * |
||
| 286 | * @param string $errorProperty the name of the property to set in the |
||
| 287 | * event of an error. |
||
| 288 | */ |
||
| 289 | public function setErrorProperty(string $errorProperty): void |
||
| 290 | { |
||
| 291 | $this->errorProperty = $errorProperty; |
||
| 292 | } |
||
| 293 | |||
| 294 | /** |
||
| 295 | * Sets a given property to the number of statements processed. |
||
| 296 | * @param string $statementCountProperty String |
||
| 297 | */ |
||
| 298 | public function setStatementCountProperty(string $statementCountProperty): void |
||
| 299 | { |
||
| 300 | $this->statementCountProperty = $statementCountProperty; |
||
| 301 | } |
||
| 302 | |||
| 303 | public function setKeepformat(bool $keepformat): void |
||
| 304 | { |
||
| 305 | $this->keepformat = $keepformat; |
||
| 306 | } |
||
| 307 | |||
| 308 | public function setExpandProperties(bool $expandProps): void |
||
| 309 | { |
||
| 310 | $this->expandProperties = $expandProps; |
||
| 311 | } |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Load the sql file and then execute it. |
||
| 315 | * |
||
| 316 | * {@inheritdoc} |
||
| 317 | * |
||
| 318 | * @throws BuildException |
||
| 319 | */ |
||
| 320 | public function main() |
||
| 321 | { |
||
| 322 | // Set a default fetchmode if none was specified |
||
| 323 | // (We're doing that here to prevent errors loading the class is PDO is not available.) |
||
| 324 | if (null === $this->fetchMode) { |
||
| 325 | $this->fetchMode = PDO::FETCH_ASSOC; |
||
| 326 | } |
||
| 327 | |||
| 328 | // Initialize the formatters here. This ensures that any parameters passed to the formatter |
||
| 329 | // element get passed along to the actual formatter object |
||
| 330 | foreach ($this->formatters as $fe) { |
||
| 331 | $fe->prepare($this->getLocation()); |
||
| 332 | } |
||
| 333 | |||
| 334 | $savedTransaction = []; |
||
| 335 | for ($i = 0, $size = count($this->transactions); $i < $size; ++$i) { |
||
| 336 | $savedTransaction[] = clone $this->transactions[$i]; |
||
| 337 | } |
||
| 338 | |||
| 339 | $savedSqlCommand = $this->sqlCommand; |
||
| 340 | |||
| 341 | $this->sqlCommand = trim($this->sqlCommand); |
||
| 342 | |||
| 343 | try { |
||
| 344 | if ( |
||
| 345 | null === $this->srcFile |
||
| 346 | && '' === $this->sqlCommand |
||
| 347 | && empty($this->filesets) |
||
| 348 | && empty($this->filelists) |
||
| 349 | && 0 === count($this->transactions) |
||
| 350 | ) { |
||
| 351 | throw new BuildException( |
||
| 352 | 'Source file or fileset/filelist, ' |
||
| 353 | . 'transactions or sql statement ' |
||
| 354 | . 'must be set!', |
||
| 355 | $this->getLocation() |
||
| 356 | ); |
||
| 357 | } |
||
| 358 | |||
| 359 | if (null !== $this->srcFile && !$this->srcFile->exists()) { |
||
| 360 | throw new BuildException('Source file does not exist!', $this->getLocation()); |
||
| 361 | } |
||
| 362 | |||
| 363 | // deal with the filesets |
||
| 364 | foreach ($this->filesets as $fs) { |
||
| 365 | $ds = $fs->getDirectoryScanner($this->project); |
||
| 366 | $srcDir = $fs->getDir($this->project); |
||
| 367 | $srcFiles = $ds->getIncludedFiles(); |
||
| 368 | // Make a transaction for each file |
||
| 369 | foreach ($srcFiles as $srcFile) { |
||
| 370 | $t = $this->createTransaction(); |
||
| 371 | $t->setSrc(new File($srcDir, $srcFile)); |
||
| 372 | } |
||
| 373 | } |
||
| 374 | |||
| 375 | // process filelists |
||
| 376 | foreach ($this->filelists as $fl) { |
||
| 377 | $srcDir = $fl->getDir($this->project); |
||
| 378 | $srcFiles = $fl->getFiles($this->project); |
||
| 379 | // Make a transaction for each file |
||
| 380 | foreach ($srcFiles as $srcFile) { |
||
| 381 | $t = $this->createTransaction(); |
||
| 382 | $t->setSrc(new File($srcDir, $srcFile)); |
||
| 383 | } |
||
| 384 | } |
||
| 385 | |||
| 386 | // Make a transaction group for the outer command |
||
| 387 | $t = $this->createTransaction(); |
||
| 388 | if ($this->srcFile) { |
||
| 389 | $t->setSrc($this->srcFile); |
||
| 390 | } |
||
| 391 | $t->addText($this->sqlCommand); |
||
| 392 | |||
| 393 | $this->conn = $this->getConnection(); |
||
| 394 | if ($this->conn === null) { |
||
| 395 | return; |
||
| 396 | } |
||
| 397 | |||
| 398 | try { |
||
| 399 | $this->statement = null; |
||
| 400 | |||
| 401 | // Initialize the formatters. |
||
| 402 | $this->initFormatters(); |
||
| 403 | |||
| 404 | try { |
||
| 405 | // Process all transactions |
||
| 406 | for ($i = 0, $size = count($this->transactions); $i < $size; ++$i) { |
||
| 407 | if (!$this->isAutocommit() || $this->conn->inTransaction()) { |
||
| 408 | $this->log('Beginning transaction', Project::MSG_VERBOSE); |
||
| 409 | $this->conn->beginTransaction(); |
||
| 410 | } |
||
| 411 | $this->transactions[$i]->runTransaction(); |
||
| 412 | if (!$this->isAutocommit() || $this->conn->inTransaction()) { |
||
| 413 | $this->log('Committing transaction', Project::MSG_VERBOSE); |
||
| 414 | $this->conn->commit(); |
||
| 415 | } |
||
| 416 | } |
||
| 417 | } catch (Exception $e) { |
||
| 418 | $this->closeConnection(); |
||
| 419 | |||
| 420 | throw new BuildException($e); |
||
| 421 | } |
||
| 422 | } catch (IOException | PDOException $e) { |
||
| 423 | $this->closeQuietly(); |
||
| 424 | $this->setErrorProp(); |
||
| 425 | if ('abort' === $this->onError) { |
||
| 426 | throw new BuildException($e->getMessage(), $this->getLocation()); |
||
| 427 | } |
||
| 428 | } |
||
| 429 | |||
| 430 | // Close the formatters. |
||
| 431 | $this->closeFormatters(); |
||
| 432 | |||
| 433 | $this->log( |
||
| 434 | $this->goodSql . ' of ' . $this->totalSql . |
||
| 435 | ' SQL statements executed successfully' |
||
| 436 | ); |
||
| 437 | $this->setStatementCountProp($this->goodSql); |
||
| 438 | } catch (Exception $e) { |
||
| 439 | throw new BuildException($e); |
||
| 440 | } finally { |
||
| 441 | $this->transactions = $savedTransaction; |
||
| 442 | $this->sqlCommand = $savedSqlCommand; |
||
| 443 | $this->closeConnection(); |
||
| 444 | } |
||
| 445 | } |
||
| 446 | |||
| 447 | /** |
||
| 448 | * read in lines and execute them. |
||
| 449 | * |
||
| 450 | * @throws BuildException |
||
| 451 | */ |
||
| 452 | public function runStatements(Reader $reader): void |
||
| 453 | { |
||
| 454 | if (self::DELIM_NONE === $this->delimiterType) { |
||
| 455 | $splitter = new DummyPDOQuerySplitter($this, $reader); |
||
| 456 | } elseif (self::DELIM_NORMAL === $this->delimiterType && 0 === strpos((string) $this->getUrl(), 'pgsql:')) { |
||
| 457 | $splitter = new PgsqlPDOQuerySplitter($this, $reader); |
||
| 458 | } else { |
||
| 459 | $splitter = new DefaultPDOQuerySplitter($this, $reader, $this->delimiterType); |
||
| 460 | } |
||
| 461 | |||
| 462 | $splitter->setExpandProperties($this->expandProperties); |
||
| 463 | $splitter->setKeepformat($this->keepformat); |
||
| 464 | |||
| 465 | try { |
||
| 466 | while (null !== ($query = $splitter->nextQuery())) { |
||
| 467 | $this->log('SQL: ' . $query, Project::MSG_VERBOSE); |
||
| 468 | $this->execSQL($query); |
||
| 469 | } |
||
| 470 | } catch (PDOException $e) { |
||
| 471 | throw new BuildException($e); |
||
| 472 | } |
||
| 473 | } |
||
| 474 | |||
| 475 | /** |
||
| 476 | * PDOSQLExecTask as condition. |
||
| 477 | * |
||
| 478 | * Returns false when the database connection fails, and true otherwise. |
||
| 479 | * This method only uses three properties: url (required), userId and |
||
| 480 | * password. |
||
| 481 | * |
||
| 482 | * The database connection is not stored in a variable, this allow to |
||
| 483 | * immediately close the connections since there's no reference to it. |
||
| 484 | * |
||
| 485 | * @author Jawira Portugal <[email protected]> |
||
| 486 | */ |
||
| 487 | public function evaluate(): bool |
||
| 488 | { |
||
| 489 | if (empty($this->getUrl())) { |
||
| 490 | throw new BuildException('url is required'); |
||
| 491 | } |
||
| 492 | |||
| 493 | $this->log('Trying to reach ' . $this->getUrl(), Project::MSG_DEBUG); |
||
| 494 | |||
| 495 | try { |
||
| 496 | new PDO($this->getUrl(), $this->getUserId(), $this->getPassword()); |
||
| 497 | } catch (PDOException $ex) { |
||
| 498 | $this->log($ex->getMessage(), Project::MSG_VERBOSE); |
||
| 499 | |||
| 500 | return false; |
||
| 501 | } |
||
| 502 | |||
| 503 | $this->log('Successful connection to ' . $this->getUrl(), Project::MSG_DEBUG); |
||
| 504 | |||
| 505 | return true; |
||
| 506 | } |
||
| 507 | |||
| 508 | /** |
||
| 509 | * Whether the passed-in SQL statement is a SELECT statement. |
||
| 510 | * This does a pretty simple match, checking to see if statement starts with |
||
| 511 | * 'select' (but not 'select into'). |
||
| 512 | * |
||
| 513 | * @param string $sql |
||
| 514 | * |
||
| 515 | * @return bool whether specified SQL looks like a SELECT query |
||
| 516 | */ |
||
| 517 | protected function isSelectSql($sql): bool |
||
| 522 | } |
||
| 523 | |||
| 524 | /** |
||
| 525 | * Exec the sql statement. |
||
| 526 | * |
||
| 527 | * @param string $sql |
||
| 528 | * |
||
| 529 | * @throws BuildException |
||
| 530 | */ |
||
| 531 | protected function execSQL($sql): void |
||
| 532 | { |
||
| 533 | // Check and ignore empty statements |
||
| 534 | if (empty(trim($sql))) { |
||
| 535 | return; |
||
| 536 | } |
||
| 537 | |||
| 538 | try { |
||
| 539 | ++$this->totalSql; |
||
| 540 | |||
| 541 | $this->statement = $this->conn->query($sql); |
||
| 542 | |||
| 543 | // only call processResults() for statements that return actual data (such as 'select') |
||
| 544 | if ($this->statement->columnCount() > 0) { |
||
| 545 | $this->processResults(); |
||
| 546 | } |
||
| 547 | |||
| 548 | $this->statement->closeCursor(); |
||
| 549 | $this->statement = null; |
||
| 550 | |||
| 551 | ++$this->goodSql; |
||
| 552 | } catch (PDOException $e) { |
||
| 553 | $this->log('Failed to execute: ' . $sql, Project::MSG_ERR); |
||
| 554 | $this->setErrorProp(); |
||
| 555 | if ('abort' !== $this->onError) { |
||
| 556 | $this->log((string) $e, Project::MSG_ERR); |
||
| 557 | } |
||
| 558 | if ('continue' !== $this->onError) { |
||
| 559 | throw new BuildException('Failed to execute SQL', $e); |
||
| 560 | } |
||
| 561 | $this->log($e->getMessage(), Project::MSG_ERR); |
||
| 562 | } |
||
| 563 | } |
||
| 564 | |||
| 565 | /** |
||
| 566 | * Returns configured PDOResultFormatter objects |
||
| 567 | * (which were created from PDOSQLExecFormatterElement objects). |
||
| 568 | * |
||
| 569 | * @return PDOResultFormatter[] |
||
| 570 | */ |
||
| 571 | protected function getConfiguredFormatters(): array |
||
| 572 | { |
||
| 573 | $formatters = []; |
||
| 574 | foreach ($this->formatters as $fe) { |
||
| 575 | $formatter = $fe->getFormatter(); |
||
| 576 | if ($formatter instanceof PlainPDOResultFormatter) { |
||
| 577 | $formatter->setStatementCounter($this->goodSql); |
||
| 578 | } |
||
| 579 | $formatters[] = $formatter; |
||
| 580 | } |
||
| 581 | |||
| 582 | return $formatters; |
||
| 583 | } |
||
| 584 | |||
| 585 | /** |
||
| 586 | * Initialize the formatters. |
||
| 587 | */ |
||
| 588 | protected function initFormatters(): void |
||
| 589 | { |
||
| 590 | $formatters = $this->getConfiguredFormatters(); |
||
| 591 | foreach ($formatters as $formatter) { |
||
| 592 | $formatter->initialize(); |
||
| 593 | } |
||
| 594 | } |
||
| 595 | |||
| 596 | /** |
||
| 597 | * Run cleanup and close formatters. |
||
| 598 | */ |
||
| 599 | protected function closeFormatters(): void |
||
| 600 | { |
||
| 601 | $formatters = $this->getConfiguredFormatters(); |
||
| 602 | foreach ($formatters as $formatter) { |
||
| 603 | $formatter->close(); |
||
| 604 | } |
||
| 605 | } |
||
| 606 | |||
| 607 | /** |
||
| 608 | * Passes results from query to any formatters. |
||
| 609 | * |
||
| 610 | * @throws PDOException |
||
| 611 | */ |
||
| 612 | protected function processResults(): void |
||
| 613 | { |
||
| 614 | $this->log('Processing new result set.', Project::MSG_VERBOSE); |
||
| 615 | |||
| 616 | $formatters = $this->getConfiguredFormatters(); |
||
| 617 | |||
| 618 | try { |
||
| 619 | while ($row = $this->statement->fetch($this->fetchMode)) { |
||
| 620 | foreach ($formatters as $formatter) { |
||
| 621 | $formatter->processRow($row); |
||
| 622 | } |
||
| 623 | } |
||
| 624 | } catch (Exception $x) { |
||
| 625 | $this->log('Error processing results: ' . $x->getMessage(), Project::MSG_ERR); |
||
| 626 | foreach ($formatters as $formatter) { |
||
| 627 | $formatter->close(); |
||
| 628 | } |
||
| 629 | |||
| 630 | throw new BuildException($x); |
||
| 631 | } |
||
| 632 | } |
||
| 633 | |||
| 634 | /** |
||
| 635 | * Closes current connection. |
||
| 636 | */ |
||
| 637 | protected function closeConnection(): void |
||
| 638 | { |
||
| 639 | if ($this->conn) { |
||
| 640 | unset($this->conn); |
||
| 641 | $this->conn = null; |
||
| 642 | } |
||
| 643 | } |
||
| 644 | |||
| 645 | final protected function setErrorProp(): void |
||
| 646 | { |
||
| 647 | $this->setProperty($this->errorProperty, 'true'); |
||
| 648 | } |
||
| 649 | |||
| 650 | final protected function setStatementCountProp(int $statementCount): void |
||
| 651 | { |
||
| 652 | $this->setProperty($this->statementCountProperty, (string) $statementCount); |
||
| 653 | } |
||
| 654 | |||
| 655 | /** |
||
| 656 | * @param string|null $name |
||
| 657 | * @param string $value |
||
| 658 | */ |
||
| 659 | private function setProperty(?string $name, string $value): void |
||
| 660 | { |
||
| 661 | if ($name !== null) { |
||
| 662 | $this->getProject()->setNewProperty($name, $value); |
||
| 663 | } |
||
| 664 | } |
||
| 665 | |||
| 666 | /** |
||
| 667 | * Closes an unused connection after an error and doesn't rethrow |
||
| 668 | * a possible PDOException |
||
| 669 | */ |
||
| 670 | private function closeQuietly(): void |
||
| 679 | } |
||
| 680 | } |
||
| 681 |