Skip to content

Commit

Permalink
[PropertyInfo] Fix write visibility for Asymmetric Visibility and Vir…
Browse files Browse the repository at this point in the history
…tual Properties
  • Loading branch information
pan93412 authored and nicolas-grekas committed Nov 25, 2024
1 parent 9543e69 commit a039629
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 5 deletions.
30 changes: 25 additions & 5 deletions Extractor/ReflectionExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,12 +617,18 @@ private function isAllowedProperty(string $class, string $property, bool $writeA
try {
$reflectionProperty = new \ReflectionProperty($class, $property);

if (\PHP_VERSION_ID >= 80100 && $writeAccessRequired && $reflectionProperty->isReadOnly()) {
return false;
}
if ($writeAccessRequired) {
if (\PHP_VERSION_ID >= 80100 && $reflectionProperty->isReadOnly()) {
return false;
}

if (\PHP_VERSION_ID >= 80400 && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) {
return false;
}

if (\PHP_VERSION_ID >= 80400 && $writeAccessRequired && ($reflectionProperty->isProtectedSet() || $reflectionProperty->isPrivateSet())) {
return false;
if (\PHP_VERSION_ID >= 80400 &&$reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
return false;
}
}

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

private function getWriteVisiblityForProperty(\ReflectionProperty $reflectionProperty): string
{
if (\PHP_VERSION_ID >= 80400) {
if ($reflectionProperty->isVirtual() && !$reflectionProperty->hasHook(\PropertyHookType::Set)) {
return PropertyWriteInfo::VISIBILITY_PRIVATE;
}

if ($reflectionProperty->isPrivateSet()) {
return PropertyWriteInfo::VISIBILITY_PRIVATE;
}

if ($reflectionProperty->isProtectedSet()) {
return PropertyWriteInfo::VISIBILITY_PROTECTED;
}
}

if ($reflectionProperty->isPrivate()) {
return PropertyWriteInfo::VISIBILITY_PRIVATE;
}
Expand Down
64 changes: 64 additions & 0 deletions Tests/Extractor/ReflectionExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy;
use Symfony\Component\PropertyInfo\Tests\Fixtures\VirtualProperties;
use Symfony\Component\PropertyInfo\Type;

/**
Expand Down Expand Up @@ -699,4 +700,67 @@ public function testAsymmetricVisibility()
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'publicProtected'));
$this->assertFalse($this->extractor->isWritable(AsymmetricVisibility::class, 'protectedPrivate'));
}

/**
* @requires PHP 8.4
*/
public function testVirtualProperties()
{
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualNoSetHook'));
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualSetHookOnly'));
$this->assertTrue($this->extractor->isReadable(VirtualProperties::class, 'virtualHook'));
$this->assertFalse($this->extractor->isWritable(VirtualProperties::class, 'virtualNoSetHook'));
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualSetHookOnly'));
$this->assertTrue($this->extractor->isWritable(VirtualProperties::class, 'virtualHook'));
}

/**
* @dataProvider provideAsymmetricVisibilityMutator
* @requires PHP 8.4
*/
public function testAsymmetricVisibilityMutator(string $property, string $readVisibility, string $writeVisibility)
{
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
$readMutator = $extractor->getReadInfo(AsymmetricVisibility::class, $property);
$writeMutator = $extractor->getWriteInfo(AsymmetricVisibility::class, $property, [
'enable_getter_setter_extraction' => true,
]);

$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
$this->assertSame($readVisibility, $readMutator->getVisibility());
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
}

public static function provideAsymmetricVisibilityMutator(): iterable
{
yield ['publicPrivate', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
yield ['publicProtected', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PROTECTED];
yield ['protectedPrivate', PropertyReadInfo::VISIBILITY_PROTECTED, PropertyWriteInfo::VISIBILITY_PRIVATE];
}

/**
* @dataProvider provideVirtualPropertiesMutator
* @requires PHP 8.4
*/
public function testVirtualPropertiesMutator(string $property, string $readVisibility, string $writeVisibility)
{
$extractor = new ReflectionExtractor(null, null, null, true, ReflectionExtractor::ALLOW_PUBLIC | ReflectionExtractor::ALLOW_PROTECTED | ReflectionExtractor::ALLOW_PRIVATE);
$readMutator = $extractor->getReadInfo(VirtualProperties::class, $property);
$writeMutator = $extractor->getWriteInfo(VirtualProperties::class, $property, [
'enable_getter_setter_extraction' => true,
]);

$this->assertSame(PropertyReadInfo::TYPE_PROPERTY, $readMutator->getType());
$this->assertSame(PropertyWriteInfo::TYPE_PROPERTY, $writeMutator->getType());
$this->assertSame($readVisibility, $readMutator->getVisibility());
$this->assertSame($writeVisibility, $writeMutator->getVisibility());
}

public static function provideVirtualPropertiesMutator(): iterable
{
yield ['virtualNoSetHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PRIVATE];
yield ['virtualSetHookOnly', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
yield ['virtualHook', PropertyReadInfo::VISIBILITY_PUBLIC, PropertyWriteInfo::VISIBILITY_PUBLIC];
}
}
19 changes: 19 additions & 0 deletions Tests/Fixtures/VirtualProperties.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\PropertyInfo\Tests\Fixtures;

class VirtualProperties
{
public bool $virtualNoSetHook { get => true; }
public bool $virtualSetHookOnly { set => $value; }
public bool $virtualHook { get => true; set => $value; }
}

0 comments on commit a039629

Please sign in to comment.