TYPO3 CMS  TYPO3_6-2
ObjectConverter.php
Go to the documentation of this file.
1 <?php
3 
4 /* *
5  * This script belongs to the Extbase framework *
6  * *
7  * It is free software; you can redistribute it and/or modify it under *
8  * the terms of the GNU Lesser General Public License as published by the *
9  * Free Software Foundation, either version 3 of the License, or (at your *
10  * option) any later version. *
11  * *
12  * This script is distributed in the hope that it will be useful, but *
13  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14  * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
15  * General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU Lesser General Public *
18  * License along with the script. *
19  * If not, see http://www.gnu.org/licenses/lgpl.html *
20  * *
21  * The TYPO3 project - inspiring people to share! *
22  * */
29 
34 
39 
43  protected $sourceTypes = array('array');
44 
48  protected $targetType = 'object';
49 
53  protected $priority = 0;
54 
59  protected $objectManager;
60 
65  protected $objectContainer;
66 
71  protected $reflectionService;
72 
80  public function canConvertFrom($source, $targetType) {
81  return !is_subclass_of($targetType, 'TYPO3\\CMS\\Extbase\\DomainObject\\AbstractDomainObject');
82  }
83 
90  public function getSourceChildPropertiesToBeConverted($source) {
91  if (isset($source['__type'])) {
92  unset($source['__type']);
93  }
94  return $source;
95  }
96 
106  public function getTypeOfChildProperty($targetType, $propertyName, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration) {
107  $configuredTargetType = $configuration->getConfigurationFor($propertyName)->getConfigurationValue('TYPO3\\CMS\\Extbase\\Property\\TypeConverter\\ObjectConverter', self::CONFIGURATION_TARGET_TYPE);
108  if ($configuredTargetType !== NULL) {
109  return $configuredTargetType;
110  }
111 
112  $specificTargetType = $this->objectContainer->getImplementationClassName($targetType);
113  if ($this->reflectionService->hasMethod($specificTargetType, \TYPO3\CMS\Extbase\Reflection\ObjectAccess::buildSetterMethodName($propertyName))) {
114  $methodParameters = $this->reflectionService->getMethodParameters($specificTargetType, \TYPO3\CMS\Extbase\Reflection\ObjectAccess::buildSetterMethodName($propertyName));
115  $methodParameter = current($methodParameters);
116  if (!isset($methodParameter['type'])) {
117  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);
118  } else {
119  return $methodParameter['type'];
120  }
121  } else {
122  $methodParameters = $this->reflectionService->getMethodParameters($specificTargetType, '__construct');
123  if (isset($methodParameters[$propertyName]) && isset($methodParameters[$propertyName]['type'])) {
124  return $methodParameters[$propertyName]['type'];
125  } else {
126  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('Property "' . $propertyName . '" had no setter or constructor argument in target object of type "' . $specificTargetType . '".', 1303379126);
127  }
128  }
129  }
130 
143  public function convertFrom($source, $targetType, array $convertedChildProperties = array(), \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration = NULL) {
144  $object = $this->buildObject($convertedChildProperties, $targetType);
145  foreach ($convertedChildProperties as $propertyName => $propertyValue) {
146  $result = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($object, $propertyName, $propertyValue);
147  if ($result === FALSE) {
148  $exceptionMessage = sprintf(
149  '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.',
150  $propertyName,
151  (is_object($propertyValue) ? get_class($propertyValue) : gettype($propertyValue)),
153  );
154  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException($exceptionMessage, 1304538165);
155  }
156  }
157 
158  return $object;
159  }
160 
172  public function getTargetTypeForSource($source, $originalTargetType, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration = NULL) {
173  $targetType = $originalTargetType;
174 
175  if (is_array($source) && array_key_exists('__type', $source)) {
176  $targetType = $source['__type'];
177 
178  if ($configuration === NULL) {
179  throw new \InvalidArgumentException('A property mapping configuration must be given, not NULL.', 1326277369);
180  }
181  if ($configuration->getConfigurationValue('TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter', self::CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED) !== TRUE) {
182  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);
183  }
184 
185  // FIXME: The following check and the checkInheritanceChainWithoutIsA() method should be removed if we raise the PHP requirement to 5.3.9 or higher
186  if (version_compare(phpversion(), '5.3.8', '>')) {
187  if ($targetType !== $originalTargetType && is_a($targetType, $originalTargetType, TRUE) === FALSE) {
188  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidDataTypeException('The given type "' . $targetType . '" is not a subtype of "' . $originalTargetType . '".', 1317048056);
189  }
190  } else {
191  $targetType = $this->checkInheritanceChainWithoutIsA($targetType, $originalTargetType);
192  }
193  }
194 
195  return $targetType;
196  }
197 
208  protected function buildObject(array &$possibleConstructorArgumentValues, $objectType) {
209  $specificObjectType = $this->objectContainer->getImplementationClassName($objectType);
210  if ($this->reflectionService->hasMethod($specificObjectType, '__construct')) {
211  $constructorSignature = $this->reflectionService->getMethodParameters($specificObjectType, '__construct');
212  $constructorArguments = array();
213  foreach ($constructorSignature as $constructorArgumentName => $constructorArgumentInformation) {
214  if (array_key_exists($constructorArgumentName, $possibleConstructorArgumentValues)) {
215  $constructorArguments[] = $possibleConstructorArgumentValues[$constructorArgumentName];
216  unset($possibleConstructorArgumentValues[$constructorArgumentName]);
217  } elseif ($constructorArgumentInformation['optional'] === TRUE) {
218  $constructorArguments[] = $constructorArgumentInformation['defaultValue'];
219  } else {
220  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('Missing constructor argument "' . $constructorArgumentName . '" for object of type "' . $objectType . '".', 1268734872);
221  }
222  }
223  return call_user_func_array(array($this->objectManager, 'get'), array_merge(array($objectType), $constructorArguments));
224  } else {
225  return $this->objectManager->get($objectType);
226  }
227  }
228 
238  protected function checkInheritanceChainWithoutIsA($targetType, $originalTargetType) {
239  $targetTypeToCompare = $targetType;
240  do {
241  if ($targetTypeToCompare === $originalTargetType) {
242  return $targetType;
243  }
244  } while ($targetTypeToCompare = get_parent_class($targetTypeToCompare));
245 
246  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidDataTypeException('The given type "' . $targetType . '" is not a subtype of "' . $originalTargetType . '".', 1360928582);
247  }
248 
249 }
convertFrom($source, $targetType, array $convertedChildProperties=array(), \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration=NULL)
getTargetTypeForSource($source, $originalTargetType, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration=NULL)
checkInheritanceChainWithoutIsA($targetType, $originalTargetType)
getTypeOfChildProperty($targetType, $propertyName, \TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface $configuration)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static setProperty(&$subject, $propertyName, $propertyValue, $forceDirectAccess=FALSE)
buildObject(array &$possibleConstructorArgumentValues, $objectType)