[PropertyInfo] Support singular adder and remover

This commit is contained in:
Kévin Dunglas 2016-03-28 11:03:47 +02:00
parent 3a165e551d
commit 4cbb60c382
No known key found for this signature in database
GPG Key ID: 4D04EBEF06AAF3A6
4 changed files with 77 additions and 13 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\PropertyInfo\Extractor; namespace Symfony\Component\PropertyInfo\Extractor;
use Symfony\Component\Inflector\Inflector;
use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
@ -55,13 +56,17 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
return; return;
} }
$reflectionProperties = $reflectionClass->getProperties();
$properties = array(); $properties = array();
foreach ($reflectionClass->getProperties(\ReflectionProperty::IS_PUBLIC) as $reflectionProperty) { foreach ($reflectionProperties as $reflectionProperty) {
$properties[$reflectionProperty->name] = true; if ($reflectionProperty->isPublic()) {
$properties[$reflectionProperty->name] = true;
}
} }
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
$propertyName = $this->getPropertyName($reflectionMethod->name); $propertyName = $this->getPropertyName($reflectionMethod->name, $reflectionProperties);
if (!$propertyName || isset($properties[$propertyName])) { if (!$propertyName || isset($properties[$propertyName])) {
continue; continue;
} }
@ -312,17 +317,25 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
private function getMutatorMethod($class, $property) private function getMutatorMethod($class, $property)
{ {
$ucProperty = ucfirst($property); $ucProperty = ucfirst($property);
$ucSingulars = (array) Inflector::singularize($ucProperty);
foreach (self::$mutatorPrefixes as $prefix) { foreach (self::$mutatorPrefixes as $prefix) {
try { $names = array($ucProperty);
$reflectionMethod = new \ReflectionMethod($class, $prefix.$ucProperty); if (in_array($prefix, self::$arrayMutatorPrefixes)) {
$names = array_merge($names, $ucSingulars);
}
// Parameter can be optional to allow things like: method(array $foo = null) foreach ($names as $name) {
if ($reflectionMethod->getNumberOfParameters() >= 1) { try {
return array($reflectionMethod, $prefix); $reflectionMethod = new \ReflectionMethod($class, $prefix.$name);
// Parameter can be optional to allow things like: method(array $foo = null)
if ($reflectionMethod->getNumberOfParameters() >= 1) {
return array($reflectionMethod, $prefix);
}
} catch (\ReflectionException $reflectionException) {
// Try the next one if method does not exist
} }
} catch (\ReflectionException $reflectionException) {
// Try the next prefix if the method doesn't exist
} }
} }
} }
@ -330,15 +343,28 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
/** /**
* Extracts a property name from a method name. * Extracts a property name from a method name.
* *
* @param string $methodName * @param string $methodName
* @param \ReflectionProperty[] $reflectionProperties
* *
* @return string * @return string
*/ */
private function getPropertyName($methodName) private function getPropertyName($methodName, array $reflectionProperties)
{ {
$pattern = implode('|', array_merge(self::$accessorPrefixes, self::$mutatorPrefixes)); $pattern = implode('|', array_merge(self::$accessorPrefixes, self::$mutatorPrefixes));
if (preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) { if (preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) {
if (!in_array($matches[1], self::$arrayMutatorPrefixes)) {
return $matches[2];
}
foreach ($reflectionProperties as $reflectionProperty) {
foreach ((array) Inflector::singularize($reflectionProperty->name) as $name) {
if (strtolower($name) === strtolower($matches[2])) {
return $reflectionProperty->name;
}
}
}
return $matches[2]; return $matches[2];
} }
} }

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\PropertyInfo\Tests\Extractor; namespace Symfony\Component\PropertyInfo\Tests\Extractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\Tests\Fixtures\AdderRemoverDummy;
use Symfony\Component\PropertyInfo\Type; use Symfony\Component\PropertyInfo\Type;
/** /**
@ -119,4 +120,11 @@ class ReflectionExtractorTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array())); $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array()));
$this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array())); $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array()));
} }
public function testSingularize()
{
$this->assertTrue($this->extractor->isWritable(AdderRemoverDummy::class, 'analyses'));
$this->assertTrue($this->extractor->isWritable(AdderRemoverDummy::class, 'feet'));
$this->assertEquals(array('analyses', 'feet'), $this->extractor->getProperties(AdderRemoverDummy::class));
}
} }

View File

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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;
/**
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class AdderRemoverDummy
{
private $analyses;
private $feet;
public function addAnalyse(Dummy $analyse)
{
}
public function removeFoot(Dummy $foot)
{
}
}

View File

@ -23,7 +23,8 @@
} }
], ],
"require": { "require": {
"php": ">=5.5.9" "php": ">=5.5.9",
"symfony/inflector": "~3.1"
}, },
"require-dev": { "require-dev": {
"symfony/serializer": "~2.8|~3.0", "symfony/serializer": "~2.8|~3.0",