mirror of
https://github.com/doctrine/KeyValueStore.git
synced 2026-03-24 16:52:17 +01:00
Compare commits
1 Commits
master
...
enhancemen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d8dde073 |
1
.php_cs
1
.php_cs
@@ -61,6 +61,7 @@ $config = Symfony\CS\Config\Config::create()
|
||||
'align_equals',
|
||||
'concat_with_spaces',
|
||||
'header_comment',
|
||||
'logical_not_operators_with_spaces',
|
||||
'logical_not_operators_with_successor_space',
|
||||
'multiline_spaces_before_semicolon',
|
||||
'newline_after_open_tag',
|
||||
|
||||
26
.travis.yml
26
.travis.yml
@@ -1,37 +1,17 @@
|
||||
language: php
|
||||
|
||||
services:
|
||||
- docker
|
||||
- mongodb
|
||||
- redis-server
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
-
|
||||
key_url: 'https://packagecloud.io/gpg.key'
|
||||
sourceline: 'deb https://packagecloud.io/basho/riak/ubuntu/ trusty main'
|
||||
-
|
||||
key_url: 'https://packagecloud.io/gpg.key'
|
||||
sourceline: 'deb-src https://packagecloud.io/basho/riak/ubuntu/ trusty main'
|
||||
update: true
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
- hhvm
|
||||
|
||||
before_install:
|
||||
- docker run -d -p 8000:8000 amazon/dynamodb-local
|
||||
- sudo apt-get install -y --allow-unauthenticated riak
|
||||
- sudo service riak start
|
||||
- pecl install --force mongodb
|
||||
- if [[ ${TRAVIS_PHP_VERSION:0:1} != "7" ]]; then sh ./tests/travis.sh; fi
|
||||
- if [[ $TRAVIS_PHP_VERSION != "hhvm" && $TRAVIS_PHP_VERSION != "7.0" ]]; then sh ./tests/travis.sh; fi
|
||||
- composer self-update
|
||||
|
||||
install:
|
||||
|
||||
@@ -23,7 +23,7 @@ Following vendors are targeted:
|
||||
* Doctrine\Common\Cache provider (Implemented)
|
||||
* RDBMS (Implemented)
|
||||
* Couchbase (Implemented)
|
||||
* Amazon DynamoDB (Implemented)
|
||||
* Amazon DynamoDB
|
||||
* CouchDB (Implemented)
|
||||
* Cassandra
|
||||
* MongoDB (Implemented)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Upgrade to 0.3
|
||||
|
||||
## BC Break: Fixed MongoDB storage usage
|
||||
|
||||
Before v0.3 the storage name associated to a class wasn't used when the storage is `MongoDbStorage`.
|
||||
In order to be consistent with other storage drivers, the `storageName` is now used for the collection name when storing and data.
|
||||
To get the same behavior as in older versions, pass the collection name given in the constructor arguments as storage name.
|
||||
@@ -1,21 +1,19 @@
|
||||
{
|
||||
"name": "doctrine/key-value-store",
|
||||
"require": {
|
||||
"php": "^5.5|^7.0",
|
||||
"doctrine/common": "^2.4"
|
||||
"php": ">=5.5",
|
||||
"doctrine/common": "^2.4",
|
||||
"doctrine/couchdb": "^1.0.0-beta4"
|
||||
},
|
||||
"require-dev": {
|
||||
"datastax/php-driver": "^1.0",
|
||||
"doctrine/couchdb": "^1.0.0-beta4",
|
||||
"phpunit/phpunit": "^4.8|^5.0",
|
||||
"aws/aws-sdk-php": "^3.8",
|
||||
"php-riak/riak-client": "^1.0@alpha",
|
||||
"mongodb/mongodb": "^1.4"
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"riak/riak-client": "dev-master"
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "to use the DynamoDB storage",
|
||||
"doctrine/couchdb": "to use the CouchDB storage",
|
||||
"ext-couchbase": "to use the Couchbase storage"
|
||||
"riak/riak-client": "to use the Riak storage",
|
||||
"ext-couchbase": "to use the Couchbase storage",
|
||||
"aws/aws-sdk-php": "to use the DynamoDB storage"
|
||||
},
|
||||
"description": "Simple Key-Value Store Abstraction Layer that maps to PHP objects, allowing for many backends.",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -8,7 +8,7 @@ This guide covers getting started with the Doctrine Key Value Store.
|
||||
|
||||
To use the KeyValueStore you actually need:
|
||||
|
||||
- PHP 5.6 or above
|
||||
- PHP 5.5 or above
|
||||
- Composer Package Manager (`Install Composer
|
||||
<http://getcomposer.org/doc/00-intro.md>`_)
|
||||
|
||||
|
||||
@@ -52,32 +52,17 @@ database backends, you have to configure the actual storage you want to use.
|
||||
This configuration is obviously specific to all the different storage drivers.
|
||||
So far the following drivers exist (and are documented here):
|
||||
|
||||
* PHP Array
|
||||
* Doctrine Cache Backend
|
||||
* SQL Backend with Doctrine DBAL
|
||||
* Microsoft Windows Azure Table
|
||||
* Couchbase
|
||||
* CouchDB
|
||||
* DynamoDB
|
||||
* MongoDB
|
||||
* Riak
|
||||
|
||||
Also all those storage backends obviously have different dependencies in terms
|
||||
of PHP libraries or PHP PECL extensions.
|
||||
|
||||
PHP Array
|
||||
---------
|
||||
|
||||
PHP array is used mainly for development and teesting purposes.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
use Doctrine\KeyValueStore\Storage\ArrayStorage;
|
||||
|
||||
$storage = new ArrayStorage();
|
||||
|
||||
Doctrine Cache Backend
|
||||
----------------------
|
||||
|
||||
@@ -146,26 +131,6 @@ as a storage layer through the Windows Azure PHP SDK:
|
||||
|
||||
$storage = new AzureSdkTableStorage($client);
|
||||
|
||||
Cassandra
|
||||
---------
|
||||
|
||||
Cassandra is supported through the `PECL extension <https://pecl.php.net/package/cassandra>`_
|
||||
and the `DataStax PHP driver <https://github.com/datastax/php-driver>`_:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
use Cassandra;
|
||||
use Cassandra\SimpleStatement;
|
||||
use Doctrine\KeyValueStore\Storage\CassandraStorage;
|
||||
|
||||
$cluster = Cassandra::cluster()->build();
|
||||
$session = $cluster->connect();
|
||||
$session->execute(new SimpleStatement('USE doctrine'));
|
||||
|
||||
$storage = new CassandraStorage($session);
|
||||
|
||||
Couchbase
|
||||
---------
|
||||
|
||||
@@ -199,53 +164,39 @@ CouchDB storage setup based on `doctrine/couchdb-client <https://github.com/doct
|
||||
|
||||
$storage = new CouchDbStorage($client);
|
||||
|
||||
DynamoDb
|
||||
---------
|
||||
|
||||
DynamoDb is supported through the `AWS SDK for PHP <https://aws.amazon.com/sdk-for-php/>`_
|
||||
Create your tables via the AWS DynamoDb console or using the `PHP based API <http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelPHPTableOperationsExample.html>`_
|
||||
See the `AWS docs <http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/UsingPHP.html#PHPSDKCredentialsSet>`_ for more information on configuring credentials for the client.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
$client = DynamoDbClient::factory([...])
|
||||
|
||||
$storage = new DynamoDbStorage($client);
|
||||
|
||||
MongoDB
|
||||
-------
|
||||
|
||||
MongoDB is based on `mongodb/mongodb <https://github.com/mongodb/mongo-php-library>`_:
|
||||
MongoDB support is provided using a `Database <https://docs.mongodb.com/php-library/current/reference/class/MongoDBDatabase/>`_
|
||||
instance.
|
||||
Mongo support is provided using a `Mongo <http://php.net/manual/en/class.mongo.php>`_
|
||||
instance, the collection name and the database name.
|
||||
|
||||
Both the options ``collection`` and ``database`` are required.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
use MongoDB\Client;
|
||||
use Doctrine\KeyValueStore\Storage\MongoDbStorage;
|
||||
|
||||
$client = new Client(/* connection parameters and options */);
|
||||
$conn = new \Mongo(/* connection parameters and options */);
|
||||
|
||||
$storage = new MongoDbStorage($client->your_database);
|
||||
$storage = new MongoDbStorage($conn, array(
|
||||
'collection' => 'your_collection',
|
||||
'database' => 'your_database',
|
||||
));
|
||||
|
||||
Riak
|
||||
----
|
||||
|
||||
Riak support is provided through the library `php-riak/riak-client <https://github.com/php-riak/riak-client>`_ :
|
||||
Riak support is provided through the library `riak/riak-client <https://github.com/nacmartin/riak-client>`_ :
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
use Doctrine\KeyValueStore\Storage\RiakStorage;
|
||||
use Riak\Client\RiakClientBuilder;
|
||||
use Riak\Client;
|
||||
|
||||
$conn = (new RiakClientBuilder())
|
||||
->withNodeUri(/* connection DNS */)
|
||||
->build();
|
||||
$conn = new Riak(/* connection parameters */);
|
||||
|
||||
$storage = new RiakStorage($conn);
|
||||
|
||||
@@ -45,7 +45,7 @@ class Configuration
|
||||
*/
|
||||
public function getMappingDriverImpl()
|
||||
{
|
||||
if (! isset($this->config['mappingDriver'])) {
|
||||
if ( ! isset($this->config['mappingDriver'])) {
|
||||
throw KeyValueStoreException::mappingDriverMissing();
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class Configuration
|
||||
*/
|
||||
public function getMetadataCache()
|
||||
{
|
||||
if (! isset($this->config['metadataCache'])) {
|
||||
if ( ! isset($this->config['metadataCache'])) {
|
||||
$this->config['metadataCache'] = new ArrayCache();
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ class Configuration
|
||||
*/
|
||||
public function getIdConverterStrategy()
|
||||
{
|
||||
if (! isset($this->config['idConverter'])) {
|
||||
if ( ! isset($this->config['idConverter'])) {
|
||||
$this->config['idConverter'] = new NullIdConverter();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class EntityManager
|
||||
*/
|
||||
public function find($className, $key)
|
||||
{
|
||||
return $this->unitOfWork->reconstititute($className, $key);
|
||||
return $this->unitOfWork->reconsititute($className, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,7 +71,7 @@ class Response
|
||||
*/
|
||||
public function getHeader($name)
|
||||
{
|
||||
if (! isset($this->headers[$name])) {
|
||||
if ( ! isset($this->headers[$name])) {
|
||||
return;
|
||||
}
|
||||
return $this->headers[$name];
|
||||
|
||||
@@ -157,7 +157,7 @@ class SocketClient implements Client
|
||||
|
||||
// Remove leading newlines, should not accur at all, actually.
|
||||
while (true) {
|
||||
if (! (($line = fgets($this->connection)) !== false) || ! (($lineContent = rtrim($line)) === '')) {
|
||||
if ( ! (($line = fgets($this->connection)) !== false) || ! (($lineContent = rtrim($line)) === '')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@ class SocketClient implements Client
|
||||
|
||||
// Read response body
|
||||
$body = '';
|
||||
if (! isset($headers['transfer-encoding']) ||
|
||||
if ( ! isset($headers['transfer-encoding']) ||
|
||||
($headers['transfer-encoding'] !== 'chunked')) {
|
||||
// HTTP 1.1 supports chunked transfer encoding, if the according
|
||||
// header is not set, just read the specified amount of bytes.
|
||||
|
||||
@@ -26,14 +26,14 @@ class CompositeIdHandler implements IdHandlingStrategy
|
||||
{
|
||||
public function normalizeId(ClassMetadata $metadata, $key)
|
||||
{
|
||||
if (! $metadata->isCompositeKey && ! is_array($key)) {
|
||||
if ( ! $metadata->isCompositeKey && ! is_array($key)) {
|
||||
$id = [$metadata->identifier[0] => $key];
|
||||
} elseif (! is_array($key)) {
|
||||
} elseif ( ! is_array($key)) {
|
||||
throw new \InvalidArgumentException('Array of identifier key-value pairs is expected!');
|
||||
} else {
|
||||
$id = [];
|
||||
foreach ($metadata->identifier as $field) {
|
||||
if (! isset($key[$field])) {
|
||||
if ( ! isset($key[$field])) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Missing identifier field $field in request for the primary key."
|
||||
);
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
<?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\KeyValueStore;
|
||||
|
||||
class InvalidArgumentException extends KeyValueStoreException
|
||||
{
|
||||
public static function invalidType($name, $expectedType, &$actual)
|
||||
{
|
||||
return new static(
|
||||
sprintf('The %s must be a %s, got "%s" instead.', $name, $expectedType, gettype($actual)),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public static function invalidLength($name, $min, $max)
|
||||
{
|
||||
return new static(
|
||||
sprintf('The %s must be at least %d but no more than %d chars.', $name, $min, $max),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public static function invalidTableName($name)
|
||||
{
|
||||
return new static(
|
||||
sprintf('Invalid table name: %s', $name),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -52,14 +52,14 @@ class AnnotationDriver implements MappingDriver
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata)
|
||||
{
|
||||
$class = $metadata->getReflectionClass();
|
||||
if (! $class) {
|
||||
if ( ! $class) {
|
||||
// this happens when running annotation driver in combination with
|
||||
// static reflection services. This is not the nicest fix
|
||||
$class = new \ReflectionClass($metadata->name);
|
||||
}
|
||||
|
||||
$entityAnnot = $this->reader->getClassAnnotation($class, 'Doctrine\KeyValueStore\Mapping\Annotations\Entity');
|
||||
if (! $entityAnnot) {
|
||||
if ( ! $entityAnnot) {
|
||||
throw new \InvalidArgumentException($metadata->name . ' is not a valid key-value-store entity.');
|
||||
}
|
||||
$metadata->storageName = $entityAnnot->storageName;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
namespace Doctrine\KeyValueStore\Mapping;
|
||||
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata as BaseClassMetadata;
|
||||
use ReflectionClass;
|
||||
|
||||
class ClassMetadata implements BaseClassMetadata
|
||||
{
|
||||
@@ -51,7 +50,7 @@ class ClassMetadata implements BaseClassMetadata
|
||||
|
||||
public function mapField($mapping)
|
||||
{
|
||||
if (! isset($this->transientFields[$mapping['fieldName']])) {
|
||||
if ( ! isset($this->transientFields[$mapping['fieldName']])) {
|
||||
$this->fields[$mapping['fieldName']] = $mapping;
|
||||
}
|
||||
}
|
||||
@@ -94,7 +93,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
}
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fully-qualified class name of this persistent class.
|
||||
*
|
||||
@@ -102,7 +100,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +111,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +120,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function getReflectionClass()
|
||||
{
|
||||
return new ReflectionClass($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +131,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function isIdentifier($fieldName)
|
||||
{
|
||||
return in_array($fieldName, $this->identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +142,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function hasField($fieldName)
|
||||
{
|
||||
return isset($this->fields[$fieldName]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +153,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function hasAssociation($fieldName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,7 +164,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function isSingleValuedAssociation($fieldName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,7 +175,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function isCollectionValuedAssociation($fieldName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +186,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function getFieldNames()
|
||||
{
|
||||
return array_column($this->fields, 'fieldName');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,7 +195,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function getIdentifierFieldNames()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,7 +242,6 @@ class ClassMetadata implements BaseClassMetadata
|
||||
*/
|
||||
public function isAssociationInverseSide($assocName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,12 +58,12 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
$class->storageName = $parent->storageName;
|
||||
}
|
||||
|
||||
if (! $class->storageName) {
|
||||
if ( ! $class->storageName) {
|
||||
$parts = explode('\\', $class->name);
|
||||
$class->storageName = end($parts);
|
||||
}
|
||||
|
||||
if (! $class->identifier) {
|
||||
if ( ! $class->identifier) {
|
||||
throw new \InvalidArgumentException('Class ' . $class->name . ' has no identifier.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,4 @@ namespace Doctrine\KeyValueStore;
|
||||
|
||||
class NotFoundException extends KeyValueStoreException
|
||||
{
|
||||
public static function notFoundByKey($key)
|
||||
{
|
||||
return new static(sprintf('Could not find an item with key: %s', $key), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,9 +208,9 @@ class RangeQuery
|
||||
{
|
||||
$storage = $this->em->unwrap();
|
||||
|
||||
if (! $storage instanceof RangeQueryStorage) {
|
||||
if ( ! ($storage instanceof RangeQueryStorage)) {
|
||||
throw new \RuntimeException(
|
||||
'The storage backend ' . $storage->getName() . ' does not support range queries.'
|
||||
'The storage backend ' . $this->storage->getName() . ' does not support range queries.'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
93
lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php
Normal file
93
lib/Doctrine/KeyValueStore/Storage/AbstractStorage.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?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\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;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<?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\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
|
||||
/**
|
||||
* Array storage, mainly used for development purposes.
|
||||
*
|
||||
* @author Emanuele Minotto <minottoemanuele@gmail.com>
|
||||
*/
|
||||
class ArrayStorage implements Storage
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
public function supportsPartialUpdates()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this storage support composite primary keys?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsCompositePrimaryKeys()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this storage require composite primary keys?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function requiresCompositePrimaryKeys()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert data into the storage key specified.
|
||||
*
|
||||
* @param array|string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function insert($storageName, $key, array $data)
|
||||
{
|
||||
$this->update($storageName, $key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data into the given key.
|
||||
*
|
||||
* @param array|string $key
|
||||
* @param array $data
|
||||
*/
|
||||
public function update($storageName, $key, array $data)
|
||||
{
|
||||
if (!isset($this->data[$storageName])) {
|
||||
$this->data[$storageName] = [];
|
||||
}
|
||||
|
||||
$this->data[$storageName][serialize($key)] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete data at key
|
||||
*
|
||||
* @param array|string $key
|
||||
*/
|
||||
public function delete($storageName, $key)
|
||||
{
|
||||
if (!isset($this->data[$storageName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($this->data[$storageName][serialize($key)])) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->data[$storageName][serialize($key)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find data at key
|
||||
*
|
||||
* @param array|string $key
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function find($storageName, $key)
|
||||
{
|
||||
if (!isset($this->data[$storageName])) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (!isset($this->data[$storageName][serialize($key)])) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
unset($this->data[$storageName][serialize($key)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a name of the underlying storage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'array';
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ use WindowsAzure\Table\TableRestProxy;
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class AzureSdkTableStorage implements Storage, RangeQueryStorage
|
||||
class AzureSdkTableStorage extends AbstractStorage implements RangeQueryStorage
|
||||
{
|
||||
/**
|
||||
* @var \WindowsAzure\Table\TableRestProxy
|
||||
@@ -184,7 +184,7 @@ class AzureSdkTableStorage implements Storage, RangeQueryStorage
|
||||
$filters = ['PartitionKey eq ' . $this->quoteFilterValue($query->getPartitionKey())];
|
||||
|
||||
foreach ($query->getConditions() as $condition) {
|
||||
if (! in_array($condition[0], ['eq', 'neq', 'le', 'lt', 'ge', 'gt'])) {
|
||||
if ( ! in_array($condition[0], ['eq', 'neq', 'le', 'lt', 'ge', 'gt'])) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Windows Azure Table only supports eq, neq, le, lt, ge, gt as conditions.'
|
||||
);
|
||||
|
||||
@@ -31,7 +31,7 @@ use Doctrine\KeyValueStore\NotFoundException;
|
||||
*
|
||||
* @uses https://github.com/datastax/php-driver
|
||||
*/
|
||||
class CassandraStorage implements Storage
|
||||
class CassandraStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var \Cassandra\Session
|
||||
@@ -160,7 +160,7 @@ class CassandraStorage implements Storage
|
||||
$result = $this->session->execute($stmt, $options);
|
||||
$rows = iterator_to_array($result);
|
||||
|
||||
if (! isset($rows[0])) {
|
||||
if ( ! isset($rows[0])) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ use Doctrine\CouchDB\CouchDBClient;
|
||||
*
|
||||
* @author Emanuele Minotto <minottoemanuele@gmail.com>
|
||||
*/
|
||||
final class CouchDbStorage implements Storage
|
||||
final class CouchDbStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var CouchDBClient
|
||||
@@ -112,29 +112,4 @@ final class CouchDbStorage implements Storage
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ use Doctrine\KeyValueStore\NotFoundException;
|
||||
/**
|
||||
* @author Simon Schick <simonsimcity@gmail.com>
|
||||
*/
|
||||
class CouchbaseStorage implements Storage
|
||||
class CouchbaseStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var \Couchbase
|
||||
|
||||
@@ -30,7 +30,7 @@ use Doctrine\KeyValueStore\NotFoundException;
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DBALStorage implements Storage
|
||||
class DBALStorage extends AbstractStorage
|
||||
{
|
||||
private $conn;
|
||||
private $table;
|
||||
@@ -142,7 +142,7 @@ class DBALStorage implements Storage
|
||||
|
||||
$data = $stmt->fetchColumn();
|
||||
|
||||
if (! $data) {
|
||||
if ( ! $data) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ use Doctrine\Common\Cache\Cache;
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DoctrineCacheStorage implements Storage
|
||||
class DoctrineCacheStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var Doctrine\Common\Cache\Cache
|
||||
@@ -60,20 +60,6 @@ class DoctrineCacheStorage implements Storage
|
||||
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);
|
||||
|
||||
@@ -21,50 +21,34 @@
|
||||
namespace Doctrine\KeyValueStore\Storage;
|
||||
|
||||
use Aws\DynamoDb\DynamoDbClient;
|
||||
use Aws\DynamoDb\Marshaler;
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Aws\DynamoDb\Exception\ResourceNotFoundException;
|
||||
use Aws\DynamoDb\Iterator\ItemIterator;
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
|
||||
/**
|
||||
* DynamoDb storage.
|
||||
* DyanmoDb storage
|
||||
*
|
||||
* @author Stan Lemon <stosh1985@gmail.com>
|
||||
*/
|
||||
class DynamoDbStorage implements Storage
|
||||
class DynamoDbStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var DynamoDbClient
|
||||
* @var \Aws\DynamoDb\DynamoDbClient
|
||||
*/
|
||||
private $client;
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var Marshaler
|
||||
* Constructor
|
||||
*
|
||||
* @param \Aws\DynamoDb\DynamoDbClient $client
|
||||
*/
|
||||
private $marshaler;
|
||||
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
private $descriptionCache;
|
||||
|
||||
/**
|
||||
* @param DynamoDbClient $client The client for connecting to AWS DynamoDB
|
||||
* @param Marshaler|null $marshaler (optional) Marshaller for converting data to/from DynamoDB format
|
||||
* @param Cache|null $descriptionCache Cache used to store tables description
|
||||
*/
|
||||
public function __construct(
|
||||
DynamoDbClient $client,
|
||||
Marshaler $marshaler = null,
|
||||
Cache $descriptionCache = null
|
||||
) {
|
||||
public function __construct(DynamoDbClient $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->marshaler = $marshaler ?: new Marshaler();
|
||||
$this->descriptionCache = $descriptionCache ?: new ArrayCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function supportsPartialUpdates()
|
||||
{
|
||||
@@ -72,7 +56,7 @@ class DynamoDbStorage implements Storage
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function supportsCompositePrimaryKeys()
|
||||
{
|
||||
@@ -80,7 +64,7 @@ class DynamoDbStorage implements Storage
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function requiresCompositePrimaryKeys()
|
||||
{
|
||||
@@ -88,98 +72,77 @@ class DynamoDbStorage implements Storage
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a key to be in a valid format for lookups for DynamoDB. If passing an array, that means that the key
|
||||
* is the name of the key and the value is the actual value for the lookup.
|
||||
*
|
||||
* @param string $storageName Table name
|
||||
* @param array|string $key Key name
|
||||
*
|
||||
* @return array The key in DynamoDB format
|
||||
*/
|
||||
private function prepareKey($storageName, $key)
|
||||
{
|
||||
if (! $this->descriptionCache->contains($storageName)) {
|
||||
$result = $this->client->describeTable([
|
||||
'TableName' => $storageName,
|
||||
]);
|
||||
|
||||
$keys = isset($result['Table']['KeySchema'])
|
||||
? $result['Table']['KeySchema']
|
||||
: [];
|
||||
$keys = array_column($keys, 'AttributeName') ?: [];
|
||||
|
||||
$this->descriptionCache->save($storageName, $keys);
|
||||
}
|
||||
|
||||
$keys = isset($keys) ? $keys : $this->descriptionCache->fetch($storageName);
|
||||
$keys = array_combine($keys, array_fill(0, (count($keys) - 1) ?: 1, $key));
|
||||
|
||||
if (!is_array($key)) {
|
||||
$key = [
|
||||
$storageName => $key,
|
||||
];
|
||||
}
|
||||
|
||||
$keys = array_intersect_assoc($keys, $key) ?: $keys;
|
||||
|
||||
return $this->marshaler->marshalItem($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function insert($storageName, $key, array $data)
|
||||
{
|
||||
$this->client->putItem([
|
||||
'TableName' => $storageName,
|
||||
'Item' => $this->prepareKey($storageName, $key) + $this->marshaler->marshalItem($data),
|
||||
$this->createTable($storageName);
|
||||
|
||||
$this->prepareData($key, $data);
|
||||
|
||||
$result = $this->client->putItem([
|
||||
'TableName' => $storageName,
|
||||
'Item' => $this->client->formatAttributes($data),
|
||||
'ReturnConsumedCapacity' => 'TOTAL',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function update($storageName, $key, array $data)
|
||||
{
|
||||
// we are using PUT so we just replace the original item, if the key
|
||||
// does not exist, it will be created.
|
||||
$this->insert($storageName, $key, $data);
|
||||
$this->prepareData($key, $data);
|
||||
|
||||
unset($data['id']);
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
$data[$k] = [
|
||||
'Value' => $this->client->formatValue($v),
|
||||
];
|
||||
}
|
||||
|
||||
$result = $this->client->updateItem([
|
||||
'TableName' => $storageName,
|
||||
'Key' => [
|
||||
'id' => ['S' => $key],
|
||||
],
|
||||
'AttributeUpdates' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function delete($storageName, $key)
|
||||
{
|
||||
$this->client->deleteItem([
|
||||
'Key' => $this->prepareKey($storageName, $key),
|
||||
$result = $this->client->deleteItem([
|
||||
'TableName' => $storageName,
|
||||
'Key' => [
|
||||
'id' => ['S' => $key],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function find($storageName, $key)
|
||||
{
|
||||
$keys = $this->prepareKey($storageName, $key);
|
||||
|
||||
$item = $this->client->getItem([
|
||||
'ConsistentRead' => true,
|
||||
'Key' => $keys,
|
||||
$iterator = new ItemIterator($this->client->getScanIterator([
|
||||
'TableName' => $storageName,
|
||||
]);
|
||||
'Key' => [
|
||||
'Id' => ['S' => $key],
|
||||
],
|
||||
]));
|
||||
|
||||
if (! $item->hasKey('Item')) {
|
||||
throw NotFoundException::notFoundByKey($key);
|
||||
$results = $iterator->toArray();
|
||||
|
||||
if (count($results)) {
|
||||
return array_shift($results);
|
||||
}
|
||||
|
||||
$item = $item->get('Item');
|
||||
|
||||
$result = $this->marshaler->unmarshalItem($item);
|
||||
$result = array_diff_key($result, $keys);
|
||||
|
||||
return $result;
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,4 +154,53 @@ class DynamoDbStorage implements Storage
|
||||
{
|
||||
return 'dynamodb';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tableName
|
||||
*/
|
||||
protected function createTable($tableName)
|
||||
{
|
||||
try {
|
||||
$this->client->describeTable([
|
||||
'TableName' => $tableName,
|
||||
]);
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
$this->client->createTable([
|
||||
'AttributeDefinitions' => [
|
||||
[
|
||||
'AttributeName' => 'id',
|
||||
'AttributeType' => 'S',
|
||||
],
|
||||
],
|
||||
'TableName' => $tableName,
|
||||
'KeySchema' => [
|
||||
[
|
||||
'AttributeName' => 'id',
|
||||
'KeyType' => 'HASH',
|
||||
],
|
||||
],
|
||||
'ProvisionedThroughput' => [
|
||||
'ReadCapacityUnits' => 1,
|
||||
'WriteCapacityUnits' => 1,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param array $data
|
||||
*/
|
||||
protected function prepareData($key, &$data)
|
||||
{
|
||||
$data = array_merge($data, [
|
||||
'id' => $key,
|
||||
]);
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if ($value === null || $value === [] || $value === '') {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,66 @@
|
||||
namespace Doctrine\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
use MongoDB\Database;
|
||||
|
||||
/**
|
||||
* MongoDb storage
|
||||
*
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*/
|
||||
class MongoDbStorage implements Storage
|
||||
class MongoDbStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var Database
|
||||
* @var \Mongo
|
||||
*/
|
||||
private $database;
|
||||
protected $mongo;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
* @var array
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
protected $dbOptions;
|
||||
|
||||
/**
|
||||
* @var \MongoCollection
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Mongo $mongo
|
||||
* @param array $dbOptions
|
||||
*/
|
||||
public function __construct(\Mongo $mongo, array $dbOptions = [])
|
||||
{
|
||||
$this->database = $database;
|
||||
$this->mongo = $mongo;
|
||||
$this->dbOptions = array_merge([
|
||||
'database' => '',
|
||||
'collection' => '',
|
||||
], $dbOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the mongodb collection
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
if (null !== $this->collection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->dbOptions['database'])) {
|
||||
throw new \RuntimeException('The option "database" must be set');
|
||||
}
|
||||
if (empty($this->dbOptions['collection'])) {
|
||||
throw new \RuntimeException('The option "collection" must be set');
|
||||
}
|
||||
|
||||
$this->collection = $this
|
||||
->mongo
|
||||
->selectDB($this->dbOptions['database'])
|
||||
->selectCollection($this->dbOptions['collection']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,12 +112,14 @@ class MongoDbStorage implements Storage
|
||||
*/
|
||||
public function insert($storageName, $key, array $data)
|
||||
{
|
||||
$this->database
|
||||
->selectCollection($storageName)
|
||||
->insertOne([
|
||||
'key' => $key,
|
||||
'value' => $data,
|
||||
]);
|
||||
$this->initialize();
|
||||
|
||||
$value = [
|
||||
'key' => $key,
|
||||
'value' => $data,
|
||||
];
|
||||
|
||||
$this->collection->insert($value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,14 +127,14 @@ class MongoDbStorage implements Storage
|
||||
*/
|
||||
public function update($storageName, $key, array $data)
|
||||
{
|
||||
$this->database
|
||||
->selectCollection($storageName)
|
||||
->replaceOne([
|
||||
'key' => $key,
|
||||
], [
|
||||
'key' => $key,
|
||||
'value' => $data,
|
||||
]);
|
||||
$this->initialize();
|
||||
|
||||
$value = [
|
||||
'key' => $key,
|
||||
'value' => $data,
|
||||
];
|
||||
|
||||
$this->collection->update(['key' => $key], $value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,11 +142,9 @@ class MongoDbStorage implements Storage
|
||||
*/
|
||||
public function delete($storageName, $key)
|
||||
{
|
||||
$this->database
|
||||
->selectCollection($storageName)
|
||||
->deleteOne([
|
||||
'key' => $key,
|
||||
]);
|
||||
$this->initialize();
|
||||
|
||||
$this->collection->remove(['key' => $key]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,23 +152,15 @@ class MongoDbStorage implements Storage
|
||||
*/
|
||||
public function find($storageName, $key)
|
||||
{
|
||||
$result = $this->database
|
||||
->selectCollection($storageName, [
|
||||
'typeMap' => [
|
||||
'array' => 'array',
|
||||
'document' => 'array',
|
||||
'root' => 'array',
|
||||
],
|
||||
])
|
||||
->findOne([
|
||||
'key' => $key,
|
||||
]);
|
||||
$this->initialize();
|
||||
|
||||
if (! $result || ! $result['value']) {
|
||||
throw new NotFoundException();
|
||||
$value = $this->collection->findOne(['key' => $key], ['value']);
|
||||
|
||||
if ($value) {
|
||||
return $value['value'];
|
||||
}
|
||||
|
||||
return $result['value'];
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@ use Doctrine\KeyValueStore\NotFoundException;
|
||||
/**
|
||||
* @author Marcel Araujo <admin@marcelaraujo.me>
|
||||
*/
|
||||
class RedisStorage implements Storage
|
||||
class RedisStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var \Redis
|
||||
@@ -118,7 +118,7 @@ class RedisStorage implements Storage
|
||||
{
|
||||
$key = $this->getKeyName($key);
|
||||
|
||||
if (! $this->client->exists($key)) {
|
||||
if ( ! $this->client->exists($key)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,26 +21,25 @@
|
||||
namespace Doctrine\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
use Riak\Client\Command\Kv\DeleteValue;
|
||||
use Riak\Client\Command\Kv\FetchValue;
|
||||
use Riak\Client\Command\Kv\StoreValue;
|
||||
use Riak\Client\Core\Query\RiakLocation;
|
||||
use Riak\Client\Core\Query\RiakNamespace;
|
||||
use Riak\Client\Core\Query\RiakObject;
|
||||
use Riak\Client\RiakClient;
|
||||
use Riak\Client\RiakException;
|
||||
use Riak\Client;
|
||||
|
||||
/**
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*/
|
||||
class RiakStorage implements Storage
|
||||
class RiakStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var RiakClient
|
||||
* @var \Riak\Client
|
||||
*/
|
||||
private $client;
|
||||
protected $client;
|
||||
|
||||
public function __construct(RiakClient $riak)
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \Riak\Client $riak
|
||||
* @param string $bucketName
|
||||
*/
|
||||
public function __construct(Client $riak)
|
||||
{
|
||||
$this->client = $riak;
|
||||
}
|
||||
@@ -69,25 +68,14 @@ class RiakStorage implements Storage
|
||||
return false;
|
||||
}
|
||||
|
||||
private function store($storageName, $key, array $data)
|
||||
{
|
||||
$location = $this->getRiakLocation($storageName, $key);
|
||||
|
||||
$riakObject = new RiakObject();
|
||||
$riakObject->setContentType('application/json');
|
||||
$riakObject->setValue(json_encode($data));
|
||||
|
||||
$store = StoreValue::builder($location, $riakObject)->build();
|
||||
|
||||
$this->client->execute($store);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function insert($storageName, $key, array $data)
|
||||
{
|
||||
$this->store($storageName, $key, $data);
|
||||
$bucket = $this->client->bucket($storageName);
|
||||
$object = $bucket->newObject($key, $data);
|
||||
$object->store();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +83,12 @@ class RiakStorage implements Storage
|
||||
*/
|
||||
public function update($storageName, $key, array $data)
|
||||
{
|
||||
$this->store($storageName, $key, $data);
|
||||
$bucket = $this->client->bucket($storageName);
|
||||
/** @var $object \Riak\Object */
|
||||
$object = $bucket->get($key);
|
||||
|
||||
$object->setData($data);
|
||||
$object->store();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,15 +96,17 @@ class RiakStorage implements Storage
|
||||
*/
|
||||
public function delete($storageName, $key)
|
||||
{
|
||||
$location = $this->getRiakLocation($storageName, $key);
|
||||
$bucket = $this->client->bucket($storageName);
|
||||
|
||||
$delete = DeleteValue::builder($location)->build();
|
||||
/** @var $object \Riak\Object */
|
||||
$object = $bucket->get($key);
|
||||
|
||||
try {
|
||||
$this->client->execute($delete);
|
||||
} catch (RiakException $exception) {
|
||||
// deletion can fail silent
|
||||
if ( ! $object->exists()) {
|
||||
// object does not exist, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
$object->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,29 +114,16 @@ class RiakStorage implements Storage
|
||||
*/
|
||||
public function find($storageName, $key)
|
||||
{
|
||||
$location = $this->getRiakLocation($storageName, $key);
|
||||
$bucket = $this->client->bucket($storageName);
|
||||
|
||||
// fetch object
|
||||
$fetch = FetchValue::builder($location)->build();
|
||||
/** @var $object \Riak\Object */
|
||||
$object = $bucket->get($key);
|
||||
|
||||
try {
|
||||
$result = $this->client->execute($fetch);
|
||||
} catch (RiakException $exception) {
|
||||
throw new NotFoundException();
|
||||
if ( ! $object->exists()) {
|
||||
throw new NotFoundException;
|
||||
}
|
||||
|
||||
$json = (string) $result
|
||||
->getValue()
|
||||
->getValue();
|
||||
|
||||
return json_decode($json, true);
|
||||
}
|
||||
|
||||
private function getRiakLocation($storageName, $key)
|
||||
{
|
||||
$namespace = new RiakNamespace('default', $storageName);
|
||||
|
||||
return new RiakLocation($namespace, $key);
|
||||
return $object->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@ use Doctrine\KeyValueStore\NotFoundException;
|
||||
*
|
||||
* @author Stan Lemon <stosh1985@gmail.com>
|
||||
*/
|
||||
class SimpleDbStorage implements Storage
|
||||
class SimpleDbStorage extends AbstractStorage
|
||||
{
|
||||
/**
|
||||
* @var \Aws\SimpleDb\SimpleDbClient
|
||||
|
||||
@@ -36,7 +36,7 @@ use Doctrine\KeyValueStore\Storage\WindowsAzureTable\HttpStorageException;
|
||||
*
|
||||
* @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';
|
||||
|
||||
@@ -338,7 +338,7 @@ class WindowsAzureTableStorage implements Storage, RangeQueryStorage
|
||||
|
||||
$filters = ['PartitionKey eq ' . $this->quoteFilterValue($query->getPartitionKey())];
|
||||
foreach ($query->getConditions() as $condition) {
|
||||
if (! in_array($condition[0], ['eq', 'neq', 'le', 'lt', 'ge', 'gt'])) {
|
||||
if ( ! in_array($condition[0], ['eq', 'neq', 'le', 'lt', 'ge', 'gt'])) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Windows Azure Table only supports eq, neq, le, lt, ge, gt as conditions.'
|
||||
);
|
||||
|
||||
@@ -85,13 +85,13 @@ class UnitOfWork
|
||||
return;
|
||||
}
|
||||
|
||||
public function reconstititute($className, $key)
|
||||
public function reconsititute($className, $key)
|
||||
{
|
||||
$class = $this->cmf->getMetadataFor($className);
|
||||
$id = $this->idHandler->normalizeId($class, $key);
|
||||
$data = $this->storageDriver->find($class->storageName, $id);
|
||||
|
||||
if (! $data) {
|
||||
if ( ! $data) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ class UnitOfWork
|
||||
$originalData = $this->originalData[spl_object_hash($object)];
|
||||
|
||||
foreach ($snapshot as $field => $value) {
|
||||
if (! isset($originalData[$field]) || $originalData[$field] !== $value) {
|
||||
if ( ! isset($originalData[$field]) || $originalData[$field] !== $value) {
|
||||
$changeSet[$field] = $value;
|
||||
}
|
||||
}
|
||||
@@ -159,13 +159,13 @@ class UnitOfWork
|
||||
$data = [];
|
||||
|
||||
foreach ($class->reflFields as $fieldName => $reflProperty) {
|
||||
if (! isset($class->fields[$fieldName]['id'])) {
|
||||
if ( ! isset($class->fields[$fieldName]['id'])) {
|
||||
$data[$fieldName] = $reflProperty->getValue($object);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (get_object_vars($object) as $property => $value) {
|
||||
if (! isset($data[$property])) {
|
||||
if ( ! isset($data[$property])) {
|
||||
$data[$property] = $value;
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ class UnitOfWork
|
||||
$class = $this->cmf->getMetadataFor(get_class($object));
|
||||
$id = $this->idHandler->getIdentifier($class, $object);
|
||||
|
||||
if (! $id) {
|
||||
if ( ! $id) {
|
||||
throw new \RuntimeException('Trying to persist entity that has no id.');
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ class UnitOfWork
|
||||
public function scheduleForDelete($object)
|
||||
{
|
||||
$oid = spl_object_hash($object);
|
||||
if (! isset($this->identifiers[$oid])) {
|
||||
if ( ! isset($this->identifiers[$oid])) {
|
||||
throw new \RuntimeException(
|
||||
'Object scheduled for deletion is not managed. Only managed objects can be deleted.'
|
||||
);
|
||||
@@ -242,7 +242,7 @@ class UnitOfWork
|
||||
$id = $this->idHandler->getIdentifier($class, $object);
|
||||
$id = $this->idConverter->serialize($class, $id);
|
||||
|
||||
if (! $id) {
|
||||
if ( ! $id) {
|
||||
throw new \RuntimeException('Trying to persist entity that has no id.');
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,5 @@
|
||||
<var name="DOCTRINE_KEYVALUE_AZURE_AUTHSCHEMA" value="sharedlite" />
|
||||
<var name="DOCTRINE_KEYVALUE_AZURE_NAME" value="" />
|
||||
<var name="DOCTRINE_KEYVALUE_AZURE_KEY" value="" />
|
||||
<env name="RIAK_DNS" value="" />
|
||||
<env name="DYNAMODB_DNS" value="" />
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
@@ -21,11 +21,7 @@
|
||||
namespace Doctrine\Tests\KeyValueStore\Mapping;
|
||||
|
||||
use Doctrine\KeyValueStore\Mapping\ClassMetadata;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Doctrine\KeyValueStore\Mapping\ClassMetadata
|
||||
*/
|
||||
class ClassMetadataTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $metadata;
|
||||
@@ -72,118 +68,4 @@ class ClassMetadataTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertEquals([], $this->metadata->fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getIdentifier
|
||||
*/
|
||||
public function testGetIdentifier()
|
||||
{
|
||||
$identifier = $this->metadata->getIdentifier();
|
||||
|
||||
$this->assertInternalType('array', $identifier);
|
||||
|
||||
foreach ($identifier as $key => $value) {
|
||||
$this->assertInternalType('integer', $key);
|
||||
$this->assertInternalType('string', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getReflectionClass
|
||||
*/
|
||||
public function testGetReflectionClass()
|
||||
{
|
||||
$reflectionClass = $this->metadata->getReflectionClass();
|
||||
|
||||
$this->assertInstanceOf(ReflectionClass::class, $reflectionClass);
|
||||
$this->assertSame(__CLASS__, $reflectionClass->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isIdentifier
|
||||
*/
|
||||
public function testIsIdentifier()
|
||||
{
|
||||
$this->metadata->mapIdentifier('id');
|
||||
|
||||
$this->assertTrue($this->metadata->isIdentifier('id'));
|
||||
$this->assertFalse($this->metadata->isIdentifier('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::hasField
|
||||
*/
|
||||
public function testHasField()
|
||||
{
|
||||
$this->metadata->mapField(['fieldName' => 'foo']);
|
||||
|
||||
$this->assertTrue($this->metadata->hasField('foo'));
|
||||
$this->assertFalse($this->metadata->hasField('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::hasAssociation
|
||||
*/
|
||||
public function testHasAssociation()
|
||||
{
|
||||
$this->assertFalse($this->metadata->hasAssociation(sha1(rand())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isSingleValuedAssociation
|
||||
*/
|
||||
public function testIsSingleValuedAssociation()
|
||||
{
|
||||
$this->assertFalse($this->metadata->isSingleValuedAssociation(sha1(rand())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isCollectionValuedAssociation
|
||||
*/
|
||||
public function testIsCollectionValuedAssociation()
|
||||
{
|
||||
$this->assertFalse($this->metadata->isCollectionValuedAssociation(sha1(rand())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getFieldNames
|
||||
*/
|
||||
public function testGetFieldNames()
|
||||
{
|
||||
$this->metadata->mapField(['fieldName' => 'foo']);
|
||||
|
||||
$fieldNames = $this->metadata->getFieldNames();
|
||||
|
||||
$this->assertInternalType('array', $fieldNames);
|
||||
|
||||
foreach ($fieldNames as $key => $value) {
|
||||
$this->assertInternalType('integer', $key);
|
||||
$this->assertInternalType('string', $value);
|
||||
}
|
||||
|
||||
$this->assertSame(['foo'], $fieldNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getIdentifierFieldNames
|
||||
*/
|
||||
public function testGetIdentifierFieldNames()
|
||||
{
|
||||
$identifierFieldNames = $this->metadata->getIdentifierFieldNames();
|
||||
|
||||
$this->assertInternalType('array', $identifierFieldNames);
|
||||
|
||||
foreach ($identifierFieldNames as $key => $value) {
|
||||
$this->assertInternalType('integer', $key);
|
||||
$this->assertInternalType('string', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::isAssociationInverseSide
|
||||
*/
|
||||
public function testIsAssociationInverseSide()
|
||||
{
|
||||
$this->assertFalse($this->metadata->isAssociationInverseSide(sha1(rand())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
<?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\Query;
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Doctrine\KeyValueStore\EntityManager;
|
||||
use Doctrine\KeyValueStore\Query\RangeQuery;
|
||||
use Doctrine\KeyValueStore\Storage\DoctrineCacheStorage;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
use ReflectionClass;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Doctrine\KeyValueStore\Query\RangeQuery
|
||||
*/
|
||||
class RangeQueryTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $className;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $partitionKey;
|
||||
|
||||
/**
|
||||
* @var RangeQuery
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
$this->entityManager = $this
|
||||
->getMockBuilder(EntityManager::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->className = sha1(rand());
|
||||
$this->partitionKey = sha1(rand());
|
||||
|
||||
$this->object = new RangeQuery(
|
||||
$this->entityManager,
|
||||
$this->className,
|
||||
$this->partitionKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setLimit
|
||||
* @covers ::getLimit
|
||||
*/
|
||||
public function testLimit()
|
||||
{
|
||||
$limit = rand();
|
||||
|
||||
$setterOutput = $this->object->setLimit($limit);
|
||||
|
||||
$this->assertInstanceOf(RangeQuery::class, $setterOutput);
|
||||
$this->assertSame($limit, $this->object->getLimit());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getClassName
|
||||
*/
|
||||
public function testGetClassName()
|
||||
{
|
||||
$this->assertSame(
|
||||
$this->className,
|
||||
$this->object->getClassName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getPartitionKey
|
||||
*/
|
||||
public function testGetPartitionKey()
|
||||
{
|
||||
$this->assertSame(
|
||||
$this->partitionKey,
|
||||
$this->object->getPartitionKey()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getConditions
|
||||
*/
|
||||
public function testGetConditions()
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($this->object);
|
||||
$constants = $reflectionClass->getConstants();
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
|
||||
$this->assertInternalType('array', $conditions);
|
||||
|
||||
foreach ($conditions as $condition) {
|
||||
$this->assertArrayHasKey($condition[0], $constants);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeEquals
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeEquals()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeEquals($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_EQ, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeNotEquals
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeNotEquals()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeNotEquals($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_NEQ, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeLessThan
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeLessThan()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeLessThan($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_LT, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeLessThanEquals
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeLessThanEquals()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeLessThanEquals($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_LE, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeGreaterThan
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeGreaterThan()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeGreaterThan($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_GT, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::rangeGreaterThanEquals
|
||||
* @depends testGetConditions
|
||||
*/
|
||||
public function testRangeGreaterThanEquals()
|
||||
{
|
||||
$value = 'test';
|
||||
|
||||
$output = $this->object->rangeGreaterThanEquals($value);
|
||||
$this->assertInstanceOf(RangeQuery::class, $output);
|
||||
|
||||
$conditions = $this->object->getConditions();
|
||||
$this->assertArraySubset(
|
||||
[[RangeQuery::CONDITION_GE, $value]],
|
||||
$conditions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::execute
|
||||
*/
|
||||
public function testWrongExecute()
|
||||
{
|
||||
$this->entityManager
|
||||
->method('unwrap')
|
||||
->willReturn(new DoctrineCacheStorage(new ArrayCache));
|
||||
|
||||
$this->setExpectedException(RuntimeException::class);
|
||||
$this->object->execute();
|
||||
}
|
||||
}
|
||||
@@ -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;'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ abstract class AbstractStorageTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testInsertCompositeKey()
|
||||
{
|
||||
if (! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
$this->markTestSkipped('Composite keys need to be supported for this test to run.');
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ abstract class AbstractStorageTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testUpdateCompositeKey()
|
||||
{
|
||||
if (! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
$this->markTestSkipped('Composite keys need to be supported for this test to run.');
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ abstract class AbstractStorageTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testDeleteCompositeKey()
|
||||
{
|
||||
if (! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
$this->markTestSkipped('Composite keys need to be supported for this test to run.');
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ abstract class AbstractStorageTestCase extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testFindCompositeKey()
|
||||
{
|
||||
if (! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
if ( ! $this->storage->supportsCompositePrimaryKeys()) {
|
||||
$this->markTestSkipped('Composite keys need to be supported for this test to run.');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
<?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\ArrayStorage;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* @author Emanuele Minotto <minottoemanuele@gmail.com>
|
||||
*/
|
||||
class ArrayStorageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var ArrayStorage
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
protected function setup()
|
||||
{
|
||||
$this->storage = new ArrayStorage();
|
||||
}
|
||||
|
||||
public function testSupportsPartialUpdates()
|
||||
{
|
||||
$this->assertFalse($this->storage->supportsPartialUpdates());
|
||||
}
|
||||
|
||||
public function testSupportsCompositePrimaryKeys()
|
||||
{
|
||||
$this->assertFalse($this->storage->supportsCompositePrimaryKeys());
|
||||
}
|
||||
|
||||
public function testRequiresCompositePrimaryKeys()
|
||||
{
|
||||
$this->assertFalse($this->storage->requiresCompositePrimaryKeys());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider methodsProvider
|
||||
*/
|
||||
public function testInsert($method)
|
||||
{
|
||||
$data = [
|
||||
'author' => 'John Doe',
|
||||
'title' => 'example book',
|
||||
];
|
||||
|
||||
$this->storage->$method('foo', 'bar', $data);
|
||||
|
||||
$reflector = new ReflectionProperty(ArrayStorage::class, 'data');
|
||||
$reflector->setAccessible(true);
|
||||
|
||||
$storedValue = $reflector->getValue($this->storage);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'foo' => [
|
||||
serialize('bar') => $data,
|
||||
],
|
||||
],
|
||||
$storedValue
|
||||
);
|
||||
|
||||
$this->storage->$method('foo', 'bar', $data);
|
||||
$this->assertCount(1, $storedValue);
|
||||
$this->assertCount(1, $storedValue['foo']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function methodsProvider()
|
||||
{
|
||||
return [
|
||||
['insert'],
|
||||
['update'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->assertEquals('array', $this->storage->getName());
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
<?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\DynamoDbStorage;
|
||||
use Aws\DynamoDb\DynamoDbClient;
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
|
||||
/**
|
||||
* @covers \Doctrine\KeyValueStore\Storage\DynamoDbStorage
|
||||
*/
|
||||
class DynamoDbStorageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
const DATA = [
|
||||
'author' => 'John Doe',
|
||||
'title' => 'example book',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var DynamoDbClient|null
|
||||
*/
|
||||
private static $client;
|
||||
|
||||
/**
|
||||
* @var DynamoDbStorage
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
$dns = getenv('DYNAMODB_DNS');
|
||||
|
||||
if (empty($dns)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static::$client = DynamoDbClient::factory(array(
|
||||
'credentials' => [
|
||||
'key' => 'YOUR_KEY',
|
||||
'secret' => 'YOUR_SECRET',
|
||||
],
|
||||
'region' => 'us-west-2',
|
||||
'endpoint' => $dns,
|
||||
'version' => 'latest',
|
||||
'retries' => 1,
|
||||
));
|
||||
|
||||
try {
|
||||
static::$client->deleteTable([
|
||||
'TableName' => 'dynamodb',
|
||||
]);
|
||||
} catch (\Exception $exception) {
|
||||
// table does not exist
|
||||
}
|
||||
|
||||
try {
|
||||
static::$client->createTable(array(
|
||||
'TableName' => 'dynamodb',
|
||||
'AttributeDefinitions' => array(
|
||||
array(
|
||||
'AttributeName' => 'id',
|
||||
'AttributeType' => 'S',
|
||||
),
|
||||
),
|
||||
'KeySchema' => array(
|
||||
array(
|
||||
'AttributeName' => 'id',
|
||||
'KeyType' => 'HASH',
|
||||
),
|
||||
),
|
||||
'ProvisionedThroughput' => array(
|
||||
'ReadCapacityUnits' => 10,
|
||||
'WriteCapacityUnits' => 20,
|
||||
),
|
||||
));
|
||||
} catch (\Exception $exception) {
|
||||
static::$client = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
if (! static::$client) {
|
||||
$this->markTestSkipped('DynamoDB is required.');
|
||||
}
|
||||
|
||||
$this->storage = new DynamoDbStorage(static::$client);
|
||||
}
|
||||
|
||||
public function testInsertAndFind()
|
||||
{
|
||||
$this->storage->insert('dynamodb', 'testInsertAndFind', self::DATA);
|
||||
|
||||
$data = $this->storage->find('dynamodb', 'testInsertAndFind');
|
||||
|
||||
$this->assertEquals(self::DATA, $data);
|
||||
}
|
||||
|
||||
public function testUpdate()
|
||||
{
|
||||
$this->storage->insert('dynamodb', 'testUpdate', self::DATA);
|
||||
|
||||
$newData = [
|
||||
'foo' => 'bar',
|
||||
];
|
||||
|
||||
$this->storage->update('dynamodb', 'testUpdate', $newData);
|
||||
|
||||
$data = $this->storage->find('dynamodb', 'testUpdate');
|
||||
$this->assertEquals($newData, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsertAndFind
|
||||
*/
|
||||
public function testFindWithNotExistKey()
|
||||
{
|
||||
$this->setExpectedException(NotFoundException::class);
|
||||
$this->storage->find('dynamodb', 'not-existing-key');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsertAndFind
|
||||
* @depends testFindWithNotExistKey
|
||||
*/
|
||||
public function testDelete()
|
||||
{
|
||||
$this->storage->insert('dynamodb', 'testDelete', self::DATA);
|
||||
$this->storage->delete('dynamodb', 'testDelete');
|
||||
|
||||
$this->setExpectedException(NotFoundException::class);
|
||||
$this->storage->find('dynamodb', 'testDelete');
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->assertEquals('dynamodb', $this->storage->getName());
|
||||
}
|
||||
}
|
||||
@@ -20,34 +20,37 @@
|
||||
|
||||
namespace Doctrine\Tests\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
use Doctrine\KeyValueStore\Storage\MongoDbStorage;
|
||||
use MongoDB\Client;
|
||||
|
||||
/**
|
||||
* MongoDb storage testcase
|
||||
*
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*
|
||||
* @covers \Doctrine\KeyValueStore\Storage\MongoDbStorage
|
||||
* @requires extension mongodb
|
||||
* @requires extension mongo
|
||||
*/
|
||||
class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var MongoDbStorage
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->client = new Client();
|
||||
$this->storage = new MongoDbStorage($this->client->test);
|
||||
$this->mongo = $this->getMock('\Mongo');
|
||||
|
||||
$this->mongodb = $this->getMockBuilder('\MongoDB')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->mongo->expects($this->any())
|
||||
->method('selectDB')
|
||||
->will($this->returnValue($this->mongodb));
|
||||
|
||||
$this->collection = $this->getMockBuilder('MongoCollection')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->mongodb->expects($this->once())
|
||||
->method('selectCollection')
|
||||
->will($this->returnValue($this->collection));
|
||||
|
||||
$this->storage = new MongoDbStorage($this->mongo, [
|
||||
'collection' => 'test',
|
||||
'database' => 'test',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testInsert()
|
||||
@@ -57,21 +60,20 @@ class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
|
||||
'title' => 'example book',
|
||||
];
|
||||
|
||||
$this->storage->insert('mongodb', 'testInsert', $data);
|
||||
$dbDataset = [];
|
||||
|
||||
$result = $this->client
|
||||
->test
|
||||
->mongodb
|
||||
->findOne([
|
||||
'key' => 'testInsert',
|
||||
]);
|
||||
$this->collection->expects($this->once())
|
||||
->method('insert')
|
||||
->will($this->returnCallback(function ($data) use (&$dbDataset) {
|
||||
$dbDataset[] = $data;
|
||||
}));
|
||||
|
||||
$this->assertSame($data, $result['value']->getArrayCopy());
|
||||
$this->storage->insert('mongodb', '1', $data);
|
||||
$this->assertCount(1, $dbDataset);
|
||||
|
||||
$this->assertEquals([['key' => '1', 'value' => $data]], $dbDataset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
*/
|
||||
public function testUpdate()
|
||||
{
|
||||
$data = [
|
||||
@@ -79,67 +81,80 @@ class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
|
||||
'title' => 'example book',
|
||||
];
|
||||
|
||||
$this->storage->insert('mongodb', 'testUpdate', [
|
||||
'foo' => 'bar',
|
||||
]);
|
||||
$this->storage->update('mongodb', 'testUpdate', $data);
|
||||
$dbDataset = [];
|
||||
|
||||
$result = $this->client
|
||||
->test
|
||||
->mongodb
|
||||
->findOne([
|
||||
'key' => 'testUpdate',
|
||||
]);
|
||||
$this->collection->expects($this->once())
|
||||
->method('update')
|
||||
->will($this->returnCallback(function ($citeria, $data) use (&$dbDataset) {
|
||||
$dbDataset = [$citeria, $data];
|
||||
}));
|
||||
|
||||
$this->assertSame($data, $result['value']->getArrayCopy());
|
||||
$this->storage->update('mongodb', '1', $data);
|
||||
|
||||
$this->assertEquals(['key' => '1'], $dbDataset[0]);
|
||||
$this->assertEquals(['key' => '1', 'value' => $data], $dbDataset[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
*/
|
||||
public function testDelete()
|
||||
{
|
||||
$this->storage->insert('mongodb', 'testDelete', [
|
||||
'foo' => 'bar',
|
||||
]);
|
||||
$dataset = [
|
||||
[
|
||||
'key' => 'foobar',
|
||||
'value' => [
|
||||
'author' => 'John Doe',
|
||||
'title' => 'example book',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->storage->delete('mongodb', 'testDelete');
|
||||
$this->collection->expects($this->once())
|
||||
->method('remove')
|
||||
->will($this->returnCallback(function ($citeria) use (&$dataset) {
|
||||
foreach ($dataset as $key => $row) {
|
||||
if ($row['key'] === $citeria['key']) {
|
||||
unset($dataset[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
$result = $this->client
|
||||
->test
|
||||
->mongodb
|
||||
->findOne([
|
||||
'key' => 'testDelete',
|
||||
]);
|
||||
$this->storage->delete('test', 'foobar');
|
||||
|
||||
$this->assertNull($result);
|
||||
$this->assertCount(0, $dataset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
*/
|
||||
public function testFind()
|
||||
{
|
||||
$dataset = [
|
||||
'author' => 'John Doe',
|
||||
'title' => 'example book',
|
||||
[
|
||||
'key' => 'foobar',
|
||||
'value' => [
|
||||
'author' => 'John Doe',
|
||||
'title' => 'example book',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->storage->insert('mongodb', 'testFind', $dataset);
|
||||
$this->collection->expects($this->once())
|
||||
->method('findOne')
|
||||
->will($this->returnCallback(function ($citeria, $fields) use (&$dataset) {
|
||||
foreach ($dataset as $key => $row) {
|
||||
if ($row['key'] === $citeria['key']) {
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
$data = $this->storage->find('mongodb', 'testFind');
|
||||
$data = $this->storage->find('test', 'foobar');
|
||||
|
||||
$this->assertEquals($dataset, $data);
|
||||
}
|
||||
|
||||
public function testFindWithNotExistKey()
|
||||
{
|
||||
$this->setExpectedException(NotFoundException::class);
|
||||
$this->storage->find('mongodb', 'not-existing-key');
|
||||
$this->assertEquals($dataset[0]['value'], $data);
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->storage->initialize();
|
||||
|
||||
$this->assertEquals('mongodb', $this->storage->getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,46 +20,30 @@
|
||||
|
||||
namespace Doctrine\Tests\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\KeyValueStore\NotFoundException;
|
||||
use Doctrine\KeyValueStore\Storage\RiakStorage;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
use Riak\Client\Command\Kv\Builder\ListKeysBuilder;
|
||||
use Riak\Client\Command\Kv\FetchValue;
|
||||
use Riak\Client\Core\Query\RiakLocation;
|
||||
use Riak\Client\Core\Query\RiakNamespace;
|
||||
use Riak\Client\Core\Query\RiakObject;
|
||||
use Riak\Client\Core\Transport\RiakTransportException;
|
||||
use Riak\Client\RiakClient;
|
||||
use Riak\Client\RiakClientBuilder;
|
||||
|
||||
/**
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*/
|
||||
class RiakStorageTest extends PHPUnit_Framework_TestCase
|
||||
class RiakStorageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var RiakClient
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var RiakStorage
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
protected function setUp()
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
private $riak;
|
||||
|
||||
protected function setup()
|
||||
{
|
||||
$dns = getenv('RIAK_DNS');
|
||||
$this->riak = $this->getMockBuilder('Riak\\Client')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
if (empty($dns)) {
|
||||
$this->markTestSkipped('Missing Riak DNS');
|
||||
}
|
||||
|
||||
$this->client = (new RiakClientBuilder())
|
||||
->withNodeUri($dns)
|
||||
->build();
|
||||
|
||||
$this->storage = new RiakStorage($this->client);
|
||||
$this->storage = new RiakStorage($this->riak);
|
||||
}
|
||||
|
||||
public function testSupportsPartialUpdates()
|
||||
@@ -79,124 +63,186 @@ class RiakStorageTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
public function testInsert()
|
||||
{
|
||||
$data = [
|
||||
'title' => 'Riak test',
|
||||
];
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->storage->insert('riak-test', 'foobar', $data);
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$location = $this->getRiakLocation();
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$fetch = FetchValue::builder($location)->build();
|
||||
$objectMock->expects($this->once())
|
||||
->method('store');
|
||||
|
||||
$json = (string) $this->client
|
||||
->execute($fetch)
|
||||
->getValue()
|
||||
->getValue();
|
||||
$that = $this;
|
||||
$bucket->expects($this->once())
|
||||
->method('newObject')
|
||||
->will($this->returnCallback(function ($key, $data) use ($objectMock, $that) {
|
||||
$that->assertEquals('foobar', $key);
|
||||
$that->assertEquals(['title' => 'Riak test'], $data);
|
||||
return $objectMock;
|
||||
}));
|
||||
|
||||
$this->assertSame($data, json_decode($json, true));
|
||||
$this->storage->insert('riak-test', 'foobar', ['title' => 'Riak test']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
*/
|
||||
public function testUpdate()
|
||||
{
|
||||
$data = [
|
||||
'title' => 'Riak update',
|
||||
];
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->storage->insert('riak-test', 'foobar', [
|
||||
'title' => 'Riak insert',
|
||||
]);
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$location = $this->getRiakLocation();
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$this->assertTotalBucketKeys(1, $location);
|
||||
$bucket->expects($this->once())
|
||||
->method('get')
|
||||
->will($this->returnValue($objectMock));
|
||||
|
||||
$this->storage->update('riak-test', 'foobar', $data);
|
||||
$that = $this;
|
||||
$objectMock->expects($this->once())
|
||||
->method('setData')
|
||||
->will($this->returnCallback(function ($data) use ($that) {
|
||||
$that->assertEquals(['title' => 'Riak cookbook'], $data);
|
||||
}));
|
||||
|
||||
$fetch = FetchValue::builder($location)->build();
|
||||
$objectMock->expects($this->once())
|
||||
->method('store');
|
||||
|
||||
$json = (string) $this->client
|
||||
->execute($fetch)
|
||||
->getValue()
|
||||
->getValue();
|
||||
|
||||
$this->assertSame($data, json_decode($json, true));
|
||||
$this->assertTotalBucketKeys(1, $location);
|
||||
$this->storage->update('riak-test', 'foobar', ['title' => 'Riak cookbook']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
*/
|
||||
public function testDelete()
|
||||
{
|
||||
$this->testInsert();
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$bucket->expects($this->once())
|
||||
->method('get')
|
||||
->with('foobar')
|
||||
->will($this->returnValue($objectMock));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('exists')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('delete');
|
||||
|
||||
$this->storage->delete('riak-test', 'foobar');
|
||||
|
||||
$location = $this->getRiakLocation();
|
||||
|
||||
$fetch = FetchValue::builder($location)->build();
|
||||
|
||||
$this->setExpectedException(RiakTransportException::class);
|
||||
$this->client->execute($fetch);
|
||||
|
||||
$this->assertTotalBucketKeys(0, $location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testDelete
|
||||
*/
|
||||
public function testDeleteWithNotExistKey()
|
||||
{
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$bucket->expects($this->once())
|
||||
->method('get')
|
||||
->with('foobar')
|
||||
->will($this->returnValue($objectMock));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('exists')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$objectMock->expects($this->never())
|
||||
->method('delete');
|
||||
|
||||
$this->storage->delete('riak-test', 'foobar');
|
||||
$this->storage->delete('riak-test', 'foobar');
|
||||
}
|
||||
|
||||
public function testFind()
|
||||
{
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$bucket->expects($this->once())
|
||||
->method('get')
|
||||
->with('foobar')
|
||||
->will($this->returnValue($objectMock));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('exists')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('getData')
|
||||
->will($this->returnValue(['title' => 'Riak Test']));
|
||||
|
||||
$this->assertEquals(['title' => 'Riak Test'], $this->storage->find('riaktest', 'foobar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testInsert
|
||||
* @expectedException Doctrine\KeyValueStore\NotFoundException
|
||||
*/
|
||||
public function testFind()
|
||||
{
|
||||
$data = [
|
||||
'title' => 'Riak test',
|
||||
];
|
||||
|
||||
$this->storage->insert('riak-test', 'foobar', $data);
|
||||
|
||||
$result = $this->storage->find('riak-test', 'foobar');
|
||||
|
||||
$this->assertSame($data, $result);
|
||||
}
|
||||
|
||||
public function testFindWithNotExistKey()
|
||||
{
|
||||
$this->setExpectedException(NotFoundException::class);
|
||||
$this->storage->find('riak-test', 'foobar-1');
|
||||
$objectMock = $this->getMockBuilder('Riak\Object')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$bucket = $this->getMockBuilder('Riak\Bucket')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->riak->expects($this->once())
|
||||
->method('bucket')
|
||||
->will($this->returnValue($bucket));
|
||||
|
||||
$bucket->expects($this->once())
|
||||
->method('get')
|
||||
->with('foobar')
|
||||
->will($this->returnValue($objectMock));
|
||||
|
||||
$objectMock->expects($this->once())
|
||||
->method('exists')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$objectMock->expects($this->never())
|
||||
->method('getData');
|
||||
|
||||
$this->storage->find('riak-test', 'foobar');
|
||||
}
|
||||
|
||||
public function testGetName()
|
||||
{
|
||||
$this->assertEquals('riak', $this->storage->getName());
|
||||
}
|
||||
|
||||
private function assertTotalBucketKeys($expectedTotal, $location)
|
||||
{
|
||||
$command = (new ListKeysBuilder($location->getNamespace()))->build();
|
||||
|
||||
$iterator = $this->client
|
||||
->execute($command)
|
||||
->getIterator();
|
||||
|
||||
$this->assertCount($expectedTotal, iterator_to_array($iterator));
|
||||
}
|
||||
|
||||
private function getRiakLocation()
|
||||
{
|
||||
$namespace = new RiakNamespace('default', 'riak-test');
|
||||
|
||||
return new RiakLocation($namespace, 'foobar');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
|
||||
namespace Doctrine\Tests\KeyValueStore\Storage;
|
||||
|
||||
use Doctrine\KeyValueStore\Http\Client;
|
||||
use Doctrine\KeyValueStore\Http\Response;
|
||||
use Doctrine\KeyValueStore\Storage\WindowsAzureTable\AuthorizationSchema;
|
||||
use Doctrine\KeyValueStore\Storage\WindowsAzureTableStorage;
|
||||
|
||||
class WindowsAzureTableStorageTest extends AbstractStorageTestCase
|
||||
@@ -31,14 +29,8 @@ class WindowsAzureTableStorageTest extends AbstractStorageTestCase
|
||||
|
||||
protected function createStorage()
|
||||
{
|
||||
$this->client = $this
|
||||
->getMockBuilder(Client::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$auth = $this
|
||||
->getMockBuilder(AuthorizationSchema::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->client = $this->getMock('Doctrine\KeyValueStore\Http\Client');
|
||||
$auth = $this->getMock('Doctrine\KeyValueStore\Storage\WindowsAzureTable\AuthorizationSchema');
|
||||
$auth->expects($this->any())->method('signRequest')->will($this->returnValue('Authorization: SharedKeyLite testaccount1:uay+rilMVayH/SVI8X+a3fL8k/NxCnIePdyZSkqvydM='));
|
||||
|
||||
$storage = new WindowsAzureTableStorage(
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
if (! @include __DIR__ . '/../vendor/autoload.php') {
|
||||
if ( ! @include __DIR__ . '/../vendor/autoload.php') {
|
||||
die(<<<'EOT'
|
||||
You must set up the project dependencies, run the following commands:
|
||||
wget http://getcomposer.org/composer.phar
|
||||
|
||||
@@ -7,5 +7,6 @@ sudo apt-get install -y libuv-dev libssl-dev
|
||||
cd /tmp && git clone https://github.com/datastax/php-driver.git && cd php-driver && git submodule update --init
|
||||
cd ext && ./install.sh && cd "$TRAVIS_BUILD_DIR"
|
||||
echo "extension=cassandra.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
|
||||
# PECL extensions
|
||||
echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
# PHP extensions
|
||||
yes | pecl install mongo
|
||||
yes | pecl install redis
|
||||
|
||||
Reference in New Issue
Block a user