🌐 AI搜索 & 代理 主页
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private function loadFiles(\ReflectionClass $class): void
$file = $class->getFileName();
if (false !== $file && is_file($file)) {
foreach ($this->excludedVendors as $vendor) {
if (str_starts_with($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
if (\in_array($file[\strlen($vendor)] ?? '', ['/', \DIRECTORY_SEPARATOR], true) && str_starts_with($file, $vendor)) {
$file = false;
break;
}
Expand Down Expand Up @@ -154,6 +154,13 @@ private function generateSignature(\ReflectionClass $class): iterable
}

foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
foreach ($this->excludedVendors as $vendor) {
$file = $m->getFileName();
if (\in_array($file[\strlen($vendor)] ?? '', ['/', \DIRECTORY_SEPARATOR], true) && str_starts_with($file, $vendor)) {
continue 2;
}
}

foreach ($m->getAttributes() as $a) {
$attributes[] = [$a->getName(), (string) $a];
}
Expand Down
55 changes: 53 additions & 2 deletions src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\DependencyInjection;

use Composer\Autoload\ClassLoader;
use Composer\InstalledVersions;
use Symfony\Component\Config\Resource\ClassExistenceResource;
use Symfony\Component\Config\Resource\ComposerResource;
Expand Down Expand Up @@ -46,6 +47,7 @@
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\ErrorHandler\DebugClassLoader;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

Expand Down Expand Up @@ -117,7 +119,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private array $vendors;

/**
* @var array<string, bool> the cache for paths being in vendor directories
* @var array<string, bool> whether a path is in a vendor directory
*/
private array $pathsInVendor = [];

Expand Down Expand Up @@ -262,6 +264,53 @@ public function addResource(ResourceInterface $resource): static
if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) {
return $this;
}
if ($resource instanceof FileExistenceResource && $this->inVendors($resource->getResource())) {
return $this;
}
if ($resource instanceof FileResource && $this->inVendors($resource->getResource())) {
return $this;
}
if ($resource instanceof DirectoryResource && $this->inVendors($resource->getResource())) {
return $this;
}
if ($resource instanceof ClassExistenceResource) {
$class = $resource->getResource();

$inVendor = false;
foreach (spl_autoload_functions() as $autoloader) {
if (!\is_array($autoloader)) {
continue;
}

if ($autoloader[0] instanceof DebugClassLoader) {
$autoloader = $autoloader[0]->getClassLoader();
}

if (!\is_array($autoloader) || !$autoloader[0] instanceof ClassLoader || !$autoloader[0]->findFile(__CLASS__)) {
continue;
}

foreach ($autoloader[0]->getPrefixesPsr4() as $prefix => $dirs) {
if ('' === $prefix || !str_starts_with($class, $prefix)) {
continue;
}

foreach ($dirs as $dir) {
if (!$dir = realpath($dir)) {
continue;
}

if (!$inVendor = $this->inVendors($dir)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic looks wrong to me. Configuring a namespace prefixed to match a given directory does not mean that all classes matching that prefix must be defined in that folder.
For instance, all our mailer bridges have a namespace prefix that can also be matched by the prefix of the symfony/mailer package. And nothing prevents the project-level code to also define classes with that namespace (best practices is to keep your project-level code in a different namespace than your vendors, but that's not a requirement, and I know some projects do weird things).

For existing classes, we can optimize the class existence resource if the class is defined in the vendor folder (by checking the actual class definition, not folders in which it is maybe defined). For non-existent classes, we should not optimize the resource (or we should optimize it only based on all possible autoloading locations)

break 3;
}
}
}
}

if ($inVendor) {
return $this;
}
}

$this->resources[(string) $resource] = $resource;

Expand Down Expand Up @@ -1693,8 +1742,10 @@ private function inVendors(string $path): bool
}

foreach ($this->vendors as $vendor) {
if (str_starts_with($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
if (\in_array($path[\strlen($vendor)] ?? '', ['/', \DIRECTORY_SEPARATOR], true) && str_starts_with($path, $vendor)) {
$this->pathsInVendor[$vendor.'/composer'] = false;
$this->addResource(new FileResource($vendor.'/composer/installed.json'));
$this->pathsInVendor[$vendor.'/composer'] = true;

return $this->pathsInVendor[$path] = true;
}
Expand Down