diff --git a/DependencyInjection/FOSElasticaExtension.php b/DependencyInjection/FOSElasticaExtension.php index 9bf732e..7a72d96 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; @@ -171,7 +172,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); @@ -180,12 +181,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'])); } @@ -324,8 +325,14 @@ class FOSElasticaExtension extends Extension return $typeConfig['model_to_elastica_transformer']['service']; } + if ($this->serializerConfig) { + $abstractId = sprintf('fos_elastica.model_to_elastica_identifier_transformer'); + } else { + $abstractId = sprintf('fos_elastica.model_to_elastica_transformer'); + } + $serviceId = sprintf('fos_elastica.model_to_elastica_transformer.%s.%s', $indexName, $typeName); - $serviceDef = new DefinitionDecorator('fos_elastica.model_to_elastica_transformer'); + $serviceDef = new DefinitionDecorator($abstractId); $serviceDef->replaceArgument(0, array( 'identifier' => $typeConfig['identifier'] )); @@ -336,12 +343,24 @@ 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 = 'fos_elastica.object_serializer_persister'; + } else { + $abstractId = 'fos_elastica.object_persister'; + $arguments[] = $this->typeFields[sprintf('%s/%s', $indexName, $typeName)]; + } $serviceId = sprintf('fos_elastica.object_persister.%s.%s', $indexName, $typeName); - $serviceDef = new DefinitionDecorator('fos_elastica.object_persister'); - $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)]); + $serviceDef = new DefinitionDecorator($abstractId); + 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..269515b --- /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 ad6b13b..77c280d 100644 --- a/Resources/config/config.xml +++ b/Resources/config/config.xml @@ -49,6 +49,12 @@ + + + + + + @@ -56,6 +62,13 @@ + + + + + + + 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/ModelToElasticaAutoTransformerTest.php b/Tests/Transformer/ModelToElasticaAutoTransformerTest.php index 9990fa2..d2c181a 100644 --- a/Tests/Transformer/ModelToElasticaAutoTransformerTest.php +++ b/Tests/Transformer/ModelToElasticaAutoTransformerTest.php @@ -118,7 +118,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 new file mode 100644 index 0000000..f1a77d4 --- /dev/null +++ b/Tests/Transformer/ModelToElasticaIdentifierTransformerTest.php @@ -0,0 +1,65 @@ +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; + } +} diff --git a/Transformer/ModelToElasticaIdentifierTransformer.php b/Transformer/ModelToElasticaIdentifierTransformer.php new file mode 100644 index 0000000..654850f --- /dev/null +++ b/Transformer/ModelToElasticaIdentifierTransformer.php @@ -0,0 +1,26 @@ +propertyAccessor->getValue($object, $this->options['identifier']); + return new Document($identifier); + } +}