Adding new persister and new transformer to make use of the serializer support of elastica when persisting doctrine objects

This commit is contained in:
Lea Haensenberger 2013-07-17 08:58:15 +02:00
parent 00f37835fc
commit 5b6a1f7bd6
4 changed files with 169 additions and 14 deletions

View file

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

View file

@ -0,0 +1,97 @@
<?php
namespace FOS\ElasticaBundle\Persister;
use Elastica\Type;
use FOS\ElasticaBundle\Transformer\ModelToElasticaTransformerInterface;
/**
* Inserts, replaces and deletes single objects in an elastica type, making use
* of elastica's serializer support to convert objects in to elastica documents.
* Accepts domain model objects and passes them directly to elastica
*
* @author Lea Haensenberber <lea.haensenberger@gmail.com>
*/
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());
}
}

View file

@ -52,6 +52,12 @@
<argument /> <!-- properties mapping -->
</service>
<service id="fos_elastica.object_serializer_persister.prototype" class="FOS\ElasticaBundle\Persister\ObjectSerializerPersister" abstract="true">
<argument /> <!-- type -->
<argument /> <!-- model to elastica transformer -->
<argument /> <!-- model -->
</service>
<service id="fos_elastica.finder.prototype" class="FOS\ElasticaBundle\Finder\TransformedFinder" public="true" abstract="true">
<argument /> <!-- searchable -->
<argument /> <!-- transformer -->
@ -64,6 +70,13 @@
</call>
</service>
<service id="fos_elastica.model_to_elastica_transformer.prototype.identifier" class="FOS\ElasticaBundle\Transformer\ModelToElasticaIdentifierTransformer" public="false" abstract="true">
<argument /> <!-- options -->
<call method="setPropertyAccessor">
<argument type="service" id="fos_elastica.property_accessor" />
</call>
</service>
<service id="fos_elastica.elastica_to_model_transformer.collection.prototype" class="%fos_elastica.elastica_to_model_transformer.collection.class%" public="true" abstract="true">
<argument type="collection" /> <!-- transformers -->
</service>

View file

@ -0,0 +1,26 @@
<?php
namespace FOS\ElasticaBundle\Transformer;
use Elastica\Document;
/**
* Creates an elastica document with the id of
* the doctrine object as elastica document id
*/
class ModelToElasticaIdentifierTransformer extends ModelToElasticaAutoTransformer
{
/**
* Creates an elastica document with the id of the doctrine object as id
*
* @param object $object the object to convert
* @param array $fields the keys we want to have in the returned array
*
* @return Document
**/
public function transform($object, array $fields)
{
$identifier = $this->propertyAccessor->getValue($object, $this->options['identifier']);
return new Document($identifier);
}
}