8000 bug #58963 [PropertyInfo] Fix write visibility for Asymmetric Visibil… · symfony/symfony@ec691c8 · GitHub
[go: up one dir, main page]

Skip to content

Commit ec691c8

Browse files
bug #58963 [PropertyInfo] Fix write visibility for Asymmetric Visibility and Virtual Properties (xabbuh, pan93412)
This PR was merged into the 5.4 branch. Discussion ---------- [PropertyInfo] Fix write visibility for Asymmetric Visibility and Virtual Properties | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix #58556 | License | MIT - [ ] Rebase after #58959 and #58962 is merged. Commits ------- 964bf1f [PropertyInfo] Fix write visibility for Asymmetric Visibility and Virtual Properties
2 parents 294a39f + 964bf1f commit ec691c8

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -617,12 +617,18 @@ private function isAllowedProperty(string $class, string $property, bool $writeA
617617
try {
618618
$reflectionProperty = new \ReflectionProperty($class, $property);
619619

620-
if (\PHP_VERSION_ID >= 80100 && $writeAccessRequired && $reflectionProperty->isReadOnly()) {
621-
return false;
622-
}
620+
if ($writeAccessRequired) {
621+
if (\PHP_VERSION_ID >= 80100 && $reflectionProperty->isReadOnly()) {
622+
return false;
623+
}
624+
625+
if (\PHP_VERSION_ID >= 80400 && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) {
626+
return false;
627+
}
623628

624-
if (\PHP_VERSION_ID >= 80400 && $writeAccessRequired && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) {
625-
return false;
629+
if (\PHP_VERSION_ID >= 80400 &&$reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
630+
return false;
631+
}
626632
}
627633

628634
return (bool) ($reflectionProperty->getModifiers() & $this->propertyReflectionFlags);
@@ -863,6 +869,20 @@ private function getReadVisiblityForMethod(\ReflectionMethod $reflectionMethod):
863869

864870
private function getWriteVisiblityForProperty(\ReflectionProperty $reflectionProperty): string
865871
{
872+
if (\PHP_VERSION_ID >= 80400) {
873+
if ($reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
874+
return PropertyWriteInfo::VISIBILITY_PRIVATE;
875+
}
876+
877+
if ($reflectionProperty->isPrivateSet()) {
878+
return PropertyWriteInfo::VISIBILITY_PRIVATE;
879+
}
880+
881+
if ($reflectionProperty->isProtectedSet()) {
882+
return PropertyWriteInfo::VISIBILITY_PROTECTED;
883+
}
884+
}
885+
866886
if ($reflectionProperty->isPrivate()) {
867887
return PropertyWriteInfo::VISIBILITY_PRIVATE;
868888
}

src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy;
2929
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy;
3030
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy;
31+
use Symfony\Component\PropertyInfo\Tests\Fixtures\VirtualProperties;
3132
use Symfony\Component\PropertyInfo\Type;
3233

3334
/**
@@ -699,4 +700,67 @@ public function testAsymmetricVisibility()
699700
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
700701
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
701702
}
703+
704+
/**
705+
* @requires PHP 8.4
706+
*/
707+
public function testVirtualProperties()
708+
{
709+
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualNoSetHook'));
710+
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualSetHookOnly'));
711+
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualHook'));
712+
$this->assertFalse($this->extractor->isWritable(VirtualProperties::class, 'virtualNoSetHook'));
713+
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualSetHookOnly'));
714+
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualHook'));
715+
}
716+
717+
/**
718+
* @dataProvider provideAsymmetricVisibilityMutator
719+
* @requires PHP 8.4
720+
*/
721+
public function testAsymmetricVisibilityMutator(string $property, string $readVisibility, string $writeVisibility)
722+
{
723+
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
724+
$readMutator = $extractor->getReadInfo(AsymmetricVisibility::class, $property);
725+
$writeMutator = $extractor->getWriteInfo(AsymmetricVisibility::class, $property, [
726+
'enable_getter_setter_extraction' => true,
727+
]);
728+
729+
$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
730+
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
731+
$this->assertSame($readVisibility, $readMutator->getVisibility());
732+
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
733+
}
734+
735+
public static function provideAsymmetricVisibilityMutator(): iterable
736+
{
737+
yield ['publicPrivate', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
738+
yield ['publicProtected', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PROTECTED];
739+
yield ['protectedPrivate', PropertyReadInfo::VISIBILITY_PROTECTED, PropertyWriteInfo::VISIBILITY_PRIVATE];
740+
}
741+
742+
/**
743+
* @dataProvider provideVirtualPropertiesMutator
744+
* @requires PHP 8.4
745+
*/
746+
public function testVirtualPropertiesMutator(string $property, string $readVisibility, string $writeVisibility)
747+
{
748+
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
749+
$readMutator = $extractor->getReadInfo(VirtualProperties::class, $property);
750+
$writeMutator = $extractor->getWriteInfo(VirtualProperties::class, $property, [
751+
'enable_getter_setter_extraction' => true,
752+
]);
753+
754+
$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
755+
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
756+
$this->assertSame($readVisibility, $readMutator->getVisibility());
757+
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
758+
}
759+
760+
public static function provideVirtualPropertiesMutator(): iterable
761+
{
762+
yield ['virtualNoSetHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
763+
yield ['virtualSetHookOnly', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
764+
yield ['virtualHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
765+
}
702766
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Tests\Fixtures;
13+
14+
class VirtualProperties
15+
{
16+
public bool $virtualNoSetHook { get => true; }
17+
public bool $virtualSetHookOnly { set => $value; }
18+
public bool $virtualHook { get => true; set => $value; }
19+
}

0 commit comments

Comments
 (0)
0