8000 feature #30704 [PropertyInfo] Add accessor and mutator extractor inte… · symfony/symfony@a1e4222 · GitHub
[go: up one dir, main page]

Skip to content

Commit a1e4222

Browse 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

13 files changed

+807
-342
lines changed

src/Symfony/Component/PropertyAccess/CHANGELOG.md

Lines 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

Lines changed: 81 additions & 299 deletions
Large diffs are not rendered by default.

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

Lines 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

Lines 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

Lines 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

Lines 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

Lines changed: 333 additions & 39 deletions
Large diffs are not rendered by default.
Lines 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+
}
Lines changed: 25 additions & 0 deletions
< 2851 td data-grid-cell-id="diff-5f9b6777bc8f9dea6a822082cb2e34e08223649607765f021870da09a8ffa6fc-empty-1-1" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
+
<?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+
}
Lines 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< 10000 /code>+
/**
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+
}
Lines 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