TYPO3 CMS  TYPO3_8-7
ObjectAccessTest.php
Go to the documentation of this file.
1 <?php
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  */
20 
24 class ObjectAccessTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
25 {
29  protected $dummyObject;
30 
34  protected function setUp()
35  {
36  $this->dummyObject = new DummyClassWithGettersAndSetters();
37  $this->dummyObject->setProperty('string1');
38  $this->dummyObject->setAnotherProperty(42);
39  $this->dummyObject->shouldNotBePickedUp = true;
40  }
41 
46  {
47  $property = ObjectAccess::getProperty($this->dummyObject, 'property');
48  $this->assertEquals($property, 'string1');
49  }
50 
55  {
56  $property = ObjectAccess::getProperty($this->dummyObject, 'publicProperty2');
57  $this->assertEquals($property, 42, 'A property of a given object was not returned correctly.');
58  }
59 
64  {
65  $property = ObjectAccess::getProperty($this->dummyObject, 'unexposedProperty', true);
66  $this->assertEquals($property, 'unexposed', 'A property of a given object was not returned correctly.');
67  }
68 
73  {
74  $this->dummyObject->unknownProperty = 'unknown';
75  $property = ObjectAccess::getProperty($this->dummyObject, 'unknownProperty', true);
76  $this->assertEquals($property, 'unknown', 'A property of a given object was not returned correctly.');
77  }
78 
83  {
84  $this->expectException(PropertyNotAccessibleException::class);
85  $this->expectExceptionCode(1302855001);
86  ObjectAccess::getProperty($this->dummyObject, 'notExistingProperty', true);
87  }
88 
93  {
94  $this->expectException(PropertyNotAccessibleException::class);
95  $this->expectExceptionCode(1476109666);
96  ObjectAccess::getProperty($this->dummyObject, 'notExistingProperty');
97  }
98 
103  {
104  $result = ObjectAccess::getProperty([], 'notExistingProperty');
105  $this->assertNull($result);
106  }
107 
112  {
113  $property = ObjectAccess::getProperty($this->dummyObject, 'booleanProperty');
114  $this->assertTrue($property);
115  }
116 
121  {
122  $this->expectException(\InvalidArgumentException::class);
123  $this->expectExceptionCode(1231178303);
124  ObjectAccess::getProperty($this->dummyObject, new \ArrayObject());
125  }
126 
131  {
132  $this->expectException(\InvalidArgumentException::class);
133  $this->expectExceptionCode(1231178878);
134  ObjectAccess::setProperty($this->dummyObject, new \ArrayObject(), 42);
135  }
136 
141  {
142  $this->assertFalse(ObjectAccess::setProperty($this->dummyObject, 'protectedProperty', 42));
143  }
144 
149  {
150  $this->assertTrue(ObjectAccess::setProperty($this->dummyObject, 'unexposedProperty', 'was set anyway', true));
151  $this->assertAttributeEquals('was set anyway', 'unexposedProperty', $this->dummyObject);
152  }
153 
158  {
159  $this->assertTrue(ObjectAccess::setProperty($this->dummyObject, 'unknownProperty', 'was set anyway', true));
160  $this->assertAttributeEquals('was set anyway', 'unknownProperty', $this->dummyObject);
161  }
162 
167  {
168  ObjectAccess::setProperty($this->dummyObject, 'property', 4242);
169  $this->assertEquals($this->dummyObject->getProperty(), 4242, 'setProperty does not work with setter.');
170  }
171 
176  {
177  ObjectAccess::setProperty($this->dummyObject, 'publicProperty', 4242);
178  $this->assertEquals($this->dummyObject->publicProperty, 4242, 'setProperty does not work with public property.');
179  }
180 
185  {
186  $arrayObject = new \ArrayObject();
187  $array = [];
188  ObjectAccess::setProperty($arrayObject, 'publicProperty', 4242);
189  ObjectAccess::setProperty($array, 'key', 'value');
190  $this->assertEquals(4242, $arrayObject['publicProperty']);
191  $this->assertEquals('value', $array['key']);
192  }
193 
198  {
199  $arrayObject = new \ArrayObject(['key' => 'value']);
200  $actual = ObjectAccess::getProperty($arrayObject, 'key');
201  $this->assertEquals('value', $actual, 'getProperty does not work with ArrayObject property.');
202  }
203 
208  {
209  $objectStorage = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
210  $object = new \stdClass();
211  $objectStorage->attach($object);
212  $actual = ObjectAccess::getProperty($objectStorage, 0);
213  $this->assertSame($object, $actual, 'getProperty does not work with ObjectStorage property.');
214  }
215 
220  {
221  $arrayAccessInstance = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\ArrayAccessClass(['key' => 'value']);
222  $actual = ObjectAccess::getProperty($arrayAccessInstance, 'key');
223  $this->assertEquals('value', $actual, 'getProperty does not work with Array Access property.');
224  }
225 
230  {
231  $arrayAccessInstance = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\ArrayAccessClass([]);
232  $actual = ObjectAccess::getProperty($arrayAccessInstance, 'virtual');
233  $this->assertEquals('default-value', $actual, 'getProperty does not work with Array Access property.');
234  }
235 
240  {
241  $arrayAccessInstance = new \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\ArrayAccessClass(['virtual' => 'overridden-value']);
242  $actual = ObjectAccess::getProperty($arrayAccessInstance, 'virtual');
243  $this->assertEquals('overridden-value', $actual, 'getProperty does not work with Array Access property.');
244  }
245 
250  {
251  $array = ['key' => 'value'];
252  $expected = ObjectAccess::getProperty($array, 'key');
253  $this->assertEquals($expected, 'value', 'getProperty does not work with Array property.');
254  }
255 
260  {
261  $array = ['parent' => ['key' => 'value']];
262  $actual = ObjectAccess::getPropertyPath($array, 'parent.key');
263  $this->assertEquals('value', $actual, 'getPropertyPath does not work with Array property.');
264  }
265 
270  {
271  $array = ['parent' => new \ArrayObject(['key' => 'value'])];
272  $actual = ObjectAccess::getPropertyPath($array, 'parent.key');
273  $this->assertEquals('value', $actual, 'getPropertyPath does not work with Array Access property.');
274  }
275 
280  {
281  $objectStorage = $this->setUpObjectStorageWithTwoItems();
282  $array = [
283  'parent' => $objectStorage,
284  ];
285  $this->assertSame('value', ObjectAccess::getPropertyPath($array, 'parent.0.key'));
286  $this->assertSame('value2', ObjectAccess::getPropertyPath($array, 'parent.1.key'));
287  }
288 
293  {
294  $objectStorage = $this->setUpObjectStorageWithTwoItems();
295  $i = 0;
296  foreach ($objectStorage as $object) {
297  ObjectAccess::getPropertyPath($objectStorage, '0.key');
298  $i++;
299  }
300  $this->assertSame(2, $i);
301  }
302 
306  protected function setUpObjectStorageWithTwoItems()
307  {
308  $objectStorage = new ObjectStorage();
309  $exampleObject = new \stdClass();
310  $exampleObject->key = 'value';
311  $exampleObject2 = new \stdClass();
312  $exampleObject2->key = 'value2';
313  $objectStorage->attach($exampleObject);
314  $objectStorage->attach($exampleObject2);
315  return $objectStorage;
316  }
317 
322  {
323  $objectStorage = $this->setUpSplObjectStorageWithTwoItems();
324  $array = [
325  'parent' => $objectStorage,
326  ];
327  $this->assertSame('value', ObjectAccess::getPropertyPath($array, 'parent.0.key'));
328  $this->assertSame('value2', ObjectAccess::getPropertyPath($array, 'parent.1.key'));
329  }
330 
335  {
336  $objectStorage = $this->setUpSplObjectStorageWithTwoItems();
337  $i = 0;
338  foreach ($objectStorage as $object) {
339  ObjectAccess::getPropertyPath($objectStorage, '0.key');
340  $i++;
341  }
342  $this->assertSame(2, $i);
343  }
344 
349  {
350  $objectStorage = new \SplObjectStorage();
351  $exampleObject = new \stdClass();
352  $exampleObject->key = 'value';
353  $exampleObject2 = new \stdClass();
354  $exampleObject2->key = 'value2';
355  $objectStorage->attach($exampleObject);
356  $objectStorage->attach($exampleObject2);
357  return $objectStorage;
358  }
359 
364  {
365  $gettablePropertyNames = ObjectAccess::getGettablePropertyNames($this->dummyObject);
366  $expectedPropertyNames = ['anotherBooleanProperty', 'anotherProperty', 'booleanProperty', 'property', 'property2', 'publicProperty', 'publicProperty2', 'someValue'];
367  $this->assertEquals($gettablePropertyNames, $expectedPropertyNames, 'getGettablePropertyNames returns not all gettable properties.');
368  }
369 
374  {
375  $dateTimeZone = new \DateTimeZone('+2');
376  $gettablePropertyNames = ObjectAccess::getGettablePropertyNames($dateTimeZone);
377  $expectedPropertyNames = ['location', 'name'];
378  $this->assertArraySubset($expectedPropertyNames, $gettablePropertyNames);
379  }
380 
385  {
386  $settablePropertyNames = ObjectAccess::getSettablePropertyNames($this->dummyObject);
387  $expectedPropertyNames = ['anotherBooleanProperty', 'anotherProperty', 'property', 'property2', 'publicProperty', 'publicProperty2', 'writeOnlyMagicProperty'];
388  $this->assertEquals($settablePropertyNames, $expectedPropertyNames, 'getSettablePropertyNames returns not all settable properties.');
389  }
390 
395  {
396  $stdClassObject = new \stdClass();
397  $stdClassObject->property = 'string1';
398  $stdClassObject->property2 = null;
399  $settablePropertyNames = ObjectAccess::getSettablePropertyNames($stdClassObject);
400  $expectedPropertyNames = ['property', 'property2'];
401  $this->assertEquals($expectedPropertyNames, $settablePropertyNames, 'getSettablePropertyNames returns not all settable properties.');
402  }
403 
408  {
409  $allProperties = ObjectAccess::getGettableProperties($this->dummyObject);
410  $expectedProperties = [
411  'anotherBooleanProperty' => true,
412  'anotherProperty' => 42,
413  'booleanProperty' => true,
414  'property' => 'string1',
415  'property2' => null,
416  'publicProperty' => null,
417  'publicProperty2' => 42,
418  'someValue' => true,
419  ];
420  $this->assertEquals($allProperties, $expectedProperties, 'expectedProperties did not return the right values for the properties.');
421  }
422 
427  {
428  $stdClassObject = new \stdClass();
429  $stdClassObject->property = 'string1';
430  $stdClassObject->property2 = null;
431  $stdClassObject->publicProperty2 = 42;
432  $allProperties = ObjectAccess::getGettableProperties($stdClassObject);
433  $expectedProperties = [
434  'property' => 'string1',
435  'property2' => null,
436  'publicProperty2' => 42
437  ];
438  $this->assertEquals($expectedProperties, $allProperties, 'expectedProperties did not return the right values for the properties.');
439  }
440 
445  {
446  $this->assertTrue(ObjectAccess::isPropertySettable($this->dummyObject, 'writeOnlyMagicProperty'));
447  $this->assertTrue(ObjectAccess::isPropertySettable($this->dummyObject, 'publicProperty'));
448  $this->assertTrue(ObjectAccess::isPropertySettable($this->dummyObject, 'property'));
449  $this->assertFalse(ObjectAccess::isPropertySettable($this->dummyObject, 'privateProperty'));
450  $this->assertFalse(ObjectAccess::isPropertySettable($this->dummyObject, 'shouldNotBePickedUp'));
451  }
452 
457  {
458  $stdClassObject = new \stdClass();
459  $stdClassObject->property = 'foo';
460  $this->assertTrue(ObjectAccess::isPropertySettable($stdClassObject, 'property'));
461  $this->assertFalse(ObjectAccess::isPropertySettable($stdClassObject, 'undefinedProperty'));
462  }
463 
471  public function isPropertyGettableTellsIfAPropertyCanBeRetrieved($property, $expected)
472  {
473  $this->assertEquals($expected, ObjectAccess::isPropertyGettable($this->dummyObject, $property));
474  }
475 
479  public function propertyGettableTestValues()
480  {
481  return [
482  ['publicProperty', true],
483  ['property', true],
484  ['booleanProperty', true],
485  ['anotherBooleanProperty', true],
486  ['privateProperty', false],
487  ['writeOnlyMagicProperty', false]
488  ];
489  }
490 
495  {
496  $arrayObject = new \ArrayObject();
497  $arrayObject['key'] = 'v';
498  $this->assertTrue(ObjectAccess::isPropertyGettable($arrayObject, 'key'));
499  $this->assertFalse(ObjectAccess::isPropertyGettable($arrayObject, 'undefinedKey'));
500  }
501 
506  {
507  $stdClassObject = new \stdClass();
508  $stdClassObject->property = 'foo';
509  $this->assertTrue(ObjectAccess::isPropertyGettable($stdClassObject, 'property'));
510  $this->assertFalse(ObjectAccess::isPropertyGettable($stdClassObject, 'undefinedProperty'));
511  }
512 
517  {
518  $alternativeObject = new DummyClassWithGettersAndSetters();
519  $alternativeObject->setProperty('test');
520  $this->dummyObject->setProperty2($alternativeObject);
521  $expected = 'test';
522  $actual = ObjectAccess::getPropertyPath($this->dummyObject, 'property2.property');
523  $this->assertEquals($expected, $actual);
524  }
525 
530  {
531  $alternativeObject = new DummyClassWithGettersAndSetters();
532  $alternativeObject->setProperty(new \stdClass());
533  $this->dummyObject->setProperty2($alternativeObject);
534  $this->assertNull(ObjectAccess::getPropertyPath($this->dummyObject, 'property2.property.not.existing'));
535  }
536 
541  {
542  $string = 'Hello world';
543  $this->assertNull(ObjectAccess::getPropertyPath($string, 'property2'));
544  }
545 
550  {
551  $object = new \stdClass();
552  $object->foo = 'Hello World';
553  $this->assertNull(ObjectAccess::getPropertyPath($object, 'foo.bar'));
554  }
555 }
static isPropertyGettable($object, $propertyName)
static isPropertySettable($object, $propertyName)
static getProperty($subject, $propertyName, $forceDirectAccess=false)
static getPropertyPath($subject, $propertyPath)
static setProperty(&$subject, $propertyName, $propertyValue, $forceDirectAccess=false)