[FEATURE] Backport Object Type Converter from Flow
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Reflection / ObjectAccessTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * All rights reserved
8 *
9 * This class is a backport of the corresponding class of TYPO3 Flow.
10 * All credits go to the TYPO3 Flow team.
11 *
12 * This script is part of the TYPO3 project. The TYPO3 project is
13 * free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The GNU General Public License can be found at
19 * http://www.gnu.org/copyleft/gpl.html.
20 *
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
28 require_once __DIR__ . '/Fixture/DummyClassWithGettersAndSetters.php';
29 require_once __DIR__ . '/Fixture/ArrayAccessClass.php';
30
31 /**
32 * Test Unit Test Base Class
33 */
34 class ObjectAccessTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
35
36 protected $dummyObject;
37
38 public function setUp() {
39 $this->dummyObject = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithGettersAndSetters();
40 $this->dummyObject->setProperty('string1');
41 $this->dummyObject->setAnotherProperty(42);
42 $this->dummyObject->shouldNotBePickedUp = TRUE;
43 }
44
45 /**
46 * @test
47 */
48 public function getPropertyReturnsExpectedValueForGetterProperty() {
49 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'property');
50 $this->assertEquals($property, 'string1');
51 }
52
53 /**
54 * @test
55 */
56 public function getPropertyReturnsExpectedValueForPublicProperty() {
57 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'publicProperty2');
58 $this->assertEquals($property, 42, 'A property of a given object was not returned correctly.');
59 }
60
61 /**
62 * @test
63 */
64 public function getPropertyReturnsExpectedValueForUnexposedPropertyIfForceDirectAccessIsTrue() {
65 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'unexposedProperty', TRUE);
66 $this->assertEquals($property, 'unexposed', 'A property of a given object was not returned correctly.');
67 }
68
69 /**
70 * @test
71 */
72 public function getPropertyReturnsExpectedValueForUnknownPropertyIfForceDirectAccessIsTrue() {
73 $this->dummyObject->unknownProperty = 'unknown';
74 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'unknownProperty', TRUE);
75 $this->assertEquals($property, 'unknown', 'A property of a given object was not returned correctly.');
76 }
77
78 /**
79 * @test
80 * @expectedException \TYPO3\CMS\Extbase\Reflection\Exception\PropertyNotAccessibleException
81 */
82 public function getPropertyReturnsPropertyNotAccessibleExceptionForNotExistingPropertyIfForceDirectAccessIsTrue() {
83 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'notExistingProperty', TRUE);
84 }
85
86 /**
87 * @test
88 * @expectedException \TYPO3\CMS\Extbase\Reflection\Exception\PropertyNotAccessibleException
89 */
90 public function getPropertyReturnsThrowsExceptionIfPropertyDoesNotExist() {
91 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'notExistingProperty');
92 }
93
94 /**
95 * @test
96 * @expectedException \TYPO3\CMS\Extbase\Reflection\Exception\PropertyNotAccessibleException
97 */
98 public function getPropertyReturnsThrowsExceptionIfArrayKeyDoesNotExist() {
99 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty(array(), 'notExistingProperty');
100 }
101
102 /**
103 * @test
104 */
105 public function getPropertyTriesToCallABooleanGetterMethodIfItExists() {
106 $property = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, 'booleanProperty');
107 $this->assertTrue($property);
108 }
109
110 /**
111 * @test
112 * @expectedException \InvalidArgumentException
113 */
114 public function getPropertyThrowsExceptionIfThePropertyNameIsNotAString() {
115 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($this->dummyObject, new \ArrayObject());
116 }
117
118 /**
119 * @test
120 * @expectedException \InvalidArgumentException
121 */
122 public function setPropertyThrowsExceptionIfThePropertyNameIsNotAString() {
123 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, new \ArrayObject(), 42);
124 }
125
126 /**
127 * @test
128 */
129 public function setPropertyReturnsFalseIfPropertyIsNotAccessible() {
130 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, 'protectedProperty', 42));
131 }
132
133 /**
134 * @test
135 */
136 public function setPropertySetsValueIfPropertyIsNotAccessibleWhenForceDirectAccessIsTrue() {
137 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, 'unexposedProperty', 'was set anyway', TRUE));
138 $this->assertAttributeEquals('was set anyway', 'unexposedProperty', $this->dummyObject);
139 }
140
141 /**
142 * @test
143 */
144 public function setPropertySetsValueIfPropertyDoesNotExistWhenForceDirectAccessIsTrue() {
145 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, 'unknownProperty', 'was set anyway', TRUE));
146 $this->assertAttributeEquals('was set anyway', 'unknownProperty', $this->dummyObject);
147 }
148
149 /**
150 * @test
151 */
152 public function setPropertyCallsASetterMethodToSetThePropertyValueIfOneIsAvailable() {
153 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, 'property', 4242);
154 $this->assertEquals($this->dummyObject->getProperty(), 4242, 'setProperty does not work with setter.');
155 }
156
157 /**
158 * @test
159 */
160 public function setPropertyWorksWithPublicProperty() {
161 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($this->dummyObject, 'publicProperty', 4242);
162 $this->assertEquals($this->dummyObject->publicProperty, 4242, 'setProperty does not work with public property.');
163 }
164
165 /**
166 * @test
167 */
168 public function setPropertyCanDirectlySetValuesInAnArrayObjectOrArray() {
169 $arrayObject = new \ArrayObject();
170 $array = array();
171 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($arrayObject, 'publicProperty', 4242);
172 \TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty($array, 'key', 'value');
173 $this->assertEquals(4242, $arrayObject['publicProperty']);
174 $this->assertEquals('value', $array['key']);
175 }
176
177 /**
178 * @test
179 */
180 public function getPropertyCanAccessPropertiesOfAnArrayObject() {
181 $arrayObject = new \ArrayObject(array('key' => 'value'));
182 $actual = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($arrayObject, 'key');
183 $this->assertEquals('value', $actual, 'getProperty does not work with ArrayObject property.');
184 }
185
186 /**
187 * @test
188 */
189 public function getPropertyCanAccessPropertiesOfAnObjectImplementingArrayAccess() {
190 $arrayAccessInstance = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\ArrayAccessClass(array('key' => 'value'));
191 $actual = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($arrayAccessInstance, 'key');
192 $this->assertEquals('value', $actual, 'getProperty does not work with Array Access property.');
193 }
194
195 /**
196 * @test
197 */
198 public function getPropertyCanAccessPropertiesOfAnArray() {
199 $array = array('key' => 'value');
200 $expected = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getProperty($array, 'key');
201 $this->assertEquals($expected, 'value', 'getProperty does not work with Array property.');
202 }
203
204 /**
205 * @test
206 */
207 public function getPropertyPathCanAccessPropertiesOfAnArray() {
208 $array = array('parent' => array('key' => 'value'));
209 $actual = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($array, 'parent.key');
210 $this->assertEquals('value', $actual, 'getPropertyPath does not work with Array property.');
211 }
212
213 /**
214 * @test
215 */
216 public function getPropertyPathCanAccessPropertiesOfAnObjectImplementingArrayAccess() {
217 $array = array('parent' => new \ArrayObject(array('key' => 'value')));
218 $actual = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($array, 'parent.key');
219 $this->assertEquals('value', $actual, 'getPropertyPath does not work with Array Access property.');
220 }
221
222 /**
223 * @test
224 */
225 public function getPropertyPathCanNotAccessPropertiesOfAnSplObjectStorageObject() {
226 $objectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
227 $exampleObject = new \stdClass();
228 $exampleObject->key = 'value';
229 $objectStorage->attach($exampleObject);
230 $array = array(
231 'parent' => $objectStorage,
232 );
233 $this->assertNull(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($array, 'parent.0.key'));
234 }
235
236 /**
237 * @test
238 */
239 public function getGettablePropertyNamesReturnsAllPropertiesWhichAreAvailable() {
240 $gettablePropertyNames = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettablePropertyNames($this->dummyObject);
241 $expectedPropertyNames = array('anotherProperty', 'booleanProperty', 'property', 'property2', 'publicProperty', 'publicProperty2');
242 $this->assertEquals($gettablePropertyNames, $expectedPropertyNames, 'getGettablePropertyNames returns not all gettable properties.');
243 }
244
245 /**
246 * @test
247 */
248 public function getSettablePropertyNamesReturnsAllPropertiesWhichAreAvailable() {
249 $settablePropertyNames = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getSettablePropertyNames($this->dummyObject);
250 $expectedPropertyNames = array('anotherProperty', 'property', 'property2', 'publicProperty', 'publicProperty2', 'writeOnlyMagicProperty');
251 $this->assertEquals($settablePropertyNames, $expectedPropertyNames, 'getSettablePropertyNames returns not all settable properties.');
252 }
253
254 /**
255 * @test
256 */
257 public function getSettablePropertyNamesReturnsPropertyNamesOfStdClass() {
258 $stdClassObject = new \stdClass();
259 $stdClassObject->property = 'string1';
260 $stdClassObject->property2 = NULL;
261 $settablePropertyNames = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getSettablePropertyNames($stdClassObject);
262 $expectedPropertyNames = array('property', 'property2');
263 $this->assertEquals($expectedPropertyNames, $settablePropertyNames, 'getSettablePropertyNames returns not all settable properties.');
264 }
265
266 /**
267 * @test
268 */
269 public function getGettablePropertiesReturnsTheCorrectValuesForAllProperties() {
270 $allProperties = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettableProperties($this->dummyObject);
271 $expectedProperties = array(
272 'anotherProperty' => 42,
273 'booleanProperty' => TRUE,
274 'property' => 'string1',
275 'property2' => NULL,
276 'publicProperty' => NULL,
277 'publicProperty2' => 42
278 );
279 $this->assertEquals($allProperties, $expectedProperties, 'expectedProperties did not return the right values for the properties.');
280 }
281
282 /**
283 * @test
284 */
285 public function getGettablePropertiesReturnsPropertiesOfStdClass() {
286 $stdClassObject = new \stdClass();
287 $stdClassObject->property = 'string1';
288 $stdClassObject->property2 = NULL;
289 $stdClassObject->publicProperty2 = 42;
290 $allProperties = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getGettableProperties($stdClassObject);
291 $expectedProperties = array(
292 'property' => 'string1',
293 'property2' => NULL,
294 'publicProperty2' => 42
295 );
296 $this->assertEquals($expectedProperties, $allProperties, 'expectedProperties did not return the right values for the properties.');
297 }
298
299 /**
300 * @test
301 */
302 public function isPropertySettableTellsIfAPropertyCanBeSet() {
303 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($this->dummyObject, 'writeOnlyMagicProperty'));
304 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($this->dummyObject, 'publicProperty'));
305 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($this->dummyObject, 'property'));
306 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($this->dummyObject, 'privateProperty'));
307 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($this->dummyObject, 'shouldNotBePickedUp'));
308 }
309
310 /**
311 * @test
312 */
313 public function isPropertySettableWorksOnStdClass() {
314 $stdClassObject = new \stdClass();
315 $stdClassObject->property = 'foo';
316 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($stdClassObject, 'property'));
317 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertySettable($stdClassObject, 'undefinedProperty'));
318 }
319
320 /**
321 * @test
322 */
323 public function isPropertyGettableTellsIfAPropertyCanBeRetrieved() {
324 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'publicProperty'));
325 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'property'));
326 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'booleanProperty'));
327 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'privateProperty'));
328 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'writeOnlyMagicProperty'));
329 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($this->dummyObject, 'shouldNotBePickedUp'));
330 }
331
332 /**
333 * @test
334 */
335 public function isPropertyGettableWorksOnArrayAccessObjects() {
336 $arrayObject = new \ArrayObject();
337 $arrayObject['key'] = 'v';
338 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($arrayObject, 'key'));
339 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($arrayObject, 'undefinedKey'));
340 }
341
342 /**
343 * @test
344 */
345 public function isPropertyGettableWorksOnStdClass() {
346 $stdClassObject = new \stdClass();
347 $stdClassObject->property = 'foo';
348 $this->assertTrue(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($stdClassObject, 'property'));
349 $this->assertFalse(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::isPropertyGettable($stdClassObject, 'undefinedProperty'));
350 }
351
352 /**
353 * @test
354 */
355 public function getPropertyPathCanRecursivelyGetPropertiesOfAnObject() {
356 $alternativeObject = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithGettersAndSetters();
357 $alternativeObject->setProperty('test');
358 $this->dummyObject->setProperty2($alternativeObject);
359 $expected = 'test';
360 $actual = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($this->dummyObject, 'property2.property');
361 $this->assertEquals($expected, $actual);
362 }
363
364 /**
365 * @test
366 */
367 public function getPropertyPathReturnsNullForNonExistingPropertyPath() {
368 $alternativeObject = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithGettersAndSetters();
369 $alternativeObject->setProperty(new \stdClass());
370 $this->dummyObject->setProperty2($alternativeObject);
371 $this->assertNull(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($this->dummyObject, 'property2.property.not.existing'));
372 }
373
374 /**
375 * @test
376 */
377 public function getPropertyPathReturnsNullIfSubjectIsNoObject() {
378 $string = 'Hello world';
379 $this->assertNull(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($string, 'property2'));
380 }
381
382 /**
383 * @test
384 */
385 public function getPropertyPathReturnsNullIfSubjectOnPathIsNoObject() {
386 $object = new \stdClass();
387 $object->foo = 'Hello World';
388 $this->assertNull(\TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($object, 'foo.bar'));
389 }
390 }
391
392 ?>