Skip to content

Commit 7ba526b

Browse files
committed
[PropertyInfo] Added support for extracting type from constructor
1 parent 07766b3 commit 7ba526b

File tree

4 files changed

+136
-4
lines changed

4 files changed

+136
-4
lines changed

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

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,16 @@ public function getProperties($class, array $context = array())
100100
*/
101101
public function getTypes($class, $property, array $context = array())
102102
{
103-
if ($fromMutator = $this->extractFromMutator($class, $property)) {
104-
return $fromMutator;
103+
if ($type = $this->extractFromMutator($class, $property)) {
104+
return $type;
105105
}
106106

107-
if ($fromAccessor = $this->extractFromAccessor($class, $property)) {
108-
return $fromAccessor;
107+
if ($type = $this->extractFromAccessor($class, $property)) {
108+
return $type;
109+
}
110+
111+
if ($type = $this->extractFromConstructor($class, $property)) {
112+
return $type;
109113
}
110114
}
111115

@@ -185,6 +189,40 @@ private function extractFromAccessor(string $class, string $property): ?array
185189
return null;
186190
}
187191

192+
/**
193+
* Tries to extract type information from constructor.
194+
*
195+
* @return Type[]|null
196+
*/
197+
private function extractFromConstructor(string $class, string $property): ?array
198+
{
199+
try {
200+
$reflectionClass = new \ReflectionClass($class);
201+
} catch (\ReflectionException $e) {
202+
return null;
203+
}
204+
205+
$constructor = $reflectionClass->getConstructor();
206+
207+
if (!$constructor) {
208+
return null;
209+
}
210+
211+
foreach ($constructor->getParameters() as $parameter) {
212+
if ($property !== $parameter->name) {
213+
continue;
214+
}
215+
216+
return array($this->extractFromReflectionType($parameter->getType()));
217+
}
218+
219+
if ($reflectionClass->getParentClass()) {
220+
return $this->extractFromConstructor($reflectionClass->getParentClass()->getName(), $property);
221+
}
222+
223+
return null;
224+
}
225+
188226
private function extractFromReflectionType(\ReflectionType $reflectionType): Type
189227
{
190228
$phpTypeOrClass = $reflectionType->getName();

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,24 @@ public function testGetPropertiesWithNoPrefixes()
113113
);
114114
}
115115

116+
public function testGetPropertiesPhp71()
117+
{
118+
$noPrefixExtractor = new ReflectionExtractor();
119+
120+
$this->assertSame(
121+
array(
122+
'string',
123+
'stringOrNull',
124+
'foo',
125+
'buz',
126+
'bar',
127+
'baz',
128+
'intWithAccessor',
129+
),
130+
$noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71Dummy')
131+
);
132+
}
133+
116134
/**
117135
* @dataProvider typesProvider
118136
*/
@@ -170,9 +188,22 @@ public function php71TypesProvider()
170188
array('bar', array(new Type(Type::BUILTIN_TYPE_INT, true))),
171189
array('baz', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))),
172190
array('donotexist', null),
191+
array('string', array(new Type(Type::BUILTIN_TYPE_STRING, false))),
192+
array('stringOrNull', array(new Type(Type::BUILTIN_TYPE_STRING, true))),
193+
array('intPrivate', array(new Type(Type::BUILTIN_TYPE_INT, false))),
194+
array('intWithAccessor', array(new Type(Type::BUILTIN_TYPE_INT, false))),
173195
);
174196
}
175197

198+
public function testExtractPhp71TypeWithParentConstructor()
199+
{
200+
$property = 'string';
201+
$type = array(new Type(Type::BUILTIN_TYPE_STRING, false));
202+
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild', $property, array()));
203+
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild2', $property, array()));
204+
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php71DummyChild3', $property, array()));
205+
}
206+
176207
/**
177208
* @dataProvider getReadableProperties
178209
*/

src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php71Dummy.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
*/
1717
class Php71Dummy
1818
{
19+
public $string;
20+
21+
public $stringOrNull;
22+
23+
private $intPrivate;
24+
25+
private $intWithAccessor;
26+
27+
public function __construct(string $string, ?string $stringOrNull, int $intPrivate, int $intWithAccessor)
28+
{
29+
$this->string = $string;
30+
$this->stringOrNull = $stringOrNull;
31+
$this->intPrivate = $intPrivate;
32+
$this->intWithAccessor = $intWithAccessor;
33+
}
34+
1935
public function getFoo(): ?array
2036
{
2137
}
@@ -31,4 +47,9 @@ public function setBar(?int $bar)
3147
public function addBaz(string $baz)
3248
{
3349
}
50+
51+
public function getIntWithAccessor()
52+
{
53+
return $this->intWithAccessor;
54+
}
3455
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 Php71DummyParent
15+
{
16+
public $string;
17+
18+
public function __construct(string $string)
19+
{
20+
$this->string = $string;
21+
}
22+
}
23+
24+
class Php71DummyChild extends Php71DummyParent
25+
{
26+
public function __construct(string $string)
27+
{
28+
parent::__construct($string);
29+
}
30+
}
31+
32+
class Php71DummyChild2 extends Php71DummyParent
33+
{
34+
}
35+
36+
class Php71DummyChild3 extends Php71DummyParent
37+
{
38+
public function __construct()
39+
{
40+
parent::__construct('hello');
41+
}
42+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy