init
This commit is contained in:
240
backend/vendor/symfony/framework-bundle/DependencyInjection/Compiler/PhpConfigReferenceDumpPass.php
vendored
Normal file
240
backend/vendor/symfony/framework-bundle/DependencyInjection/Compiler/PhpConfigReferenceDumpPass.php
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\Config\Definition\ArrayNode;
|
||||
use Symfony\Component\Config\Definition\ArrayShapeGenerator;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\Config\Definition\PrototypedArrayNode;
|
||||
use Symfony\Component\Config\Loader\ParamConfigurator;
|
||||
use Symfony\Component\Config\Resource\FileResource;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\AppReference;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Symfony\Component\Routing\Loader\Configurator\RoutesReference;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class PhpConfigReferenceDumpPass implements CompilerPassInterface
|
||||
{
|
||||
private const REFERENCE_TEMPLATE = <<<'PHP'
|
||||
<?php
|
||||
|
||||
// This file is auto-generated and is for apps only. Bundles SHOULD NOT rely on its content.
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
|
||||
use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
|
||||
{APP_TYPES}
|
||||
final class App
|
||||
{
|
||||
{APP_PARAM}
|
||||
public static function config(array $config): array
|
||||
{
|
||||
/** @var ConfigType $config */
|
||||
$config = AppReference::config($config);
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Symfony\Component\Routing\Loader\Configurator;
|
||||
|
||||
{ROUTES_TYPES}
|
||||
final class Routes
|
||||
{
|
||||
{ROUTES_PARAM}
|
||||
public static function config(array $config): array
|
||||
{
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
|
||||
PHP;
|
||||
|
||||
private const WHEN_ENV_APP_TEMPLATE = <<<'PHPDOC'
|
||||
|
||||
* "when@{ENV}"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
* services?: ServicesConfig,{SHAPE}
|
||||
* },
|
||||
PHPDOC;
|
||||
|
||||
private const ROUTES_TYPES_TEMPLATE = <<<'PHPDOC'
|
||||
|
||||
* @psalm-type RoutesConfig = array{{SHAPE}
|
||||
* ...<string, RouteConfig|ImportConfig|AliasConfig>
|
||||
* }
|
||||
*/
|
||||
PHPDOC;
|
||||
|
||||
private const WHEN_ENV_ROUTES_TEMPLATE = <<<'PHPDOC'
|
||||
|
||||
* "when@{ENV}"?: array<string, RouteConfig|ImportConfig|AliasConfig>,
|
||||
PHPDOC;
|
||||
|
||||
public function __construct(
|
||||
private string $referenceFile,
|
||||
private array $bundlesDefinition,
|
||||
) {
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$knownEnvs = $container->hasParameter('.container.known_envs') ? $container->getParameter('.container.known_envs') : [$container->getParameter('kernel.environment')];
|
||||
$knownEnvs = array_unique($knownEnvs);
|
||||
sort($knownEnvs);
|
||||
$extensionsPerEnv = [];
|
||||
$appTypes = '';
|
||||
|
||||
$anyEnvExtensions = [];
|
||||
$registeredExtensions = $container->getExtensions();
|
||||
foreach ($this->bundlesDefinition as $bundle => $envs) {
|
||||
if (!is_subclass_of($bundle, BundleInterface::class)) {
|
||||
continue;
|
||||
}
|
||||
if (!$extension = (new $bundle())->getContainerExtension()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extensionAlias = $extension->getAlias();
|
||||
if (isset($registeredExtensions[$extensionAlias])) {
|
||||
$extension = $registeredExtensions[$extensionAlias];
|
||||
unset($registeredExtensions[$extensionAlias]);
|
||||
}
|
||||
|
||||
if (!$configuration = $this->getConfiguration($extension, $container)) {
|
||||
continue;
|
||||
}
|
||||
$tree = $configuration->getConfigTreeBuilder()->buildTree();
|
||||
if ($tree instanceof ArrayNode && !$tree instanceof PrototypedArrayNode && !$tree->getChildren()) {
|
||||
continue;
|
||||
}
|
||||
$anyEnvExtensions[$extensionAlias] = $extension;
|
||||
$type = $this->camelCase($extensionAlias).'Config';
|
||||
$appTypes .= \sprintf("\n * @psalm-type %s = %s", $type, ArrayShapeGenerator::generate($tree));
|
||||
|
||||
foreach ($knownEnvs as $env) {
|
||||
if ($envs[$env] ?? $envs['all'] ?? false) {
|
||||
$extensionsPerEnv[$env][] = $extension;
|
||||
} else {
|
||||
unset($anyEnvExtensions[$extensionAlias]);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($registeredExtensions as $alias => $extension) {
|
||||
if (!$configuration = $this->getConfiguration($extension, $container)) {
|
||||
continue;
|
||||
}
|
||||
$tree = $configuration->getConfigTreeBuilder()->buildTree();
|
||||
if ($tree instanceof ArrayNode && !$tree instanceof PrototypedArrayNode && !$tree->getChildren()) {
|
||||
continue;
|
||||
}
|
||||
$anyEnvExtensions[$alias] = $extension;
|
||||
$type = $this->camelCase($alias).'Config';
|
||||
$appTypes .= \sprintf("\n * @psalm-type %s = %s", $type, ArrayShapeGenerator::generate($tree));
|
||||
}
|
||||
krsort($extensionsPerEnv);
|
||||
|
||||
$r = new \ReflectionClass(AppReference::class);
|
||||
|
||||
if (false === $i = strpos($phpdoc = $r->getDocComment(), "\n * @psalm-type ConfigType = ")) {
|
||||
throw new \LogicException(\sprintf('Cannot insert config shape in "%s".', AppReference::class));
|
||||
}
|
||||
$appTypes = substr_replace($phpdoc, $appTypes, $i, 0);
|
||||
|
||||
if (false === $i = strrpos($phpdoc = $appTypes, "\n * ...<string, ExtensionType|array{")) {
|
||||
throw new \LogicException(\sprintf('Cannot insert config shape in "%s".', AppReference::class));
|
||||
}
|
||||
$appTypes = substr_replace($phpdoc, $this->getShapeForExtensions($anyEnvExtensions, $container), $i, 0);
|
||||
$i += \strlen($appTypes) - \strlen($phpdoc);
|
||||
|
||||
foreach ($extensionsPerEnv as $env => $extensions) {
|
||||
$appTypes = substr_replace($appTypes, strtr(self::WHEN_ENV_APP_TEMPLATE, [
|
||||
'{ENV}' => $env,
|
||||
'{SHAPE}' => $this->getShapeForExtensions($extensions, $container, ' '),
|
||||
]), $i, 0);
|
||||
}
|
||||
$appParam = $r->getMethod('config')->getDocComment();
|
||||
|
||||
$r = new \ReflectionClass(RoutesReference::class);
|
||||
|
||||
if (false === $i = strpos($phpdoc = $r->getDocComment(), "\n * @psalm-type RoutesConfig = ")) {
|
||||
throw new \LogicException(\sprintf('Cannot insert config shape in "%s".', RoutesReference::class));
|
||||
}
|
||||
$routesTypes = '';
|
||||
foreach ($knownEnvs as $env) {
|
||||
$routesTypes .= strtr(self::WHEN_ENV_ROUTES_TEMPLATE, ['{ENV}' => $env]);
|
||||
}
|
||||
if ('' !== $routesTypes) {
|
||||
$routesTypes = strtr(self::ROUTES_TYPES_TEMPLATE, ['{SHAPE}' => $routesTypes]);
|
||||
$routesTypes = substr_replace($phpdoc, $routesTypes, $i);
|
||||
}
|
||||
|
||||
$appTypes = str_replace('\\'.ParamConfigurator::class, 'Param', $appTypes);
|
||||
|
||||
if (!class_exists(Expression::class)) {
|
||||
$appTypes = str_replace('|ExpressionConfigurator', '', $appTypes);
|
||||
}
|
||||
|
||||
$configReference = strtr(self::REFERENCE_TEMPLATE, [
|
||||
'{APP_TYPES}' => $appTypes,
|
||||
'{APP_PARAM}' => $appParam,
|
||||
'{ROUTES_TYPES}' => $routesTypes,
|
||||
'{ROUTES_PARAM}' => $r->getMethod('config')->getDocComment(),
|
||||
]);
|
||||
|
||||
$dir = \dirname($this->referenceFile);
|
||||
if (is_dir($dir) && is_writable($dir)) {
|
||||
if (!is_file($this->referenceFile) || file_get_contents($this->referenceFile) !== $configReference) {
|
||||
file_put_contents($this->referenceFile, $configReference);
|
||||
}
|
||||
$container->addResource(new FileResource($this->referenceFile));
|
||||
}
|
||||
}
|
||||
|
||||
private function camelCase(string $input): string
|
||||
{
|
||||
$output = ucfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $input))));
|
||||
|
||||
return preg_replace('#\W#', '', $output);
|
||||
}
|
||||
|
||||
private function getConfiguration(ExtensionInterface $extension, ContainerBuilder $container): ?ConfigurationInterface
|
||||
{
|
||||
return match (true) {
|
||||
$extension instanceof ConfigurationInterface => $extension,
|
||||
$extension instanceof ConfigurationExtensionInterface => $extension->getConfiguration([], $container),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
private function getShapeForExtensions(array $extensions, ContainerBuilder $container, string $indent = ''): string
|
||||
{
|
||||
$shape = '';
|
||||
foreach ($extensions as $extension) {
|
||||
if ($this->getConfiguration($extension, $container)) {
|
||||
$type = $this->camelCase($extension->getAlias()).'Config';
|
||||
$shape .= \sprintf("\n * %s%s?: %s,", $indent, $extension->getAlias(), $type);
|
||||
}
|
||||
}
|
||||
|
||||
return $shape;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user