Neos\Flow\Property\TypeConverter\PersistentObjectConverter::convertFrom PHP Method

convertFrom() public method

Convert an object from $source to an entity or a value object.
public convertFrom ( mixed $source, string $targetType, array $convertedChildProperties = [], Neos\Flow\Property\PropertyMappingConfigurationInterface $configuration = null ) : object | Neos\Flow\Property\TypeConverter\Error\TargetNotFoundError
$source mixed
$targetType string
$convertedChildProperties array
$configuration Neos\Flow\Property\PropertyMappingConfigurationInterface
return object | Neos\Flow\Property\TypeConverter\Error\TargetNotFoundError the converted entity/value object or an instance of TargetNotFoundError if the object could not be resolved
    public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null)
    {
        if (is_array($source)) {
            if ($this->reflectionService->isClassAnnotatedWith($targetType, ValueObject::class)) {
                if (isset($source['__identity']) && count($source) > 1) {
                    // @TODO fix that in the URI building and transfer VOs as values instead as with their identities
                    // Unset identity for value objects to use constructor mapping, since the identity is determined from
                    // property values after construction
                    unset($source['__identity']);
                }
            }
            $object = $this->handleArrayData($source, $targetType, $convertedChildProperties, $configuration);
            if ($object instanceof TargetNotFoundError) {
                return $object;
            }
        } elseif (is_string($source)) {
            if ($source === '') {
                return null;
            }
            $object = $this->fetchObjectFromPersistence($source, $targetType);
            if ($object === null) {
                return new TargetNotFoundError(sprintf('Object of type "%s" with identity "%s" not found.', $targetType, $source), 1412283033);
            }
        } else {
            throw new \InvalidArgumentException('Only strings and arrays are accepted.', 1305630314);
        }
        $objectConstructorArguments = $this->getConstructorArgumentsForClass(TypeHandling::getTypeForValue($object));
        foreach ($convertedChildProperties as $propertyName => $propertyValue) {
            // We need to check for "immutable" constructor arguments that have no setter and remove them.
            if (isset($objectConstructorArguments[$propertyName]) && !ObjectAccess::isPropertySettable($object, $propertyName)) {
                $currentPropertyValue = ObjectAccess::getProperty($object, $propertyName);
                if ($currentPropertyValue === $propertyValue) {
                    continue;
                } else {
                    $exceptionMessage = sprintf('Property "%s" having a value of type "%s" could not be set in target object of type "%s". The property has no setter and is not equal to the value in the object, in that case it would have been skipped.', $propertyName, is_object($propertyValue) ? TypeHandling::getTypeForValue($propertyValue) : gettype($propertyValue), $targetType);
                    throw new InvalidTargetException($exceptionMessage, 1421498771);
                }
            }
            $result = ObjectAccess::setProperty($object, $propertyName, $propertyValue);
            if ($result === false) {
                $exceptionMessage = sprintf('Property "%s" having a value of type "%s" could not be set in target object of type "%s". Make sure that the property is accessible properly, for example via an appropriate setter method.', $propertyName, is_object($propertyValue) ? TypeHandling::getTypeForValue($propertyValue) : gettype($propertyValue), $targetType);
                throw new InvalidTargetException($exceptionMessage, 1297935345);
            }
        }
        return $object;
    }

Usage Example

 /**
  * Convert an object from $source to an \Neos\Media\Domain\Model\AssetInterface implementation
  *
  * @param mixed $source
  * @param string $targetType must implement 'Neos\Media\Domain\Model\AssetInterface'
  * @param array $convertedChildProperties
  * @param PropertyMappingConfigurationInterface $configuration
  * @return Error|AssetInterface The converted Asset, a Validation Error or NULL
  * @throws InvalidTargetException
  */
 public function convertFrom($source, $targetType, array $convertedChildProperties = array(), PropertyMappingConfigurationInterface $configuration = null)
 {
     $object = null;
     if (is_string($source) && $source !== '') {
         $source = array('__identity' => $source);
     }
     if (isset($convertedChildProperties['resource']) && $convertedChildProperties['resource'] instanceof PersistentResource) {
         $resource = $convertedChildProperties['resource'];
         if (isset($this->resourcesAlreadyConvertedToAssets[$resource->getSha1()])) {
             $object = $this->resourcesAlreadyConvertedToAssets[$resource->getSha1()];
         }
         // This is pretty late to override the targetType, but usually you want to determine the model type from the resource when a new resource was uploaded...
         $targetType = $this->applyModelMappingStrategy($targetType, $resource, $source);
     }
     if ($object === null) {
         if ($configuration !== null && $configuration->getConfigurationValue(self::class, self::CONFIGURATION_ONE_PER_RESOURCE) === true && isset($convertedChildProperties['resource'])) {
             $resource = $convertedChildProperties['resource'];
             $possibleAsset = $this->assetRepository->findOneByResourceSha1($resource->getSha1());
             if ($possibleAsset !== null) {
                 $this->resourceManager->deleteResource($resource);
                 return $possibleAsset;
             }
         }
         $object = parent::convertFrom($source, $targetType, $convertedChildProperties, $configuration);
     }
     if ($object instanceof AssetInterface) {
         $object = $this->applyTypeSpecificHandling($object, $source, $convertedChildProperties, $configuration);
         if ($object !== null) {
             $this->resourcesAlreadyConvertedToAssets[$object->getResource()->getSha1()] = $object;
             if (isset($resource) && $resource !== $object->getResource()) {
                 $this->resourceManager->deleteResource($resource);
             }
         }
     }
     return $object;
 }