config = array_merge(array( 'identifier' => 'id', ), $config); $this->indexable = $indexable; $this->objectPersister = $objectPersister; $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); if ($logger && $this->objectPersister instanceof ObjectPersister) { $this->objectPersister->setLogger($logger); } } /** * Looks for new objects that should be indexed. * * @param LifecycleEventArgs $eventArgs */ public function postPersist(LifecycleEventArgs $eventArgs) { $entity = $eventArgs->getObject(); if ($this->objectPersister->handlesObject($entity) && $this->isObjectIndexable($entity)) { $this->scheduledForInsertion[] = $entity; } } /** * Looks for objects being updated that should be indexed or removed from the index. * * @param LifecycleEventArgs $eventArgs */ public function postUpdate(LifecycleEventArgs $eventArgs) { $entity = $eventArgs->getObject(); if ($this->objectPersister->handlesObject($entity)) { if ($this->isObjectIndexable($entity)) { $this->scheduledForUpdate[] = $entity; } else { // Delete if no longer indexable $this->scheduleForDeletion($entity); } } } /** * Delete objects preRemove instead of postRemove so that we have access to the id. Because this is called * preRemove, first check that the entity is managed by Doctrine. * * @param LifecycleEventArgs $eventArgs */ public function preRemove(LifecycleEventArgs $eventArgs) { $entity = $eventArgs->getObject(); if ($this->objectPersister->handlesObject($entity)) { $this->scheduleForDeletion($entity); } } /** * Persist scheduled objects to ElasticSearch * After persisting, clear the scheduled queue to prevent multiple data updates when using multiple flush calls. */ private function persistScheduled() { if (count($this->scheduledForInsertion)) { $this->objectPersister->insertMany($this->scheduledForInsertion); $this->scheduledForInsertion = array(); } if (count($this->scheduledForUpdate)) { $this->objectPersister->replaceMany($this->scheduledForUpdate); $this->scheduledForUpdate = array(); } if (count($this->scheduledForDeletion)) { $this->objectPersister->deleteManyByIdentifiers($this->scheduledForDeletion); $this->scheduledForDeletion = array(); } } /** * Iterate through scheduled actions before flushing to emulate 2.x behavior. * Note that the ElasticSearch index will fall out of sync with the source * data in the event of a crash during flush. * * This method is only called in legacy configurations of the listener. * * @deprecated This method should only be called in applications that depend * on the behaviour that entities are indexed regardless of if a * flush is successful. */ public function preFlush() { $this->persistScheduled(); } /** * Iterating through scheduled actions *after* flushing ensures that the * ElasticSearch index will be affected only if the query is successful. */ public function postFlush() { $this->persistScheduled(); } /** * Record the specified identifier to delete. Do not need to entire object. * * @param object $object */ private function scheduleForDeletion($object) { if ($identifierValue = $this->propertyAccessor->getValue($object, $this->config['identifier'])) { $this->scheduledForDeletion[] = $identifierValue; } } /** * Checks if the object is indexable or not. * * @param object $object * * @return bool */ private function isObjectIndexable($object) { return $this->indexable->isObjectIndexable( $this->config['indexName'], $this->config['typeName'], $object ); } }