Skip to content

Commit b3b30ac

Browse files
committed
refactor(symfony): self-contained property_info chain with cache decoration
| Q | A | ------------- | --- | Branch? | main | Tickets | Fix #7876 | License | MIT | Doc PR | Closes api-platform/docs#2262 Drop the PropertyInfoPass compiler pass and register a self-sufficient extractor chain directly in api.php: ReflectionExtractor always, plus PhpDocExtractor and PhpStanExtractor under class_exists guards. Decorate api_platform.property_info with PropertyInfoCacheExtractor over the cache.property_info pool so metadata extraction is cached regardless of framework.property_info being enabled. Extractors remain tagged on property_info.* so ecosystem extractors (e.g. Doctrine's) still flow into the composite via tagged_iterator.
1 parent 6150a1f commit b3b30ac

6 files changed

Lines changed: 39 additions & 124 deletions

File tree

src/Symfony/Bundle/ApiPlatformBundle.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\JsonStreamerTransformerPass;
2525
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass;
2626
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MutatorPass;
27-
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\PropertyInfoPass;
2827
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\SerializerMappingLoaderPass;
2928
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass;
3029
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestMercureHubPass;
@@ -59,7 +58,6 @@ public function build(ContainerBuilder $container): void
5958
$container->addCompilerPass(new TestClientPass());
6059
$container->addCompilerPass(new TestMercureHubPass());
6160
$container->addCompilerPass(new AuthenticatorManagerPass());
62-
$container->addCompilerPass(new PropertyInfoPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 200);
6361
$container->addCompilerPass(new SerializerMappingLoaderPass());
6462
$container->addCompilerPass(new MutatorPass());
6563
// Must run after Symfony's TransformerPass so we can rely on the value_object_transformer tag being processed.

src/Symfony/Bundle/DependencyInjection/Compiler/PropertyInfoPass.php

Lines changed: 0 additions & 42 deletions
This file was deleted.

src/Symfony/Bundle/Resources/config/api.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@
4646
use ApiPlatform\Symfony\Routing\Router;
4747
use ApiPlatform\Symfony\Routing\SkolemIriConverter;
4848
use Negotiation\Negotiator;
49+
use phpDocumentor\Reflection\DocBlockFactory;
50+
use phpDocumentor\Reflection\Types\ContextFactory;
51+
use PHPStan\PhpDocParser\Parser\PhpDocParser;
52+
use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor;
53+
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
54+
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
55+
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
56+
use Symfony\Component\PropertyInfo\PropertyInfoCacheExtractor;
4957
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
5058
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
5159
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
@@ -69,6 +77,29 @@
6977

7078
$services->alias('api_platform.property_accessor', 'property_accessor');
7179

80+
$services->set('api_platform.property_info.reflection_extractor', ReflectionExtractor::class)
81+
->tag('property_info.list_extractor', ['priority' => -1000])
82+
->tag('property_info.type_extractor', ['priority' => -1002])
83+
->tag('property_info.access_extractor', ['priority' => -1000])
84+
->tag('property_info.initializable_extractor', ['priority' => -1000]);
85+
86+
if (class_exists(DocBlockFactory::class)) {
87+
$services->set('api_platform.property_info.php_doc_extractor', PhpDocExtractor::class)
88+
->tag('property_info.description_extractor', ['priority' => -1000])
89+
->tag('property_info.type_extractor', ['priority' => -1001])
90+
->tag('property_info.constructor_extractor', ['priority' => -1001]);
91+
}
92+
93+
if (class_exists(PhpDocParser::class) && class_exists(ContextFactory::class)) {
94+
$services->set('api_platform.property_info.phpstan_extractor', PhpStanExtractor::class)
95+
->tag('property_info.type_extractor', ['priority' => -1000])
96+
->tag('property_info.constructor_extractor', ['priority' => -1000]);
97+
}
98+
99+
$services->set('api_platform.property_info.constructor_extractor', ConstructorExtractor::class)
100+
->args([tagged_iterator('property_info.constructor_extractor')])
101+
->tag('property_info.type_extractor', ['priority' => -999]);
102+
72103
$services->set('api_platform.property_info', PropertyInfoExtractor::class)
73104
->args([
74105
tagged_iterator('property_info.list_extractor'),
@@ -78,6 +109,13 @@
78109
tagged_iterator('property_info.initializable_extractor'),
79110
]);
80111

112+
$services->set('api_platform.property_info.cache', PropertyInfoCacheExtractor::class)
113+
->decorate('api_platform.property_info')
114+
->args([
115+
service('.inner'),
116+
service('cache.property_info'),
117+
]);
118+
81119
$services->set('api_platform.negotiator', Negotiator::class);
82120

83121
$services->set('api_platform.resource_class_resolver', ResourceClassResolver::class)

src/Symfony/Tests/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ public function testCommonConfiguration(): void
190190
'api_platform.path_segment_name_generator.dash',
191191
'api_platform.path_segment_name_generator.underscore',
192192
'api_platform.metadata.inflector',
193+
'api_platform.property_info',
193194
'api_platform.resource_class_resolver',
194195
'api_platform.route_loader',
195196
'api_platform.router',
@@ -231,7 +232,6 @@ public function testCommonConfiguration(): void
231232
'api_platform.iri_converter',
232233
'api_platform.path_segment_name_generator',
233234
'api_platform.property_accessor',
234-
'api_platform.property_info',
235235
'api_platform.serializer',
236236
'api_platform.inflector',
237237
];

src/Symfony/Tests/Bundle/DependencyInjection/Compiler/PropertyInfoPassTest.php

Lines changed: 0 additions & 77 deletions
This file was deleted.

tests/Symfony/Bundle/ApiPlatformBundleTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\JsonStreamerTransformerPass;
2626
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MetadataAwareNameConverterPass;
2727
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\MutatorPass;
28-
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\PropertyInfoPass;
2928
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\SerializerMappingLoaderPass;
3029
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestClientPass;
3130
use ApiPlatform\Symfony\Bundle\DependencyInjection\Compiler\TestMercureHubPass;
@@ -58,7 +57,6 @@ public function testBuild(): void
5857
$this->assertContains(TestClientPass::class, $passClasses);
5958
$this->assertContains(TestMercureHubPass::class, $passClasses);
6059
$this->assertContains(AuthenticatorManagerPass::class, $passClasses);
61-
$this->assertContains(PropertyInfoPass::class, $passClasses);
6260
$this->assertContains(SerializerMappingLoaderPass::class, $passClasses);
6361
$this->assertContains(MutatorPass::class, $passClasses);
6462
$this->assertContains(JsonStreamerTransformerPass::class, $passClasses);

0 commit comments

Comments
 (0)