diff --git a/Annotations/SyncEntity.php b/Annotations/SyncEntity.php new file mode 100755 index 0000000..1786a19 --- /dev/null +++ b/Annotations/SyncEntity.php @@ -0,0 +1,13 @@ +container = $container; - $this->syncService = $this->container->get('nti.sync'); - } - - public function getSubscribedEvents() - { - return array( - 'onFlush', - 'preRemove', - ); - } - - public function onFlush(OnFlushEventArgs $args) - { - - $em = $args->getEntityManager(); - $uow = $em->getUnitOfWork(); - - foreach ($uow->getScheduledEntityUpdates() as $entity) { - // Check if the entity should be synchronized - if (!($entity instanceof SyncEntityInterface)) { - continue; - } - $this->processEntity($em, $entity); - } - - } - - public function preRemove(LifecycleEventArgs $args) - { - - } - - private function processEntity(EntityManagerInterface $em, $entity) - { - $uow = $em->getUnitOfWork(); - - $timestamp = time(); - - // Check if this class itself has a lastTimestamp - if(method_exists($entity, 'setLastTimestamp')) { - $entity->setLastTimestamp($timestamp); - $uow->computeChangeSet($em->getClassMetadata(get_class($entity)), $entity); - } - - // Check if there are any relationships that should notified - $annotationReader = new AnnotationReader(); - $reflection = new \ReflectionClass(get_class($entity)); - - /** @var \ReflectionProperty $property */ - foreach ($reflection->getProperties() as $property) { - /** @var SyncParent $annotation */ - if (null !== ($annotation = $annotationReader->getPropertyAnnotation($property, SyncParent::class))) { - $getter = $annotation->getter; - $parent = $entity->$getter(); - if($parent instanceof SyncEntityInterface) { - $this->processEntity($em, $parent); - } - } - } - } -} diff --git a/EventSubscriber/DoctrineEventSubscriber.php b/EventSubscriber/DoctrineEventSubscriber.php new file mode 100755 index 0000000..0f58359 --- /dev/null +++ b/EventSubscriber/DoctrineEventSubscriber.php @@ -0,0 +1,125 @@ +container = $container; + $this->syncService = $this->container->get('nti.sync'); + } + + public function getSubscribedEvents() + { + return array( + 'onFlush', + ); + } + + public function onFlush(OnFlushEventArgs $args) + { + + $em = $args->getEntityManager(); + $uow = $em->getUnitOfWork(); + + foreach ($uow->getScheduledEntityUpdates() as $entity) { + $this->processEntity($em, $entity); + } + + foreach ($uow->getScheduledEntityInsertions() as $entity) { + $this->processEntity($em, $entity); + } + + foreach ($uow->getScheduledEntityDeletions() as $entity) { + $this->processEntity($em, $entity); + $this->container->get('nti.sync')->addToDeleteSyncState(ClassUtils::getClass($entity), $entity->getId()); + } + + /** @var PersistentCollection $collectionUpdate */ + foreach ($uow->getScheduledCollectionUpdates() as $collectionUpdate) { + foreach($collectionUpdate as $entity) { + $this->processEntity($em, $entity); + } + } + + /** @var PersistentCollection $collectionDeletion */ + foreach($uow->getScheduledCollectionDeletions() as $collectionDeletion) { + foreach($collectionDeletion as $entity) { + $this->processEntity($em, $entity); + $this->container->get('nti.sync')->addToDeleteSyncState(ClassUtils::getClass($entity), $entity->getId()); + } + } + + } + + private function processEntity(EntityManagerInterface $em, $entity) + { + + $reflection = new \ReflectionClass(ClassUtils::getClass($entity)); + $annotationReader = new AnnotationReader(); + $syncEntityAnnotation = $annotationReader->getClassAnnotation($reflection, SyncEntity::class); + // Check if the entity should be synchronized + if (!$syncEntityAnnotation) { + return; + } + + $uow = $em->getUnitOfWork(); + $timestamp = time(); + + // Update the mapping's sync state if exists + $mapping = $em->getRepository(SyncMapping::class)->findOneBy(array("class" => get_class($entity))); + if($mapping) { + $syncState = $em->getRepository(SyncState::class)->findOneBy(array("mapping" => $mapping)); + if(!$syncState) { + $syncState = new SyncState(); + $syncState->setMapping($mapping); + $em->persist($syncState); + } + $syncState->setTimestamp($timestamp); + $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(SyncState::class), $syncState); + } + + // Check if this class itself has a lastTimestamp + if(method_exists($entity, 'setLastTimestamp')) { + $entity->setLastTimestamp($timestamp); + $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(get_class($entity)), $entity); + } + + // Notify relationships + /** @var \ReflectionProperty $property */ + foreach ($reflection->getProperties() as $property) { + + /** @var SyncParent $annotation */ + if (null !== ($annotation = $annotationReader->getPropertyAnnotation($property, SyncParent::class))) { + $getter = $annotation->getter; + $parent = $entity->$getter(); + dump($parent); + die; + // Using ClassUtils as $parent is actually a Proxy of the class + $reflrectionParent = new \ReflectionClass(ClassUtils::getClass($parent)); + $syncParentAnnotation = $annotationReader->getClassAnnotation($reflrectionParent, SyncEntity::class); + if(!$syncParentAnnotation) { + continue; + } + $this->processEntity($em, $parent); + } + } + } +} diff --git a/Interfaces/SyncEntityInterface.php b/Interfaces/SyncEntityInterface.php deleted file mode 100755 index 3b54861..0000000 --- a/Interfaces/SyncEntityInterface.php +++ /dev/null @@ -1,6 +0,0 @@ -em->getRepository(SyncDeleteState::class)->findFromTimestamp($mappingName, $timestamp); $newItems = $this->em->getRepository(SyncNewItemState::class)->findFromTimestampAndMapping($mappingName, $timestamp); - /** - * Failed Items Synchronization - */ - $failedItems = $this->em->getRepository('NTISyncBundle:SyncFailedItemState')->findFromTimestampAndMapping($mappingName, $timestamp); + $failedItems = $this->em->getRepository(SyncFailedItemState::class)->findFromTimestampAndMapping($mappingName, $timestamp); /** @var SyncRepositoryInterface $repository */ $repository = $this->em->getRepository($syncMapping->getClass()); @@ -88,30 +86,6 @@ public function getFromMappings($mappings) { return $changes; } - public function updateSyncState(EntityManagerInterface $em, $class, $timestamp) { - - $mapping = $em->getRepository(SyncMapping::class)->findOneBy(array("class" => $class)); - if(!$mapping) { - return; - } - - $syncState = $em->getRepository(SyncState::class)->findOneBy(array("mapping" => $mapping)); - - $uow = $em->getUnitOfWork(); - - if(!$syncState) { - $syncState = new SyncState(); - $syncState->setMapping($mapping); - $syncState->setTimestamp($timestamp); - $em->persist($syncState); - $uow->computeChangeSet($em->getClassMetadata(SyncState::class), $syncState); - } else { - $syncState->setTimestamp($timestamp); - $uow->recomputeSingleEntityChangeSet($em->getClassMetadata(SyncState::class), $syncState); - } - - } - /** * Create a new SyncDeleteState for the given class/id * @@ -122,6 +96,7 @@ public function addToDeleteSyncState($class, $id) { $this->em = $this->container->get('doctrine')->getManager(); + /** @var SyncMapping $mapping */ $mapping = $this->em->getRepository(SyncMapping::class)->findOneBy(array("class" => $class)); if(!$mapping) { return; @@ -133,12 +108,5 @@ public function addToDeleteSyncState($class, $id) { $deleteEntry->setTimestamp(time()); $this->em->persist($deleteEntry); - - try { - $this->em->flush(); - } catch (\Exception $ex) { - error_log("Unable to register deletion of object: " . $class . " with ID " . $id); - error_log($ex->getMessage()); - } } }