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