Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a1e4222

Browse filesBrowse files
committed
feature #30704 [PropertyInfo] Add accessor and mutator extractor interface and implementation on reflection (joelwurtz, Korbeil)
This PR was merged into the 5.1-dev branch. Discussion ---------- [PropertyInfo] Add accessor and mutator extractor interface and implementation on reflection | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #30248, partially: #22190, #18016, #5013, #9336, #5219, | License | MIT | Doc PR | TODO This PR brings accessor / mutator extraction on the PropertyInfo component, There is no link to existing code, as IMO it should be in another PR as this will add a dependency on property access to the property info component and not sure this is something wanted (although, it will reduce a lot of code base on the property access component as a lot of code seems to be duplicated) Code is extracted from #30248 also there is some new features (that can be removed if not wanted) * Allow extracting private accessor / mutator (will do a new PR that improve private extraction on reflection latter) * Allow extracting static accessor / mutators * Allow extracting constructor mutators Current implementation try to be as close as the PropertyAccess implementation and i did not reuse some methods already available in the class as there is some differences in implementation, but maybe it will be a good time to make this consistent (Looking forward to your input) ? Things that should be done in a new PR: * Linking property info to property access to remove a lot of duplicate code * Add a new system that allow adding Virtual Property based on this extractor Commits ------- 0a92dab Rebase, fix tests, review & update CHANGELOG fc25086 [PropertyInfo] Add accessor and mutator extractor interface and implementation on reflection
2 parents 9d7e622 + 0a92dab commit a1e4222
Copy full SHA for a1e4222

13 files changed

+807
-342
lines changed

‎src/Symfony/Component/PropertyAccess/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* Linking to PropertyInfo extractor to remove a lot of duplicate code
8+
49
4.4.0
510
-----
611

‎src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+81-299Lines changed: 81 additions & 299 deletions
Large diffs are not rendered by default.

‎src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ public function testIsWritableReturnsFalseIfNoAdderNorRemoverExists()
188188
public function testSetValueFailsIfAdderAndRemoverExistButValueIsNotTraversable()
189189
{
190190
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');
191-
$this->expectExceptionMessageRegExp('/Could not determine access type for property "axes" in class "Symfony\\\\Component\\\\PropertyAccess\\\\Tests\\\\PropertyAccessorCollectionTest_Car[^"]*": The property "axes" in class "Symfony\\\\Component\\\\PropertyAccess\\\\Tests\\\\PropertyAccessorCollectionTest_Car[^"]*" can be defined with the methods "addAxis\(\)", "removeAxis\(\)" but the new value must be an array or an instance of \\\\Traversable, "string" given./');
191+
$this->expectExceptionMessageRegExp('/The property "axes" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\PropertyAccessorCollectionTest_Car" can be defined with the methods "addAxis\(\)", "removeAxis\(\)" but the new value must be an array or an instance of \\\Traversable\./');
192192
$car = new PropertyAccessorCollectionTest_Car();
193193

194194
$this->propertyAccessor->setValue($car, 'axes', 'Not an array or Traversable');

‎src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ public function testRemoverWithoutAdder()
760760
public function testAdderAndRemoveNeedsTheExactParametersDefined()
761761
{
762762
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException');
763-
$this->expectExceptionMessageRegExp('/.*The method "addFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 0 arguments, but should accept only 1\. The method "removeFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 2 arguments, but should accept only 1\./');
763+
$this->expectExceptionMessageRegExp('/.*The method "addFoo" in class "Symfony\\\Component\\\PropertyAccess\\\Tests\\\Fixtures\\\TestAdderRemoverInvalidArgumentLength" requires 0 arguments, but should accept only 1\./');
764764
$object = new TestAdderRemoverInvalidArgumentLength();
765765
$this->propertyAccessor->setValue($object, 'foo', [1, 2]);
766766
}

‎src/Symfony/Component/PropertyAccess/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/composer.json
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": "^7.2.5",
20-
"symfony/inflector": "^4.4|^5.0"
20+
"symfony/inflector": "^4.4|^5.0",
21+
"symfony/property-info": "^5.1"
2122
},
2223
"require-dev": {
2324
"symfony/cache": "^4.4|^5.0"

‎src/Symfony/Component/PropertyInfo/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* Add support for extracting accessor and mutator via PHP Reflection
8+
49
4.3.0
510
-----
611

‎src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
+333-39Lines changed: 333 additions & 39 deletions
Large diffs are not rendered by default.
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo;
13+
14+
/**
15+
* The property read info tells how a property can be read.
16+
*
17+
* @author Joel Wurtz <jwurtz@jolicode.com>
18+
*
19+
* @internal
20+
*/
21+
final class PropertyReadInfo
22+
{
23+
public const TYPE_METHOD = 'method';
24+
public const TYPE_PROPERTY = 'property';
25+
26+
public const VISIBILITY_PUBLIC = 'public';
27+
public const VISIBILITY_PROTECTED = 'protected';
28+
public const VISIBILITY_PRIVATE = 'private';
29+
30+
private $type;
31+
32+
private $name;
33+
34+
private $visibility;
35+
36+
private $static;
37+
38+
private $byRef;
39+
40+
public function __construct(string $type, string $name, string $visibility, bool $static, bool $byRef)
41+
{
42+
$this->type = $type;
43+
$this->name = $name;
44+
$this->visibility = $visibility;
45+
$this->static = $static;
46+
$this->byRef = $byRef;
47+
}
48+
49+
/**
50+
* Get type of access.
51+
*/
52+
public function getType(): string
53+
{
54+
return $this->type;
55+
}
56+
57+
/**
58+
* Get name of the access, which can be a method name or a property name, depending on the type.
59+
*/
60+
public function getName(): string
61+
{
62+
return $this->name;
63+
}
64+
65+
public function getVisibility(): string
66+
{
67+
return $this->visibility;
68+
}
69+
70+
public function isStatic(): bool
71+
{
72+
return $this->static;
73+
}
74+
75+
/**
76+
* Whether this accessor can be accessed by reference.
77+
*/
78+
public function canBeReference(): bool
79+
{
80+
return $this->byRef;
81+
}
82+
}
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo;
13+
14+
/**
15+
* Extract read information for the property of a class.
16+
*
17+
* @author Joel Wurtz <jwurtz@jolicode.com>
18+
*/
19+
interface PropertyReadInfoExtractorInterface
20+
{
21+
/**
22+
* Get read information object for a given property of a class.
23+
*/
24+
public function getReadInfo(string $class, string $property, array $context = []): ?PropertyReadInfo;
25+
}
+123Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo;
13+
14+
/**
15+
* The write mutator defines how a property can be written.
16+
*
17+
* @author Joel Wurtz <jwurtz@jolicode.com>
18+
*
19+
* @internal
20+
*/
21+
final class PropertyWriteInfo
22+
{
23+
public const TYPE_NONE = 'none';
24+
public const TYPE_METHOD = 'method';
25+
public const TYPE_PROPERTY = 'property';
26+
public const TYPE_ADDER_AND_REMOVER = 'adder_and_remover';
27+
public const TYPE_CONSTRUCTOR = 'constructor';
28+
29+
public const VISIBILITY_PUBLIC = 'public';
30+
public const VISIBILITY_PROTECTED = 'protected';
31+
public const VISIBILITY_PRIVATE = 'private';
32+
33+
private $type;
34+
private $name;
35+
private $visibility;
36+
private $static;
37+
private $adderInfo;
38+
private $removerInfo;
39+
private $errors = [];
40+
41+
public function __construct(string $type = self::TYPE_NONE, string $name = null, string $visibility = null, bool $static = null)
42+
{
43+
$this->type = $type;
44+
$this->name = $name;
45+
$this->visibility = $visibility;
46+
$this->static = $static;
47+
}
48+
49+
public function getType(): string
50+
{
51+
return $this->type;
52+
}
53+
54+
public function getName(): string
55+
{
56+
if (null === $this->name) {
57+
throw new \LogicException("Calling getName() when having a mutator of type {$this->type} is not tolerated");
58+
}
59+
60+
return $this->name;
61+
}
62+
63+
public function setAdderInfo(self $adderInfo): void
64+
{
65+
$this->adderInfo = $adderInfo;
66+
}
67+
68+
public function getAdderInfo(): self
69+
{
70+
if (null === $this->adderInfo) {
71+
throw new \LogicException("Calling getAdderInfo() when having a mutator of type {$this->type} is not tolerated");
72+
}
73+
74+
return $this->adderInfo;
75+
}
76+
77+
public function setRemoverInfo(self $removerInfo): void
78+
{
79+
$this->removerInfo = $removerInfo;
80+
}
81+
82+
public function getRemoverInfo(): self
83+
{
84+
if (null === $this->removerInfo) {
85+
throw new \LogicException("Calling getRemoverInfo() when having a mutator of type {$this->type} is not tolerated");
86+
}
87+
88+
return $this->removerInfo;
89+
}
90+
91+
public function getVisibility(): string
92+
{
93+
if (null === $this->visibility) {
94+
throw new \LogicException("Calling getVisibility() when having a mutator of type {$this->type} is not tolerated");
95+
}
96+
97+
return $this->visibility;
98+
}
99+
100+
public function isStatic(): bool
101+
{
102+
if (null === $this->static) {
103+
throw new \LogicException("Calling isStatic() when having a mutator of type {$this->type} is not tolerated");
104+
}
105+
106+
return $this->static;
107+
}
108+
109+
public function setErrors(array $errors): void
110+
{
111+
$this->errors = $errors;
112+
}
113+
114+
public function getErrors(): array
115+
{
116+
return $this->errors;
117+
}
118+
119+
public function hasErrors(): bool
120+
{
121+
return (bool) \count($this->errors);
122+
}
123+
}
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\PropertyInfo;
13+
14+
/**
15+
* Extract write information for the property of a class.
16+
*
17+
* @author Joel Wurtz <jwurtz@jolicode.com>
18+
*/
19+
interface PropertyWriteInfoExtractorInterface
20+
{
21+
/**
22+
* Get write information object for a given property of a class.
23+
*/
24+
public function getWriteInfo(string $class, string $property, array $context = []): ?PropertyWriteInfo;
25+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.