58 Commits

Author SHA1 Message Date
Emanuele Minotto
7a8465631f Merge pull request #96 from doctrine/dynamodb-refactoring
DynamoDB internal refactoring
2019-11-15 19:45:19 +01:00
Emanuele Minotto
76b76d42e9 Include DynamoDB tests on Travis 2019-10-20 14:36:57 +02:00
Emanuele Minotto
9fe32a6388 Add DynamoDB to documentation 2019-10-20 14:36:57 +02:00
Emanuele Minotto
1089486506 DynamoDbStorage internal refactoring 2019-10-20 14:36:57 +02:00
Emanuele Minotto
e32cd91113 Merge pull request #94 from doctrine/issues/91
RiakStorage upgrade
2019-09-20 21:42:29 +02:00
EmanueleMinotto
8f07e47320 Replace riak client with php-riak/riak-client 2019-09-20 21:28:57 +02:00
EmanueleMinotto
186c8e04d2 Add riak to Travis 2019-09-11 21:55:39 +02:00
Emanuele Minotto
fe7dcc5c79 Merge pull request #95 from doctrine/issues/93
MongoDbStorage upgrade
2019-09-11 21:42:11 +02:00
EmanueleMinotto
218a870dd3 Create UPGRADE.md 2019-09-11 21:36:23 +02:00
EmanueleMinotto
b62b9ea098 Drop PHP 5.5 support 2019-09-11 21:36:23 +02:00
EmanueleMinotto
3800fa4d5c Add mongo to Travis 2019-09-11 21:36:23 +02:00
EmanueleMinotto
a50dade76d Replace legacy Mongo class with MongoDB Client 2019-09-11 21:36:23 +02:00
EmanueleMinotto
6f154f5378 Add mongodb/mongodb dependency 2019-09-08 08:23:09 +02:00
Emanuele Minotto
ac4c317a7e Merge pull request #92 from doctrine/fix-tests-for-maintainance
Fix storage tests for maintainance
2019-09-03 08:31:00 +02:00
EmanueleMinotto
705d5fc1d1 Add different versions support 2019-08-31 15:44:22 +02:00
EmanueleMinotto
465bd365f7 Remove HHVM support 2019-08-31 15:44:22 +02:00
EmanueleMinotto
9fb5e498ed Replace deprecated TestCase::getMock 2019-08-31 15:44:22 +02:00
EmanueleMinotto
573723ab3c Skip legacy Riak tests 2019-08-31 15:03:05 +02:00
Emanuele Minotto
8ba3db4ce7 Merge pull request #79 from larowlan/dynamodb
Enhances existing dynamodb implementation and adds docs
2016-07-05 23:08:02 +02:00
Lee Rowlands
bb1ba64453 Revert changes to composer.json 2016-06-06 10:09:09 +10:00
Lee Rowlands
903f6a8c97 Update docs to use new format 2016-03-24 11:44:07 +10:00
Lee Rowlands
0a5917a2a9 PHPCS fixes 2016-03-23 09:26:05 +10:00
Lee Rowlands
b7daeb0d19 Restore missing Riak dependency 2016-03-23 09:19:17 +10:00
Lee Rowlands
06e11dae33 Remove redundant docs 2016-03-23 09:18:22 +10:00
Lee Rowlands
4584d99529 Add missing docs 2016-03-23 09:17:59 +10:00
Lee Rowlands
54e05f9acd Fix typo 2016-03-23 09:17:00 +10:00
Lee Rowlands
4d4a17aca9 Update documentation for DynamoDb 2016-03-23 08:45:44 +10:00
Lee Rowlands
b2a4e320b0 Combine existing DynamoDb implementation with new AmazonDynamoDb and expands tests 2016-03-23 08:13:32 +10:00
Marco Pivetta
b2906e209e Merge pull request #78 from doctrine/feature/array-storage
Add array storage for development/testing purposes
2016-03-11 13:34:51 +01:00
Emanuele Minotto
f29622194e Add array storage for development/testing purposes 2016-03-09 23:18:37 +01:00
Marco Pivetta
2517bb04c5 Merge pull request #77 from doctrine/fix/redis-on-travis
Redis on TravisCI setup as PECL extension
2016-03-09 23:17:48 +01:00
Emanuele Minotto
a0d85c1c27 Redis on TravisCI setup as PECL extension 2016-02-26 00:36:39 +01:00
Nick Ilyin
0d9c10edf2 Replaced @exception annotations 2016-02-03 09:41:57 -05:00
Nick Ilyin
606ca8b29d License headers and added @covers 2016-02-03 09:41:57 -05:00
Nick Ilyin
1ffab2e77d More precise info for NotFoundException 2016-02-03 09:41:57 -05:00
Nick Ilyin
e0878ca97a Converted keys to consts 2016-02-03 09:41:56 -05:00
Nick Ilyin
7877050062 Comment cleanups 2016-02-03 09:41:56 -05:00
Nick Ilyin
cc3e478d10 Accessor level refactors 2016-02-03 09:41:56 -05:00
Nick Ilyin
79bee991a2 Exception refactoring 2016-02-03 09:41:56 -05:00
Nick Ilyin
f61ce21d4b Members downgraded to private 2016-02-03 09:41:56 -05:00
Nick Ilyin
58f98f8a94 Removed unnecessary not empty check 2016-02-03 09:41:56 -05:00
Nick Ilyin
902da8f693 Moved AWS to require-dev 2016-02-03 09:41:53 -05:00
Nick Ilyin
84d5db7073 Cleaner options; php 5.4 compat 2016-02-03 09:40:42 -05:00
Nick Ilyin
ef425578fb Whitespace; useless comment 2016-02-03 09:40:42 -05:00
Nick Ilyin
518f4211b0 Implementation for Amazon DynamoDB 2016-02-03 09:40:35 -05:00
Marco Pivetta
bad3b56f4b Merge pull request #71 from doctrine/fix/missing-methods
Added some missing methods
2015-12-30 20:11:57 +01:00
Marco Pivetta
2836bc0cfd Merge pull request #70 from doctrine/fix/instance-reference
Fixed wrong instance reference
2015-12-30 20:10:25 +01:00
Marco Pivetta
6000d76099 Merge pull request #69 from doctrine/fix/composer-dependencies
Moved CouchDB to require-dev + suggestions
2015-12-30 20:09:15 +01:00
Marco Pivetta
b095170bdc Merge pull request #68 from doctrine/enhancement/coding-style
Removed space before logical negation operator
2015-12-30 20:07:26 +01:00
Marco Pivetta
fe7195fc2d Merge pull request #66 from doctrine/docs/cassandra-configuration
Added Cassandra configuration
2015-12-30 20:07:03 +01:00
Emanuele Minotto
e282c1d9f6 added some missing methods 2015-12-30 18:32:18 +01:00
Emanuele Minotto
e2f7ea54f7 added fix' test 2015-12-28 23:44:41 +01:00
Emanuele Minotto
03a2413e99 fixed wrong instance reference 2015-12-21 00:42:01 +01:00
Emanuele Minotto
2c99b71d19 moved couchdb to require-dev + suggestions 2015-12-21 00:38:10 +01:00
Emanuele Minotto
fe1e155e69 coding style 2015-12-21 00:34:14 +01:00
Emanuele Minotto
ec14ab554a Merge pull request #67 from zeroedin-bill/reconstitute-typo-fix
fix typo reconsitute -> reconstititute
2015-12-16 19:18:38 +01:00
Bill Schaller
3c7ba8415e fix typo reconsitute -> reconstititute 2015-12-16 10:20:28 -05:00
Emanuele Minotto
69832f5423 added Cassandra configuration 2015-12-16 00:18:52 +01:00
42 changed files with 1364 additions and 537 deletions

View File

@@ -61,7 +61,6 @@ $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',

View File

@@ -1,17 +1,37 @@
language: php
services:
- docker
- mongodb
- redis-server
php:
- 5.5
- 5.6
- 7.0
- hhvm
- 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
before_install:
- if [[ $TRAVIS_PHP_VERSION != "hhvm" && $TRAVIS_PHP_VERSION != "7.0" ]]; then sh ./tests/travis.sh; fi
- 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
- composer self-update
install:

View File

@@ -23,7 +23,7 @@ Following vendors are targeted:
* Doctrine\Common\Cache provider (Implemented)
* RDBMS (Implemented)
* Couchbase (Implemented)
* Amazon DynamoDB
* Amazon DynamoDB (Implemented)
* CouchDB (Implemented)
* Cassandra
* MongoDB (Implemented)

7
UPGRADE.md Normal file
View File

@@ -0,0 +1,7 @@
# 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.

View File

@@ -1,19 +1,21 @@
{
"name": "doctrine/key-value-store",
"require": {
"php": ">=5.5",
"doctrine/common": "^2.4",
"doctrine/couchdb": "^1.0.0-beta4"
"php": "^5.5|^7.0",
"doctrine/common": "^2.4"
},
"require-dev": {
"datastax/php-driver": "^1.0",
"phpunit/phpunit": "^4.8",
"riak/riak-client": "dev-master"
"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"
},
"suggest": {
"riak/riak-client": "to use the Riak storage",
"ext-couchbase": "to use the Couchbase storage",
"aws/aws-sdk-php": "to use the DynamoDB storage"
"aws/aws-sdk-php": "to use the DynamoDB storage",
"doctrine/couchdb": "to use the CouchDB storage",
"ext-couchbase": "to use the Couchbase storage"
},
"description": "Simple Key-Value Store Abstraction Layer that maps to PHP objects, allowing for many backends.",
"license": "MIT",

View File

@@ -8,7 +8,7 @@ This guide covers getting started with the Doctrine Key Value Store.
To use the KeyValueStore you actually need:
- PHP 5.5 or above
- PHP 5.6 or above
- Composer Package Manager (`Install Composer
<http://getcomposer.org/doc/00-intro.md>`_)

View File

@@ -52,17 +52,32 @@ 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
----------------------
@@ -131,6 +146,26 @@ 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
---------
@@ -164,39 +199,53 @@ CouchDB storage setup based on `doctrine/couchdb-client <https://github.com/doct
$storage = new CouchDbStorage($client);
MongoDB
-------
DynamoDb
---------
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.
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.
.. code-block:: php
<?php
use MongoDB\Client;
use Doctrine\KeyValueStore\Storage\MongoDbStorage;
$conn = new \Mongo(/* connection parameters and options */);
$client = new Client(/* connection parameters and options */);
$storage = new MongoDbStorage($conn, array(
'collection' => 'your_collection',
'database' => 'your_database',
));
$storage = new MongoDbStorage($client->your_database);
Riak
----
Riak support is provided through the library `riak/riak-client <https://github.com/nacmartin/riak-client>`_ :
Riak support is provided through the library `php-riak/riak-client <https://github.com/php-riak/riak-client>`_ :
.. code-block:: php
<?php
use Doctrine\KeyValueStore\Storage\RiakStorage;
use Riak\Client;
use Riak\Client\RiakClientBuilder;
$conn = new Riak(/* connection parameters */);
$conn = (new RiakClientBuilder())
->withNodeUri(/* connection DNS */)
->build();
$storage = new RiakStorage($conn);

View File

@@ -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();
}

View File

@@ -66,7 +66,7 @@ class EntityManager
*/
public function find($className, $key)
{
return $this->unitOfWork->reconsititute($className, $key);
return $this->unitOfWork->reconstititute($className, $key);
}
/**

View File

@@ -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];

View File

@@ -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.

View File

@@ -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."
);

View File

@@ -0,0 +1,48 @@
<?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
);
}
}

View File

@@ -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;

View File

@@ -21,6 +21,7 @@
namespace Doctrine\KeyValueStore\Mapping;
use Doctrine\Common\Persistence\Mapping\ClassMetadata as BaseClassMetadata;
use ReflectionClass;
class ClassMetadata implements BaseClassMetadata
{
@@ -50,7 +51,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;
}
}
@@ -93,6 +94,7 @@ class ClassMetadata implements BaseClassMetadata
}
return $id;
}
/**
* Get fully-qualified class name of this persistent class.
*
@@ -100,6 +102,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function getName()
{
return $this->name;
}
/**
@@ -111,6 +114,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
@@ -120,6 +124,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function getReflectionClass()
{
return new ReflectionClass($this->name);
}
/**
@@ -131,6 +136,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function isIdentifier($fieldName)
{
return in_array($fieldName, $this->identifier);
}
/**
@@ -142,6 +148,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function hasField($fieldName)
{
return isset($this->fields[$fieldName]);
}
/**
@@ -153,6 +160,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function hasAssociation($fieldName)
{
return false;
}
/**
@@ -164,6 +172,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function isSingleValuedAssociation($fieldName)
{
return false;
}
/**
@@ -175,6 +184,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function isCollectionValuedAssociation($fieldName)
{
return false;
}
/**
@@ -186,6 +196,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function getFieldNames()
{
return array_column($this->fields, 'fieldName');
}
/**
@@ -195,6 +206,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function getIdentifierFieldNames()
{
return $this->identifier;
}
/**
@@ -242,6 +254,7 @@ class ClassMetadata implements BaseClassMetadata
*/
public function isAssociationInverseSide($assocName)
{
return false;
}
/**

View File

@@ -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.');
}
}

View File

@@ -22,4 +22,8 @@ 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);
}
}

View File

@@ -208,9 +208,9 @@ class RangeQuery
{
$storage = $this->em->unwrap();
if ( ! ($storage instanceof RangeQueryStorage)) {
if (! $storage instanceof RangeQueryStorage) {
throw new \RuntimeException(
'The storage backend ' . $this->storage->getName() . ' does not support range queries.'
'The storage backend ' . $storage->getName() . ' does not support range queries.'
);
}

View File

@@ -0,0 +1,136 @@
<?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';
}
}

View File

@@ -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.'
);

View File

@@ -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();
}

View File

@@ -127,7 +127,7 @@ final class CouchDbStorage implements Storage
return $finalKey . $key;
}
if ( ! is_array($key)) {
if (! is_array($key)) {
throw new \InvalidArgumentException('The key should be a string or a flat array.');
}

View File

@@ -142,7 +142,7 @@ class DBALStorage implements Storage
$data = $stmt->fetchColumn();
if ( ! $data) {
if (! $data) {
throw new NotFoundException();
}

View File

@@ -62,7 +62,7 @@ class DoctrineCacheStorage implements Storage
private function flattenKey($storageName, $key)
{
if ( ! $this->supportsCompositeKeys) {
if (! $this->supportsCompositeKeys) {
return $storageName . '-' . $key;
}

View File

@@ -21,34 +21,50 @@
namespace Doctrine\KeyValueStore\Storage;
use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Exception\ResourceNotFoundException;
use Aws\DynamoDb\Iterator\ItemIterator;
use Aws\DynamoDb\Marshaler;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Cache\Cache;
use Doctrine\KeyValueStore\NotFoundException;
/**
* DyanmoDb storage
* DynamoDb storage.
*
* @author Stan Lemon <stosh1985@gmail.com>
*/
class DynamoDbStorage implements Storage
{
/**
* @var \Aws\DynamoDb\DynamoDbClient
* @var DynamoDbClient
*/
protected $client;
private $client;
/**
* Constructor
*
* @param \Aws\DynamoDb\DynamoDbClient $client
* @var Marshaler
*/
public function __construct(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
) {
$this->client = $client;
$this->marshaler = $marshaler ?: new Marshaler();
$this->descriptionCache = $descriptionCache ?: new ArrayCache();
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function supportsPartialUpdates()
{
@@ -56,7 +72,7 @@ class DynamoDbStorage implements Storage
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function supportsCompositePrimaryKeys()
{
@@ -64,7 +80,7 @@ class DynamoDbStorage implements Storage
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function requiresCompositePrimaryKeys()
{
@@ -72,77 +88,98 @@ class DynamoDbStorage implements Storage
}
/**
* {@inheritDoc}
* 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
*/
public function insert($storageName, $key, array $data)
private function prepareKey($storageName, $key)
{
$this->createTable($storageName);
if (! $this->descriptionCache->contains($storageName)) {
$result = $this->client->describeTable([
'TableName' => $storageName,
]);
$this->prepareData($key, $data);
$keys = isset($result['Table']['KeySchema'])
? $result['Table']['KeySchema']
: [];
$keys = array_column($keys, 'AttributeName') ?: [];
$result = $this->client->putItem([
'TableName' => $storageName,
'Item' => $this->client->formatAttributes($data),
'ReturnConsumedCapacity' => 'TOTAL',
]);
}
$this->descriptionCache->save($storageName, $keys);
}
/**
* {@inheritDoc}
*/
public function update($storageName, $key, array $data)
{
$this->prepareData($key, $data);
$keys = isset($keys) ? $keys : $this->descriptionCache->fetch($storageName);
$keys = array_combine($keys, array_fill(0, (count($keys) - 1) ?: 1, $key));
unset($data['id']);
foreach ($data as $k => $v) {
$data[$k] = [
'Value' => $this->client->formatValue($v),
if (!is_array($key)) {
$key = [
$storageName => $key,
];
}
$result = $this->client->updateItem([
$keys = array_intersect_assoc($keys, $key) ?: $keys;
return $this->marshaler->marshalItem($keys);
}
/**
* {@inheritdoc}
*/
public function insert($storageName, $key, array $data)
{
$this->client->putItem([
'TableName' => $storageName,
'Key' => [
'id' => ['S' => $key],
],
'AttributeUpdates' => $data,
'Item' => $this->prepareKey($storageName, $key) + $this->marshaler->marshalItem($data),
]);
}
/**
* {@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);
}
/**
* {@inheritdoc}
*/
public function delete($storageName, $key)
{
$result = $this->client->deleteItem([
$this->client->deleteItem([
'Key' => $this->prepareKey($storageName, $key),
'TableName' => $storageName,
'Key' => [
'id' => ['S' => $key],
],
]);
}
/**
* {@inheritDoc}
* {@inheritdoc}
*/
public function find($storageName, $key)
{
$iterator = new ItemIterator($this->client->getScanIterator([
$keys = $this->prepareKey($storageName, $key);
$item = $this->client->getItem([
'ConsistentRead' => true,
'Key' => $keys,
'TableName' => $storageName,
'Key' => [
'Id' => ['S' => $key],
],
]));
]);
$results = $iterator->toArray();
if (count($results)) {
return array_shift($results);
if (! $item->hasKey('Item')) {
throw NotFoundException::notFoundByKey($key);
}
throw new NotFoundException();
$item = $item->get('Item');
$result = $this->marshaler->unmarshalItem($item);
$result = array_diff_key($result, $keys);
return $result;
}
/**
@@ -154,53 +191,4 @@ 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]);
}
}
}
}

View File

@@ -21,6 +21,7 @@
namespace Doctrine\KeyValueStore\Storage;
use Doctrine\KeyValueStore\NotFoundException;
use MongoDB\Database;
/**
* MongoDb storage
@@ -30,57 +31,16 @@ use Doctrine\KeyValueStore\NotFoundException;
class MongoDbStorage implements Storage
{
/**
* @var \Mongo
* @var Database
*/
protected $mongo;
private $database;
/**
* @var array
* @param Database $database
*/
protected $dbOptions;
/**
* @var \MongoCollection
*/
protected $collection;
/**
* Constructor
*
* @param \Mongo $mongo
* @param array $dbOptions
*/
public function __construct(\Mongo $mongo, array $dbOptions = [])
public function __construct(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']);
$this->database = $database;
}
/**
@@ -112,14 +72,12 @@ class MongoDbStorage implements Storage
*/
public function insert($storageName, $key, array $data)
{
$this->initialize();
$value = [
'key' => $key,
'value' => $data,
];
$this->collection->insert($value);
$this->database
->selectCollection($storageName)
->insertOne([
'key' => $key,
'value' => $data,
]);
}
/**
@@ -127,14 +85,14 @@ class MongoDbStorage implements Storage
*/
public function update($storageName, $key, array $data)
{
$this->initialize();
$value = [
'key' => $key,
'value' => $data,
];
$this->collection->update(['key' => $key], $value);
$this->database
->selectCollection($storageName)
->replaceOne([
'key' => $key,
], [
'key' => $key,
'value' => $data,
]);
}
/**
@@ -142,9 +100,11 @@ class MongoDbStorage implements Storage
*/
public function delete($storageName, $key)
{
$this->initialize();
$this->collection->remove(['key' => $key]);
$this->database
->selectCollection($storageName)
->deleteOne([
'key' => $key,
]);
}
/**
@@ -152,15 +112,23 @@ class MongoDbStorage implements Storage
*/
public function find($storageName, $key)
{
$this->initialize();
$result = $this->database
->selectCollection($storageName, [
'typeMap' => [
'array' => 'array',
'document' => 'array',
'root' => 'array',
],
])
->findOne([
'key' => $key,
]);
$value = $this->collection->findOne(['key' => $key], ['value']);
if ($value) {
return $value['value'];
if (! $result || ! $result['value']) {
throw new NotFoundException();
}
throw new NotFoundException();
return $result['value'];
}
/**

View File

@@ -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();
}

View File

@@ -21,7 +21,14 @@
namespace Doctrine\KeyValueStore\Storage;
use Doctrine\KeyValueStore\NotFoundException;
use Riak\Client;
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;
/**
* @author Markus Bachmann <markus.bachmann@bachi.biz>
@@ -29,17 +36,11 @@ use Riak\Client;
class RiakStorage implements Storage
{
/**
* @var \Riak\Client
* @var RiakClient
*/
protected $client;
private $client;
/**
* Constructor
*
* @param \Riak\Client $riak
* @param string $bucketName
*/
public function __construct(Client $riak)
public function __construct(RiakClient $riak)
{
$this->client = $riak;
}
@@ -68,14 +69,25 @@ 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)
{
$bucket = $this->client->bucket($storageName);
$object = $bucket->newObject($key, $data);
$object->store();
$this->store($storageName, $key, $data);
}
/**
@@ -83,12 +95,7 @@ class RiakStorage implements Storage
*/
public function update($storageName, $key, array $data)
{
$bucket = $this->client->bucket($storageName);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
$object->setData($data);
$object->store();
$this->store($storageName, $key, $data);
}
/**
@@ -96,17 +103,15 @@ class RiakStorage implements Storage
*/
public function delete($storageName, $key)
{
$bucket = $this->client->bucket($storageName);
$location = $this->getRiakLocation($storageName, $key);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
$delete = DeleteValue::builder($location)->build();
if ( ! $object->exists()) {
// object does not exist, do nothing
return;
try {
$this->client->execute($delete);
} catch (RiakException $exception) {
// deletion can fail silent
}
$object->delete();
}
/**
@@ -114,16 +119,29 @@ class RiakStorage implements Storage
*/
public function find($storageName, $key)
{
$bucket = $this->client->bucket($storageName);
$location = $this->getRiakLocation($storageName, $key);
/** @var $object \Riak\Object */
$object = $bucket->get($key);
// fetch object
$fetch = FetchValue::builder($location)->build();
if ( ! $object->exists()) {
throw new NotFoundException;
try {
$result = $this->client->execute($fetch);
} catch (RiakException $exception) {
throw new NotFoundException();
}
return $object->getData();
$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);
}
/**

View File

@@ -61,7 +61,7 @@ class WindowsAzureTableStorage implements Storage, RangeQueryStorage
</entry>';
const XML_TEMPLATE_TABLE = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title />
<updated></updated>
<author>
@@ -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.'
);

View File

@@ -85,13 +85,13 @@ class UnitOfWork
return;
}
public function reconsititute($className, $key)
public function reconstititute($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.');
}

View File

@@ -16,5 +16,7 @@
<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>

View File

@@ -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 {

View File

@@ -21,7 +21,11 @@
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;
@@ -68,4 +72,118 @@ 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())));
}
}

View File

@@ -0,0 +1,250 @@
<?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();
}
}

View File

@@ -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.');
}

View File

@@ -0,0 +1,102 @@
<?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());
}
}

View File

@@ -0,0 +1,157 @@
<?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());
}
}

View File

@@ -20,37 +20,34 @@
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>
*
* @requires extension mongo
* @covers \Doctrine\KeyValueStore\Storage\MongoDbStorage
* @requires extension mongodb
*/
class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Client
*/
private $client;
/**
* @var MongoDbStorage
*/
private $storage;
protected function setUp()
{
$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',
]);
$this->client = new Client();
$this->storage = new MongoDbStorage($this->client->test);
}
public function testInsert()
@@ -60,20 +57,21 @@ class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
'title' => 'example book',
];
$dbDataset = [];
$this->storage->insert('mongodb', 'testInsert', $data);
$this->collection->expects($this->once())
->method('insert')
->will($this->returnCallback(function ($data) use (&$dbDataset) {
$dbDataset[] = $data;
}));
$result = $this->client
->test
->mongodb
->findOne([
'key' => 'testInsert',
]);
$this->storage->insert('mongodb', '1', $data);
$this->assertCount(1, $dbDataset);
$this->assertEquals([['key' => '1', 'value' => $data]], $dbDataset);
$this->assertSame($data, $result['value']->getArrayCopy());
}
/**
* @depends testInsert
*/
public function testUpdate()
{
$data = [
@@ -81,80 +79,67 @@ class MongoDbStorageTest extends \PHPUnit_Framework_TestCase
'title' => 'example book',
];
$dbDataset = [];
$this->storage->insert('mongodb', 'testUpdate', [
'foo' => 'bar',
]);
$this->storage->update('mongodb', 'testUpdate', $data);
$this->collection->expects($this->once())
->method('update')
->will($this->returnCallback(function ($citeria, $data) use (&$dbDataset) {
$dbDataset = [$citeria, $data];
}));
$result = $this->client
->test
->mongodb
->findOne([
'key' => 'testUpdate',
]);
$this->storage->update('mongodb', '1', $data);
$this->assertEquals(['key' => '1'], $dbDataset[0]);
$this->assertEquals(['key' => '1', 'value' => $data], $dbDataset[1]);
$this->assertSame($data, $result['value']->getArrayCopy());
}
/**
* @depends testInsert
*/
public function testDelete()
{
$dataset = [
[
'key' => 'foobar',
'value' => [
'author' => 'John Doe',
'title' => 'example book',
],
],
];
$this->storage->insert('mongodb', 'testDelete', [
'foo' => 'bar',
]);
$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]);
}
}
}
));
$this->storage->delete('mongodb', 'testDelete');
$this->storage->delete('test', 'foobar');
$result = $this->client
->test
->mongodb
->findOne([
'key' => 'testDelete',
]);
$this->assertCount(0, $dataset);
$this->assertNull($result);
}
/**
* @depends testInsert
*/
public function testFind()
{
$dataset = [
[
'key' => 'foobar',
'value' => [
'author' => 'John Doe',
'title' => 'example book',
],
],
'author' => 'John Doe',
'title' => 'example book',
];
$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;
}
}
}
));
$this->storage->insert('mongodb', 'testFind', $dataset);
$data = $this->storage->find('test', 'foobar');
$data = $this->storage->find('mongodb', 'testFind');
$this->assertEquals($dataset[0]['value'], $data);
$this->assertEquals($dataset, $data);
}
public function testFindWithNotExistKey()
{
$this->setExpectedException(NotFoundException::class);
$this->storage->find('mongodb', 'not-existing-key');
}
public function testGetName()
{
$this->storage->initialize();
$this->assertEquals('mongodb', $this->storage->getName());
}
}

View File

@@ -20,30 +20,46 @@
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;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $riak;
protected function setup()
protected function setUp()
{
$this->riak = $this->getMockBuilder('Riak\\Client')
->disableOriginalConstructor()
->getMock();
$dns = getenv('RIAK_DNS');
$this->storage = new RiakStorage($this->riak);
if (empty($dns)) {
$this->markTestSkipped('Missing Riak DNS');
}
$this->client = (new RiakClientBuilder())
->withNodeUri($dns)
->build();
$this->storage = new RiakStorage($this->client);
}
public function testSupportsPartialUpdates()
@@ -63,186 +79,124 @@ class RiakStorageTest extends \PHPUnit_Framework_TestCase
public function testInsert()
{
$bucket = $this->getMockBuilder('Riak\Bucket')
->disableOriginalConstructor()
->getMock();
$data = [
'title' => 'Riak test',
];
$this->riak->expects($this->once())
->method('bucket')
->will($this->returnValue($bucket));
$this->storage->insert('riak-test', 'foobar', $data);
$objectMock = $this->getMockBuilder('Riak\Object')
->disableOriginalConstructor()
->getMock();
$location = $this->getRiakLocation();
$objectMock->expects($this->once())
->method('store');
$fetch = FetchValue::builder($location)->build();
$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;
}));
$json = (string) $this->client
->execute($fetch)
->getValue()
->getValue();
$this->storage->insert('riak-test', 'foobar', ['title' => 'Riak test']);
}
public function testUpdate()
{
$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')
->will($this->returnValue($objectMock));
$that = $this;
$objectMock->expects($this->once())
->method('setData')
->will($this->returnCallback(function ($data) use ($that) {
$that->assertEquals(['title' => 'Riak cookbook'], $data);
}));
$objectMock->expects($this->once())
->method('store');
$this->storage->update('riak-test', 'foobar', ['title' => 'Riak cookbook']);
}
public function testDelete()
{
$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');
}
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');
}
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'));
$this->assertSame($data, json_decode($json, true));
}
/**
* @expectedException Doctrine\KeyValueStore\NotFoundException
* @depends testInsert
*/
public function testUpdate()
{
$data = [
'title' => 'Riak update',
];
$this->storage->insert('riak-test', 'foobar', [
'title' => 'Riak insert',
]);
$location = $this->getRiakLocation();
$this->assertTotalBucketKeys(1, $location);
$this->storage->update('riak-test', 'foobar', $data);
$fetch = FetchValue::builder($location)->build();
$json = (string) $this->client
->execute($fetch)
->getValue()
->getValue();
$this->assertSame($data, json_decode($json, true));
$this->assertTotalBucketKeys(1, $location);
}
/**
* @depends testInsert
*/
public function testDelete()
{
$this->testInsert();
$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()
{
$this->storage->delete('riak-test', 'foobar');
$this->storage->delete('riak-test', 'foobar');
}
/**
* @depends testInsert
*/
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()
{
$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');
$this->setExpectedException(NotFoundException::class);
$this->storage->find('riak-test', 'foobar-1');
}
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');
}
}

View File

@@ -20,7 +20,9 @@
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
@@ -29,8 +31,14 @@ class WindowsAzureTableStorageTest extends AbstractStorageTestCase
protected function createStorage()
{
$this->client = $this->getMock('Doctrine\KeyValueStore\Http\Client');
$auth = $this->getMock('Doctrine\KeyValueStore\Storage\WindowsAzureTable\AuthorizationSchema');
$this->client = $this
->getMockBuilder(Client::class)
->disableOriginalConstructor()
->getMock();
$auth = $this
->getMockBuilder(AuthorizationSchema::class)
->disableOriginalConstructor()
->getMock();
$auth->expects($this->any())->method('signRequest')->will($this->returnValue('Authorization: SharedKeyLite testaccount1:uay+rilMVayH/SVI8X+a3fL8k/NxCnIePdyZSkqvydM='));
$storage = new WindowsAzureTableStorage(

View File

@@ -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

View File

@@ -7,6 +7,5 @@ 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*||"`
# PHP extensions
yes | pecl install mongo
yes | pecl install redis
# PECL extensions
echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini