-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[PropertyAccess] Allow custom property accessors #22190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
77b0366
to
66e6b48
Compare
{ | ||
$classMetadata = new ClassMetadata('c'); | ||
|
||
$a1 = $this->createMock('Symfony\Component\PropertyAccess\Mapping\PropertyMetadata'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to fail on PHP 5.5 & PHPUnit 4.8.35. ClassMetadataTest
extends PHPUnit\Framework\TestCase
which implements that method, so I'm not sure on how to solve this. It doesn't fail on any other scenarios. Any ideas?
totally agree with you that Symfony needs some component for reading metadata. |
Ok. I think this PR is ready for review. Did we make the cut for Symfony 3.3? 😅 |
{ | ||
// Overwrite only if not defined | ||
if (null === $this->getter) { | ||
$this->getter = $propertyMetadata->getGetter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function call is not needed here.
/** | ||
* Merges another PropertyMetadata with the current one. | ||
* | ||
* @param PropertyMetadata $propertyMetadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@param self $propertyMetadata
.
Actually it could be self
in the signature as well but this is not common in the code base, so I don't if it should be done.
@@ -912,7 +936,7 @@ private function getPropertyPath($propertyPath) | |||
* | |||
* @return AdapterInterface | |||
* | |||
* @throws RuntimeException When the Cache Component isn't available | |||
* @throws \RuntimeException When the Cache Component isn't available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change should not target master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't recall making this change, I'll revert it. Thank you!
private function getPropertyMetadata($class, $property) | ||
{ | ||
if ($this->cacheItemPool) { | ||
$key = $class.'\\'.$property; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not using a dot as separator directly since it's gonna be replaced?
if ($this->classMetadataFactory) { | ||
$classMetadata = $this->classMetadataFactory->getMetadataFor($class); | ||
if ($classMetadata) { | ||
$metadataCollection = $classMetadata->getPropertyMetadataCollection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add a getMetadataForProperty($property)
method that would return the metadata or null and remove the overhead below, the block could then look like:
$metadata = null;
if ($this->classMetadataFactory && $classMetadata = $this->classMetadataFactory->getMetadataFor($class) ) {
$metadata = $classMetadata->getMetadataForProperty($property);
}
return $metadata;
/** | ||
* Merges a {@link ClassMetadata} into the current one. | ||
* | ||
* @param ClassMetadata $classMetadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@param self $classMetadata
|
||
$class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); | ||
|
||
if (class_exists($class) || interface_exists($class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return class_exists($class) || interface_exists($class)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😅
{ | ||
if ($metadata && $metadata->getAdder() && $metadata->getRemover()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't find anything in this PR related to this requirement, it should be clear somewhere that in one is set this other is required.
Although I feel like one should should be enough, perhaps allowing to mix adder and remover guessing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just mimicking the actual PropertyAccess
behavior, in which both methods must be defined to activate this kind of accessors. You're right, docs should warn about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to fix one of the accessor and let the component guess the other one, seems reasonable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! It would be awesome if it was covered by tests too to prevent regression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
66e6b48
to
d3eb07e
Compare
@HeahDude, thank you very much for the review! |
ce94b7d
to
0691fb2
Compare
@@ -133,6 +141,11 @@ class PropertyAccessor implements PropertyAccessorInterface | |||
private $cacheItemPool; | |||
|
|||
/** | |||
* @var MetadataFactoryInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing |null
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is really necessary? Then it should be also added to $classMetadataFactory
above...
0691fb2
to
58aad1f
Compare
@@ -158,11 +171,12 @@ class PropertyAccessor implements PropertyAccessorInterface | |||
* @param bool $throwExceptionOnInvalidIndex | |||
* @param CacheItemPoolInterface $cacheItemPool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, same here, missing the new argument by the way ;).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed! Thanks
58aad1f
to
5e8f0dd
Compare
3ec7ce5
to
2d9fc7a
Compare
Annotation names changed as per @HeahDude request. Suggestions welcomed! |
The CI builds don't seem to be happy. Can you have a look at the failing tests? |
Sure! |
e27b1b6
to
72943a1
Compare
Done |
72943a1
to
2f2ad49
Compare
* | ||
* @param PropertyMetadata $propertyMetadata | ||
*/ | ||
public function addPropertyMetadata(PropertyMetadata $propertyMetadata) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we can make this value object immutable? We do that for new VO (PSR-7 style, see the PropertyInfo component for instance).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be done. But I'm curious about what would be the benefits. This class is used internally only, it's not exposed outside the component. Some parts of this code are borrowed from the Serializer
component but I infer that the current implementation intent is to allow fast & easy merging of metadata from different sources and classes in the hierarchy.
I wonder if we should also take the changes proposed in #23789 into account. |
c228dbd
to
146916b
Compare
146916b
to
e6aa7f1
Compare
3.4 does not accept features anymore. |
It's a shame. Well, if someone wants to take this PR over, please go ahead. I don't think I'll be able to invest more time into it (too many rebases and changes since 3.1) at least until next summer. |
I believe #30248 will help here, as it introduce the concept of extracting Accessor / Extractor from the metadata |
…rface 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
#30704 has been merged |
We've just moved away from |
Here is the first of the two PR related to #18016. This implements changes on the
PropertyAccess
component and will be followed by another one leveraging the new features into theFrameworkBundle
.Now it is possible to override the property accessors (getters, setters, adders and removers) using annotations or YAML config files. Metadata is automatically cached in the pool configured for the property path cache.
Some examples of how to use the new feature:
Annotations:
YAML:
XML: