Example #1
0
 /**
  * {@inheritDoc}
  */
 public function apply(PropertyMetadata $propertyMetadata, array $collectedValues, MergeContext $context)
 {
     $reflectionProperty = $propertyMetadata->reflection;
     $mergeableObjectCollection = $context->getPropertyAccessor()->getValue($reflectionProperty, $context->getMergeTo());
     foreach ($collectedValues['missing'] as $missingValue) {
         $mergeableObjectCollection[] = $missingValue;
     }
     $context->getPropertyAccessor()->setValue($reflectionProperty, $context->getMergeTo(), $mergeableObjectCollection);
 }
Example #2
0
 /**
  * Merges an object property.
  *
  * @param PropertyMetadata $property Metadata of the property
  * @param MergeContext     $context  The current mergingcontext
  */
 public function mergeObject(PropertyMetadata $property, MergeContext $context)
 {
     $reflectionProperty = $property->reflection;
     $leftValue = $context->getPropertyAccessor()->getValue($reflectionProperty, $context->getMergeFrom());
     $rightValue = $context->getPropertyAccessor()->getValue($reflectionProperty, $context->getMergeTo());
     if (null === $rightValue) {
         $context->getPropertyAccessor()->setValue($reflectionProperty, $context->getMergeTo(), $leftValue);
     } else {
         $context->getGraphWalker()->accept($leftValue, $rightValue);
     }
 }
Example #3
0
 /**
  * {@inheritDoc}
  *
  * @TODO This mehtod needs to be refactored.
  */
 public function merge(PropertyMetadata $propertyMetadata, MergeContext $context)
 {
     $innerType = $propertyMetadata->innerType;
     $reflectionProperty = $propertyMetadata->reflection;
     if (!$innerType) {
         throw new MergeException('You must provide an inner type.');
     }
     $reflectionClass = new \ReflectionClass($innerType);
     $innerClassMetadata = $context->getGraphWalker()->getMetadataFactory()->getMetadataForClass($innerType);
     $objectIdentifier = $innerClassMetadata->objectIdentifier;
     if ($objectIdentifier === null) {
         throw new MergeException('You must provide at least one identifier field.');
     }
     $sourceCollection = $reflectionProperty->getValue($context->getMergeFrom());
     $targetCollection = $reflectionProperty->getValue($context->getMergeTo());
     if (!$sourceCollection instanceof \Traversable && !is_array($sourceCollection)) {
         return;
     }
     if (!$targetCollection instanceof \Traversable && !is_array($targetCollection)) {
         return;
     }
     $collectedValues = array('missing' => array(), 'removed' => array());
     foreach ($sourceCollection as $sourceItem) {
         foreach ($targetCollection as $targetItem) {
             if ($this->isMergeable($objectIdentifier, $reflectionClass, $sourceItem, $targetItem)) {
                 $context->getGraphWalker()->accept($sourceItem, $targetItem);
                 continue 2;
             }
         }
         array_push($collectedValues['missing'], $sourceItem);
     }
     $this->applyCollectionMergeStrategy($propertyMetadata, $collectedValues, $context);
 }
Example #4
0
 /**
  * Walks over the objectproperties which are marked as mergeable.
  *
  * @param object        $mergeFrom
  * @param object        $mergeTo
  * @param ClassMetadata $classMetadata
  *
  * @throws \Exception
  */
 protected function walkProperties($mergeFrom, $mergeTo, $classMetadata)
 {
     // Preventing the object to be visited again.
     $this->visitedObjects[spl_object_hash($mergeFrom)] = true;
     // Preparing a new MergeContext.
     $mergeContext = new MergeContext($classMetadata, $this, $mergeFrom, $mergeTo);
     // Dispatching the premerge event.
     $this->eventDispatcher->dispatch(Events::PRE_MERGE, new MergeEvent(MergeEvent::TYPE_PRE, $mergeContext));
     foreach ($classMetadata->propertyMetadata as $comparableProperty) {
         /** @var PropertyMetadata $comparableProperty */
         if ($comparableProperty->ignoreNullValue) {
             $currentValue = $mergeContext->getPropertyAccessor()->getValue($comparableProperty->reflection, $mergeContext->getMergeFrom());
             if (null === $currentValue) {
                 continue;
             }
         }
         switch ($comparableProperty->type) {
             case 'string':
             case 'object':
             case 'boolean':
             case 'mixed':
                 // calls a type specified merge method on the visitor.
                 $this->visitor->{'merge' . ucfirst($comparableProperty->type)}($comparableProperty, $mergeContext);
                 break;
             default:
                 // If the type is not one of the default types, try to merge this property by a handler.
                 try {
                     $this->visitor->mergeByHandler($comparableProperty, $mergeContext);
                 } catch (\Exception $e) {
                     throw $e;
                 }
                 break;
         }
     }
     // Dispatching the postmerge event.
     $this->eventDispatcher->dispatch(Events::POST_MERGE, new MergeEvent(MergeEvent::TYPE_POST, $mergeContext));
 }