-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[PropertyAccess][PropertyInfo] customize behavior for property hooks on read and write #59246
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
base: 7.4
Are you sure you want to change the base?
Conversation
c4ef85d
to
399efcf
Compare
public bool $virtualSetHookOnly { set => $value; } | ||
public bool $virtualHook { get => true; set => $value; } | ||
public bool $virtualSetHookOnly { set (bool $value) { } } | ||
public bool $virtualHook { get => true; set (bool $value) { } } |
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 updated this fixtures because PHP does not report these properties as Virtual, see reproducer
0900ef7
to
379e96c
Compare
Tests are failing on 8.2 / highest deps because of other components (Bridge\twig, Bundle\FrameworkBundle, Component\HttpKernel). It leaves us with psalm for which PHP 8.4 support can be tracked here: vimeo/psalm#11107. Not sure how to deal with it here. |
src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
Outdated
Show resolved
Hide resolved
a396856
to
73f2e3f
Compare
@mtarld Thanks for your feedback, I think everything is covered now :) |
src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
Outdated
Show resolved
Hide resolved
bd1f4a1
to
0c5bb13
Compare
src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
Outdated
Show resolved
Hide resolved
0c5bb13
to
0eaa1d4
Compare
Thanks @mtarld for your previous review, sorry I took so long to make the changes. |
0eaa1d4
to
0d100a9
Compare
@OskarStark thanks for your feedback, I renamed the variables. |
Hi @mtarld do you think we might be good on this pull request ? Thanks ! 🙏 |
Would it be sufficient to split those PR into two separate feature PRs? |
src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
Outdated
Show resolved
Hide resolved
if ($hasProperty && (($r = $reflClass->getProperty($property))->getModifiers() & $this->propertyReflectionFlags)) { | ||
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisibilityForProperty($r), $r->isStatic(), true, $this->propertyHasHook($r, 'get'), $this->propertyIsVirtual($r)); | ||
} | ||
|
||
if ($hasProperty && (($r = $reflClass->getProperty($property))->getModifiers() & $this->propertyReflectionFlags)) { | ||
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, $this->getReadVisibilityForProperty($r), $r->isStatic(), true); | ||
if ($allowMagicGet && $reflClass->hasMethod('__get') && (($r = $reflClass->getMethod('__get'))->getModifiers() & $this->methodReflectionFlags)) { | ||
return new PropertyReadInfo(PropertyReadInfo::TYPE_PROPERTY, $property, PropertyReadInfo::VISIBILITY_PUBLIC, false, $r->returnsReference(), false, false); | ||
} |
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 these if
s has been inverted?
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.
See that comment #59246 (comment)
0d100a9
to
3990cad
Compare
@mtarld thanks for the feedback |
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 not sure I like this new feature of PropertyAccess. Until now, PropertyAccess never accesses the internal state of the object through Reflection (Reflection is used only for instrospection of the class structure). All reads and writes are done through the public API of the class until now.
@@ -47,6 +47,10 @@ class PropertyAccessor implements PropertyAccessorInterface | |||
/** @var int Allow magic __call methods */ | |||
public const MAGIC_CALL = ReflectionExtractor::ALLOW_MAGIC_CALL; | |||
|
|||
public const BYPASS_PROPERTY_HOOK_NONE = 0; | |||
public const BYPASS_PROPERTY_HOOK_READ = 1 << 1; | |||
public const BYPASS_PROPERTY_HOOK_WRITE = 1 << 0; |
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.
constants for a bit mask are generally defined in increasing order (so that new cases are added at the end of the list). This reverse order is unusual to me
3990cad
to
7963304
Compare
…ty hooks on read and write
7963304
to
e4901fb
Compare
@stof I thought it would be very relevant in this component as this follows new opportunities offered by the language, wdyt ? |
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.
LGTM, I just have minor comments
@@ -1,6 +1,11 @@ | |||
CHANGELOG | |||
========= | |||
|
|||
7.3 |
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.
7.3 | |
7.4 |
* @param int-mask-of<self::BYPASS_PROPERTY_HOOK_*> $bypassPropertyHooks A bitwise combination of the BYPASS_PROPERTY_HOOK_* constants | ||
* to specify the hooks you want to bypass, | ||
* or self::BYPASS_PROPERTY_HOOK_NONE for none |
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.
looks like the previous arguments could also nicely benefit from similar int-mask-of
let's align them also
the text looks redundant to me:
* @param int-mask-of<self::BYPASS_PROPERTY_HOOK_*> $bypassPropertyHooks A bitwise combination of the BYPASS_PROPERTY_HOOK_* constants | |
* to specify the hooks you want to bypass, | |
* or self::BYPASS_PROPERTY_HOOK_NONE for none | |
* @param int-mask-of<self::BYPASS_PROPERTY_HOOK_*> $bypassPropertyHooks |
7.3 | ||
--- | ||
|
||
* Allow to customize behavior for property hooks on read and write |
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.
* Allow to customize behavior for property hooks on read and write | |
* Add `PropertyAccessor::BYPASS_PROPERTY_HOOK_*` constants to customize behavior for property hooks |
@@ -894,6 +894,16 @@ private function isMethodAccessible(\ReflectionClass $class, string $methodName, | |||
return [false, $errors]; | |||
} | |||
|
|||
private function propertyHasHook(\ReflectionProperty $property, string $hookType): bool | |||
{ | |||
return \PHP_VERSION_ID >= 80400 && $property->hasHook(\PropertyHookType::from($hookType)); |
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'd prefer inlining these two methods: they'd look needles to me on 8.0
@@ -17,7 +17,7 @@ | |||
], | |||
"require": { | |||
"php": ">=8.2", | |||
"symfony/property-info": "^6.4|^7.0" | |||
"symfony/property-info": "^7.3" |
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.
"symfony/property-info": "^7.3" | |
"symfony/property-info": "^7.4|^8.0" |
@@ -4,6 +4,7 @@ CHANGELOG | |||
7.3 | |||
--- | |||
|
|||
* Gather data from property hooks in ReflectionExtractor |
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.
* Gather data from property hooks in ReflectionExtractor | |
* Gather info about property hooks in ReflectionExtractor |
@xavierleune having property hooks in the language does not mean that accessing the backing value of a hook is a public API of the class. Thinking about this again, I'm actually voting -1 on this feature. I'd like to keep the existing behavior of the component that always uses the public API of the class to access things. This makes things a lot easier to reason about (and to document). |
This pull requests adds 2 new (tiny) features:
Have a nice day!