Skip to content

Commit 8c47b47

Browse files
committed
Remove non-autoloadable classes from preload
1 parent e9a7026 commit 8c47b47

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class PhpDumper extends Dumper
9090
private $serviceLocatorTag;
9191
private $exportedVariables = [];
9292
private $baseClass;
93+
private $preloadableCache = [];
9394

9495
/**
9596
* @var ProxyDumper
@@ -335,7 +336,7 @@ class %s extends {$options['class']}
335336
if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) {
336337
continue;
337338
}
338-
if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined()) {
339+
if ($this->isPreloadable($class)) {
339340
$code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class);
340341
}
341342
}
@@ -398,6 +399,57 @@ class %s extends {$options['class']}
398399
return $code;
399400
}
400401

402+
private function isPreloadable(string $class): ?bool
403+
{
404+
if (array_key_exists($class, $this->preloadableCache)) {
405+
return $this->preloadableCache[$class];
406+
}
407+
$this->preloadableCache[$class] = true; // prevent recursion
408+
409+
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
410+
return $this->preloadableCache[$class] = false;
411+
}
412+
$reflection = new \ReflectionClass($class);
413+
if (!$reflection->isUserDefined()) {
414+
return $this->preloadableCache[$class] = null;
415+
}
416+
417+
// Since PHP 8.1, typehinted properties does not have to be auto-loadable.
418+
// Before PHP 8.0, user can not define typehinted properties
419+
if (\PHP_VERSION_ID >= 80100 || \PHP_VERSION_ID < 80000) {
420+
return $this->preloadableCache[$class] = true;
421+
}
422+
423+
foreach ($reflection->getProperties() as $property) {
424+
if (null === $type = $property->getType()) {
425+
continue;
426+
}
427+
$typesToCheck = [$type];
428+
while (!empty($typesToCheck)) {
429+
$typeToCheck = array_shift($typesToCheck);
430+
if ($typeToCheck instanceof \ReflectionUnionType || $typeToCheck instanceof \ReflectionIntersectionType) {
431+
foreach ($typeToCheck->getTypes() as $t) {
432+
$typesToCheck[] = $t;
433+
}
434+
435+
continue;
436+
}
437+
if (!$typeToCheck instanceof \ReflectionNamedType) {
438+
continue;
439+
}
440+
$typeName = $typeToCheck->getName();
441+
if (!$typeName || str_contains($typeName, '$') || \in_array($typeName, ['int', 'false', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) {
442+
continue;
443+
}
444+
if (false === $this->isPreloadable($typeName)) {
445+
return $this->preloadableCache[$class] = false;
446+
}
447+
}
448+
}
449+
450+
return $this->preloadableCache[$class] = true;
451+
}
452+
401453
/**
402454
* Retrieves the currently set proxy dumper or instantiates one.
403455
*/

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10_as_files.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ require __DIR__.'/Container%s/ProjectServiceContainer.php';
137137
require __DIR__.'/Container%s/getClosureService.php';
138138

139139
$classes = [];
140-
$classes[] = 'FooClass';
141140
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
142141

143142
Preloader::preload($classes);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -935,17 +935,8 @@ require __DIR__.'/Container%s/getBAR2Service.php';
935935

936936
$classes = [];
937937
$classes[] = 'Bar\FooClass';
938-
$classes[] = 'Baz';
939-
$classes[] = 'ConfClass';
940-
$classes[] = 'Bar';
941938
$classes[] = 'BazClass';
942-
$classes[] = 'Foo';
943939
$classes[] = 'LazyContext';
944-
$classes[] = 'FooBarBaz';
945-
$classes[] = 'FactoryClass';
946-
$classes[] = 'Some\Sidekick1';
947-
$classes[] = 'Some\Sidekick2';
948-
$classes[] = 'Request';
949940
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
950941

951942
Preloader::preload($classes);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -566,17 +566,8 @@ require __DIR__.'/Container%s/ProjectServiceContainer.php';
566566

567567
$classes = [];
568568
$classes[] = 'Bar\FooClass';
569-
$classes[] = 'Baz';
570-
$classes[] = 'ConfClass';
571-
$classes[] = 'Bar';
572569
$classes[] = 'BazClass';
573-
$classes[] = 'Foo';
574570
$classes[] = 'LazyContext';
575-
$classes[] = 'FooBarBaz';
576-
$classes[] = 'FactoryClass';
577-
$classes[] = 'Some\Sidekick1';
578-
$classes[] = 'Some\Sidekick2';
579-
$classes[] = 'Request';
580571
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
581572

582573
Preloader::preload($classes);

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