‪TYPO3CMS  ‪main
ObjectConverterTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use PHPUnit\Framework\Attributes\Test;
28 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
31 
32 final class ‪ObjectConverterTest extends FunctionalTestCase
33 {
34  protected bool ‪$initializeDatabase = false;
35 
36  #[Test]
37  public function ‪convertToObject(): void
38  {
39  $propertyMapper = $this->get(PropertyMapper::class);
40 
41  $model = new class () extends ‪AbstractEntity {
45  protected $name;
46 
47  public function setName(string $name): void
48  {
49  $this->name = $name;
50  }
51  };
52 
54  $object = $propertyMapper->convert(['name' => 'John Doe'], get_class($model));
55 
56  self::assertInstanceOf(get_class($model), $object);
57  self::assertSame('John Doe', $object->_getProperty('name'));
58  }
59 
60  #[Test]
61  public function ‪convertToObjectViaTypeInArray(): void
62  {
63  $propertyMapper = $this->get(PropertyMapper::class);
64 
65  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
66  $propertyMapperConfiguration->allowAllProperties();
67  $propertyMapperConfiguration->setTypeConverterOption(
68  ObjectConverter::class,
70  true
71  );
72 
74  $object = $propertyMapper->convert(
75  ['name' => 'John Doe', '__type' => Cat::class],
76  Animal::class,
77  $propertyMapperConfiguration
78  );
79 
80  self::assertInstanceOf(Cat::class, $object);
81  self::assertSame('John Doe', $object->getName());
82  }
83 
84  #[Test]
86  {
87  $class = new class () {
88  public $name;
89  };
90 
91  $propertyMapper = $this->get(PropertyMapper::class);
92  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
93  $propertyMapperConfiguration->allowAllProperties();
94  $propertyMapperConfiguration
95  ->forProperty('name')
96  ->setTypeConverterOption(
97  ObjectConverter::class,
99  'string'
100  )
101  ;
102 
103  $result = $propertyMapper->convert(
104  ['name' => 'foo'],
105  get_class($class),
106  $propertyMapperConfiguration
107  );
108 
109  self::assertSame('foo', $result->name);
110  }
111 
112  #[Test]
114  {
115  $class = new class ('') {
116  private $name;
117  public function __construct(string $name)
118  {
119  $this->name = $name;
120  }
121  public function getName(): string
122  {
123  return $this->name;
124  }
125  };
126 
127  $propertyMapper = $this->get(PropertyMapper::class);
128  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
129  $propertyMapperConfiguration->allowAllProperties();
130 
131  $result = $propertyMapper->convert(
132  ['name' => 'foo'],
133  get_class($class),
134  $propertyMapperConfiguration
135  );
136 
137  self::assertSame('foo', $result->getName());
138  }
139 
140  #[Test]
141  public function collectionTypesAreConsideredInMapping(): void
142  {
143  $class = new class () {
147  protected ‪ObjectStorage $collection;
148 
152  public function getCollection(): ‪ObjectStorage
153  {
154  return $this->collection;
155  }
156 
160  public function setCollection(‪ObjectStorage $collection): void
161  {
162  $this->collection = $collection;
163  }
164  };
165 
166  $propertyMapper = $this->get(PropertyMapper::class);
167  $propertyMapperConfiguration = new PropertyMappingConfiguration();
168  $propertyMapperConfiguration->allowAllProperties();
169  $propertyMapperConfiguration->forProperty('collection.*')->allowAllProperties();
170 
171  $result = $propertyMapper->convert(
172  ['collection' => [['name' => 'Zebra'], ['name' => 'Lion']]],
173  get_class($class),
174  $propertyMapperConfiguration
175  );
176 
177  self::assertSame(2, $result->getCollection()->count());
178  self::assertSame('Zebra', $result->getCollection()->current()->getName());
179  $result->getCollection()->next();
180  self::assertSame('Lion', $result->getCollection()->current()->getName());
181  }
182 
183  #[Test]
185  {
186  $class = new class () {
187  private $name;
188  public function setName(string $name): void
189  {
190  $this->name = $name;
191  }
192  public function getName(): string
193  {
194  return $this->name;
195  }
196  };
197 
198  $propertyMapper = $this->get(PropertyMapper::class);
199  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
200  $propertyMapperConfiguration->allowAllProperties();
201 
202  $result = $propertyMapper->convert(
203  ['name' => 'foo'],
204  get_class($class),
205  $propertyMapperConfiguration
206  );
207 
208  self::assertSame('foo', $result->getName());
209  }
210 
211  #[Test]
213  {
214  $class = new class () {};
215 
216  $className = get_class($class);
217  $propertyName = 'name';
218 
219  $this->expectException(Exception::class);
220  $this->expectExceptionCode(1297759968);
221  $this->expectExceptionMessage('Exception while property mapping at property path "": Type of child property "' . $propertyName . '" of class "' . $className . '" could not be derived from constructor arguments as said class does not have a constructor defined.');
222 
223  $propertyMapper = $this->get(PropertyMapper::class);
224  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
225  $propertyMapperConfiguration->allowAllProperties();
226 
227  $propertyMapper->convert(
228  [$propertyName => 'foo'],
229  $className,
230  $propertyMapperConfiguration
231  );
232  }
233 
234  #[Test]
236  {
237  $class = new class () {
238  public function __construct() {}
239  };
240 
241  $className = get_class($class);
242  $propertyName = 'name';
243 
244  $this->expectException(Exception::class);
245  $this->expectExceptionCode(1297759968);
246  $this->expectExceptionMessage('Exception while property mapping at property path "": Type of child property "' . $propertyName . '" of class "' . $className . '" could not be derived from constructor arguments as the constructor of said class does not have a parameter with property name "' . $propertyName . '".');
247 
248  $propertyMapper = $this->get(PropertyMapper::class);
249  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
250  $propertyMapperConfiguration->allowAllProperties();
251 
252  $propertyMapper->convert(
253  [$propertyName => 'foo'],
254  $className,
255  $propertyMapperConfiguration
256  );
257  }
258 
259  #[Test]
261  {
262  $class = new class () {
263  public function __construct($name = null) {}
264  };
265 
266  $className = get_class($class);
267  $propertyName = 'name';
268 
269  $this->expectException(Exception::class);
270  $this->expectExceptionCode(1297759968);
271  $this->expectExceptionMessage('Exception while property mapping at property path "": Type of child property "' . $propertyName . '" of class "' . $className . '" could not be derived from constructor argument "' . $propertyName . '". This usually happens if the argument misses a type hint.');
272 
273  $propertyMapper = $this->get(PropertyMapper::class);
274  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
275  $propertyMapperConfiguration->allowAllProperties();
276 
277  $propertyMapper->convert(
278  [$propertyName => 'foo'],
279  $className,
280  $propertyMapperConfiguration
281  );
282  }
283 
284  #[Test]
286  {
287  $this->expectException(Exception::class);
288  $this->expectExceptionCode(1297759968);
289  $this->expectExceptionMessage('Exception while property mapping at property path "": Setter for property "name" had no type hint or documentation in target object of type "');
290 
291  $class = new class () {
292  public function setName($name): void {}
293  };
294 
295  $propertyMapper = $this->get(PropertyMapper::class);
296  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
297  $propertyMapperConfiguration->allowAllProperties();
298 
299  $propertyMapper->convert(
300  ['name' => 'foo'],
301  get_class($class),
302  $propertyMapperConfiguration
303  );
304  }
305 
306  #[Test]
308  {
309  $this->expectException(Exception::class);
310  $this->expectExceptionCode(1297759968);
311  $this->expectExceptionMessage('Exception while property mapping at property path "": Property "name" having a value of type "string" could not be set in target object of type "');
312 
313  $class = new class () {
314  private $name;
315  };
316 
317  $propertyMapper = $this->get(PropertyMapper::class);
318  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
319  $propertyMapperConfiguration->allowAllProperties();
320  $propertyMapperConfiguration
321  ->forProperty('name')
322  ->setTypeConverterOption(
323  ObjectConverter::class,
325  'string'
326  )
327  ;
328 
329  $propertyMapper->convert(
330  ['name' => 'foo'],
331  get_class($class),
332  $propertyMapperConfiguration
333  );
334  }
335 
336  #[Test]
338  {
339  $class = new class ('', '') {
340  public $name;
341  public $color;
342  public function __construct(string $name, ?string $color = 'red')
343  {
344  $this->name = $name;
345  $this->color = $color;
346  }
347  };
348 
349  $result = $this->get(PropertyMapper::class)->convert(
350  ['name' => 'foo'],
351  get_class($class)
352  );
353 
354  self::assertSame('foo', $result->name);
355  self::assertSame('red', $result->color);
356  }
357 
358  #[Test]
360  {
361  $this->expectException(Exception::class);
362  $this->expectExceptionCode(1297759968);
363  $this->expectExceptionMessage('Exception while property mapping at property path "": Missing constructor argument "color" for object of type "');
364 
365  $class = new class ('', '') {
366  public $name;
367  public $color;
368  public function __construct(string $name, string $color)
369  {
370  $this->name = $name;
371  $this->color = $color;
372  }
373  };
374 
375  $this->get(PropertyMapper::class)->convert(
376  ['name' => 'foo'],
377  get_class($class)
378  );
379  }
380 
381  #[Test]
383  {
384  $this->expectException(Exception::class);
385  $this->expectExceptionCode(1297759968);
386  $this->expectExceptionMessage('Exception while property mapping at property path "": Override of target type not allowed. To enable this, you need to set the PropertyMappingConfiguration Value "CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED" to TRUE.');
387 
388  $class = new class () {};
389 
390  $this->get(PropertyMapper::class)->convert(
391  ['__type' => Animal::class],
392  get_class($class)
393  );
394  }
395 
396  #[Test]
398  {
399  $this->expectException(Exception::class);
400  $this->expectExceptionCode(1297759968);
401  $this->expectExceptionMessage('Exception while property mapping at property path "": The given type "TYPO3Tests\TypeConverterTest\Domain\Model\Animal" is not a subtype of "');
402 
403  $class = new class () {};
404 
405  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
406  $propertyMapperConfiguration->allowAllProperties();
407  $propertyMapperConfiguration->setTypeConverterOption(
408  ObjectConverter::class,
410  true
411  );
412 
413  $this->get(PropertyMapper::class)->convert(
414  ['__type' => Animal::class],
415  get_class($class),
416  $propertyMapperConfiguration
417  );
418  }
419 
420  #[Test]
422  {
423  // XCLASS the animal class
424  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][Animal::class] = [
425  'className' => Cat::class,
426  ];
427 
428  $propertyMapper = $this->get(PropertyMapper::class);
429 
430  $propertyMapperConfiguration = new ‪PropertyMappingConfiguration();
431  $propertyMapperConfiguration->allowAllProperties();
432 
433  $object = $propertyMapper->convert(
434  ['name' => 'John Doe'],
435  Animal::class,
436  $propertyMapperConfiguration
437  );
438 
439  self::assertInstanceOf(Cat::class, $object);
440  }
441 }
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTargetTypeForSourceThrowsInvalidPropertyMappingConfigurationExceptionIfTargetTypeOverridingIsNotAllowed
‪getTargetTypeForSourceThrowsInvalidPropertyMappingConfigurationExceptionIfTargetTypeOverridingIsNotAllowed()
Definition: ObjectConverterTest.php:381
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\CONFIGURATION_TARGET_TYPE
‪const CONFIGURATION_TARGET_TYPE
Definition: ObjectConverter.php:40
‪TYPO3Tests\TypeConverterTest\Domain\Model\Animal
Definition: Animal.php:21
‪TYPO3\CMS\Extbase\Property\Exception
Definition: DuplicateObjectException.php:18
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\buildObjectUsesDefaultValueOfOptionalConstructorArguments
‪buildObjectUsesDefaultValueOfOptionalConstructorArguments()
Definition: ObjectConverterTest.php:336
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyReturnsTypeDefinedByConstructorArgument
‪getTypeOfChildPropertyReturnsTypeDefinedByConstructorArgument()
Definition: ObjectConverterTest.php:112
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertySetterDoesNotDefineAType
‪getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertySetterDoesNotDefineAType()
Definition: ObjectConverterTest.php:284
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyTypeCannotBeDerivedFromExistingConstructorArgument
‪getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyTypeCannotBeDerivedFromExistingConstructorArgument()
Definition: ObjectConverterTest.php:259
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyTypeCannotBeDerivedFromNonExistingConstructorArgument
‪getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyTypeCannotBeDerivedFromNonExistingConstructorArgument()
Definition: ObjectConverterTest.php:234
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyReturnsTypeDefinedByPropertyMappingConfiguration
‪getTypeOfChildPropertyReturnsTypeDefinedByPropertyMappingConfiguration()
Definition: ObjectConverterTest.php:84
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest
Definition: ObjectConverterTest.php:33
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\convertFromThrowsInvalidTargetExceptionIfPropertiesCannotBeSet
‪convertFromThrowsInvalidTargetExceptionIfPropertiesCannotBeSet()
Definition: ObjectConverterTest.php:306
‪TYPO3\CMS\Extbase\DomainObject\AbstractEntity
Definition: AbstractEntity.php:22
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter\CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED
‪const CONFIGURATION_OVERRIDE_TARGET_TYPE_ALLOWED
Definition: ObjectConverter.php:45
‪TYPO3\CMS\Extbase\Persistence\ObjectStorage
Definition: ObjectStorage.php:34
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter
Definition: ArrayConverterTest.php:18
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyReturnsTypeDefinedBySetter
‪getTypeOfChildPropertyReturnsTypeDefinedBySetter()
Definition: ObjectConverterTest.php:183
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\buildObjectThrowsInvalidTargetExceptionIfMandatoryConstructorArgumentIsMissing
‪buildObjectThrowsInvalidTargetExceptionIfMandatoryConstructorArgumentIsMissing()
Definition: ObjectConverterTest.php:358
‪TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration
Definition: PropertyMappingConfiguration.php:22
‪TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface
Definition: DomainObjectInterface.php:33
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\convertWithRegisteredSubclassReturnsInstanceOfRegisteredSubclass
‪convertWithRegisteredSubclassReturnsInstanceOfRegisteredSubclass()
Definition: ObjectConverterTest.php:420
‪TYPO3\CMS\Extbase\Property\PropertyMapper
Definition: PropertyMapper.php:30
‪TYPO3\CMS\Extbase\Property\TypeConverter\ObjectConverter
Definition: ObjectConverter.php:36
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyIsNotAccessible
‪getTypeOfChildPropertyThrowsInvalidTargetExceptionIfPropertyIsNotAccessible()
Definition: ObjectConverterTest.php:211
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\$initializeDatabase
‪bool $initializeDatabase
Definition: ObjectConverterTest.php:34
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3Tests\TypeConverterTest\Domain\Model\Cat
Definition: Cat.php:21
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\getTargetTypeForSourceThrowsInvalidDataTypeExceptionIfOverriddenTargetTypeIsNotASubtypeOfOriginalTargetType
‪getTargetTypeForSourceThrowsInvalidDataTypeExceptionIfOverriddenTargetTypeIsNotASubtypeOfOriginalTargetType()
Definition: ObjectConverterTest.php:396
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\convertToObjectViaTypeInArray
‪convertToObjectViaTypeInArray()
Definition: ObjectConverterTest.php:60
‪TYPO3\CMS\Extbase\Tests\Functional\Property\TypeConverter\ObjectConverterTest\convertToObject
‪convertToObject()
Definition: ObjectConverterTest.php:37