diff --git a/DependencyInjection/FOQElasticaExtension.php b/DependencyInjection/FOQElasticaExtension.php
index 163e4ae..f4c0636 100644
--- a/DependencyInjection/FOQElasticaExtension.php
+++ b/DependencyInjection/FOQElasticaExtension.php
@@ -316,14 +316,8 @@ class FOQElasticaExtension extends Extension
$listenerDef = new DefinitionDecorator($abstractListenerId);
$listenerDef->replaceArgument(0, new Reference($objectPersisterId));
$listenerDef->replaceArgument(1, $typeConfig['model']);
- $events = array();
- $doctrineEvents = array('insert' => 'postPersist', 'update' => 'postUpdate', 'delete' => 'postRemove');
- foreach ($doctrineEvents as $event => $doctrineEvent) {
- if (isset($typeConfig['listener'][$event]) && $typeConfig['listener'][$event]) {
- $events[] = $doctrineEvent;
- }
- }
- $listenerDef->replaceArgument(2, $events);
+ $listenerDef->replaceArgument(3, $typeConfig['identifier']);
+ $listenerDef->replaceArgument(2, $this->getDoctrineEvents($typeConfig));
switch ($typeConfig['driver']) {
case 'orm': $listenerDef->addTag('doctrine.event_subscriber'); break;
case 'mongodb': $listenerDef->addTag('doctrine.common.event_subscriber'); break;
@@ -333,6 +327,24 @@ class FOQElasticaExtension extends Extension
return $listenerId;
}
+ private function getDoctrineEvents(array $typeConfig)
+ {
+ $events = array();
+ $eventMapping = array(
+ 'insert' => array('postPersist'),
+ 'update' => array('postUpdate'),
+ 'delete' => array('postRemove', 'preRemove')
+ );
+
+ foreach ($eventMapping as $event => $doctrineEvents) {
+ if (isset($typeConfig['listener'][$event]) && $typeConfig['listener'][$event]) {
+ $events = array_merge($events, $doctrineEvents);
+ }
+ }
+
+ return $events;
+ }
+
protected function loadTypeFinder(array $typeConfig, ContainerBuilder $container, $elasticaToModelId, $typeDef, $indexName, $typeName)
{
if (isset($typeConfig['finder']['service'])) {
diff --git a/Doctrine/AbstractListener.php b/Doctrine/AbstractListener.php
index 343f9c2..548ccc6 100644
--- a/Doctrine/AbstractListener.php
+++ b/Doctrine/AbstractListener.php
@@ -28,14 +28,19 @@ abstract class AbstractListener
*/
protected $events;
+ protected $esIdentifierField;
+ protected $scheduledForRemoval;
+
/**
* Constructor
**/
- public function __construct(ObjectPersisterInterface $objectPersister, $objectClass, array $events)
+ public function __construct(ObjectPersisterInterface $objectPersister, $objectClass, array $events, $esIdentifierField = 'id')
{
- $this->objectPersister = $objectPersister;
- $this->objectClass = $objectClass;
- $this->events = $events;
+ $this->objectPersister = $objectPersister;
+ $this->objectClass = $objectClass;
+ $this->events = $events;
+ $this->esIdentifierField = $esIdentifierField;
+ $this->scheduledForRemoval = array();
}
/**
@@ -46,4 +51,19 @@ abstract class AbstractListener
return $this->events;
}
+ protected function scheduleForRemoval($object, $objectManager)
+ {
+ $metadata = $objectManager->getClassMetadata($this->objectClass);
+ $esId = $metadata->getFieldValue($object, $this->esIdentifierField);
+ $this->scheduledForRemoval[spl_object_hash($object)] = $esId;
+ }
+
+ protected function removeIfScheduled($object)
+ {
+ $objectHash = spl_object_hash($object);
+ if (isset($this->scheduledForRemoval[$objectHash])) {
+ $this->objectPersister->deleteById($this->scheduledForRemoval[$objectHash]);
+ unset($this->scheduledForRemoval[$objectHash]);
+ }
+ }
}
diff --git a/Doctrine/MongoDB/Listener.php b/Doctrine/MongoDB/Listener.php
index 89c7502..5853e0f 100644
--- a/Doctrine/MongoDB/Listener.php
+++ b/Doctrine/MongoDB/Listener.php
@@ -26,12 +26,21 @@ class Listener extends AbstractListener implements EventSubscriber
}
}
+ public function preRemove(LifecycleEventArgs $eventArgs)
+ {
+ $document = $eventArgs->getDocument();
+
+ if ($document instanceof $this->objectClass) {
+ $this->scheduleForRemoval($document, $eventArgs->getDocumentManager());
+ }
+ }
+
public function postRemove(LifecycleEventArgs $eventArgs)
{
$document = $eventArgs->getDocument();
if ($document instanceof $this->objectClass) {
- $this->objectPersister->deleteOne($document);
+ $this->removeIfScheduled($document);
}
}
}
diff --git a/Doctrine/ORM/Listener.php b/Doctrine/ORM/Listener.php
index 7e5bea8..57318b9 100644
--- a/Doctrine/ORM/Listener.php
+++ b/Doctrine/ORM/Listener.php
@@ -26,12 +26,21 @@ class Listener extends AbstractListener implements EventSubscriber
}
}
+ public function preRemove(LifecycleEventArgs $eventArgs)
+ {
+ $entity = $eventArgs->getEntity();
+
+ if ($entity instanceof $this->objectClass) {
+ $this->scheduleForRemoval($entity, $eventArgs->getEntityManager());
+ }
+ }
+
public function postRemove(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof $this->objectClass) {
- $this->objectPersister->deleteOne($entity);
+ $this->removeIfScheduled($entity);
}
}
}
diff --git a/Persister/ObjectPersister.php b/Persister/ObjectPersister.php
index 87653f4..47bbbe5 100644
--- a/Persister/ObjectPersister.php
+++ b/Persister/ObjectPersister.php
@@ -67,6 +67,19 @@ class ObjectPersister implements ObjectPersisterInterface
$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
*
@@ -91,5 +104,4 @@ class ObjectPersister implements ObjectPersisterInterface
{
return $this->transformer->transform($object, $this->fields);
}
-
}
diff --git a/Persister/ObjectPersisterInterface.php b/Persister/ObjectPersisterInterface.php
index 3cf12d2..962a88c 100644
--- a/Persister/ObjectPersisterInterface.php
+++ b/Persister/ObjectPersisterInterface.php
@@ -32,6 +32,15 @@ interface ObjectPersisterInterface
**/
function deleteOne($object);
+ /**
+ * Deletes one object in the type by id
+ *
+ * @param mixed $id
+ *
+ * @return null
+ **/
+ function deleteById($id);
+
/**
* Inserts an array of objects in the type
*
diff --git a/Resources/config/mongodb.xml b/Resources/config/mongodb.xml
index 5a95da3..a1bd8d3 100644
--- a/Resources/config/mongodb.xml
+++ b/Resources/config/mongodb.xml
@@ -18,6 +18,7 @@
+
diff --git a/Resources/config/orm.xml b/Resources/config/orm.xml
index 059a002..3803853 100644
--- a/Resources/config/orm.xml
+++ b/Resources/config/orm.xml
@@ -18,6 +18,7 @@
+
diff --git a/Tests/Doctrine/MongoDB/ListenerTest.php b/Tests/Doctrine/MongoDB/ListenerTest.php
index eff42d7..0b664dd 100644
--- a/Tests/Doctrine/MongoDB/ListenerTest.php
+++ b/Tests/Doctrine/MongoDB/ListenerTest.php
@@ -11,7 +11,6 @@ class Document{}
*/
class ListenerTest extends \PHPUnit_Framework_TestCase
{
-
public function testObjectInsertedOnPersist()
{
$persisterMock = $this->getMockBuilder('FOQ\ElasticaBundle\Persister\ObjectPersisterInterface')
@@ -33,7 +32,7 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->method('insertOne')
->with($this->equalTo($document));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $listener = new Listener($persisterMock, $objectName, array());
$listener->postPersist($eventArgsMock);
}
@@ -58,7 +57,7 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->method('replaceOne')
->with($this->equalTo($document));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $listener = new Listener($persisterMock, $objectName, array());
$listener->postUpdate($eventArgsMock);
}
@@ -72,19 +71,90 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->disableOriginalConstructor()
->getMock();
- $objectName = 'FOQ\ElasticaBundle\Tests\Doctrine\MongoDB\Document';
- $document = new Document();
+ $documentManagerMock = $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentManager')
+ ->disableOriginalConstructor()
+ ->getMock();
- $eventArgsMock->expects($this->once())
+ $metadataMock = $this->getMockBuilder('Doctrine\ODM\MongoDB\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectName = 'FOQ\ElasticaBundle\Tests\Doctrine\MongoDB\Document';
+ $document = new Document();
+ $documentId = 78;
+
+ $eventArgsMock->expects($this->any())
->method('getDocument')
->will($this->returnValue($document));
- $persisterMock->expects($this->once())
- ->method('deleteOne')
- ->with($this->equalTo($document));
+ $eventArgsMock->expects($this->any())
+ ->method('getDocumentManager')
+ ->will($this->returnValue($documentManagerMock));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $documentManagerMock->expects($this->any())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadataMock));
+
+ $metadataMock->expects($this->any())
+ ->method('getFieldValue')
+ ->with($this->equalTo($document), $this->equalTo('id'))
+ ->will($this->returnValue($documentId));
+
+ $persisterMock->expects($this->once())
+ ->method('deleteById')
+ ->with($this->equalTo($documentId));
+
+ $listener = new Listener($persisterMock, $objectName, array());
+ $listener->preRemove($eventArgsMock);
$listener->postRemove($eventArgsMock);
}
+ public function testObjectWithNonStandardIdentifierDeletedOnRemove()
+ {
+ $persisterMock = $this->getMockBuilder('FOQ\ElasticaBundle\Persister\ObjectPersisterInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $eventArgsMock = $this->getMockBuilder('Doctrine\ODM\MongoDB\Event\LifecycleEventArgs')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $documentManagerMock = $this->getMockBuilder('Doctrine\ODM\MongoDB\DocumentManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $metadataMock = $this->getMockBuilder('Doctrine\ODM\MongoDB\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectName = 'FOQ\ElasticaBundle\Tests\Doctrine\MongoDB\Document';
+ $document = new Document();
+ $documentIdentifier = 826;
+ $identifierField = 'identifier';
+
+ $eventArgsMock->expects($this->any())
+ ->method('getDocument')
+ ->will($this->returnValue($document));
+
+ $eventArgsMock->expects($this->any())
+ ->method('getDocumentManager')
+ ->will($this->returnValue($documentManagerMock));
+
+ $documentManagerMock->expects($this->any())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadataMock));
+
+ $metadataMock->expects($this->any())
+ ->method('getFieldValue')
+ ->with($this->equalTo($document), $this->equalTo($identifierField))
+ ->will($this->returnValue($documentIdentifier));
+
+ $persisterMock->expects($this->once())
+ ->method('deleteById')
+ ->with($this->equalTo($documentIdentifier));
+
+ $listener = new Listener($persisterMock, $objectName, array(), 'identifier');
+ $listener->preRemove($eventArgsMock);
+ $listener->postRemove($eventArgsMock);
+ }
}
diff --git a/Tests/Doctrine/ORM/ListenerTest.php b/Tests/Doctrine/ORM/ListenerTest.php
index ac733f7..9a632c3 100644
--- a/Tests/Doctrine/ORM/ListenerTest.php
+++ b/Tests/Doctrine/ORM/ListenerTest.php
@@ -11,7 +11,6 @@ class Entity{}
*/
class ListenerTest extends \PHPUnit_Framework_TestCase
{
-
public function testObjectInsertedOnPersist()
{
$persisterMock = $this->getMockBuilder('FOQ\ElasticaBundle\Persister\ObjectPersisterInterface')
@@ -33,7 +32,7 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->method('insertOne')
->with($this->equalTo($entity));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $listener = new Listener($persisterMock, $objectName, array());
$listener->postPersist($eventArgsMock);
}
@@ -58,7 +57,7 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->method('replaceOne')
->with($this->equalTo($entity));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $listener = new Listener($persisterMock, $objectName, array());
$listener->postUpdate($eventArgsMock);
}
@@ -72,19 +71,90 @@ class ListenerTest extends \PHPUnit_Framework_TestCase
->disableOriginalConstructor()
->getMock();
+ $entityManagerMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $metadataMock = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+
$objectName = 'FOQ\ElasticaBundle\Tests\Doctrine\ORM\Entity';
$entity = new Entity;
+ $entityId = 21;
- $eventArgsMock->expects($this->once())
+ $eventArgsMock->expects($this->any())
->method('getEntity')
->will($this->returnValue($entity));
- $persisterMock->expects($this->once())
- ->method('deleteOne')
- ->with($this->equalTo($entity));
+ $eventArgsMock->expects($this->any())
+ ->method('getEntityManager')
+ ->will($this->returnValue($entityManagerMock));
- $listener = new Listener($persisterMock, $objectName, array(), null);
+ $entityManagerMock->expects($this->any())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadataMock));
+
+ $metadataMock->expects($this->any())
+ ->method('getFieldValue')
+ ->with($this->equalTo($entity), $this->equalTo('id'))
+ ->will($this->returnValue($entityId));
+
+ $persisterMock->expects($this->once())
+ ->method('deleteById')
+ ->with($this->equalTo($entityId));
+
+ $listener = new Listener($persisterMock, $objectName, array());
+ $listener->preRemove($eventArgsMock);
$listener->postRemove($eventArgsMock);
}
+ public function testObjectWithNonStandardIdentifierDeletedOnRemove()
+ {
+ $persisterMock = $this->getMockBuilder('FOQ\ElasticaBundle\Persister\ObjectPersisterInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $eventArgsMock = $this->getMockBuilder('Doctrine\ORM\Event\LifecycleEventArgs')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityManagerMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $metadataMock = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectName = 'FOQ\ElasticaBundle\Tests\Doctrine\ORM\Entity';
+ $entity = new Entity;
+ $entityIdentifier = 924;
+ $identifierField = 'identifier';
+
+ $eventArgsMock->expects($this->any())
+ ->method('getEntity')
+ ->will($this->returnValue($entity));
+
+ $eventArgsMock->expects($this->any())
+ ->method('getEntityManager')
+ ->will($this->returnValue($entityManagerMock));
+
+ $entityManagerMock->expects($this->any())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadataMock));
+
+ $metadataMock->expects($this->any())
+ ->method('getFieldValue')
+ ->with($this->equalTo($entity), $this->equalTo($identifierField))
+ ->will($this->returnValue($entityIdentifier));
+
+ $persisterMock->expects($this->once())
+ ->method('deleteById')
+ ->with($this->equalTo($entityIdentifier));
+
+ $listener = new Listener($persisterMock, $objectName, array(), $identifierField);
+ $listener->preRemove($eventArgsMock);
+ $listener->postRemove($eventArgsMock);
+ }
}