From b5d8dde07355577b41f879bd6508774971b1cf7e Mon Sep 17 00:00:00 2001 From: Emanuele Minotto Date: Wed, 16 Dec 2015 00:03:09 +0100 Subject: [PATCH] shared key flattening --- .../KeyValueStore/Storage/AbstractStorage.php | 93 +++++++++++++++++++ .../Storage/AzureSdkTableStorage.php | 2 +- .../Storage/CassandraStorage.php | 2 +- .../KeyValueStore/Storage/CouchDbStorage.php | 27 +----- .../Storage/CouchbaseStorage.php | 2 +- .../KeyValueStore/Storage/DBALStorage.php | 2 +- .../Storage/DoctrineCacheStorage.php | 16 +--- .../KeyValueStore/Storage/DynamoDbStorage.php | 2 +- .../KeyValueStore/Storage/MongoDbStorage.php | 2 +- .../KeyValueStore/Storage/RedisStorage.php | 2 +- .../KeyValueStore/Storage/RiakStorage.php | 2 +- .../KeyValueStore/Storage/SimpleDbStorage.php | 2 +- .../Storage/WindowsAzureTableStorage.php | 4 +- .../Functional/Storage/CassandraTest.php | 2 +- .../Storage/AbstractStorageTest.php | 80 ++++++++++++++++ 15 files changed, 187 insertions(+), 53 deletions(-) create mode 100644 lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php create mode 100644 tests/Doctrine/Tests/KeyValueStore/Storage/AbstractStorageTest.php diff --git a/lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php b/lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php new file mode 100644 index 0000000..d8113e8 --- /dev/null +++ b/lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php @@ -0,0 +1,93 @@ +. + */ + +namespace Doctrine\KeyValueStore\Storage; + +abstract class AbstractStorage implements Storage +{ + /** + * {@inheritDoc} + */ + abstract public function supportsPartialUpdates(); + + /** + * {@inheritDoc} + */ + abstract public function supportsCompositePrimaryKeys(); + + /** + * {@inheritDoc} + */ + abstract public function requiresCompositePrimaryKeys(); + + /** + * {@inheritDoc} + */ + abstract public function insert($storageName, $key, array $data); + + /** + * {@inheritDoc} + */ + abstract public function update($storageName, $key, array $data); + + /** + * {@inheritDoc} + */ + abstract public function delete($storageName, $key); + + /** + * {@inheritDoc} + */ + abstract public function find($storageName, $key); + + /** + * {@inheritDoc} + */ + abstract public function getName(); + + /** + * Used to flattening keys. + * + * @param string $storageName + * @param string|int|float|bool|array $key + * + * @return string + */ + protected function flattenKey($storageName, $key) + { + if (is_scalar($key)) { + return $storageName . '-' . $key; + } + + if ( ! is_array($key)) { + throw new \InvalidArgumentException('The key should be a string or a flat array.'); + } + + ksort($key); + + $hash = $storageName . '-oid:'; + + foreach ($key as $property => $value) { + $hash .= $property . '=' . $value . ';'; + } + + return $hash; + } +} diff --git a/lib/Doctrine/KeyValueStore/Storage/AzureSdkTableStorage.php b/lib/Doctrine/KeyValueStore/Storage/AzureSdkTableStorage.php index 12fe0cb..8b5e831 100644 --- a/lib/Doctrine/KeyValueStore/Storage/AzureSdkTableStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/AzureSdkTableStorage.php @@ -33,7 +33,7 @@ * * @author Benjamin Eberlei */ -class AzureSdkTableStorage implements Storage, RangeQueryStorage +class AzureSdkTableStorage extends AbstractStorage implements RangeQueryStorage { /** * @var \WindowsAzure\Table\TableRestProxy diff --git a/lib/Doctrine/KeyValueStore/Storage/CassandraStorage.php b/lib/Doctrine/KeyValueStore/Storage/CassandraStorage.php index 47cf7bf..f58de8c 100644 --- a/lib/Doctrine/KeyValueStore/Storage/CassandraStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/CassandraStorage.php @@ -31,7 +31,7 @@ * * @uses https://github.com/datastax/php-driver */ -class CassandraStorage implements Storage +class CassandraStorage extends AbstractStorage { /** * @var \Cassandra\Session diff --git a/lib/Doctrine/KeyValueStore/Storage/CouchDbStorage.php b/lib/Doctrine/KeyValueStore/Storage/CouchDbStorage.php index 39ef86c..72311fa 100644 --- a/lib/Doctrine/KeyValueStore/Storage/CouchDbStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/CouchDbStorage.php @@ -30,7 +30,7 @@ * * @author Emanuele Minotto */ -final class CouchDbStorage implements Storage +final class CouchDbStorage extends AbstractStorage { /** * @var CouchDBClient @@ -112,29 +112,4 @@ public function getName() { return 'couchdb'; } - - /** - * @param string $storageName - * @param array|string $key - * - * @return string - */ - private function flattenKey($storageName, $key) - { - $finalKey = $storageName . '-'; - - if (is_string($key)) { - return $finalKey . $key; - } - - if ( ! is_array($key)) { - throw new \InvalidArgumentException('The key should be a string or a flat array.'); - } - - foreach ($key as $property => $value) { - $finalKey .= sprintf('%s:%s-', $property, $value); - } - - return $finalKey; - } } diff --git a/lib/Doctrine/KeyValueStore/Storage/CouchbaseStorage.php b/lib/Doctrine/KeyValueStore/Storage/CouchbaseStorage.php index 4fca169..f0624a0 100644 --- a/lib/Doctrine/KeyValueStore/Storage/CouchbaseStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/CouchbaseStorage.php @@ -25,7 +25,7 @@ /** * @author Simon Schick */ -class CouchbaseStorage implements Storage +class CouchbaseStorage extends AbstractStorage { /** * @var \Couchbase diff --git a/lib/Doctrine/KeyValueStore/Storage/DBALStorage.php b/lib/Doctrine/KeyValueStore/Storage/DBALStorage.php index 6f720c8..ddbfca4 100644 --- a/lib/Doctrine/KeyValueStore/Storage/DBALStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/DBALStorage.php @@ -30,7 +30,7 @@ * * @author Benjamin Eberlei */ -class DBALStorage implements Storage +class DBALStorage extends AbstractStorage { private $conn; private $table; diff --git a/lib/Doctrine/KeyValueStore/Storage/DoctrineCacheStorage.php b/lib/Doctrine/KeyValueStore/Storage/DoctrineCacheStorage.php index acf3642..d81fbfd 100644 --- a/lib/Doctrine/KeyValueStore/Storage/DoctrineCacheStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/DoctrineCacheStorage.php @@ -30,7 +30,7 @@ * * @author Benjamin Eberlei */ -class DoctrineCacheStorage implements Storage +class DoctrineCacheStorage extends AbstractStorage { /** * @var Doctrine\Common\Cache\Cache @@ -60,20 +60,6 @@ public function requiresCompositePrimaryKeys() return false; } - private function flattenKey($storageName, $key) - { - if ( ! $this->supportsCompositeKeys) { - return $storageName . '-' . $key; - } - - $hash = $storageName . '-oid:'; - ksort($key); - foreach ($key as $property => $value) { - $hash .= $property . '=' . $value . ';'; - } - return $hash; - } - public function insert($storageName, $key, array $data) { $key = $this->flattenKey($storageName, $key); diff --git a/lib/Doctrine/KeyValueStore/Storage/DynamoDbStorage.php b/lib/Doctrine/KeyValueStore/Storage/DynamoDbStorage.php index 5fd366b..eac50a6 100644 --- a/lib/Doctrine/KeyValueStore/Storage/DynamoDbStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/DynamoDbStorage.php @@ -30,7 +30,7 @@ * * @author Stan Lemon */ -class DynamoDbStorage implements Storage +class DynamoDbStorage extends AbstractStorage { /** * @var \Aws\DynamoDb\DynamoDbClient diff --git a/lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php b/lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php index a9ba59a..90b7927 100644 --- a/lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/MongoDbStorage.php @@ -27,7 +27,7 @@ * * @author Markus Bachmann */ -class MongoDbStorage implements Storage +class MongoDbStorage extends AbstractStorage { /** * @var \Mongo diff --git a/lib/Doctrine/KeyValueStore/Storage/RedisStorage.php b/lib/Doctrine/KeyValueStore/Storage/RedisStorage.php index 0a30862..0b264e6 100644 --- a/lib/Doctrine/KeyValueStore/Storage/RedisStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/RedisStorage.php @@ -25,7 +25,7 @@ /** * @author Marcel Araujo */ -class RedisStorage implements Storage +class RedisStorage extends AbstractStorage { /** * @var \Redis diff --git a/lib/Doctrine/KeyValueStore/Storage/RiakStorage.php b/lib/Doctrine/KeyValueStore/Storage/RiakStorage.php index 41facdc..f98d96b 100644 --- a/lib/Doctrine/KeyValueStore/Storage/RiakStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/RiakStorage.php @@ -26,7 +26,7 @@ /** * @author Markus Bachmann */ -class RiakStorage implements Storage +class RiakStorage extends AbstractStorage { /** * @var \Riak\Client diff --git a/lib/Doctrine/KeyValueStore/Storage/SimpleDbStorage.php b/lib/Doctrine/KeyValueStore/Storage/SimpleDbStorage.php index 730c21b..5983ee6 100644 --- a/lib/Doctrine/KeyValueStore/Storage/SimpleDbStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/SimpleDbStorage.php @@ -31,7 +31,7 @@ * * @author Stan Lemon */ -class SimpleDbStorage implements Storage +class SimpleDbStorage extends AbstractStorage { /** * @var \Aws\SimpleDb\SimpleDbClient diff --git a/lib/Doctrine/KeyValueStore/Storage/WindowsAzureTableStorage.php b/lib/Doctrine/KeyValueStore/Storage/WindowsAzureTableStorage.php index 4114146..ccdd525 100644 --- a/lib/Doctrine/KeyValueStore/Storage/WindowsAzureTableStorage.php +++ b/lib/Doctrine/KeyValueStore/Storage/WindowsAzureTableStorage.php @@ -36,7 +36,7 @@ * * @deprecated This class is deprecated and will be removed in 2.0, use the AzureSdkTableStorage instead. */ -class WindowsAzureTableStorage implements Storage, RangeQueryStorage +class WindowsAzureTableStorage extends AbstractStorage implements RangeQueryStorage { const WINDOWS_AZURE_TABLE_BASEURL = 'https://%s.table.core.windows.net'; @@ -61,7 +61,7 @@ class WindowsAzureTableStorage implements Storage, RangeQueryStorage '; const XML_TEMPLATE_TABLE = ' - + <updated></updated> <author> diff --git a/tests/Doctrine/Tests/KeyValueStore/Functional/Storage/CassandraTest.php b/tests/Doctrine/Tests/KeyValueStore/Functional/Storage/CassandraTest.php index 9d6d196..cee92dc 100644 --- a/tests/Doctrine/Tests/KeyValueStore/Functional/Storage/CassandraTest.php +++ b/tests/Doctrine/Tests/KeyValueStore/Functional/Storage/CassandraTest.php @@ -33,7 +33,7 @@ class CassandraTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $cluster = Cassandra::cluster()->build(); + $cluster = Cassandra::cluster()->build(); $this->session = $cluster->connect(); try { diff --git a/tests/Doctrine/Tests/KeyValueStore/Storage/AbstractStorageTest.php b/tests/Doctrine/Tests/KeyValueStore/Storage/AbstractStorageTest.php new file mode 100644 index 0000000..ff81598 --- /dev/null +++ b/tests/Doctrine/Tests/KeyValueStore/Storage/AbstractStorageTest.php @@ -0,0 +1,80 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Tests\KeyValueStore\Storage; + +use Doctrine\KeyValueStore\Storage\AbstractStorage; +use PHPUnit_Framework_TestCase; +use ReflectionClass; + +/** + * @covers \Doctrine\KeyValueStore\Storage\AbstractStorage + */ +class AbstractStorageTest extends PHPUnit_Framework_TestCase +{ + /** + * @var AbstractStorage + */ + protected $object; + + public function setUp() + { + $this->object = $this->getMockForAbstractClass(AbstractStorage::class); + } + + /** + * @dataProvider keysDataProvider + */ + public function testFlattenKey($storageName, $key, $expected) + { + $reflectionClass = new ReflectionClass($this->object); + $method = $reflectionClass->getMethod('flattenKey'); + $method->setAccessible(true); + + $hash = $method->invokeArgs($this->object, [$storageName, $key]); + + $this->assertInternalType('string', $hash); + $this->assertSame($expected, $hash); + } + + /** + * @return array + */ + public function keysDataProvider() + { + return [ + // key: string + ['foo', 'bar', 'foo-bar'], + ['foo', 0.0, 'foo-0'], + ['foo', 0.05, 'foo-0.05'], + ['foo', 1, 'foo-1'], + ['foo', 1.0, 'foo-1'], + ['foo', 1.05, 'foo-1.05'], + ['foo', false, 'foo-'], + ['foo', true, 'foo-1'], + // key: array + ['foo', ['bar', 'test'], 'foo-oid:0=bar;1=test;'], + ['foo', ['bar', 0.0], 'foo-oid:0=bar;1=0;'], + ['foo', ['test' => 3, 'bar' => 5], 'foo-oid:bar=5;test=3;'], + ['foo', ['test' => 3.1, 'bar' => 5.0], 'foo-oid:bar=5;test=3.1;'], + ['foo', ['test' => true, 'bar' => false], 'foo-oid:bar=;test=1;'], + ]; + } +}