From 7810b3eed51b6ca6ff502f134d4f49b133050030 Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Fri, 14 Oct 2022 16:51:50 +0200 Subject: [PATCH 1/3] :arrow_up: Compatibility with doctrine/dbal 3.x --- .github/workflows/ci.yml | 1 + Makefile | 4 ++-- src/Gaufrette/Adapter/DoctrineDbal.php | 21 ++++++++++++++++--- .../Functional/Adapter/DoctrineDbalTest.php | 9 +++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57786979..69107972 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,7 @@ jobs: - { php: '8.1', packages: 'aws/aws-sdk-php:^3.158', phpspec: 'spec/Gaufrette/Adapter/AwsS3Spec.php' } - { php: '8.1', packages: 'google/apiclient:^2.12', phpspec: 'spec/Gaufrette/Adapter/GoogleCloudStorageSpec.php' } - { php: '8.1', packages: 'doctrine/dbal:^2.3', phpspec: 'spec/Gaufrette/Adapter/DoctrineDbalSpec.php' } + - { php: '8.1', packages: 'doctrine/dbal:^3.4', phpspec: 'spec/Gaufrette/Adapter/DoctrineDbalSpec.php' } - { php: '8.1', packages: 'league/flysystem:^1.0', phpspec: 'spec/Gaufrette/Adapter/FlysystemSpec.php' } - { php: '8.1', packages: 'microsoft/azure-storage-blob:^1.0', phpspec: 'spec/Gaufrette/Adapter/AzureBlobStore' } - { php: '8.1', packages: 'mongodb/mongodb:^1.1', phpspec: 'spec/Gaufrette/Adapter/GridFSSpec.php' } diff --git a/Makefile b/Makefile index fc29c04e..b4942d83 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ docker.all-deps: docker.deps ## Install dependencies docker/run-task php${PHP_VERSION} composer require --no-update \ aws/aws-sdk-php:^3.158 \ google/apiclient:^2.12 \ - doctrine/dbal:^2.3 \ + doctrine/dbal:^3.4 \ league/flysystem:^1.0 \ microsoft/azure-storage-blob:^1.0 \ phpseclib/phpseclib:^2.0 \ @@ -67,7 +67,7 @@ require-all-legacy: # kept for compatibility with the old CI config, to be remov composer require --no-update \ aws/aws-sdk-php:^3.158 \ google/apiclient:^2.12 \ - doctrine/dbal:^2.3 \ + doctrine/dbal:^3.4 \ league/flysystem:^1.0 \ microsoft/azure-storage-blob:^1.0 \ phpseclib/phpseclib:^2.0 \ diff --git a/src/Gaufrette/Adapter/DoctrineDbal.php b/src/Gaufrette/Adapter/DoctrineDbal.php index 337b1de6..1d725e3f 100644 --- a/src/Gaufrette/Adapter/DoctrineDbal.php +++ b/src/Gaufrette/Adapter/DoctrineDbal.php @@ -88,7 +88,12 @@ public function checksum($key) */ public function exists($key) { - return (boolean) $this->connection->fetchColumn( + $method = 'fetchOne'; // dbal 3.x + if (!method_exists($this->connection, $method)) { + $method = 'fetchColumn'; // dbal 2.x + } + + return (boolean) $this->connection->$method( sprintf( 'SELECT COUNT(%s) FROM %s WHERE %s = :key', $this->getQuotedColumn('key'), @@ -153,7 +158,12 @@ public function isDirectory($key) private function getColumnValue($key, $column) { - $value = $this->connection->fetchColumn( + $method = 'fetchOne'; // dbal 3.x + if (!method_exists($this->connection, $method)) { + $method = 'fetchColumn'; // dbal 2.x + } + + $value = $this->connection->$method( sprintf( 'SELECT %s FROM %s WHERE %s = :key', $this->getQuotedColumn($column), @@ -173,7 +183,12 @@ public function listKeys($prefix = '') { $prefix = trim($prefix); - $keys = $this->connection->fetchAll( + $method = 'fetchAllAssociative'; // dbal 3.x + if (!method_exists($this->connection, 'fetchAllAssociative')) { + $method = 'fetchAll'; // dbal 2.x + } + + $keys = $this->connection->$method( sprintf( 'SELECT %s AS _key FROM %s WHERE %s LIKE :pattern', $this->getQuotedColumn('key'), diff --git a/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php b/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php index df53f63c..d2ebf64a 100644 --- a/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php +++ b/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php @@ -29,7 +29,14 @@ protected function setUp(): void $schema = $this->connection->getSchemaManager()->createSchema(); $table = $schema->createTable('gaufrette'); - $table->addColumn('key', 'string', ['unique' => true]); + $column = $table->addColumn('key', 'string'); + if (method_exists($column, 'setPlatformOption')) { + // dbal 3.4+ + $column->setPlatformOption('unique', true); + } else { + // dbal 2.x + $column->setUnique(true); + } $table->addColumn('content', 'blob'); $table->addColumn('mtime', 'integer'); $table->addColumn('checksum', 'string', ['length' => 32]); From 6834362e3f8cac73526ecf4e678a8a9907bf3282 Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Fri, 14 Oct 2022 16:57:04 +0200 Subject: [PATCH 2/3] :white_check_mark: fix usage of method_exist for phpspec --- spec/Gaufrette/Adapter/DoctrineDbalSpec.php | 63 +++++++++++++++++---- src/Gaufrette/Adapter/DoctrineDbal.php | 19 +++++-- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/spec/Gaufrette/Adapter/DoctrineDbalSpec.php b/spec/Gaufrette/Adapter/DoctrineDbalSpec.php index 091ee157..24f1d309 100644 --- a/spec/Gaufrette/Adapter/DoctrineDbalSpec.php +++ b/spec/Gaufrette/Adapter/DoctrineDbalSpec.php @@ -6,7 +6,7 @@ require_once 'functions.php'; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Result; use PhpSpec\ObjectBehavior; use Prophecy\Argument; @@ -46,13 +46,18 @@ function it_checks_if_file_exists(Connection $connection) return sprintf('"%s"', $argument[0]); }); + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection - ->fetchColumn('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(12); $this->exists('filename')->shouldReturn(true); $connection - ->fetchColumn('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(0); $this->exists('filename')->shouldReturn(false); } @@ -67,8 +72,14 @@ function it_writes_to_new_file(Connection $connection) ->will(function ($argument) { return sprintf('"%s"', $argument[0]); }); + + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection - ->fetchColumn('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(false); $connection ->insert( @@ -90,13 +101,18 @@ function it_writes_to_new_file(Connection $connection) */ function it_write_file(Connection $connection) { + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection ->quoteIdentifier(Argument::any()) ->will(function ($argument) { return sprintf('"%s"', $argument[0]); }); $connection - ->fetchColumn('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT COUNT("key") FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(true); $connection ->update( @@ -120,13 +136,18 @@ function it_write_file(Connection $connection) */ function it_reads_file(Connection $connection) { + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection ->quoteIdentifier(Argument::any()) ->will(function ($argument) { return sprintf('"%s"', $argument[0]); }); $connection - ->fetchColumn('SELECT "content" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT "content" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn('some content'); $this->read('filename')->shouldReturn('some content'); @@ -137,13 +158,18 @@ function it_reads_file(Connection $connection) */ function it_calculates_checksum(Connection $connection) { + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection ->quoteIdentifier(Argument::any()) ->will(function ($argument) { return sprintf('"%s"', $argument[0]); }); $connection - ->fetchColumn('SELECT "checksum" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT "checksum" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(1234); $this->checksum('filename')->shouldReturn(1234); @@ -154,13 +180,18 @@ function it_calculates_checksum(Connection $connection) */ function it_gets_mtime(Connection $connection) { + $method = 'fetchOne'; // dbal 3.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchColumn'; // BC layer for dbal 2.x + } + $connection ->quoteIdentifier(Argument::any()) ->will(function ($argument) { return sprintf('"%s"', $argument[0]); }); $connection - ->fetchColumn('SELECT "mtime" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) + ->$method('SELECT "mtime" FROM "someTableName" WHERE "key" = :key', ['key' => 'filename']) ->willReturn(1234); $this->mtime('filename')->shouldReturn(1234); @@ -194,11 +225,19 @@ function it_renames_file(Connection $connection) /** * @param \Doctrine\DBAL\Connection $connection - * @param \Doctrine\DBAL\Statement $stmt */ - function it_get_keys(Connection $connection, Statement $stmt) + function it_get_keys(Connection $connection, $result) { - $stmt->fetchAll(\PDO::FETCH_COLUMN)->willReturn(['filename', 'filename1', 'filename2']); + if (class_exists(Result::class)) { + // dbal 3.x + $result->beADoubleOf(Result::class); + $result->fetchAllNumeric()->willReturn(['filename', 'filename1', 'filename2']); + } else { + // BC layer for dbal 2.x + $result->beADoubleOf(\Doctrine\DBAL\Statement::class); + $result->fetchAll(\PDO::FETCH_COLUMN)->willReturn(['filename', 'filename1', 'filename2']); + } + $connection ->quoteIdentifier(Argument::any()) ->will(function ($argument) { @@ -206,7 +245,7 @@ function it_get_keys(Connection $connection, Statement $stmt) }); $connection ->executeQuery('SELECT "key" FROM "someTableName"') - ->willReturn($stmt); + ->willReturn($result); $this->keys()->shouldReturn(['filename', 'filename1', 'filename2']); } diff --git a/src/Gaufrette/Adapter/DoctrineDbal.php b/src/Gaufrette/Adapter/DoctrineDbal.php index 1d725e3f..af3b4159 100644 --- a/src/Gaufrette/Adapter/DoctrineDbal.php +++ b/src/Gaufrette/Adapter/DoctrineDbal.php @@ -2,6 +2,7 @@ namespace Gaufrette\Adapter; +use Doctrine\DBAL\Result; use Gaufrette\Adapter; use Gaufrette\Util; use Doctrine\DBAL\Connection; @@ -52,6 +53,12 @@ public function keys() $this->getQuotedTable() )); + if (class_exists(Result::class)) { + // dbal 3.x + return $stmt->fetchAllNumeric(); + } + + // BC layer for dbal 2.x return $stmt->fetchAll(\PDO::FETCH_COLUMN); } @@ -89,8 +96,8 @@ public function checksum($key) public function exists($key) { $method = 'fetchOne'; // dbal 3.x - if (!method_exists($this->connection, $method)) { - $method = 'fetchColumn'; // dbal 2.x + if (!method_exists(Connection::class, $method)) { + $method = 'fetchColumn'; // BC layer for dbal 2.x } return (boolean) $this->connection->$method( @@ -159,8 +166,8 @@ public function isDirectory($key) private function getColumnValue($key, $column) { $method = 'fetchOne'; // dbal 3.x - if (!method_exists($this->connection, $method)) { - $method = 'fetchColumn'; // dbal 2.x + if (!method_exists(Connection::class, $method)) { + $method = 'fetchColumn'; // BC layer for dbal 2.x } $value = $this->connection->$method( @@ -184,8 +191,8 @@ public function listKeys($prefix = '') $prefix = trim($prefix); $method = 'fetchAllAssociative'; // dbal 3.x - if (!method_exists($this->connection, 'fetchAllAssociative')) { - $method = 'fetchAll'; // dbal 2.x + if (!method_exists(Connection::class, 'fetchAllAssociative')) { + $method = 'fetchAll'; // BC layer for dbal 2.x } $keys = $this->connection->$method( From 3eb2617775a6688fe909284a8a9efdc0c8dbb16c Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Fri, 14 Oct 2022 17:24:25 +0200 Subject: [PATCH 3/3] :white_check_mark: fix doctrine dbal adapter for 3.x --- spec/Gaufrette/Adapter/DoctrineDbalSpec.php | 2 +- src/Gaufrette/Adapter/DoctrineDbal.php | 2 +- tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/Gaufrette/Adapter/DoctrineDbalSpec.php b/spec/Gaufrette/Adapter/DoctrineDbalSpec.php index 24f1d309..4e723e14 100644 --- a/spec/Gaufrette/Adapter/DoctrineDbalSpec.php +++ b/spec/Gaufrette/Adapter/DoctrineDbalSpec.php @@ -231,7 +231,7 @@ function it_get_keys(Connection $connection, $result) if (class_exists(Result::class)) { // dbal 3.x $result->beADoubleOf(Result::class); - $result->fetchAllNumeric()->willReturn(['filename', 'filename1', 'filename2']); + $result->fetchFirstColumn()->willReturn(['filename', 'filename1', 'filename2']); } else { // BC layer for dbal 2.x $result->beADoubleOf(\Doctrine\DBAL\Statement::class); diff --git a/src/Gaufrette/Adapter/DoctrineDbal.php b/src/Gaufrette/Adapter/DoctrineDbal.php index af3b4159..77066d2f 100644 --- a/src/Gaufrette/Adapter/DoctrineDbal.php +++ b/src/Gaufrette/Adapter/DoctrineDbal.php @@ -55,7 +55,7 @@ public function keys() if (class_exists(Result::class)) { // dbal 3.x - return $stmt->fetchAllNumeric(); + return $stmt->fetchFirstColumn(); } // BC layer for dbal 2.x diff --git a/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php b/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php index d2ebf64a..aa9d8a39 100644 --- a/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php +++ b/tests/Gaufrette/Functional/Adapter/DoctrineDbalTest.php @@ -34,7 +34,7 @@ protected function setUp(): void // dbal 3.4+ $column->setPlatformOption('unique', true); } else { - // dbal 2.x + // BC layer dbal 2.x $column->setUnique(true); } $table->addColumn('content', 'blob');