Skip to content

Commit 58d9b3d

Browse files
authored
FormTypeGuesser by PropertyInfo (#40)
* FormTypeGuesser by PropertyInfo * ~ fix coding standard composer.json * ~ test wrong type * Update composer.json bump minimum property-info version * ~ fix wrong type test * dependency-analysis only with higher php versions * * use phpDocumentor as backup * ~ fix guesser * + fix tests * ~ fix dependency analysis * ~ cleanup * ~ fixup static analysis
1 parent 94ba8c5 commit 58d9b3d

File tree

6 files changed

+51
-23
lines changed

6 files changed

+51
-23
lines changed

.github/workflows/build.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ jobs:
5353
strategy:
5454
matrix:
5555
php-version:
56-
- "7.4"
57-
- "8.0"
5856
- "8.1"
5957
- "8.2"
6058

@@ -66,10 +64,6 @@ jobs:
6664
- "^5.4"
6765
- "^6.0"
6866

69-
exclude:
70-
- php-version: "7.4"
71-
symfony: "^6.0"
72-
7367
steps:
7468
- name: "Checkout"
7569
uses: "actions/checkout@v3"

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
],
1212
"require": {
1313
"php": ">=7.4",
14-
"brick/reflection": "^0.4",
1514
"doctrine/dbal": "^3.4",
1615
"doctrine/doctrine-bundle": "^1.9 || ^2.0",
1716
"dragonmantank/cron-expression": "^2.2 || ^3.0",
@@ -20,11 +19,13 @@
2019
"symfony/form": "^4.4 || ^5.4 || ^6.0",
2120
"symfony/http-kernel": "^4.4 || ^5.4 || ^6.0",
2221
"symfony/options-resolver": "^4.4 || ^5.4 || ^6.0",
22+
"symfony/property-info": "^4.4.49 || ^5.4 || ^6.0",
2323
"symfony/validator": "^4.4 || ^5.4 || ^6.0",
2424
"webmozart/assert": "^1.10"
2525
},
2626
"require-dev": {
2727
"matthiasnoback/symfony-dependency-injection-test": "^4.3",
28+
"phpdocumentor/reflection-docblock": "^5.3",
2829
"phpunit/phpunit": "^9.5",
2930
"psalm/plugin-phpunit": "^0.16.1",
3031
"roave/security-advisories": "dev-latest",
@@ -43,8 +44,8 @@
4344
},
4445
"config": {
4546
"allow-plugins": {
46-
"ergebnis/composer-normalize": true,
47-
"dealerdirect/phpcodesniffer-composer-installer": false
47+
"dealerdirect/phpcodesniffer-composer-installer": false,
48+
"ergebnis/composer-normalize": true
4849
},
4950
"sort-packages": true
5051
},

src/Form/TypeGuesser/CronExpressionTypeGuesser.php

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44

55
namespace Setono\CronExpressionBundle\Form\TypeGuesser;
66

7-
use Brick\Reflection\ReflectionTools;
87
use Cron\CronExpression;
9-
use ReflectionClass;
10-
use ReflectionException;
118
use Setono\CronExpressionBundle\Form\Type\CronExpressionType;
129
use Symfony\Component\Form\FormTypeGuesserInterface;
1310
use Symfony\Component\Form\Guess\Guess;
1411
use Symfony\Component\Form\Guess\TypeGuess;
1512
use Symfony\Component\Form\Guess\ValueGuess;
13+
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
14+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
15+
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
16+
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
17+
use Symfony\Component\PropertyInfo\Type;
1618

1719
final class CronExpressionTypeGuesser implements FormTypeGuesserInterface
1820
{
21+
private PropertyTypeExtractorInterface $extractor;
22+
23+
public function __construct(?PropertyTypeExtractorInterface $extractor = null)
24+
{
25+
$this->extractor = $extractor ?? $this->createExtractor();
26+
}
1927
/**
2028
* @param string $class
2129
* @param string $property
@@ -26,20 +34,17 @@ public function guessType($class, $property): ?TypeGuess
2634
return null;
2735
}
2836

29-
try {
30-
$reflectionClass = new ReflectionClass($class);
31-
$reflectionProperty = $reflectionClass->getProperty($property);
32-
} catch (ReflectionException $e) {
37+
38+
$types = $this->extractor->getTypes($class, $property);
39+
if (!$types) {
3340
return null;
3441
}
35-
36-
$reflectionTools = new ReflectionTools();
37-
$propertyTypes = $reflectionTools->getPropertyTypes($reflectionProperty);
38-
39-
if (in_array(CronExpression::class, $propertyTypes, true)) {
40-
return new TypeGuess(CronExpressionType::class, [], Guess::VERY_HIGH_CONFIDENCE);
42+
foreach ($types as $type) {
43+
if (Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() &&
44+
CronExpression::class === $type->getClassName()) {
45+
return new TypeGuess(CronExpressionType::class, [], Guess::VERY_HIGH_CONFIDENCE);
46+
}
4147
}
42-
4348
return null;
4449
}
4550

@@ -69,4 +74,12 @@ public function guessPattern($class, $property): ?ValueGuess
6974
{
7075
return null;
7176
}
77+
78+
private function createExtractor(): PropertyTypeExtractorInterface
79+
{
80+
return new PropertyInfoExtractor([], [
81+
new PhpDocExtractor(),
82+
new ReflectionExtractor(),
83+
]);
84+
}
7285
}

src/Resources/config/services.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<service id="setono_cron_expression.form.type_guesser.cron_expression"
77
class="Setono\CronExpressionBundle\Form\TypeGuesser\CronExpressionTypeGuesser">
88
<tag name="form.type_guesser"/>
9+
<argument type="service" id="property_info"/>
910
</service>
1011
</services>
1112
</container>

tests/Form/TypeGuesser/CronExpressionTypeGuesserTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ public function it_returns_null_if_property_doesnt_exist(): void
4343
$this->assertNull($this->typeGuesser->guessType(StubWithNoPhpDoc::class, 'property2'));
4444
}
4545

46+
/**
47+
* @test
48+
*/
49+
public function it_returns_null_if_property_has_wrong_type(): void
50+
{
51+
$this->assertNull($this->typeGuesser->guessType(StubWithWrongType::class, 'property'));
52+
}
53+
4654
/**
4755
* @test
4856
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\CronExpressionBundle\Tests\Form\TypeGuesser;
6+
7+
final class StubWithWrongType
8+
{
9+
/** @var \DateTime */
10+
private $property;
11+
}

0 commit comments

Comments
 (0)