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