‪TYPO3CMS  9.5
ObjectConverter.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
21 {
26 
31 
35  protected ‪$sourceTypes = ['array'];
36 
40  protected ‪$targetType = 'object';
41 
45  protected ‪$priority = 10;
46 
51 
56 
60  public function ‪injectObjectContainer(\‪TYPO3\CMS\‪Extbase\Object\Container\Container ‪$objectContainer)
61  {
62  $this->objectContainer = ‪$objectContainer;
63  }
64 
68  public function ‪injectReflectionService(\‪TYPO3\CMS\‪Extbase\Reflection\ReflectionService ‪$reflectionService)
69  {
70  $this->reflectionService = ‪$reflectionService;
71  }
72 
81  public function ‪canConvertFrom($source, ‪$targetType)
82  {
83  return !is_subclass_of(‪$targetType, \‪TYPO3\CMS\‪Extbase\DomainObject\AbstractDomainObject::class);
84  }
85 
93  public function ‪getSourceChildPropertiesToBeConverted($source)
94  {
95  if (isset($source['__type'])) {
96  unset($source['__type']);
97  }
98  return $source;
99  }
100 
111  public function ‪getTypeOfChildProperty(‪$targetType, $propertyName, \‪TYPO3\CMS\‪Extbase\Property\PropertyMappingConfigurationInterface $configuration)
112  {
113  $configuredTargetType = $configuration->getConfigurationFor($propertyName)->getConfigurationValue(\‪TYPO3\CMS\‪Extbase\Property\TypeConverter\ObjectConverter::class, self::CONFIGURATION_TARGET_TYPE);
114  if ($configuredTargetType !== null) {
115  return $configuredTargetType;
116  }
117 
118  $specificTargetType = $this->objectContainer->getImplementationClassName(‪$targetType);
119  $classSchema = $this->reflectionService->getClassSchema($specificTargetType);
120 
121  if ($classSchema->hasMethod(\‪TYPO3\CMS\‪Extbase\Reflection\ObjectAccess::buildSetterMethodName($propertyName))) {
122  $methodParameters = $classSchema->getMethod(\‪TYPO3\CMS\‪Extbase\Reflection\ObjectAccess::buildSetterMethodName($propertyName))['params'] ?? [];
123  $methodParameter = current($methodParameters);
124  if (!isset($methodParameter['type'])) {
125  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('Setter for property "' . $propertyName . '" had no type hint or documentation in target object of type "' . $specificTargetType . '".', 1303379158);
126  }
127  return $methodParameter['type'];
128  }
129  $method = $classSchema->getMethod('__construct');
130  if (empty($method)) {
131  $exceptionMessage = sprintf('Type of child property "%s" of class "%s" could not be '
132  . 'derived from constructor arguments as said class does not have a constructor '
133  . 'defined.', $propertyName, $specificTargetType);
134  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException($exceptionMessage, 1582385098);
135  }
136 
137  $methodParameters = $classSchema->getMethod('__construct')['params'] ?? [];
138  if (!isset($methodParameters[$propertyName])) {
139  $exceptionMessage = sprintf('Type of child property "%1$s" of class "%2$s" could not be '
140  . 'derived from constructor arguments as the constructor of said class does not '
141  . 'have a parameter with property name "%1$s".', $propertyName, $specificTargetType);
142  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException($exceptionMessage, 1303379126);
143  }
144 
145  $parameterType = $methodParameters[$propertyName]['type'];
146  if ($parameterType === null) {
147  $exceptionMessage = sprintf('Type of child property "%1$s" of class "%2$s" could not be '
148  . 'derived from constructor argument "%1$s". This usually happens if the argument '
149  . 'misses a type hint.', $propertyName, $specificTargetType);
150  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException($exceptionMessage, 1582385619);
151  }
152 
153  return $parameterType;
154  }
155 
169  public function ‪convertFrom($source, ‪$targetType, array $convertedChildProperties = [], \‪TYPO3\CMS\‪Extbase\Property\PropertyMappingConfigurationInterface $configuration = null)
170  {
171  $object = $this->‪buildObject($convertedChildProperties, ‪$targetType);
172  foreach ($convertedChildProperties as $propertyName => $propertyValue) {
173  $result = ‪\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($object, $propertyName, $propertyValue);
174  if ($result === false) {
175  $exceptionMessage = sprintf(
176  '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.',
177  $propertyName,
178  (is_object($propertyValue) ? get_class($propertyValue) : gettype($propertyValue)),
180  );
181  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException($exceptionMessage, 1304538165);
182  }
183  }
184 
185  return $object;
186  }
187 
200  public function ‪getTargetTypeForSource($source, $originalTargetType, \‪TYPO3\CMS\‪Extbase\Property\PropertyMappingConfigurationInterface $configuration = null)
201  {
202  ‪$targetType = $originalTargetType;
203 
204  if (is_array($source) && array_key_exists('__type', $source)) {
205  ‪$targetType = $source['__type'];
206 
207  if ($configuration === null) {
208  throw new \InvalidArgumentException('A property mapping configuration must be given, not NULL.', 1326277369);
209  }
210  if ($configuration->getConfigurationValue(\‪TYPO3\CMS\‪Extbase\Property\TypeConverter\ObjectConverter::class, self::CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED) !== true) {
211  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidPropertyMappingConfigurationException('Override of target type not allowed. To enable this, you need to set the PropertyMappingConfiguration Value "CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED" to TRUE.', 1317050430);
212  }
213 
214  if (‪$targetType !== $originalTargetType && is_a(‪$targetType, $originalTargetType, true) === false) {
215  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidDataTypeException('The given type "' . ‪$targetType . '" is not a subtype of "' . $originalTargetType . '".', 1317048056);
216  }
217  }
218 
219  return ‪$targetType;
220  }
221 
232  protected function ‪buildObject(array &$possibleConstructorArgumentValues, $objectType)
233  {
234  $specificObjectType = $this->objectContainer->getImplementationClassName($objectType);
235  $classSchema = $this->reflectionService->getClassSchema($specificObjectType);
236 
237  if ($classSchema->hasConstructor()) {
238  $constructorSignature = $classSchema->getMethod('__construct')['params'] ?? [];
239  $constructorArguments = [];
240  foreach ($constructorSignature as $constructorArgumentName => $constructorArgumentInformation) {
241  if (array_key_exists($constructorArgumentName, $possibleConstructorArgumentValues)) {
242  $constructorArguments[] = $possibleConstructorArgumentValues[$constructorArgumentName];
243  unset($possibleConstructorArgumentValues[$constructorArgumentName]);
244  } elseif ($constructorArgumentInformation['optional'] === true) {
245  $constructorArguments[] = $constructorArgumentInformation['defaultValue'];
246  } else {
247  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872);
248  }
249  }
250  return call_user_func_array([$this->objectManager, 'get'], array_merge([$objectType], $constructorArguments));
251  }
252  return $this->objectManager->get($objectType);
253  }
254 }
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\CONFIGURATION_TARGET_TYPE
‪const CONFIGURATION_TARGET_TYPE
Definition: ObjectConverter.php:25
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\$sourceTypes
‪array $sourceTypes
Definition: ObjectConverter.php:34
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\$objectContainer
‪TYPO3 CMS Extbase Object Container Container $objectContainer
Definition: ObjectConverter.php:46
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\$reflectionService
‪TYPO3 CMS Extbase Reflection ReflectionService $reflectionService
Definition: ObjectConverter.php:50
‪TYPO3\CMS\Extbase\Annotation
Definition: IgnoreValidation.php:4
‪TYPO3\CMS\Extbase\Reflection\ObjectAccess\setProperty
‪static bool setProperty(&$subject, $propertyName, $propertyValue, $forceDirectAccess=false)
Definition: ObjectAccess.php:176
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\canConvertFrom
‪bool canConvertFrom($source, $targetType)
Definition: ObjectConverter.php:76
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\buildObject
‪object buildObject(array &$possibleConstructorArgumentValues, $objectType)
Definition: ObjectConverter.php:227
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\$targetType
‪string $targetType
Definition: ObjectConverter.php:38
‪TYPO3
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\getTypeOfChildProperty
‪string getTypeOfChildProperty($targetType, $propertyName, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration)
Definition: ObjectConverter.php:106
‪TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface
Definition: PropertyMappingConfigurationInterface.php:21
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED
‪const CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED
Definition: ObjectConverter.php:30
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\getTargetTypeForSource
‪string getTargetTypeForSource($source, $originalTargetType, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration=null)
Definition: ObjectConverter.php:195
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\injectObjectContainer
‪injectObjectContainer(\TYPO3\CMS\Extbase\Object\Container\Container $objectContainer)
Definition: ObjectConverter.php:55
‪TYPO3\CMS\Extbase\Property\TypeConverter
Definition: AbstractFileCollectionConverter.php:2
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\injectReflectionService
‪injectReflectionService(\TYPO3\CMS\Extbase\Reflection\ReflectionService $reflectionService)
Definition: ObjectConverter.php:63
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\getSourceChildPropertiesToBeConverted
‪array getSourceChildPropertiesToBeConverted($source)
Definition: ObjectConverter.php:88
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter
Definition: ObjectConverter.php:21
‪TYPO3\CMS\Extbase\Property\TypeConverter\AbstractTypeConverter
Definition: AbstractTypeConverter.php:26
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\convertFrom
‪object convertFrom($source, $targetType, array $convertedChildProperties=[], \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration=null)
Definition: ObjectConverter.php:164
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\$priority
‪int $priority
Definition: ObjectConverter.php:42