From a1f89421bb1c0b9641b4fe189ab0e09ab0f25588 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 15 Oct 2020 19:07:24 +0200 Subject: [PATCH] PHP 8 compatibility. --- .github/workflows/continuous-integration.yml | 5 + composer.json | 2 +- composer.lock | 4 +- lib/Doctrine/DBAL/Driver/PDOConnection.php | 22 +-- .../DBAL/Driver/PDOQueryImplementation.php | 63 ++++++++ lib/Doctrine/DBAL/Driver/PDOStatement.php | 65 +------- .../Driver/PDOStatementImplementations.php | 140 ++++++++++++++++++ lib/Doctrine/DBAL/Statement.php | 5 + phpcs.xml.dist | 1 + 9 files changed, 221 insertions(+), 86 deletions(-) create mode 100644 lib/Doctrine/DBAL/Driver/PDOQueryImplementation.php create mode 100644 lib/Doctrine/DBAL/Driver/PDOStatementImplementations.php diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 56725b50e3b..22058d52fae 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -23,6 +23,7 @@ jobs: php-version: - "7.3" - "7.4" + - "8.0" deps: - "fixed" include: @@ -183,6 +184,9 @@ jobs: - "11" - "12" - "13" + include: + - php-version: "8.0" + postgres-version: "12" services: postgres: @@ -304,6 +308,7 @@ jobs: matrix: php-version: - "7.4" + - "8.0" mysql-version: - "5.7" - "8.0" diff --git a/composer.json b/composer.json index 3097561c32a..912f367f82d 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ {"name": "Jonathan Wage", "email": "jonwage@gmail.com"} ], "require": { - "php": "^7.3", + "php": "^7.3 || ^8", "ext-pdo": "*", "doctrine/cache": "^1.0", "doctrine/event-manager": "^1.0" diff --git a/composer.lock b/composer.lock index 47421ed61f9..1a59c5b34b6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "05d08a772cda388dbf5a250d750df309", + "content-hash": "214eb4a0ad0c676733b53f3d303618f5", "packages": [ { "name": "doctrine/cache", @@ -3927,7 +3927,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.3", + "php": "^7.3 || ^8", "ext-pdo": "*" }, "platform-dev": [], diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index 8409952cb4e..44766e8bd59 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -11,7 +11,6 @@ use PDOStatement; use function assert; -use function func_get_args; /** * PDO implementation of the Connection interface. @@ -21,6 +20,8 @@ */ class PDOConnection extends PDO implements ConnectionInterface, ServerInfoAwareConnection { + use PDOQueryImplementation; + /** * @internal The connection can be only instantiated by its driver. * @@ -83,25 +84,6 @@ public function prepare($sql, $driverOptions = []) } } - /** - * {@inheritdoc} - * - * @return PDOStatement - */ - public function query() - { - $args = func_get_args(); - - try { - $stmt = parent::query(...$args); - assert($stmt instanceof PDOStatement); - - return $stmt; - } catch (PDOException $exception) { - throw Exception::new($exception); - } - } - /** * {@inheritdoc} */ diff --git a/lib/Doctrine/DBAL/Driver/PDOQueryImplementation.php b/lib/Doctrine/DBAL/Driver/PDOQueryImplementation.php new file mode 100644 index 00000000000..a6612438b7c --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/PDOQueryImplementation.php @@ -0,0 +1,63 @@ += 80000) { + /** + * @internal + */ + trait PDOQueryImplementation + { + /** + * {@inheritdoc} + * + * @return PDOStatement + */ + public function query(?string $query = null, ?int $fetchMode = null, mixed ...$fetchModeArgs) + { + try { + $stmt = parent::query($query, $fetchMode, ...$fetchModeArgs); + assert($stmt instanceof PDOStatement); + + return $stmt; + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + } +} else { + /** + * @internal + */ + // @codingStandardsIgnoreLine PSR1.Classes.ClassDeclaration.MultipleClasses Generic.Classes.DuplicateClassName.Found + trait PDOQueryImplementation + { + /** + * {@inheritdoc} + * + * @return PDOStatement + */ + public function query() + { + $args = func_get_args(); + + try { + $stmt = parent::query(...$args); + assert($stmt instanceof PDOStatement); + + return $stmt; + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + } +} diff --git a/lib/Doctrine/DBAL/Driver/PDOStatement.php b/lib/Doctrine/DBAL/Driver/PDOStatement.php index 4a244ab4617..9802b995b24 100644 --- a/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -10,9 +10,7 @@ use PDOException; use function array_slice; -use function assert; use function func_get_args; -use function is_array; use function sprintf; use function trigger_error; @@ -26,6 +24,8 @@ */ class PDOStatement extends \PDOStatement implements StatementInterface, Result { + use PDOStatementImplementations; + private const PARAM_TYPE_MAP = [ ParameterType::NULL => PDO::PARAM_NULL, ParameterType::INTEGER => PDO::PARAM_INT, @@ -54,34 +54,6 @@ protected function __construct() { } - /** - * {@inheritdoc} - * - * @deprecated Use one of the fetch- or iterate-related methods. - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $fetchMode = $this->convertFetchMode($fetchMode); - - // This thin wrapper is necessary to shield against the weird signature - // of PDOStatement::setFetchMode(): even if the second and third - // parameters are optional, PHP will not let us remove it from this - // declaration. - try { - if ($arg2 === null && $arg3 === null) { - return parent::setFetchMode($fetchMode); - } - - if ($arg3 === null) { - return parent::setFetchMode($fetchMode, $arg2); - } - - return parent::setFetchMode($fetchMode, $arg2, $arg3); - } catch (PDOException $exception) { - throw Exception::new($exception); - } - } - /** * {@inheritdoc} */ @@ -164,39 +136,6 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX } } - /** - * {@inheritdoc} - * - * @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $args = func_get_args(); - - if (isset($args[0])) { - $args[0] = $this->convertFetchMode($args[0]); - } - - if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { - $args = []; - } elseif ($fetchArgument === null && $ctorArgs === null) { - $args = [$fetchMode]; - } elseif ($ctorArgs === null) { - $args = [$fetchMode, $fetchArgument]; - } else { - $args = [$fetchMode, $fetchArgument, $ctorArgs]; - } - - try { - $data = parent::fetchAll(...$args); - assert(is_array($data)); - - return $data; - } catch (PDOException $exception) { - throw Exception::new($exception); - } - } - /** * {@inheritdoc} * diff --git a/lib/Doctrine/DBAL/Driver/PDOStatementImplementations.php b/lib/Doctrine/DBAL/Driver/PDOStatementImplementations.php new file mode 100644 index 00000000000..ad0fb264513 --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/PDOStatementImplementations.php @@ -0,0 +1,140 @@ += 80000) { + /** + * @internal + */ + trait PDOStatementImplementations + { + /** + * {@inheritdoc} + * + * @deprecated Use one of the fetch- or iterate-related methods. + */ + public function setFetchMode($mode, ...$args) + { + $mode = $this->convertFetchMode($mode); + + $filteredArgs = array_filter($args, static function (mixed $value): bool { + return $value !== null; + }); + if (empty($filteredArgs)) { + $args = []; + } + + try { + return parent::setFetchMode($mode, ...$args); + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + + /** + * {@inheritdoc} + * + * @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. + */ + public function fetchAll($mode = null, ...$args) + { + if ($mode !== null) { + $mode = $this->convertFetchMode($mode); + } + + $filteredArgs = array_filter($args, static function (mixed $value): bool { + return $value !== null; + }); + if (empty($filteredArgs)) { + $args = []; + } + + try { + $data = parent::fetchAll($mode, ...$args); + assert(is_array($data)); + + return $data; + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + } +} else { + /** + * @internal + */ + // @codingStandardsIgnoreLine PSR1.Classes.ClassDeclaration.MultipleClasses Generic.Classes.DuplicateClassName.Found + trait PDOStatementImplementations + { + /** + * {@inheritdoc} + * + * @deprecated Use one of the fetch- or iterate-related methods. + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $fetchMode = $this->convertFetchMode($fetchMode); + + // This thin wrapper is necessary to shield against the weird signature + // of PDOStatement::setFetchMode(): even if the second and third + // parameters are optional, PHP will not let us remove it from this + // declaration. + try { + if ($arg2 === null && $arg3 === null) { + return parent::setFetchMode($fetchMode); + } + + if ($arg3 === null) { + return parent::setFetchMode($fetchMode, $arg2); + } + + return parent::setFetchMode($fetchMode, $arg2, $arg3); + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + + /** + * {@inheritdoc} + * + * @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $args = func_get_args(); + + if (isset($args[0])) { + $args[0] = $this->convertFetchMode($args[0]); + } + + if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { + $args = []; + } elseif ($fetchArgument === null && $ctorArgs === null) { + $args = [$fetchMode]; + } elseif ($ctorArgs === null) { + $args = [$fetchMode, $fetchArgument]; + } else { + $args = [$fetchMode, $fetchArgument, $ctorArgs]; + } + + try { + $data = parent::fetchAll(...$args); + assert(is_array($data)); + + return $data; + } catch (PDOException $exception) { + throw Exception::new($exception); + } + } + } +} diff --git a/lib/Doctrine/DBAL/Statement.php b/lib/Doctrine/DBAL/Statement.php index ad5d29b9a5d..57843031eea 100644 --- a/lib/Doctrine/DBAL/Statement.php +++ b/lib/Doctrine/DBAL/Statement.php @@ -10,6 +10,7 @@ use Doctrine\DBAL\Types\Type; use IteratorAggregate; use PDO; +use PDOStatement; use Throwable; use Traversable; @@ -135,6 +136,10 @@ public function bindParam($param, &$variable, $type = ParameterType::STRING, $le $this->params[$param] = $variable; $this->types[$param] = $type; + if ($this->stmt instanceof PDOStatement) { + $length = $length ?? 0; + } + return $this->stmt->bindParam($param, $variable, $type, $length); } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 8c6b82da6b0..c98f2549779 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -22,6 +22,7 @@ +