TYPO3 CMS  TYPO3_6-2
Mapper.php
Go to the documentation of this file.
1 <?php
3 
40 
46  protected $mappingResults;
47 
52  protected $validatorResolver;
53 
58  protected $reflectionService;
59 
65 
70  protected $objectManager;
71 
76  protected $queryFactory;
77 
97  public function mapAndValidate(array $propertyNames, $source, $target, $optionalPropertyNames = array(), \TYPO3\CMS\Extbase\Validation\Validator\ObjectValidatorInterface $targetObjectValidator) {
98  $backupProperties = array();
99  $this->map($propertyNames, $source, $backupProperties, $optionalPropertyNames);
100  if ($this->mappingResults->hasErrors()) {
101  return FALSE;
102  }
103  $this->map($propertyNames, $source, $target, $optionalPropertyNames);
104  if ($this->mappingResults->hasErrors()) {
105  return FALSE;
106  }
107  if ($targetObjectValidator->isValid($target) !== TRUE) {
108  $this->addErrorsFromObjectValidator($targetObjectValidator->getErrors());
109  $backupMappingResult = $this->mappingResults;
110  $this->map($propertyNames, $backupProperties, $source, $optionalPropertyNames);
111  $this->mappingResults = $backupMappingResult;
112  }
113  return !$this->mappingResults->hasErrors();
114  }
115 
122  protected function addErrorsFromObjectValidator($errors) {
123  foreach ($errors as $error) {
124  if ($error instanceof \TYPO3\CMS\Extbase\Validation\PropertyError) {
125  $propertyName = $error->getPropertyName();
126  $this->mappingResults->addError($error, $propertyName);
127  }
128  }
129  }
130 
148  public function map(array $propertyNames, $source, $target, $optionalPropertyNames = array()) {
149  if (!is_object($source) && !is_array($source)) {
150  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidSourceException('The source object must be a valid object or array, ' . gettype($target) . ' given.', 1187807099);
151  }
152  if (is_string($target) && strpbrk($target, '_\\') !== FALSE) {
153  return $this->transformToObject($source, $target, '--none--');
154  }
155  if (!is_object($target) && !is_array($target)) {
156  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('The target object must be a valid object or array, ' . gettype($target) . ' given.', 1187807100);
157  }
158  $this->mappingResults = new \TYPO3\CMS\Extbase\Property\MappingResults();
159  if (is_object($target)) {
160  $targetClassSchema = $this->reflectionService->getClassSchema(get_class($target));
161  } else {
162  $targetClassSchema = NULL;
163  }
164  foreach ($propertyNames as $propertyName) {
165  $propertyValue = NULL;
166  if (is_array($source) || $source instanceof \ArrayAccess) {
167  if (isset($source[$propertyName])) {
168  $propertyValue = $source[$propertyName];
169  }
170  } else {
171  $propertyValue = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($source, $propertyName);
172  }
173  if ($propertyValue === NULL && !in_array($propertyName, $optionalPropertyNames)) {
174  $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Required property '{$propertyName}' does not exist.", 1236785359), $propertyName);
175  } else {
176  if ($targetClassSchema !== NULL && $targetClassSchema->hasProperty($propertyName)) {
177  $propertyMetaData = $targetClassSchema->getProperty($propertyName);
178  if (in_array($propertyMetaData['type'], array('array', 'ArrayObject', 'TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE) && (strpbrk($propertyMetaData['elementType'], '_\\') !== FALSE || $propertyValue === '')) {
179  $objects = array();
180  if (is_array($propertyValue)) {
181  foreach ($propertyValue as $value) {
182  $transformedObject = $this->transformToObject($value, $propertyMetaData['elementType'], $propertyName);
183  if ($transformedObject !== NULL) {
184  $objects[] = $transformedObject;
185  }
186  }
187  }
188  // make sure we hand out what is expected
189  if ($propertyMetaData['type'] === 'ArrayObject') {
190  $propertyValue = new \ArrayObject($objects);
191  } elseif (in_array($propertyMetaData['type'], array('TYPO3\\CMS\\Extbase\\Persistence\\ObjectStorage', 'Tx_Extbase_Persistence_ObjectStorage'), TRUE)) {
192  $propertyValue = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
193  foreach ($objects as $object) {
194  $propertyValue->attach($object);
195  }
196  } else {
197  $propertyValue = $objects;
198  }
199  } elseif ($propertyMetaData['type'] === 'DateTime' || strpbrk($propertyMetaData['type'], '_\\') !== FALSE) {
200  $propertyValue = $this->transformToObject($propertyValue, $propertyMetaData['type'], $propertyName);
201  if ($propertyValue === NULL) {
202  continue;
203  }
204  }
205  } elseif (
206  $targetClassSchema !== NULL
207  && is_subclass_of($target, 'TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity')
208  && is_subclass_of($target, 'TYPO3\\CMS\\Extbase\\DomainObject\\AbstractValueObject')
209  ) {
210  $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Property '{$propertyName}' does not exist in target class schema.", 1251813614), $propertyName);
211  }
212  if (is_array($target)) {
213  $target[$propertyName] = $propertyValue;
214  } elseif (\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($target, $propertyName, $propertyValue) === FALSE) {
215  $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error("Property '{$propertyName}' could not be set.", 1236783102), $propertyName);
216  }
217  }
218  }
219  return !$this->mappingResults->hasErrors();
220  }
221 
233  protected function transformToObject($propertyValue, $targetType, $propertyName) {
234  if ($targetType === 'DateTime' || is_subclass_of($targetType, 'DateTime')) {
235  if ($propertyValue === '') {
236  $propertyValue = NULL;
237  } else {
238  try {
239  $propertyValue = $this->objectManager->get($targetType, $propertyValue);
240  } catch (\Exception $e) {
241  $propertyValue = NULL;
242  }
243  }
244  } else {
245  if (ctype_digit((string)$propertyValue)) {
246  $propertyValue = $this->findObjectByUid($targetType, $propertyValue);
247  if ($propertyValue === FALSE) {
248  $this->mappingResults->addError(new \TYPO3\CMS\Extbase\Error\Error('Querying the repository for the specified object with UUID ' . $propertyValue . ' was not successful.', 1249379517), $propertyName);
249  }
250  } elseif (is_array($propertyValue)) {
251  if (isset($propertyValue['__identity'])) {
252  $existingObject = $this->findObjectByUid($targetType, $propertyValue['__identity']);
253  if ($existingObject === FALSE) {
254  throw new \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException('Querying the repository for the specified object was not successful.', 1237305720);
255  }
256  unset($propertyValue['__identity']);
257  if (count($propertyValue) === 0) {
258  $propertyValue = $existingObject;
259  } elseif ($existingObject !== NULL) {
260  $newObject = clone $existingObject;
261  if ($this->map(array_keys($propertyValue), $propertyValue, $newObject)) {
262  $propertyValue = $newObject;
263  } else {
264  $propertyValue = NULL;
265  }
266  }
267  } else {
268  $newObject = $this->objectManager->get($targetType);
269  if ($this->map(array_keys($propertyValue), $propertyValue, $newObject)) {
270  $propertyValue = $newObject;
271  } else {
272  $propertyValue = NULL;
273  }
274  }
275  } else {
276  throw new \InvalidArgumentException('transformToObject() accepts only numeric values and arrays.', 1251814355);
277  }
278  }
279  return $propertyValue;
280  }
281 
288  public function getMappingResults() {
289  return $this->mappingResults;
290  }
291 
300  protected function findObjectByUid($dataType, $uid) {
301  $query = $this->queryFactory->create($dataType);
302  $query->getQuerySettings()->setRespectSysLanguage(FALSE);
303  $query->getQuerySettings()->setRespectStoragePage(FALSE);
304  return $query->matching($query->equals('uid', (int)$uid))->execute()->getFirst();
305  }
306 }
map(array $propertyNames, $source, $target, $optionalPropertyNames=array())
Definition: Mapper.php:148
mapAndValidate(array $propertyNames, $source, $target, $optionalPropertyNames=array(), \TYPO3\CMS\Extbase\Validation\Validator\ObjectValidatorInterface $targetObjectValidator)
Definition: Mapper.php:97
findObjectByUid($dataType, $uid)
Definition: Mapper.php:300
$uid
Definition: server.php:36
transformToObject($propertyValue, $targetType, $propertyName)
Definition: Mapper.php:233
static getProperty($subject, $propertyName, $forceDirectAccess=FALSE)