diff --git a/src/Symfony/Component/PropertyInfo/CHANGELOG.md b/src/Symfony/Component/PropertyInfo/CHANGELOG.md index 3595f75017c6d..ce7f220ce1dc1 100644 --- a/src/Symfony/Component/PropertyInfo/CHANGELOG.md +++ b/src/Symfony/Component/PropertyInfo/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.4 +--- + + * Make properties writable when a setter in camelCase exists, similar to the camelCase getter + 6.1 --- diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index ddd073593104a..ff86ef859d53d 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -205,6 +205,13 @@ public function isWritable(string $class, string $property, array $context = []) return true; } + // First test with the camelized property name + [$reflectionMethod] = $this->getMutatorMethod($class, $this->camelize($property)); + if (null !== $reflectionMethod) { + return true; + } + + // Otherwise check for the old way [$reflectionMethod] = $this->getMutatorMethod($class, $property); return null !== $reflectionMethod; diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index c1fa11fbf24e9..be7ee0b7728d3 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -26,6 +26,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\SnakeCaseDummy; use Symfony\Component\PropertyInfo\Type; /** @@ -409,6 +410,20 @@ public static function getWritableProperties() ]; } + public function testIsReadableSnakeCase() + { + $this->assertTrue($this->extractor->isReadable(SnakeCaseDummy::class, 'snake_property')); + $this->assertTrue($this->extractor->isReadable(SnakeCaseDummy::class, 'snake_readonly')); + } + + public function testIsWriteableSnakeCase() + { + $this->assertTrue($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_property')); + $this->assertFalse($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_readonly')); + // Ensure that it's still possible to write to the property using the (old) snake name + $this->assertTrue($this->extractor->isWritable(SnakeCaseDummy::class, 'snake_method')); + } + public function testSingularize() { $this->assertTrue($this->extractor->isWritable(AdderRemoverDummy::class, 'analyses')); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/SnakeCaseDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/SnakeCaseDummy.php new file mode 100644 index 0000000000000..7e46ddf729fed --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/SnakeCaseDummy.php @@ -0,0 +1,39 @@ + + * + * 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 SnakeCaseDummy +{ + private string $snake_property; + private string $snake_readOnly; + private string $snake_method; + + public function getSnakeProperty() + { + return $this->snake_property; + } + + public function getSnakeReadOnly() + { + return $this->snake_readOnly; + } + + public function setSnakeProperty($snake_property) + { + $this->snake_property = $snake_property; + } + + public function setSnake_method($snake_method) + { + $this->snake_method = $snake_method; + } +}