From 5b6a1f7bd656f6c8490035aa309334cdce415457 Mon Sep 17 00:00:00 2001 From: Lea Haensenberger Date: Wed, 17 Jul 2013 08:58:15 +0200 Subject: [PATCH 1/5] Adding new persister and new transformer to make use of the serializer support of elastica when persisting doctrine objects --- DependencyInjection/FOSElasticaExtension.php | 47 ++++++--- Persister/ObjectSerializerPersister.php | 97 +++++++++++++++++++ Resources/config/config.xml | 13 +++ .../ModelToElasticaIdentifierTransformer.php | 26 +++++ 4 files changed, 169 insertions(+), 14 deletions(-) create mode 100644 Persister/ObjectSerializerPersister.php create mode 100644 Transformer/ModelToElasticaIdentifierTransformer.php diff --git a/DependencyInjection/FOSElasticaExtension.php b/DependencyInjection/FOSElasticaExtension.php index c28fb99..9a15a83 100644 --- a/DependencyInjection/FOSElasticaExtension.php +++ b/DependencyInjection/FOSElasticaExtension.php @@ -16,6 +16,7 @@ class FOSElasticaExtension extends Extension protected $indexConfigs = array(); protected $typeFields = array(); protected $loadedDrivers = array(); + protected $serializerConfig = array(); public function load(array $configs, ContainerBuilder $container) { @@ -40,8 +41,8 @@ class FOSElasticaExtension extends Extension } $clientIdsByName = $this->loadClients($config['clients'], $container); - $serializerConfig = isset($config['serializer']) ? $config['serializer'] : null; - $indexIdsByName = $this->loadIndexes($config['indexes'], $container, $clientIdsByName, $config['default_client'], $serializerConfig); + $this->serializerConfig = isset($config['serializer']) ? $config['serializer'] : null; + $indexIdsByName = $this->loadIndexes($config['indexes'], $container, $clientIdsByName, $config['default_client']); $indexRefsByName = array_map(function($id) { return new Reference($id); }, $indexIdsByName); @@ -94,7 +95,7 @@ class FOSElasticaExtension extends Extension * @throws \InvalidArgumentException * @return array */ - protected function loadIndexes(array $indexes, ContainerBuilder $container, array $clientIdsByName, $defaultClientName, $serializerConfig) + protected function loadIndexes(array $indexes, ContainerBuilder $container, array $clientIdsByName, $defaultClientName) { $indexIds = array(); foreach ($indexes as $name => $index) { @@ -129,7 +130,7 @@ class FOSElasticaExtension extends Extension if (!empty($index['settings'])) { $this->indexConfigs[$name]['config']['settings'] = $index['settings']; } - $this->loadTypes(isset($index['types']) ? $index['types'] : array(), $container, $name, $indexId, $typePrototypeConfig, $serializerConfig); + $this->loadTypes(isset($index['types']) ? $index['types'] : array(), $container, $name, $indexId, $typePrototypeConfig); } return $indexIds; @@ -170,7 +171,7 @@ class FOSElasticaExtension extends Extension * @param $indexId * @param array $typePrototypeConfig */ - protected function loadTypes(array $types, ContainerBuilder $container, $indexName, $indexId, array $typePrototypeConfig, $serializerConfig) + protected function loadTypes(array $types, ContainerBuilder $container, $indexName, $indexId, array $typePrototypeConfig) { foreach ($types as $name => $type) { $type = self::deepArrayUnion($typePrototypeConfig, $type); @@ -179,12 +180,12 @@ class FOSElasticaExtension extends Extension $typeDef = new Definition('%fos_elastica.type.class%', $typeDefArgs); $typeDef->setFactoryService($indexId); $typeDef->setFactoryMethod('getType'); - if ($serializerConfig) { - $callbackDef = new Definition($serializerConfig['callback_class']); + if ($this->serializerConfig) { + $callbackDef = new Definition($this->serializerConfig['callback_class']); $callbackId = sprintf('%s.%s.serializer.callback', $indexId, $name); $typeDef->addMethodCall('setSerializer', array(array(new Reference($callbackId), 'serialize'))); - $callbackDef->addMethodCall('setSerializer', array(new Reference($serializerConfig['serializer']))); + $callbackDef->addMethodCall('setSerializer', array(new Reference($this->serializerConfig['serializer']))); if (isset($type['serializer']['groups'])) { $callbackDef->addMethodCall('setGroups', array($type['serializer']['groups'])); } @@ -307,7 +308,11 @@ class FOSElasticaExtension extends Extension if (isset($typeConfig['model_to_elastica_transformer']['service'])) { return $typeConfig['model_to_elastica_transformer']['service']; } - $abstractId = sprintf('fos_elastica.model_to_elastica_transformer.prototype.auto'); + if ($this->serializerConfig) { + $abstractId = sprintf('fos_elastica.model_to_elastica_transformer.prototype.identifier'); + } else { + $abstractId = sprintf('fos_elastica.model_to_elastica_transformer.prototype.auto'); + } $serviceId = sprintf('fos_elastica.model_to_elastica_transformer.%s.%s', $indexName, $typeName); $serviceDef = new DefinitionDecorator($abstractId); $serviceDef->replaceArgument(0, array( @@ -320,13 +325,27 @@ class FOSElasticaExtension extends Extension protected function loadObjectPersister(array $typeConfig, Definition $typeDef, ContainerBuilder $container, $indexName, $typeName, $transformerId) { - $abstractId = sprintf('fos_elastica.object_persister.prototype'); + if ($this->serializerConfig) { + $abstractId = sprintf('fos_elastica.object_serializer_persister.prototype'); + $arguments = array( + $typeDef, + new Reference($transformerId), + $typeConfig['model'], + ); + } else { + $abstractId = sprintf('fos_elastica.object_persister.prototype'); + $arguments = array( + $typeDef, + new Reference($transformerId), + $typeConfig['model'], + $this->typeFields[sprintf('%s/%s', $indexName, $typeName)], + ); + } $serviceId = sprintf('fos_elastica.object_persister.%s.%s', $indexName, $typeName); $serviceDef = new DefinitionDecorator($abstractId); - $serviceDef->replaceArgument(0, $typeDef); - $serviceDef->replaceArgument(1, new Reference($transformerId)); - $serviceDef->replaceArgument(2, $typeConfig['model']); - $serviceDef->replaceArgument(3, $this->typeFields[sprintf('%s/%s', $indexName, $typeName)]); + foreach ($arguments as $i => $argument) { + $serviceDef->replaceArgument($i, $argument); + } $container->setDefinition($serviceId, $serviceDef); return $serviceId; diff --git a/Persister/ObjectSerializerPersister.php b/Persister/ObjectSerializerPersister.php new file mode 100644 index 0000000..db8122a --- /dev/null +++ b/Persister/ObjectSerializerPersister.php @@ -0,0 +1,97 @@ + + */ +class ObjectSerializerPersister extends ObjectPersister +{ + public function __construct(Type $type, ModelToElasticaTransformerInterface $transformer, $objectClass) + { + $this->type = $type; + $this->transformer = $transformer; + $this->objectClass = $objectClass; + } + + /** + * Insert one object into the type + * The object will be transformed to an elastica document + * + * @param object $object + */ + public function insertOne($object) + { + $document = $this->transformToElasticaDocument($object); + $this->type->addObject($object, $document); + } + + /** + * Replaces one object in the type + * + * @param object $object + * @return null + **/ + public function replaceOne($object) + { + $document = $this->transformToElasticaDocument($object); + $this->type->deleteById($document->getId()); + $this->type->addObject($object, $document); + } + + /** + * Deletes one object in the type + * + * @param object $object + * @return null + **/ + public function deleteOne($object) + { + $document = $this->transformToElasticaDocument($object); + $this->type->deleteById($document->getId()); + } + + /** + * Deletes one object in the type by id + * + * @param mixed $id + * + * @return null + **/ + public function deleteById($id) + { + $this->type->deleteById($id); + } + + + /** + * Inserts an array of objects in the type + * + * @param array $objects array of domain model objects + **/ + public function insertMany(array $objects) + { + foreach ($objects as $object) { + $this->insertOne($object); + } + } + + /** + * Transforms an object to an elastica document + * with just the identifier set + * + * @param object $object + * @return Document the elastica document + */ + public function transformToElasticaDocument($object) + { + return $this->transformer->transform($object, array()); + } +} diff --git a/Resources/config/config.xml b/Resources/config/config.xml index 4097289..3f5f7cf 100644 --- a/Resources/config/config.xml +++ b/Resources/config/config.xml @@ -52,6 +52,12 @@ + + + + + + @@ -64,6 +70,13 @@ + + + + + + + diff --git a/Transformer/ModelToElasticaIdentifierTransformer.php b/Transformer/ModelToElasticaIdentifierTransformer.php new file mode 100644 index 0000000..416eaf7 --- /dev/null +++ b/Transformer/ModelToElasticaIdentifierTransformer.php @@ -0,0 +1,26 @@ +propertyAccessor->getValue($object, $this->options['identifier']); + return new Document($identifier); + } +} From d10e8f56c8b7e1374dae924e1a0efd2067986208 Mon Sep 17 00:00:00 2001 From: Lea Haensenberger Date: Wed, 17 Jul 2013 10:10:07 +0200 Subject: [PATCH 2/5] Tests for new provider and new transformer --- .../ObjectSerializerPersisterTest.php | 117 ++++++++++++++++++ ...delToElasticaIdentifierTransformerTest.php | 66 ++++++++++ 2 files changed, 183 insertions(+) create mode 100644 Tests/Persister/ObjectSerializerPersisterTest.php create mode 100644 Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php diff --git a/Tests/Persister/ObjectSerializerPersisterTest.php b/Tests/Persister/ObjectSerializerPersisterTest.php new file mode 100644 index 0000000..10c63ab --- /dev/null +++ b/Tests/Persister/ObjectSerializerPersisterTest.php @@ -0,0 +1,117 @@ +id; + } + + public function getName() + { + return $this->name; + } +} + +class ObjectSerializerPersisterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('Elastica\Type')) { + $this->markTestSkipped('The Elastica library classes are not available'); + } + } + + public function testThatCanReplaceObject() + { + $transformer = $this->getTransformer(); + + /** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */ + $typeMock = $this->getMockBuilder('Elastica\Type') + ->disableOriginalConstructor() + ->getMock(); + $typeMock->expects($this->once()) + ->method('deleteById') + ->with($this->equalTo(123)); + $typeMock->expects($this->once()) + ->method('addObject'); + + $objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass'); + $objectPersister->replaceOne(new POPO()); + } + + public function testThatCanInsertObject() + { + $transformer = $this->getTransformer(); + + /** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */ + $typeMock = $this->getMockBuilder('Elastica\Type') + ->disableOriginalConstructor() + ->getMock(); + $typeMock->expects($this->never()) + ->method('deleteById'); + $typeMock->expects($this->once()) + ->method('addObject'); + + $objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass'); + $objectPersister->insertOne(new POPO()); + } + + public function testThatCanDeleteObject() + { + $transformer = $this->getTransformer(); + + /** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */ + $typeMock = $this->getMockBuilder('Elastica\Type') + ->disableOriginalConstructor() + ->getMock(); + $typeMock->expects($this->once()) + ->method('deleteById'); + $typeMock->expects($this->never()) + ->method('addObject'); + + $objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass'); + $objectPersister->deleteOne(new POPO()); + } + + public function testThatCanInsertManyObjects() + { + $transformer = $this->getTransformer(); + + /** @var $typeMock \PHPUnit_Framework_MockObject_MockObject|\Elastica\Type */ + $typeMock = $this->getMockBuilder('Elastica\Type') + ->disableOriginalConstructor() + ->getMock(); + $typeMock->expects($this->never()) + ->method('deleteById'); + $typeMock->expects($this->exactly(2)) + ->method('addObject'); + $typeMock->expects($this->never()) + ->method('addObjects'); + + $objectPersister = new ObjectSerializerPersister($typeMock, $transformer, 'SomeClass'); + $objectPersister->insertMany(array(new POPO(), new POPO())); + } + + /** + * @return ModelToElasticaIdentifierTransformer + */ + private function getTransformer() + { + $transformer = new ModelToElasticaIdentifierTransformer(); + $transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor()); + + return $transformer; + } +} diff --git a/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php b/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php new file mode 100644 index 0000000..59a747a --- /dev/null +++ b/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php @@ -0,0 +1,66 @@ +id; + } + + public function getName() + { + return $this->name; + } +} + +class ModelToElasticaIdentifierTransformerTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + if (!class_exists('Elastica\Document')) { + ; + $this->markTestSkipped('The Elastica library classes are not available'); + } + } + + public function testGetDocumentWithIdentifierOnly() + { + $transformer = $this->getTransformer(); + $document = $transformer->transform(new POPO(), array()); + $data = $document->getData(); + + $this->assertInstanceOf('Elastica\Document', $document); + $this->assertEquals(123, $document->getId()); + $this->assertCount(0, $data); + } + + public function testGetDocumentWithIdentifierOnlyWithFields() + { + $transformer = $this->getTransformer(); + $document = $transformer->transform(new POPO(), array('name' => array())); + $data = $document->getData(); + + $this->assertInstanceOf('Elastica\Document', $document); + $this->assertEquals(123, $document->getId()); + $this->assertCount(0, $data); + } + + /** + * @return ModelToElasticaIdentifierTransformer + */ + private function getTransformer() + { + $transformer = new ModelToElasticaIdentifierTransformer(); + $transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor()); + + return $transformer; + } +} From 300d189a9d62559c2fc7c65d1cef03f060cc7d9f Mon Sep 17 00:00:00 2001 From: Lea Haensenberger Date: Thu, 18 Jul 2013 10:51:51 +0200 Subject: [PATCH 3/5] renaming services to avoid potential conflicts --- DependencyInjection/FOSElasticaExtension.php | 4 ++-- Resources/config/config.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DependencyInjection/FOSElasticaExtension.php b/DependencyInjection/FOSElasticaExtension.php index 9a15a83..e0f7a2d 100644 --- a/DependencyInjection/FOSElasticaExtension.php +++ b/DependencyInjection/FOSElasticaExtension.php @@ -309,7 +309,7 @@ class FOSElasticaExtension extends Extension return $typeConfig['model_to_elastica_transformer']['service']; } if ($this->serializerConfig) { - $abstractId = sprintf('fos_elastica.model_to_elastica_transformer.prototype.identifier'); + $abstractId = sprintf('fos_elastica.model_to_elastica_identifier_transformer'); } else { $abstractId = sprintf('fos_elastica.model_to_elastica_transformer.prototype.auto'); } @@ -326,7 +326,7 @@ class FOSElasticaExtension extends Extension protected function loadObjectPersister(array $typeConfig, Definition $typeDef, ContainerBuilder $container, $indexName, $typeName, $transformerId) { if ($this->serializerConfig) { - $abstractId = sprintf('fos_elastica.object_serializer_persister.prototype'); + $abstractId = sprintf('fos_elastica.object_serializer_persister'); $arguments = array( $typeDef, new Reference($transformerId), diff --git a/Resources/config/config.xml b/Resources/config/config.xml index 3f5f7cf..4d85d9f 100644 --- a/Resources/config/config.xml +++ b/Resources/config/config.xml @@ -52,7 +52,7 @@ - + @@ -70,7 +70,7 @@ - + From 77156b35aa0f70420b555151d9700591de1f6fc8 Mon Sep 17 00:00:00 2001 From: Lea Haensenberger Date: Thu, 18 Jul 2013 10:54:11 +0200 Subject: [PATCH 4/5] some formatting and cleaning up --- Persister/ObjectSerializerPersister.php | 8 ++++---- Tests/Transformer/ModelToElasticaAutoTransformerTest.php | 1 - .../ModelToElasticaIdentifierTransformerTest.php | 1 - Transformer/ModelToElasticaIdentifierTransformer.php | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Persister/ObjectSerializerPersister.php b/Persister/ObjectSerializerPersister.php index db8122a..269515b 100644 --- a/Persister/ObjectSerializerPersister.php +++ b/Persister/ObjectSerializerPersister.php @@ -16,9 +16,9 @@ class ObjectSerializerPersister extends ObjectPersister { public function __construct(Type $type, ModelToElasticaTransformerInterface $transformer, $objectClass) { - $this->type = $type; - $this->transformer = $transformer; - $this->objectClass = $objectClass; + $this->type = $type; + $this->transformer = $transformer; + $this->objectClass = $objectClass; } /** @@ -38,7 +38,7 @@ class ObjectSerializerPersister extends ObjectPersister * * @param object $object * @return null - **/ + */ public function replaceOne($object) { $document = $this->transformToElasticaDocument($object); diff --git a/Tests/Transformer/ModelToElasticaAutoTransformerTest.php b/Tests/Transformer/ModelToElasticaAutoTransformerTest.php index cbcb6bd..16bb5cd 100644 --- a/Tests/Transformer/ModelToElasticaAutoTransformerTest.php +++ b/Tests/Transformer/ModelToElasticaAutoTransformerTest.php @@ -113,7 +113,6 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase public function setUp() { if (!class_exists('Elastica\Document')) { - ; $this->markTestSkipped('The Elastica library classes are not available'); } } diff --git a/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php b/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php index 59a747a..f1a77d4 100644 --- a/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php +++ b/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php @@ -26,7 +26,6 @@ class ModelToElasticaIdentifierTransformerTest extends \PHPUnit_Framework_TestCa public function setUp() { if (!class_exists('Elastica\Document')) { - ; $this->markTestSkipped('The Elastica library classes are not available'); } } diff --git a/Transformer/ModelToElasticaIdentifierTransformer.php b/Transformer/ModelToElasticaIdentifierTransformer.php index 416eaf7..654850f 100644 --- a/Transformer/ModelToElasticaIdentifierTransformer.php +++ b/Transformer/ModelToElasticaIdentifierTransformer.php @@ -5,8 +5,8 @@ namespace FOS\ElasticaBundle\Transformer; use Elastica\Document; /** - * Creates an elastica document with the id of - * the doctrine object as elastica document id + * Creates an Elastica document with the ID of + * the Doctrine object as Elastica document ID */ class ModelToElasticaIdentifierTransformer extends ModelToElasticaAutoTransformer { From 37cfdb0df79298ece68280984a8313e71a58fde0 Mon Sep 17 00:00:00 2001 From: Lea Haensenberger Date: Thu, 18 Jul 2013 10:56:25 +0200 Subject: [PATCH 5/5] refactoring some code --- DependencyInjection/FOSElasticaExtension.php | 21 ++++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/DependencyInjection/FOSElasticaExtension.php b/DependencyInjection/FOSElasticaExtension.php index e0f7a2d..68e21dd 100644 --- a/DependencyInjection/FOSElasticaExtension.php +++ b/DependencyInjection/FOSElasticaExtension.php @@ -325,21 +325,16 @@ class FOSElasticaExtension extends Extension protected function loadObjectPersister(array $typeConfig, Definition $typeDef, ContainerBuilder $container, $indexName, $typeName, $transformerId) { + $arguments = array( + $typeDef, + new Reference($transformerId), + $typeConfig['model'], + ); if ($this->serializerConfig) { - $abstractId = sprintf('fos_elastica.object_serializer_persister'); - $arguments = array( - $typeDef, - new Reference($transformerId), - $typeConfig['model'], - ); + $abstractId = 'fos_elastica.object_serializer_persister'; } else { - $abstractId = sprintf('fos_elastica.object_persister.prototype'); - $arguments = array( - $typeDef, - new Reference($transformerId), - $typeConfig['model'], - $this->typeFields[sprintf('%s/%s', $indexName, $typeName)], - ); + $abstractId = 'fos_elastica.object_persister.prototype'; + $arguments[] = $this->typeFields[sprintf('%s/%s', $indexName, $typeName)]; } $serviceId = sprintf('fos_elastica.object_persister.%s.%s', $indexName, $typeName); $serviceDef = new DefinitionDecorator($abstractId);