[TASK] Removes eval() in extbase unit tests for TypeConverter
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Property / TypeConverter / PersistentObjectConverterTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter;
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 * */
23 use TYPO3\CMS\Core\Tests\UnitTestCase;
24 use TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter;
25 use TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures\PersistentObjectEntityFixture;
26 use TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures\PersistentObjectFixture;
27 use TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter\Fixtures\PersistentObjectValueObjectFixture;
28
29 /**
30 * Test case
31 */
32 class PersistentObjectConverterTest extends UnitTestCase {
33
34 /**
35 * @var \TYPO3\CMS\Extbase\Property\TypeConverterInterface|\PHPUnit_Framework_MockObject_MockObject
36 */
37 protected $converter;
38
39 /**
40 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService|\PHPUnit_Framework_MockObject_MockObject
41 */
42 protected $mockReflectionService;
43
44 /**
45 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface|\PHPUnit_Framework_MockObject_MockObject
46 */
47 protected $mockPersistenceManager;
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
51 */
52 protected $mockObjectManager;
53
54 /**
55 * @var \TYPO3\CMS\Extbase\Object\Container\Container|\PHPUnit_Framework_MockObject_MockObject
56 */
57 protected $mockContainer;
58
59 /**
60 * @throws \InvalidArgumentException
61 * @throws \PHPUnit_Framework_Exception
62 * @throws \RuntimeException
63 */
64 protected function setUp() {
65 $this->converter = new PersistentObjectConverter();
66 $this->mockReflectionService = $this->getMock(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class);
67 $this->inject($this->converter, 'reflectionService', $this->mockReflectionService);
68
69 $this->mockPersistenceManager = $this->getMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
70 $this->inject($this->converter, 'persistenceManager', $this->mockPersistenceManager);
71
72 $this->mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
73 $this->mockObjectManager->expects($this->any())
74 ->method('get')
75 ->will($this->returnCallback(function() {
76 $args = func_get_args();
77 $reflectionClass = new \ReflectionClass(array_shift($args));
78 if (empty($args)) {
79 return $reflectionClass->newInstance();
80 } else {
81 return $reflectionClass->newInstanceArgs($args);
82 }
83 }));
84 $this->inject($this->converter, 'objectManager', $this->mockObjectManager);
85
86 $this->mockContainer = $this->getMock(\TYPO3\CMS\Extbase\Object\Container\Container::class);
87 $this->inject($this->converter, 'objectContainer', $this->mockContainer);
88 }
89
90 /**
91 * @test
92 */
93 public function checkMetadata() {
94 $this->assertEquals(array('integer', 'string', 'array'), $this->converter->getSupportedSourceTypes(), 'Source types do not match');
95 $this->assertEquals('object', $this->converter->getSupportedTargetType(), 'Target type does not match');
96 $this->assertEquals(1, $this->converter->getPriority(), 'Priority does not match');
97 }
98
99 /**
100 * @return array
101 */
102 public function dataProviderForCanConvert() {
103 return array(
104 array(TRUE, FALSE, TRUE),
105 // is entity => can convert
106 array(FALSE, TRUE, TRUE),
107 // is valueobject => can convert
108 array(FALSE, FALSE, FALSE),
109 // is no entity and no value object => can not convert
110 );
111 }
112
113 /**
114 * @test
115 * @dataProvider dataProviderForCanConvert
116 */
117 public function canConvertFromReturnsTrueIfClassIsTaggedWithEntityOrValueObject($isEntity, $isValueObject, $expected) {
118 $className = PersistentObjectFixture::class;
119
120 if ($isEntity) {
121 $className = PersistentObjectEntityFixture::class;
122 } elseif ($isValueObject) {
123 $className = PersistentObjectValueObjectFixture::class;
124 }
125 $this->assertEquals($expected, $this->converter->canConvertFrom('myInputData', $className));
126 }
127
128 /**
129 * @test
130 */
131 public function getSourceChildPropertiesToBeConvertedReturnsAllPropertiesExceptTheIdentityProperty() {
132 $source = array(
133 'k1' => 'v1',
134 '__identity' => 'someIdentity',
135 'k2' => 'v2'
136 );
137 $expected = array(
138 'k1' => 'v1',
139 'k2' => 'v2'
140 );
141 $this->assertEquals($expected, $this->converter->getSourceChildPropertiesToBeConverted($source));
142 }
143
144 /**
145 * @test
146 */
147 public function getTypeOfChildPropertyShouldUseReflectionServiceToDetermineType() {
148 $mockSchema = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class)->disableOriginalConstructor()->getMock();
149 $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('TheTargetType')->will($this->returnValue($mockSchema));
150
151 $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue('TheTargetType'));
152 $mockSchema->expects($this->any())->method('hasProperty')->with('thePropertyName')->will($this->returnValue(TRUE));
153 $mockSchema->expects($this->any())->method('getProperty')->with('thePropertyName')->will($this->returnValue(array(
154 'type' => 'TheTypeOfSubObject',
155 'elementType' => NULL
156 )));
157 $configuration = $this->buildConfiguration(array());
158 $this->assertEquals('TheTypeOfSubObject', $this->converter->getTypeOfChildProperty('TheTargetType', 'thePropertyName', $configuration));
159 }
160
161 /**
162 * @test
163 */
164 public function getTypeOfChildPropertyShouldUseConfiguredTypeIfItWasSet() {
165 $this->mockReflectionService->expects($this->never())->method('getClassSchema');
166 $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue('foo'));
167
168 $configuration = $this->buildConfiguration(array());
169 $configuration->forProperty('thePropertyName')->setTypeConverterOption(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, PersistentObjectConverter::CONFIGURATION_TARGET_TYPE, 'Foo\Bar');
170 $this->assertEquals('Foo\Bar', $this->converter->getTypeOfChildProperty('foo', 'thePropertyName', $configuration));
171 }
172
173 /**
174 * @test
175 */
176 public function convertFromShouldFetchObjectFromPersistenceIfUuidStringIsGiven() {
177 $identifier = '17';
178 $object = new \stdClass();
179
180 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
181 $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
182 }
183
184 /**
185 * @test
186 */
187 public function convertFromShouldFetchObjectFromPersistenceIfuidStringIsGiven() {
188 $identifier = '17';
189 $object = new \stdClass();
190
191 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
192 $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
193 }
194
195 /**
196 * @test
197 */
198 public function convertFromShouldFetchObjectFromPersistenceIfOnlyIdentityArrayGiven() {
199 $identifier = '12345';
200 $object = new \stdClass();
201
202 $source = array(
203 '__identity' => $identifier
204 );
205 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
206 $this->assertSame($object, $this->converter->convertFrom($source, 'MySpecialType'));
207 }
208
209 /**
210 * @test
211 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidPropertyMappingConfigurationException
212 */
213 public function convertFromShouldThrowExceptionIfObjectNeedsToBeModifiedButConfigurationIsNotSet() {
214 $identifier = '12345';
215 $object = new \stdClass();
216 $object->someProperty = 'asdf';
217
218 $source = array(
219 '__identity' => $identifier,
220 'foo' => 'bar'
221 );
222 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
223 $this->converter->convertFrom($source, 'MySpecialType');
224 }
225
226 /**
227 * @param array $typeConverterOptions
228 * @return \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration
229 */
230 protected function buildConfiguration($typeConverterOptions) {
231 $configuration = new \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration();
232 $configuration->setTypeConverterOptions(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, $typeConverterOptions);
233 return $configuration;
234 }
235
236 /**
237 * @param int $numberOfResults
238 * @param Matcher $howOftenIsGetFirstCalled
239 * @return \stdClass
240 */
241 public function setupMockQuery($numberOfResults, $howOftenIsGetFirstCalled) {
242 $mockClassSchema = $this->getMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, array(), array('Dummy'));
243 $mockClassSchema->expects($this->any())->method('getIdentityProperties')->will($this->returnValue(array('key1' => 'someType')));
244 $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('SomeType')->will($this->returnValue($mockClassSchema));
245
246 $mockConstraint = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Qom\Comparison::class)->disableOriginalConstructor()->getMock();
247
248 $mockObject = new \stdClass();
249 $mockQuery = $this->getMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
250 $mockQueryResult = $this->getMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
251 $mockQueryResult->expects($this->any())->method('count')->will($this->returnValue($numberOfResults));
252 $mockQueryResult->expects($howOftenIsGetFirstCalled)->method('getFirst')->will($this->returnValue($mockObject));
253 $mockQuery->expects($this->any())->method('equals')->with('key1', 'value1')->will($this->returnValue($mockConstraint));
254 $mockQuery->expects($this->any())->method('matching')->with($mockConstraint)->will($this->returnValue($mockQuery));
255 $mockQuery->expects($this->any())->method('execute')->will($this->returnValue($mockQueryResult));
256
257 $this->mockPersistenceManager->expects($this->any())->method('createQueryForType')->with('SomeType')->will($this->returnValue($mockQuery));
258
259 return $mockObject;
260 }
261
262 /**
263 * @test
264 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\TargetNotFoundException
265 */
266 public function convertFromShouldReturnExceptionIfNoMatchingObjectWasFound() {
267 $this->setupMockQuery(0, $this->never());
268 $this->mockReflectionService->expects($this->never())->method('getClassSchema');
269
270 $source = array(
271 '__identity' => 123
272 );
273 $actual = $this->converter->convertFrom($source, 'SomeType');
274 $this->assertNull($actual);
275 }
276
277 /**
278 * @test
279 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\DuplicateObjectException
280 */
281 public function convertFromShouldThrowExceptionIfMoreThanOneObjectWasFound() {
282 $this->setupMockQuery(2, $this->never());
283
284 $source = array(
285 '__identity' => 666
286 );
287 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with(666)->will($this->throwException(new \TYPO3\CMS\Extbase\Property\Exception\DuplicateObjectException));
288 $this->converter->convertFrom($source, 'SomeType');
289 }
290
291 /**
292 * @test
293 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidPropertyMappingConfigurationException
294 */
295 public function convertFromShouldThrowExceptionIfObjectNeedsToBeCreatedButConfigurationIsNotSet() {
296 $source = array(
297 'foo' => 'bar'
298 );
299 $this->converter->convertFrom($source, 'MySpecialType');
300 }
301
302 /**
303 * @test
304 */
305 public function convertFromShouldCreateObject() {
306 $source = array(
307 'propertyX' => 'bar'
308 );
309 $convertedChildProperties = array(
310 'property1' => 'bar'
311 );
312 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
313 $expectedObject->property1 = 'bar';
314
315 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, '__construct')->will($this->throwException(new \ReflectionException()));
316 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class)->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class));
317 $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
318 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, $convertedChildProperties, $configuration);
319 $this->assertEquals($expectedObject, $result);
320 }
321
322 /**
323 * @test
324 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException
325 */
326 public function convertFromShouldThrowExceptionIfPropertyOnTargetObjectCouldNotBeSet() {
327 $source = array(
328 'propertyX' => 'bar'
329 );
330 $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
331 $convertedChildProperties = array(
332 'propertyNotExisting' => 'bar'
333 );
334 $this->mockObjectManager->expects($this->any())->method('get')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class)->will($this->returnValue($object));
335 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, '__construct')->will($this->returnValue(array()));
336 $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
337 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters::class, $convertedChildProperties, $configuration);
338 $this->assertSame($object, $result);
339 }
340
341 /**
342 * @test
343 */
344 public function convertFromShouldCreateObjectWhenThereAreConstructorParameters() {
345 $source = array(
346 'propertyX' => 'bar'
347 );
348 $convertedChildProperties = array(
349 'property1' => 'param1',
350 'property2' => 'bar'
351 );
352 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
353 $expectedObject->setProperty2('bar');
354
355 $this->mockReflectionService
356 ->expects($this->any())
357 ->method('getMethodParameters')
358 ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
359 ->will($this->returnValue(array(
360 'property1' => array('optional' => FALSE)
361 )));
362 $this->mockReflectionService
363 ->expects($this->any())
364 ->method('hasMethod')
365 ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
366 ->will($this->returnValue(TRUE));
367 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class)->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
368 $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
369 $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
370 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, $convertedChildProperties, $configuration);
371 $this->assertEquals($expectedObject, $result);
372 $this->assertEquals('bar', $expectedObject->getProperty2());
373 }
374
375 /**
376 * @test
377 */
378 public function convertFromShouldCreateObjectWhenThereAreOptionalConstructorParameters() {
379 $source = array(
380 'propertyX' => 'bar'
381 );
382 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('thisIsTheDefaultValue');
383
384 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue(array(
385 'property1' => array('optional' => TRUE, 'defaultValue' => 'thisIsTheDefaultValue')
386 )));
387 $this->mockReflectionService
388 ->expects($this->any())
389 ->method('hasMethod')
390 ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
391 ->will($this->returnValue(TRUE));
392 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class)->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
393 $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
394 $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
395 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, array(), $configuration);
396 $this->assertEquals($expectedObject, $result);
397 }
398
399 /**
400 * @test
401 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException
402 */
403 public function convertFromShouldThrowExceptionIfRequiredConstructorParameterWasNotFound() {
404 $source = array(
405 'propertyX' => 'bar'
406 );
407 $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
408 $convertedChildProperties = array(
409 'property2' => 'bar'
410 );
411
412 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')->will($this->returnValue(array(
413 'property1' => array('optional' => FALSE)
414 )));
415 $this->mockReflectionService
416 ->expects($this->any())
417 ->method('hasMethod')
418 ->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, '__construct')
419 ->will($this->returnValue(TRUE));
420 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class)->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
421 $this->mockContainer->expects($this->any())->method('getImplementationClassName')->will($this->returnValue(\TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class));
422 $configuration = $this->buildConfiguration(array(PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
423 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class, $convertedChildProperties, $configuration);
424 $this->assertSame($object, $result);
425 }
426
427 /**
428 * @test
429 */
430 public function convertFromShouldReturnNullForEmptyString() {
431 $source = '';
432 $result = $this->converter->convertFrom($source, \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor::class);
433 $this->assertNull($result);
434 }
435
436 }