Merge pull request #773 from merk/transformer-event

Dispatch an event when transforming objects
This commit is contained in:
Tim Nagel 2015-01-21 13:29:23 +11:00
commit 1bf59d5b66
7 changed files with 154 additions and 6 deletions

View file

@ -19,3 +19,5 @@ https://github.com/FriendsOfSymfony/FOSElasticaBundle/compare/v3.0.4...v3.1.0
this class on every request where doctrine is active. #729 this class on every request where doctrine is active. #729
* Added ability to configure `date_detection`, `numeric_detection` and * Added ability to configure `date_detection`, `numeric_detection` and
`dynamic_date_formats` for types. #753 `dynamic_date_formats` for types. #753
* New event `POST_TRANSFORM` which allows developers to add custom properties to
Elastica Documents for indexing.

78
Event/TransformEvent.php Normal file
View file

@ -0,0 +1,78 @@
<?php
/**
* This file is part of the FOSElasticaBundle project.
*
* (c) Infinite Networks Pty Ltd <http://www.infinite.net.au>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FOS\ElasticaBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class TransformEvent extends Event
{
const POST_TRANSFORM = 'fos_elastica.post_transform';
/**
* @var mixed
*/
private $document;
/**
* @var array
*/
private $fields;
/**
* @var mixed
*/
private $object;
/**
* @param mixed $document
* @param array $fields
* @param mixed $object
*/
public function __construct($document, array $fields, $object)
{
$this->document = $document;
$this->fields = $fields;
$this->object = $object;
}
/**
* @return mixed
*/
public function getDocument()
{
return $this->document;
}
/**
* @return array
*/
public function getFields()
{
return $this->fields;
}
/**
* @return mixed
*/
public function getObject()
{
return $this->object;
}
/**
* @param mixed $document
*/
public function setDocument($document)
{
$this->document = $document;
}
}

View file

@ -12,7 +12,8 @@
<services> <services>
<service id="fos_elastica.model_to_elastica_transformer" class="%fos_elastica.model_to_elastica_transformer.class%" public="false" abstract="true"> <service id="fos_elastica.model_to_elastica_transformer" class="%fos_elastica.model_to_elastica_transformer.class%" public="false" abstract="true">
<argument type="collection" /> <!-- options --> <argument type="collection" /> <!-- options -->
<argument type="service" id="event_dispatcher" /> <!-- options -->
<call method="setPropertyAccessor"> <call method="setPropertyAccessor">
<argument type="service" id="fos_elastica.property_accessor" /> <argument type="service" id="fos_elastica.property_accessor" />
</call> </call>

View file

@ -0,0 +1,33 @@
##### Custom Repositories
Since FOSElasticaBundle 3.1.0, we now dispatch an event for each transformation of an
object into an Elastica document which allows you to set custom properties on the Elastica
document for indexing.
Set up an event listener or subscriber for
`FOS\ElasticaBundle\Event\TransformEvent::POST_TRANSFORM` to be able to inject your own
parameters.
```php
class CustomPropertyListener implements EventSubscriberInterface
{
private $anotherService;
// ...
public function addCustomProperty(TransformEvent $event)
{
$document = $event->getDocument();
$custom = $this->anotherService->calculateCustom($event->getObject());
$document->set('custom', $custom);
}
public static function getSubscribedEvents()
{
return array(
TransformEvent::POST_TRANSFORM => 'addCustomProperty',
);
}
}
```

View file

@ -13,6 +13,7 @@ Cookbook Entries
---------------- ----------------
* [Aliased Indexes](cookbook/aliased-indexes.md) * [Aliased Indexes](cookbook/aliased-indexes.md)
* [Custom Indexed Properties](cookbook/custom-properties.md)
* [Custom Repositories](cookbook/custom-repositories.md) * [Custom Repositories](cookbook/custom-repositories.md)
* [HTTP Headers for Elastica](cookbook/elastica-client-http-headers.md) * [HTTP Headers for Elastica](cookbook/elastica-client-http-headers.md)
* Performance - [Logging](cookbook/logging.md) * Performance - [Logging](cookbook/logging.md)

View file

@ -2,6 +2,7 @@
namespace FOS\ElasticaBundle\Tests\Transformer\ModelToElasticaAutoTransformer; namespace FOS\ElasticaBundle\Tests\Transformer\ModelToElasticaAutoTransformer;
use FOS\ElasticaBundle\Event\TransformEvent;
use FOS\ElasticaBundle\Transformer\ModelToElasticaAutoTransformer; use FOS\ElasticaBundle\Transformer\ModelToElasticaAutoTransformer;
use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccess;
@ -132,6 +133,21 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
} }
} }
public function testTransformerDispatches()
{
$dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')
->getMock();
$dispatcher->expects($this->once())
->method('dispatch')
->with(
TransformEvent::POST_TRANSFORM,
$this->isInstanceOf('FOS\ElasticaBundle\Event\TransformEvent')
);
$transformer = $this->getTransformer($dispatcher);
$transformer->transform(new POPO(), array());
}
public function testThatCanTransformObject() public function testThatCanTransformObject()
{ {
$transformer = $this->getTransformer(); $transformer = $this->getTransformer();
@ -295,8 +311,8 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
$this->assertTrue(array_key_exists('obj', $data)); $this->assertTrue(array_key_exists('obj', $data));
$this->assertInternalType('array', $data['obj']); $this->assertInternalType('array', $data['obj']);
$this->assertEquals(array( $this->assertEquals(array(
'foo' => 'foo', 'foo' => 'foo',
'bar' => 'foo', 'bar' => 'foo',
'id' => 1 'id' => 1
), $data['obj']); ), $data['obj']);
} }
@ -387,11 +403,12 @@ class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @param null|\Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* @return ModelToElasticaAutoTransformer * @return ModelToElasticaAutoTransformer
*/ */
private function getTransformer() private function getTransformer($dispatcher = null)
{ {
$transformer = new ModelToElasticaAutoTransformer(); $transformer = new ModelToElasticaAutoTransformer(array(), $dispatcher);
$transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor()); $transformer->setPropertyAccessor(PropertyAccess::getPropertyAccessor());
return $transformer; return $transformer;

View file

@ -2,6 +2,8 @@
namespace FOS\ElasticaBundle\Transformer; namespace FOS\ElasticaBundle\Transformer;
use FOS\ElasticaBundle\Event\TransformEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Elastica\Document; use Elastica\Document;
@ -12,6 +14,11 @@ use Elastica\Document;
*/ */
class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterface class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterface
{ {
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
/** /**
* Optional parameters * Optional parameters
* *
@ -32,10 +39,12 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
* Instanciates a new Mapper * Instanciates a new Mapper
* *
* @param array $options * @param array $options
* @param EventDispatcherInterface $dispatcher
*/ */
public function __construct(array $options = array()) public function __construct(array $options = array(), EventDispatcherInterface $dispatcher = null)
{ {
$this->options = array_merge($this->options, $options); $this->options = array_merge($this->options, $options);
$this->dispatcher = $dispatcher;
} }
/** /**
@ -92,6 +101,13 @@ class ModelToElasticaAutoTransformer implements ModelToElasticaTransformerInterf
$document->set($key, $this->normalizeValue($value)); $document->set($key, $this->normalizeValue($value));
} }
if ($this->dispatcher) {
$event = new TransformEvent($document, $fields, $object);
$this->dispatcher->dispatch(TransformEvent::POST_TRANSFORM, $event);
$document = $event->getDocument();
}
return $document; return $document;
} }