[PropertyInfo] Added support for extracting type from constructor
This commit is contained in:
parent
b0facfec01
commit
adcb25ec01
@ -44,17 +44,19 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
private $mutatorPrefixes;
|
||||
private $accessorPrefixes;
|
||||
private $arrayMutatorPrefixes;
|
||||
private $enableConstructorExtraction;
|
||||
|
||||
/**
|
||||
* @param string[]|null $mutatorPrefixes
|
||||
* @param string[]|null $accessorPrefixes
|
||||
* @param string[]|null $arrayMutatorPrefixes
|
||||
*/
|
||||
public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null)
|
||||
public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null, bool $enableConstructorExtraction = true)
|
||||
{
|
||||
$this->mutatorPrefixes = null !== $mutatorPrefixes ? $mutatorPrefixes : self::$defaultMutatorPrefixes;
|
||||
$this->accessorPrefixes = null !== $accessorPrefixes ? $accessorPrefixes : self::$defaultAccessorPrefixes;
|
||||
$this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : self::$defaultArrayMutatorPrefixes;
|
||||
$this->enableConstructorExtraction = $enableConstructorExtraction;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,6 +109,13 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
if ($fromAccessor = $this->extractFromAccessor($class, $property)) {
|
||||
return $fromAccessor;
|
||||
}
|
||||
|
||||
if (
|
||||
$context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction &&
|
||||
$fromConstructor = $this->extractFromConstructor($class, $property)
|
||||
) {
|
||||
return $fromConstructor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,6 +194,40 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to extract type information from constructor.
|
||||
*
|
||||
* @return Type[]|null
|
||||
*/
|
||||
private function extractFromConstructor(string $class, string $property): ?array
|
||||
{
|
||||
try {
|
||||
$reflectionClass = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$constructor = $reflectionClass->getConstructor();
|
||||
|
||||
if (!$constructor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($constructor->getParameters() as $parameter) {
|
||||
if ($property !== $parameter->name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return array($this->extractFromReflectionType($parameter->getType()));
|
||||
}
|
||||
|
||||
if ($parentClass = $reflectionClass->getParentClass()) {
|
||||
return $this->extractFromConstructor($parentClass->getName(), $property);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function extractFromReflectionType(\ReflectionType $reflectionType): Type
|
||||
{
|
||||
$phpTypeOrClass = $reflectionType->getName();
|
||||
|
@ -114,6 +114,24 @@ class ReflectionExtractorTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetPropertiesPhp71()
|
||||
{
|
||||
$noPrefixExtractor = new ReflectionExtractor();
|
||||
|
||||
$this->assertSame(
|
||||
array(
|
||||
'string',
|
||||
'stringOrNull',
|
||||
'foo',
|
||||
'buz',
|
||||
'bar',
|
||||
'baz',
|
||||
'intWithAccessor',
|
||||
),
|
||||
$noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider typesProvider
|
||||
*/
|
||||
@ -171,9 +189,22 @@ class ReflectionExtractorTest extends TestCase
|
||||
array('bar', array(new Type(Type::BUILTIN_TYPE_INT, true))),
|
||||
array('baz', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))),
|
||||
array('donotexist', null),
|
||||
array('string', array(new Type(Type::BUILTIN_TYPE_STRING, false))),
|
||||
array('stringOrNull', array(new Type(Type::BUILTIN_TYPE_STRING, true))),
|
||||
array('intPrivate', array(new Type(Type::BUILTIN_TYPE_INT, false))),
|
||||
array('intWithAccessor', array(new Type(Type::BUILTIN_TYPE_INT, false))),
|
||||
);
|
||||
}
|
||||
|
||||
public function testExtractPhp71TypeWithParentConstructor()
|
||||
{
|
||||
$property = 'string';
|
||||
$type = array(new Type(Type::BUILTIN_TYPE_STRING, false));
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild', $property, array()));
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild2', $property, array()));
|
||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild3', $property, array()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getReadableProperties
|
||||
*/
|
||||
|
@ -16,6 +16,22 @@ namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
|
||||
*/
|
||||
class Php71Dummy
|
||||
{
|
||||
public $string;
|
||||
|
||||
public $stringOrNull;
|
||||
|
||||
private $intPrivate;
|
||||
|
||||
private $intWithAccessor;
|
||||
|
||||
public function __construct(string $string, ?string $stringOrNull, int $intPrivate, int $intWithAccessor)
|
||||
{
|
||||
$this->string = $string;
|
||||
$this->stringOrNull = $stringOrNull;
|
||||
$this->intPrivate = $intPrivate;
|
||||
$this->intWithAccessor = $intWithAccessor;
|
||||
}
|
||||
|
||||
public function getFoo(): ?array
|
||||
{
|
||||
}
|
||||
@ -31,4 +47,9 @@ class Php71Dummy
|
||||
public function addBaz(string $baz)
|
||||
{
|
||||
}
|
||||
|
||||
public function getIntWithAccessor()
|
||||
{
|
||||
return $this->intWithAccessor;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
<?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;
|
||||
|
||||
class Php71DummyParent
|
||||
{
|
||||
public $string;
|
||||
|
||||
public function __construct(string $string)
|
||||
{
|
||||
$this->string = $string;
|
||||
}
|
||||
}
|
||||
|
||||
class Php71DummyChild extends Php71DummyParent
|
||||
{
|
||||
public function __construct(string $string)
|
||||
{
|
||||
parent::__construct($string);
|
||||
}
|
||||
}
|
||||
|
||||
class Php71DummyChild2 extends Php71DummyParent
|
||||
{
|
||||
}
|
||||
|
||||
class Php71DummyChild3 extends Php71DummyParent
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('hello');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user