From 474daf976ead5014620d16a2c55cc44cf01ca397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 22 Oct 2019 08:38:34 +0200 Subject: [PATCH] Allows URL DSN in Lock and Cache --- .../Cache/Tests/Adapter/PdoAdapterTest.php | 29 ++++++++++++++++++ .../Component/Cache/Traits/PdoTrait.php | 12 ++++++-- src/Symfony/Component/Lock/Store/PdoStore.php | 12 ++++++-- .../Lock/Tests/Store/PdoStoreTest.php | 30 +++++++++++++++++++ src/Symfony/Component/Lock/composer.json | 5 +++- 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php index ec9e00d3c9..c827c5ba4d 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php @@ -71,4 +71,33 @@ class PdoAdapterTest extends AdapterTestCase $this->assertFalse($newItem->isHit()); $this->assertSame(0, $getCacheItemCount(), 'PDOAdapter must clean up expired items'); } + + /** + * @dataProvider provideDsn + */ + public function testDsn(string $dsn, string $file = null) + { + try { + $pool = new PdoAdapter($dsn); + $pool->createTable(); + + $item = $pool->getItem('key'); + $item->set('value'); + $this->assertTrue($pool->save($item)); + } finally { + if (null !== $file) { + @unlink($file); + } + } + } + + public function provideDsn() + { + $dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); + yield ['sqlite://localhost/'.$dbFile, ''.$dbFile]; + yield ['sqlite:'.$dbFile, ''.$dbFile]; + yield ['sqlite3:///'.$dbFile, ''.$dbFile]; + yield ['sqlite://localhost/:memory:']; + yield ['sqlite::memory:']; + } } diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index 273188ac29..3f0b4fc6ac 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Cache\Traits; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -370,8 +371,15 @@ trait PdoTrait private function getConnection() { if (null === $this->conn) { - $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + if (strpos($this->dsn, '://')) { + if (!class_exists(DriverManager::class)) { + throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $this->dsn)); + } + $this->conn = DriverManager::getConnection(['url' => $this->dsn]); + } else { + $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } } if (null === $this->driver) { if ($this->conn instanceof \PDO) { diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index 93a49092d7..c2dbd622ff 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Lock\Store; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\InvalidTtlException; @@ -229,8 +230,15 @@ class PdoStore implements StoreInterface private function getConnection() { if (null === $this->conn) { - $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + if (strpos($this->dsn, '://')) { + if (!class_exists(DriverManager::class)) { + throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $this->dsn)); + } + $this->conn = DriverManager::getConnection(['url' => $this->dsn]); + } else { + $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } } return $this->conn; diff --git a/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php index eb24cb1de4..81a0c9b454 100644 --- a/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php @@ -73,4 +73,34 @@ class PdoStoreTest extends AbstractStoreTest return new PdoStore('sqlite:'.self::$dbFile, [], 0.1, 0.1); } + + /** + * @dataProvider provideDsn + */ + public function testDsn(string $dsn, string $file = null) + { + $key = new Key(uniqid(__METHOD__, true)); + + try { + $store = new PdoStore($dsn); + $store->createTable(); + + $store->save($key); + $this->assertTrue($store->exists($key)); + } finally { + if (null !== $file) { + @unlink($file); + } + } + } + + public function provideDsn() + { + $dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); + yield ['sqlite://localhost/'.$dbFile, ''.$dbFile]; + yield ['sqlite:'.$dbFile, ''.$dbFile]; + yield ['sqlite3:///'.$dbFile, ''.$dbFile]; + yield ['sqlite://localhost/:memory:']; + yield ['sqlite::memory:']; + } } diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json index 5909a421ea..8e82285b40 100644 --- a/src/Symfony/Component/Lock/composer.json +++ b/src/Symfony/Component/Lock/composer.json @@ -20,10 +20,13 @@ "psr/log": "~1.0" }, "require-dev": { - "doctrine/dbal": "~2.4", + "doctrine/dbal": "~2.5", "mongodb/mongodb": "~1.1", "predis/predis": "~1.0" }, + "conflict": { + "doctrine/dbal": "<2.5" + }, "autoload": { "psr-4": { "Symfony\\Component\\Lock\\": "" }, "exclude-from-classmap": [