Skip to content

Commit

Permalink
Merge pull request #4 from ntidev/master
Browse files Browse the repository at this point in the history
Updating Master Branch
  • Loading branch information
ealcantara22 authored Jul 26, 2018
2 parents ec5b6ac + ed99513 commit d234904
Show file tree
Hide file tree
Showing 16 changed files with 606 additions and 150 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# Backup entities generated with doctrine:generate:entities command
**/Entity/*~

./.idea
13 changes: 13 additions & 0 deletions Annotations/SyncEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace NTI\SyncBundle\Annotations;
use Doctrine\Common\Annotations\Annotation\Required;

/**
* Class SyncParent
* @package NTI\SyncBundle\Annotations
* @Annotation
*/
class SyncEntity {

}
17 changes: 17 additions & 0 deletions Annotations/SyncParent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace NTI\SyncBundle\Annotations;
use Doctrine\Common\Annotations\Annotation\Required;

/**
* Class SyncParent
* @package NTI\SyncBundle\Annotations
* @Annotation
*/
class SyncParent {
/**
* @var string
* @Required()
*/
public $getter;
}
6 changes: 4 additions & 2 deletions Controller/SyncController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ public function pullAction(Request $request) {
$mappings = (isset($data["mappings"])) ? $data["mappings"] : array();
}

$changes = $this->get('nti.sync')->getFromMappings($mappings);
$resultData = $this->get('nti.sync')->getFromMappings($mappings);

return new JsonResponse($changes, 200);
$resultData = json_decode($this->container->get('jms_serializer')->serialize($resultData, 'json'), true);

return new JsonResponse($resultData, 200);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion Entity/SyncFailedItemState.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class SyncFailedItemState {
/**
* @var string
*
* @ORM\Column(name="errors", columnDefinition="TEXT", length=65535, nullable=true)
* @ORM\Column(name="errors", type="text", nullable=true)
*/
private $errors;

Expand Down
2 changes: 1 addition & 1 deletion Entity/SyncMapping.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class SyncMapping
/**
* @var string
*
* @ORM\Column(name="sync_service", type="string", length=255, nullable=false)
* @ORM\Column(name="sync_service", type="string", length=255, nullable=true)
*/
private $syncService;

Expand Down
1 change: 1 addition & 0 deletions Entity/SyncState.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class SyncState
{
const REAL_LAST_TIMESTAMP = "_real_last_timestamp";
const TOTAL_COUNT = "_total_count";
/**
* @var int
*
Expand Down
67 changes: 0 additions & 67 deletions EventListener/DoctrineEventSubscriber.php

This file was deleted.

131 changes: 131 additions & 0 deletions EventSubscriber/DoctrineEventSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

namespace NTI\SyncBundle\EventSubscriber;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\EventSubscriber;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\UnitOfWork;
use NTI\SyncBundle\Annotations\SyncEntity;
use NTI\SyncBundle\Annotations\SyncParent;
use NTI\SyncBundle\Entity\SyncMapping;
use NTI\SyncBundle\Entity\SyncState;
use Symfony\Component\DependencyInjection\ContainerInterface;

class DoctrineEventSubscriber implements EventSubscriber
{
private $container;
private $syncService;

public function __construct(ContainerInterface $container)
{
$this->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, true);
$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, true);
$this->container->get('nti.sync')->addToDeleteSyncState(ClassUtils::getClass($entity), $entity->getId());
}
}

}

private function processEntity(EntityManagerInterface $em, $entity, $deleting = false)
{

$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" => ClassUtils::getClass($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);
if($uow->getEntityState($syncState) == UnitOfWork::STATE_MANAGED) {
if($syncState->getId()) {
$uow->recomputeSingleEntityChangeSet($em->getClassMetadata(SyncState::class), $syncState);
} else {
$uow->computeChangeSet($em->getClassMetadata(SyncState::class), $syncState);
}
}
}

// Check if this class itself has a lastTimestamp
if(!$deleting && method_exists($entity, 'setLastTimestamp')) {
$entity->setLastTimestamp($timestamp);
$uow->recomputeSingleEntityChangeSet($em->getClassMetadata(ClassUtils::getClass($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();
// 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);
}
}
}
}
19 changes: 8 additions & 11 deletions Interfaces/SyncRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,29 @@

namespace NTI\SyncBundle\Interfaces;

use NTI\SyncBundle\Models\SyncPullRequestData;
use NTI\SyncBundle\Models\SyncPullResponseData;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Interface SyncRepositoryInterface
* @package NTI\SyncBundle\Interfaces
*/
interface SyncRepositoryInterface {

/**
* This function should return a plain array containing the results to be sent to the client
* This function should return an instance of SyncPullResponseData containing the results to be sent to the client
* when a sync is requested. The container is also passed as a parameter in order to give additional
* flexibility to the repository when making decision on what to show to the client. For example, if the user
* making the request only has access to a portion of the data, this can be handled via the container in this method
* of the repository.
*
* The resulting structure should be the following:
*
* array(
* "data" => (array of objects),
* SyncState::REAL_LAST_TIMESTAMP => (last updated_on date from the array of objects),
* )
* The resulting structure should be an instance of SyncPullRequestData
*
*
* @param $timestamp
* @param ContainerInterface $container
* @param array $serializationGroups
* @return mixed
* @param SyncPullRequestData $requestData
* @return SyncPullResponseData
*/
public function findFromTimestamp($timestamp, ContainerInterface $container, $serializationGroups = array());
public function findFromTimestamp(ContainerInterface $container, SyncPullRequestData $requestData);
}
Loading

0 comments on commit d234904

Please sign in to comment.