TYPO3 CMS  TYPO3_8-7
PersistentObjectConverterTest.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  * */
31 
35 class PersistentObjectConverterTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
36 {
40  protected $converter;
41 
46 
51 
55  protected $mockObjectManager;
56 
60  protected $mockContainer;
61 
67  protected function setUp()
68  {
69  $this->converter = new PersistentObjectConverter();
70  $this->mockReflectionService = $this->createMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class);
71  $this->inject($this->converter, 'reflectionService', $this->mockReflectionService);
72 
73  $this->mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
74  $this->inject($this->converter, 'persistenceManager', $this->mockPersistenceManager);
75 
76  $this->mockObjectManager = $this->createMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
77  $this->mockObjectManager->expects($this->any())
78  ->method('get')
79  ->will($this->returnCallback(function ($className, ...$arguments) {
80  $reflectionClass = new \ReflectionClass($className);
81  if (empty($arguments)) {
82  return $reflectionClass->newInstance();
83  }
84  return $reflectionClass->newInstanceArgs($arguments);
85  }));
86  $this->inject($this->converter, 'objectManager', $this->mockObjectManager);
87 
88  $this->mockContainer = $this->createMock(\TYPO3\CMS\Extbase\Object\Container\Container::class);
89  $this->inject($this->converter, 'objectContainer', $this->mockContainer);
90  }
91 
95  public function checkMetadata()
96  {
97  $this->assertEquals(['integer', 'string', 'array'], $this->converter->getSupportedSourceTypes(), 'Source types do not match');
98  $this->assertEquals('object', $this->converter->getSupportedTargetType(), 'Target type does not match');
99  $this->assertEquals(20, $this->converter->getPriority(), 'Priority does not match');
100  }
101 
105  public function dataProviderForCanConvert()
106  {
107  return [
108  [true, false, true],
109  // is entity => can convert
110  [false, true, true],
111  // is valueobject => can convert
112  [false, false, false],
113  // is no entity and no value object => can not convert
114  ];
115  }
116 
121  public function canConvertFromReturnsTrueIfClassIsTaggedWithEntityOrValueObject($isEntity, $isValueObject, $expected)
122  {
123  $className = PersistentObjectFixture::class;
124 
125  if ($isEntity) {
126  $className = PersistentObjectEntityFixture::class;
127  } elseif ($isValueObject) {
128  $className = PersistentObjectValueObjectFixture::class;
129  }
130  $this->assertEquals($expected, $this->converter->canConvertFrom('myInputData', $className));
131  }
132 
137  {
138  $source = [
139  'k1' => 'v1',
140  '__identity' => 'someIdentity',
141  'k2' => 'v2'
142  ];
143  $expected = [
144  'k1' => 'v1',
145  'k2' => 'v2'
146  ];
147  $this->assertEquals($expected, $this->converter->getSourceChildPropertiesToBeConverted($source));
148  }
149 
154  {
155  $mockSchema = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class)->disableOriginalConstructor()->getMock();
156  $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('TheTargetType')->will($this->returnValue($mockSchema));
157 
158  $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue('TheTargetType'));
159  $mockSchema->expects($this->any())->method('hasProperty')->with('thePropertyName')->will($this->returnValue(true));
160  $mockSchema->expects($this->any())->method('getProperty')->with('thePropertyName')->will($this->returnValue([
161  'type' => 'TheTypeOfSubObject',
162  'elementType' => null
163  ]));
164  $configuration = $this->buildConfiguration([]);
165  $this->assertEquals('TheTypeOfSubObject', $this->converter->getTypeOfChildProperty('TheTargetType', 'thePropertyName', $configuration));
166  }
167 
172  {
173  $this->mockReflectionService->expects($this->never())->method('getClassSchema');
174  $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue('foo'));
175 
176  $configuration = $this->buildConfiguration([]);
177  $configuration->forProperty('thePropertyName')->setTypeConverterOption(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_TARGET_TYPE, 'Foo\Bar');
178  $this->assertEquals('Foo\Bar', $this->converter->getTypeOfChildProperty('foo', 'thePropertyName', $configuration));
179  }
180 
185  {
186  $identifier = '17';
187  $object = new \stdClass();
188 
189  $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
190  $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
191  }
192 
197  {
198  $identifier = '17';
199  $object = new \stdClass();
200 
201  $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
202  $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
203  }
204 
209  {
210  $identifier = '12345';
211  $object = new \stdClass();
212 
213  $source = [
214  '__identity' => $identifier
215  ];
216  $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
217  $this->assertSame($object, $this->converter->convertFrom($source, 'MySpecialType'));
218  }
219 
224  {
225  $this->expectException(InvalidPropertyMappingConfigurationException::class);
226  $this->expectExceptionCode(1297932028);
227  $identifier = '12345';
228  $object = new \stdClass();
229  $object->someProperty = 'asdf';
230 
231  $source = [
232  '__identity' => $identifier,
233  'foo' => 'bar'
234  ];
235  $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
236  $this->converter->convertFrom($source, 'MySpecialType');
237  }
238 
243  protected function buildConfiguration($typeConverterOptions)
244  {
245  $configuration = new \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration();
246  $configuration->setTypeConverterOptions(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, $typeConverterOptions);
247  return $configuration;
248  }
249 
255  public function setupMockQuery($numberOfResults, $howOftenIsGetFirstCalled)
256  {
257  $mockClassSchema = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class)
258  ->setConstructorArgs(['Dummy'])
259  ->getMock();
260  $mockClassSchema->expects($this->any())->method('getIdentityProperties')->will($this->returnValue(['key1' => 'someType']));
261  $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('SomeType')->will($this->returnValue($mockClassSchema));
262 
263  $mockConstraint = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\Comparison::class)->disableOriginalConstructor()->getMock();
264 
265  $mockObject = new \stdClass();
266  $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
267  $mockQueryResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
268  $mockQueryResult->expects($this->any())->method('count')->will($this->returnValue($numberOfResults));
269  $mockQueryResult->expects($howOftenIsGetFirstCalled)->method('getFirst')->will($this->returnValue($mockObject));
270  $mockQuery->expects($this->any())->method('equals')->with('key1', 'value1')->will($this->returnValue($mockConstraint));
271  $mockQuery->expects($this->any())->method('matching')->with($mockConstraint)->will($this->returnValue($mockQuery));
272  $mockQuery->expects($this->any())->method('execute')->will($this->returnValue($mockQueryResult));
273 
274  $this->mockPersistenceManager->expects($this->any())->method('createQueryForType')->with('SomeType')->will($this->returnValue($mockQuery));
275 
276  return $mockObject;
277  }
278 
283  {
284  $this->expectException(TargetNotFoundException::class);
285  $this->expectExceptionCode(1297933823);
286  $this->setupMockQuery(0, $this->never());
287  $this->mockReflectionService->expects($this->never())->method('getClassSchema');
288 
289  $source = [
290  '__identity' => 123
291  ];
292  $actual = $this->converter->convertFrom($source, 'SomeType');
293  $this->assertNull($actual);
294  }
295 
300  {
301  $this->expectException(DuplicateObjectException::class);
302  // @TODO expectExceptionCode is 0
303  $this->setupMockQuery(2, $this->never());
304 
305  $source = [
306  '__identity' => 666
307  ];
308  $this->mockPersistenceManager
309  ->expects($this->any())
310  ->method('getObjectByIdentifier')
311  ->with(666)
312  ->will($this->throwException(new DuplicateObjectException('testing', 1476107580)));
313  $this->converter->convertFrom($source, 'SomeType');
314  }
315 
320  {
321  $this->expectException(InvalidPropertyMappingConfigurationException::class);
322  // @TODO expectExceptionCode is 0
323  $source = [
324  'foo' => 'bar'
325  ];
326  $this->converter->convertFrom($source, 'MySpecialType');
327  }
328 
333  {
334  $source = [
335  'propertyX' => 'bar'
336  ];
337  $convertedChildProperties = [
338  'property1' => 'bar'
339  ];
340  $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
341  $expectedObject->property1 = 'bar';
342 
343  $this->mockReflectionService
344  ->expects($this->any())
345  ->method('getMethodParameters')
346  ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, '__construct')
347  ->will($this->throwException(new \ReflectionException('testing', 1476107618)));
349  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, $convertedChildProperties, $configuration);
350  $this->assertEquals($expectedObject, $result);
351  }
352 
357  {
358  $this->expectException(InvalidTargetException::class);
359  $this->expectExceptionCode(1297935345);
360  $source = [
361  'propertyX' => 'bar'
362  ];
363  $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
364  $convertedChildProperties = [
365  'propertyNotExisting' => 'bar'
366  ];
367  $this->mockObjectManager->expects($this->any())->method('get')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class)->will($this->returnValue($object));
368  $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, '__construct')->will($this->returnValue([]));
370  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, $convertedChildProperties, $configuration);
371  $this->assertSame($object, $result);
372  }
373 
378  {
379  $source = [
380  'propertyX' => 'bar'
381  ];
382  $convertedChildProperties = [
383  'property1' => 'param1',
384  'property2' => 'bar'
385  ];
386  $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
387  $expectedObject->setProperty2('bar');
388 
389  $this->mockReflectionService
390  ->expects($this->any())
391  ->method('getMethodParameters')
392  ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
393  ->will($this->returnValue([
394  'property1' => ['optional' => false]
395  ]));
396  $this->mockReflectionService
397  ->expects($this->any())
398  ->method('hasMethod')
399  ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
400  ->will($this->returnValue(true));
401  $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
403  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, $convertedChildProperties, $configuration);
404  $this->assertEquals($expectedObject, $result);
405  $this->assertEquals('bar', $expectedObject->getProperty2());
406  }
407 
412  {
413  $source = [
414  'propertyX' => 'bar'
415  ];
416  $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('thisIsTheDefaultValue');
417 
418  $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue([
419  'property1' => ['optional' => true, 'defaultValue' => 'thisIsTheDefaultValue']
420  ]));
421  $this->mockReflectionService
422  ->expects($this->any())
423  ->method('hasMethod')
424  ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
425  ->will($this->returnValue(true));
426  $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
428  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, [], $configuration);
429  $this->assertEquals($expectedObject, $result);
430  }
431 
436  {
437  $this->expectException(InvalidTargetException::class);
438  $this->expectExceptionCode(1268734872);
439  $source = [
440  'propertyX' => 'bar'
441  ];
442  $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
443  $convertedChildProperties = [
444  'property2' => 'bar'
445  ];
446 
447  $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue([
448  'property1' => ['optional' => false]
449  ]));
450  $this->mockReflectionService
451  ->expects($this->any())
452  ->method('hasMethod')
453  ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
454  ->will($this->returnValue(true));
455  $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
457  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, $convertedChildProperties, $configuration);
458  $this->assertSame($object, $result);
459  }
460 
465  {
466  $source = '';
467  $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class);
468  $this->assertNull($result);
469  }
470 }