Subida del módulo y tema de PrestaShop

This commit is contained in:
Kaloyan
2026-04-09 18:31:51 +02:00
parent 12c253296f
commit 16b3ff9424
39262 changed files with 7418797 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Common\Cache\CacheProvider;
use Doctrine\Common\Cache\Psr6\CacheAdapter;
use Doctrine\Common\Cache\Psr6\DoctrineProvider;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use function array_keys;
use function assert;
use function in_array;
use function is_a;
use function trigger_deprecation;
/** @internal */
final class CacheCompatibilityPass implements CompilerPassInterface
{
private const CONFIGURATION_TAG = 'doctrine.orm.configuration';
private const CACHE_METHODS_PSR6_SUPPORT = [
'setMetadataCache',
'setQueryCache',
'setResultCache',
];
public function process(ContainerBuilder $container): void
{
foreach (array_keys($container->findTaggedServiceIds(self::CONFIGURATION_TAG)) as $id) {
foreach ($container->getDefinition($id)->getMethodCalls() as $methodCall) {
if ($methodCall[0] === 'setSecondLevelCacheConfiguration') {
$this->updateSecondLevelCache($container, $methodCall[1][0]);
continue;
}
if (! in_array($methodCall[0], self::CACHE_METHODS_PSR6_SUPPORT, true)) {
continue;
}
$aliasId = (string) $methodCall[1][0];
$definitionId = (string) $container->getAlias($aliasId);
$this->wrapIfNecessary($container, $aliasId, $definitionId, true);
}
}
}
private function updateSecondLevelCache(ContainerBuilder $container, Definition $slcConfigDefinition): void
{
foreach ($slcConfigDefinition->getMethodCalls() as $methodCall) {
if ($methodCall[0] !== 'setCacheFactory') {
continue;
}
$factoryDefinition = $methodCall[1][0];
assert($factoryDefinition instanceof Definition);
$aliasId = (string) $factoryDefinition->getArgument(1);
$this->wrapIfNecessary($container, $aliasId, (string) $container->getAlias($aliasId), false);
foreach ($factoryDefinition->getMethodCalls() as $factoryMethodCall) {
if ($factoryMethodCall[0] !== 'setRegion') {
continue;
}
$regionDefinition = $container->getDefinition($factoryMethodCall[1][0]);
// Get inner service for FileLock
if ($regionDefinition->getClass() === '%doctrine.orm.second_level_cache.filelock_region.class%') {
$regionDefinition = $container->getDefinition($regionDefinition->getArgument(0));
}
// We don't know how to adjust custom region classes
if ($regionDefinition->getClass() !== '%doctrine.orm.second_level_cache.default_region.class%') {
continue;
}
$driverId = (string) $regionDefinition->getArgument(1);
if (! $container->hasAlias($driverId)) {
continue;
}
$this->wrapIfNecessary($container, $driverId, (string) $container->getAlias($driverId), false);
}
break;
}
}
private function createCompatibilityLayerDefinition(ContainerBuilder $container, string $definitionId, bool $shouldBePsr6): ?Definition
{
$definition = $container->getDefinition($definitionId);
while (! $definition->getClass() && $definition instanceof ChildDefinition) {
$definition = $container->findDefinition($definition->getParent());
}
if ($shouldBePsr6 === is_a($definition->getClass(), CacheItemPoolInterface::class, true)) {
return null;
}
$targetClass = CacheProvider::class;
$targetFactory = DoctrineProvider::class;
if ($shouldBePsr6) {
$targetClass = CacheItemPoolInterface::class;
$targetFactory = CacheAdapter::class;
trigger_deprecation(
'doctrine/doctrine-bundle',
'2.4',
'Configuring doctrine/cache is deprecated. Please update the cache service "%s" to use a PSR-6 cache.',
$definitionId
);
}
return (new Definition($targetClass))
->setFactory([$targetFactory, 'wrap'])
->addArgument(new Reference($definitionId));
}
private function wrapIfNecessary(ContainerBuilder $container, string $aliasId, string $definitionId, bool $shouldBePsr6): void
{
$compatibilityLayer = $this->createCompatibilityLayerDefinition($container, $definitionId, $shouldBePsr6);
if ($compatibilityLayer === null) {
return;
}
$compatibilityLayerId = $definitionId . '.compatibility_layer';
$container->setAlias($aliasId, $compatibilityLayerId);
$container->setDefinition($compatibilityLayerId, $compatibilityLayer);
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Symfony\Component\Cache\Adapter\DoctrineDbalAdapter;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Injects Doctrine DBAL and legacy PDO adapters into their schema subscribers.
*
* Must be run later after ResolveChildDefinitionsPass.
*/
class CacheSchemaSubscriberPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
// available in Symfony 5.4 and higher
/** @psalm-suppress UndefinedClass */
$this->injectAdapters($container, 'doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber', DoctrineDbalAdapter::class);
// available in Symfony 5.1 and up to Symfony 5.4 (deprecated)
$this->injectAdapters($container, 'doctrine.orm.listeners.pdo_cache_adapter_doctrine_schema_subscriber', PdoAdapter::class);
}
private function injectAdapters(ContainerBuilder $container, string $subscriberId, string $class)
{
if (! $container->hasDefinition($subscriberId)) {
return;
}
$subscriber = $container->getDefinition($subscriberId);
$cacheAdaptersReferences = [];
foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isAbstract() || $definition->isSynthetic()) {
continue;
}
if ($definition->getClass() !== $class) {
continue;
}
$cacheAdaptersReferences[] = new Reference($id);
}
$subscriber->replaceArgument(0, $cacheAdaptersReferences);
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use function sprintf;
/**
* Processes the doctrine.dbal.schema_filter
*/
class DbalSchemaFilterPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$filters = $container->findTaggedServiceIds('doctrine.dbal.schema_filter');
$connectionFilters = [];
foreach ($filters as $id => $tagAttributes) {
foreach ($tagAttributes as $attributes) {
$name = $attributes['connection'] ?? $container->getParameter('doctrine.default_connection');
if (! isset($connectionFilters[$name])) {
$connectionFilters[$name] = [];
}
$connectionFilters[$name][] = new Reference($id);
}
}
foreach ($connectionFilters as $name => $references) {
$configurationId = sprintf('doctrine.dbal.%s_connection.configuration', $name);
if (! $container->hasDefinition($configurationId)) {
continue;
}
$definition = new ChildDefinition('doctrine.dbal.schema_asset_filter_manager');
$definition->setArgument(0, $references);
$id = sprintf('doctrine.dbal.%s_schema_asset_filter_manager', $name);
$container->setDefinition($id, $definition);
$container->findDefinition($configurationId)
->addMethodCall('setSchemaAssetsFilter', [new Reference($id)]);
}
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\Mapping\Driver\XmlDriver;
use Doctrine\ORM\Mapping\Driver\YamlDriver;
use Doctrine\Persistence\Mapping\Driver\PHPDriver;
use Doctrine\Persistence\Mapping\Driver\StaticPHPDriver;
use Doctrine\Persistence\Mapping\Driver\SymfonyFileLocator;
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterMappingsPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
/**
* Class for Symfony bundles to configure mappings for model classes not in the
* auto-mapped folder.
*
* NOTE: alias is only supported by Symfony 2.6+ and will be ignored with older versions.
*/
class DoctrineOrmMappingsPass extends RegisterMappingsPass
{
/**
* You should not directly instantiate this class but use one of the
* factory methods.
*
* @param Definition|Reference $driver Driver DI definition or reference.
* @param string[] $namespaces List of namespaces handled by $driver.
* @param string[] $managerParameters Ordered list of container parameters that
* could hold the manager name.
* doctrine.default_entity_manager is appended
* automatically.
* @param string|false $enabledParameter If specified, the compiler pass only executes
* if this parameter is defined in the service
* container.
* @param string[] $aliasMap Map of alias to namespace.
*/
public function __construct($driver, array $namespaces, array $managerParameters, $enabledParameter = false, array $aliasMap = [])
{
$managerParameters[] = 'doctrine.default_entity_manager';
parent::__construct(
$driver,
$namespaces,
$managerParameters,
'doctrine.orm.%s_metadata_driver',
$enabledParameter,
'doctrine.orm.%s_configuration',
'addEntityNamespace',
$aliasMap
);
}
/**
* @param string[] $namespaces Hashmap of directory path to namespace.
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createXmlMappingDriver(array $namespaces, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$locator = new Definition(SymfonyFileLocator::class, [$namespaces, '.orm.xml']);
$driver = new Definition(XmlDriver::class, [$locator]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
/**
* @param string[] $namespaces Hashmap of directory path to namespace
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createYamlMappingDriver(array $namespaces, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$locator = new Definition(SymfonyFileLocator::class, [$namespaces, '.orm.yml']);
$driver = new Definition(YamlDriver::class, [$locator]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
/**
* @param string[] $namespaces Hashmap of directory path to namespace
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createPhpMappingDriver(array $namespaces, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$locator = new Definition(SymfonyFileLocator::class, [$namespaces, '.php']);
$driver = new Definition(PHPDriver::class, [$locator]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
/**
* @param string[] $namespaces List of namespaces that are handled with annotation mapping
* @param string[] $directories List of directories to look for annotated classes
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createAnnotationMappingDriver(array $namespaces, array $directories, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$reader = new Reference('annotation_reader');
$driver = new Definition(AnnotationDriver::class, [$reader, $directories]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
/**
* @param string[] $namespaces List of namespaces that are handled with annotation mapping
* @param string[] $directories List of directories to look for annotated classes
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createAttributeMappingDriver(array $namespaces, array $directories, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$driver = new Definition(AttributeDriver::class, [$directories]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
/**
* @param string[] $namespaces List of namespaces that are handled with static php mapping
* @param string[] $directories List of directories to look for static php mapping files
* @param string[] $managerParameters List of parameters that could which object manager name
* your bundle uses. This compiler pass will automatically
* append the parameter name for the default entity manager
* to this list.
* @param string|false $enabledParameter Service container parameter that must be present to
* enable the mapping. Set to false to not do any check,
* optional.
* @param string[] $aliasMap Map of alias to namespace.
*
* @return self
*/
public static function createStaticPhpMappingDriver(array $namespaces, array $directories, array $managerParameters = [], $enabledParameter = false, array $aliasMap = [])
{
$driver = new Definition(StaticPHPDriver::class, [$directories]);
return new DoctrineOrmMappingsPass($driver, $namespaces, $managerParameters, $enabledParameter, $aliasMap);
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Bundle\DoctrineBundle\Mapping\ContainerEntityListenerResolver;
use Doctrine\Bundle\DoctrineBundle\Mapping\EntityListenerServiceResolver;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use function is_a;
use function method_exists;
use function sprintf;
use function substr;
/**
* Class for Symfony bundles to register entity listeners
*/
class EntityListenerPass implements CompilerPassInterface
{
use PriorityTaggedServiceTrait;
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$resolvers = $this->findAndSortTaggedServices('doctrine.orm.entity_listener', $container);
$lazyServiceReferencesByResolver = [];
foreach ($resolvers as $reference) {
$id = $reference->__toString();
foreach ($container->getDefinition($id)->getTag('doctrine.orm.entity_listener') as $attributes) {
$name = $attributes['entity_manager'] ?? $container->getParameter('doctrine.default_entity_manager');
$entityManager = sprintf('doctrine.orm.%s_entity_manager', $name);
if (! $container->hasDefinition($entityManager)) {
continue;
}
$resolverId = sprintf('doctrine.orm.%s_entity_listener_resolver', $name);
if (! $container->has($resolverId)) {
continue;
}
$resolver = $container->findDefinition($resolverId);
$resolver->setPublic(true);
if (isset($attributes['entity']) && isset($attributes['event'])) {
$this->attachToListener($container, $name, $this->getConcreteDefinitionClass($container->findDefinition($id), $container, $id), $attributes);
}
$resolverClass = $this->getResolverClass($resolver, $container, $resolverId);
$resolverSupportsLazyListeners = is_a($resolverClass, EntityListenerServiceResolver::class, true);
$lazyByAttribute = isset($attributes['lazy']) && $attributes['lazy'];
if ($lazyByAttribute && ! $resolverSupportsLazyListeners) {
throw new InvalidArgumentException(sprintf(
'Lazy-loaded entity listeners can only be resolved by a resolver implementing %s.',
EntityListenerServiceResolver::class
));
}
if (! isset($attributes['lazy']) && $resolverSupportsLazyListeners || $lazyByAttribute) {
$listener = $container->findDefinition($id);
$resolver->addMethodCall('registerService', [$this->getConcreteDefinitionClass($listener, $container, $id), $id]);
// if the resolver uses the default class we will use a service locator for all listeners
if ($resolverClass === ContainerEntityListenerResolver::class) {
if (! isset($lazyServiceReferencesByResolver[$resolverId])) {
$lazyServiceReferencesByResolver[$resolverId] = [];
}
$lazyServiceReferencesByResolver[$resolverId][$id] = new Reference($id);
} else {
$listener->setPublic(true);
}
} else {
$resolver->addMethodCall('register', [new Reference($id)]);
}
}
}
foreach ($lazyServiceReferencesByResolver as $resolverId => $listenerReferences) {
$container->findDefinition($resolverId)->setArgument(0, ServiceLocatorTagPass::register($container, $listenerReferences));
}
}
/** @param array{entity: class-string, event: string} $attributes */
private function attachToListener(ContainerBuilder $container, string $name, string $class, array $attributes): void
{
$listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $name);
if (! $container->has($listenerId)) {
return;
}
$args = [
$attributes['entity'],
$class,
$attributes['event'],
];
if (isset($attributes['method'])) {
$args[] = $attributes['method'];
} elseif (! method_exists($class, $attributes['event']) && method_exists($class, '__invoke')) {
$args[] = '__invoke';
}
$container->findDefinition($listenerId)->addMethodCall('addEntityListener', $args);
}
private function getResolverClass(Definition $resolver, ContainerBuilder $container, string $id): string
{
$resolverClass = $this->getConcreteDefinitionClass($resolver, $container, $id);
if (substr($resolverClass, 0, 1) === '%') {
// resolve container parameter first
$resolverClass = $container->getParameterBag()->resolveValue($resolverClass);
}
return $resolverClass;
}
private function getConcreteDefinitionClass(Definition $definition, ContainerBuilder $container, string $id): string
{
$class = $definition->getClass();
if ($class) {
return $class;
}
while ($definition instanceof ChildDefinition) {
$definition = $container->findDefinition($definition->getParent());
$class = $definition->getClass();
if ($class) {
return $class;
}
}
throw new InvalidArgumentException(sprintf('The service "%s" must define its class.', $id));
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Bundle\DoctrineBundle\Mapping\ClassMetadataFactory;
use Doctrine\Bundle\DoctrineBundle\Mapping\MappingDriver;
use Doctrine\ORM\Mapping\ClassMetadataFactory as ORMClassMetadataFactory;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use function array_combine;
use function array_keys;
use function array_map;
use function sprintf;
final class IdGeneratorPass implements CompilerPassInterface
{
public const ID_GENERATOR_TAG = 'doctrine.id_generator';
public const CONFIGURATION_TAG = 'doctrine.orm.configuration';
public function process(ContainerBuilder $container): void
{
$generatorIds = array_keys($container->findTaggedServiceIds(self::ID_GENERATOR_TAG));
// when ORM is not enabled
if (! $container->hasDefinition('doctrine.orm.configuration') || ! $generatorIds) {
return;
}
$generatorRefs = array_map(static function ($id) {
return new Reference($id);
}, $generatorIds);
$ref = ServiceLocatorTagPass::register($container, array_combine($generatorIds, $generatorRefs));
$container->setAlias('doctrine.id_generator_locator', new Alias((string) $ref, false));
foreach ($container->findTaggedServiceIds(self::CONFIGURATION_TAG) as $id => $tags) {
$configurationDef = $container->getDefinition($id);
$methodCalls = $configurationDef->getMethodCalls();
$metadataDriverImpl = null;
foreach ($methodCalls as $i => [$method, $arguments]) {
if ($method === 'setMetadataDriverImpl') {
$metadataDriverImpl = (string) $arguments[0];
}
if ($method !== 'setClassMetadataFactoryName') {
continue;
}
if ($arguments[0] !== ORMClassMetadataFactory::class && $arguments[0] !== ClassMetadataFactory::class) {
$class = $container->getReflectionClass($arguments[0]);
if ($class && $class->isSubclassOf(ClassMetadataFactory::class)) {
break;
}
continue 2;
}
$methodCalls[$i] = ['setClassMetadataFactoryName', [ClassMetadataFactory::class]];
}
if ($metadataDriverImpl === null) {
continue;
}
$configurationDef->setMethodCalls($methodCalls);
$container->register('.' . $metadataDriverImpl, MappingDriver::class)
->setDecoratedService($metadataDriverImpl)
->setArguments([
new Reference(sprintf('.%s.inner', $metadataDriverImpl)),
new Reference('doctrine.id_generator_locator'),
]);
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Bundle\DoctrineBundle\Middleware\ConnectionNameAwareInterface;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use function array_keys;
use function in_array;
use function is_subclass_of;
use function sprintf;
final class MiddlewaresPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (! $container->hasParameter('doctrine.connections')) {
return;
}
$middlewareAbstractDefs = [];
$middlewareConnections = [];
foreach ($container->findTaggedServiceIds('doctrine.middleware') as $id => $tags) {
$middlewareAbstractDefs[$id] = $container->getDefinition($id);
// When a def has doctrine.middleware tags with connection attributes equal to connection names
// registration of this middleware is limited to the connections with these names
foreach ($tags as $tag) {
if (! isset($tag['connection'])) {
continue;
}
$middlewareConnections[$id][] = $tag['connection'];
}
}
foreach (array_keys($container->getParameter('doctrine.connections')) as $name) {
$middlewareDefs = [];
foreach ($middlewareAbstractDefs as $id => $abstractDef) {
if (isset($middlewareConnections[$id]) && ! in_array($name, $middlewareConnections[$id], true)) {
continue;
}
$middlewareDefs[] = $childDef = $container->setDefinition(
sprintf('%s.%s', $id, $name),
new ChildDefinition($id)
);
if (! is_subclass_of($abstractDef->getClass(), ConnectionNameAwareInterface::class)) {
continue;
}
$childDef->addMethodCall('setConnectionName', [$name]);
}
$container
->getDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name))
->addMethodCall('setMiddlewares', [$middlewareDefs]);
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/** @internal */
final class RemoveLoggingMiddlewarePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if ($container->has('logger')) {
return;
}
$container->removeDefinition('doctrine.dbal.logging_middleware');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Doctrine\Bundle\DoctrineBundle\Controller\ProfilerController;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/** @internal */
final class RemoveProfilerControllerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if ($container->has('twig') && $container->has('profiler')) {
return;
}
$container->removeDefinition(ProfilerController::class);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use function array_combine;
use function array_keys;
use function array_map;
final class ServiceRepositoryCompilerPass implements CompilerPassInterface
{
public const REPOSITORY_SERVICE_TAG = 'doctrine.repository_service';
public function process(ContainerBuilder $container): void
{
// when ORM is not enabled
if (! $container->hasDefinition('doctrine.orm.container_repository_factory')) {
return;
}
$locatorDef = $container->getDefinition('doctrine.orm.container_repository_factory');
$repoServiceIds = array_keys($container->findTaggedServiceIds(self::REPOSITORY_SERVICE_TAG));
$repoReferences = array_map(static function ($id) {
return new Reference($id);
}, $repoServiceIds);
$ref = ServiceLocatorTagPass::register($container, array_combine($repoServiceIds, $repoReferences));
$locatorDef->replaceArgument(0, $ref);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler;
use Symfony\Component\Cache\Adapter\DoctrineDbalAdapter;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
use Symfony\Component\Lock\Store\DoctrineDbalStore;
use Symfony\Component\Lock\Store\PdoStore;
use Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection;
use Symfony\Component\Messenger\Transport\Doctrine\Connection as LegacyConnection;
use function array_keys;
/**
* Blacklist tables used by well-known Symfony classes.
*
* @deprecated Implement your own include/exclude mechanism
*/
class WellKnownSchemaFilterPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*/
public function process(ContainerBuilder $container)
{
$blacklist = [];
foreach ($container->getDefinitions() as $definition) {
if ($definition->isAbstract() || $definition->isSynthetic()) {
continue;
}
switch ($definition->getClass()) {
case DoctrineDbalAdapter::class:
case PdoAdapter::class:
$blacklist[] = $definition->getArguments()[3]['db_table'] ?? 'cache_items';
break;
case PdoSessionHandler::class:
$blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'sessions';
break;
case DoctrineDbalStore::class:
case PdoStore::class:
$blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'lock_keys';
break;
case LegacyConnection::class:
case Connection::class:
$blacklist[] = $definition->getArguments()[0]['table_name'] ?? 'messenger_messages';
break;
}
}
if (! $blacklist) {
return;
}
$definition = $container->getDefinition('doctrine.dbal.well_known_schema_asset_filter');
$definition->replaceArgument(0, $blacklist);
foreach (array_keys($container->getParameter('doctrine.connections')) as $name) {
$definition->addTag('doctrine.dbal.schema_filter', ['connection' => $name]);
}
}
}

View File

@@ -0,0 +1,803 @@
<?php
namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection;
use Doctrine\Common\Proxy\AbstractProxyFactory;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use ReflectionClass;
use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use function array_intersect_key;
use function array_key_exists;
use function array_keys;
use function array_pop;
use function assert;
use function class_exists;
use function constant;
use function count;
use function defined;
use function implode;
use function in_array;
use function is_array;
use function is_bool;
use function is_int;
use function is_string;
use function key;
use function method_exists;
use function reset;
use function sprintf;
use function strlen;
use function strpos;
use function strtoupper;
use function substr;
use function trigger_deprecation;
/**
* This class contains the configuration information for the bundle
*
* This information is solely responsible for how the different configuration
* sections are normalized, and merged.
*/
class Configuration implements ConfigurationInterface
{
/** @var bool */
private $debug;
/** @param bool $debug Whether to use the debug mode */
public function __construct(bool $debug)
{
$this->debug = $debug;
}
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('doctrine');
$rootNode = $treeBuilder->getRootNode();
$this->addDbalSection($rootNode);
$this->addOrmSection($rootNode);
return $treeBuilder;
}
/**
* Add DBAL section to configuration tree
*/
private function addDbalSection(ArrayNodeDefinition $node): void
{
$node
->children()
->arrayNode('dbal')
->beforeNormalization()
->ifTrue(static function ($v) {
return is_array($v) && ! array_key_exists('connections', $v) && ! array_key_exists('connection', $v);
})
->then(static function ($v) {
// Key that should not be rewritten to the connection config
$excludedKeys = ['default_connection' => true, 'types' => true, 'type' => true];
$connection = [];
foreach ($v as $key => $value) {
if (isset($excludedKeys[$key])) {
continue;
}
$connection[$key] = $v[$key];
unset($v[$key]);
}
$v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default';
$v['connections'] = [$v['default_connection'] => $connection];
return $v;
})
->end()
->children()
->scalarNode('default_connection')->end()
->end()
->fixXmlConfig('type')
->children()
->arrayNode('types')
->useAttributeAsKey('name')
->prototype('array')
->beforeNormalization()
->ifString()
->then(static function ($v) {
return ['class' => $v];
})
->end()
->children()
->scalarNode('class')->isRequired()->end()
->booleanNode('commented')
->setDeprecated(
...$this->getDeprecationMsg('The doctrine-bundle type commenting features were removed; the corresponding config parameter was deprecated in 2.0 and will be dropped in 3.0.', '2.0')
)
->end()
->end()
->end()
->end()
->end()
->fixXmlConfig('connection')
->append($this->getDbalConnectionsNode())
->end();
}
/**
* Return the dbal connections node
*/
private function getDbalConnectionsNode(): ArrayNodeDefinition
{
$treeBuilder = new TreeBuilder('connections');
$node = $treeBuilder->getRootNode();
$connectionNode = $node
->requiresAtLeastOneElement()
->useAttributeAsKey('name')
->prototype('array');
assert($connectionNode instanceof ArrayNodeDefinition);
$this->configureDbalDriverNode($connectionNode);
$collationKey = defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY')
? 'collate'
: 'collation';
$connectionNode
->fixXmlConfig('option')
->fixXmlConfig('mapping_type')
->fixXmlConfig('slave')
->fixXmlConfig('replica')
->fixXmlConfig('shard')
->fixXmlConfig('default_table_option')
->children()
->scalarNode('driver')->defaultValue('pdo_mysql')->end()
->scalarNode('platform_service')->end()
->booleanNode('auto_commit')->end()
->scalarNode('schema_filter')->end()
->booleanNode('logging')->defaultValue($this->debug)->end()
->booleanNode('profiling')->defaultValue($this->debug)->end()
->booleanNode('profiling_collect_backtrace')
->defaultValue(false)
->info('Enables collecting backtraces when profiling is enabled')
->end()
->booleanNode('profiling_collect_schema_errors')
->defaultValue(true)
->info('Enables collecting schema errors when profiling is enabled')
->end()
->scalarNode('server_version')->end()
->scalarNode('driver_class')->end()
->scalarNode('wrapper_class')->end()
->scalarNode('shard_manager_class')->end()
->scalarNode('shard_choser')->end()
->scalarNode('shard_choser_service')->end()
->booleanNode('keep_slave')
->setDeprecated(
...$this->getDeprecationMsg('The "keep_slave" configuration key is deprecated since doctrine-bundle 2.2. Use the "keep_replica" configuration key instead.', '2.2')
)
->end()
->booleanNode('keep_replica')->end()
->arrayNode('options')
->useAttributeAsKey('key')
->prototype('variable')->end()
->end()
->arrayNode('mapping_types')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('default_table_options')
->info(sprintf(
"This option is used by the schema-tool and affects generated SQL. Possible keys include 'charset','%s', and 'engine'.",
$collationKey
))
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->end();
// dbal < 2.11
$slaveNode = $connectionNode
->children()
->arrayNode('slaves')
->setDeprecated(
...$this->getDeprecationMsg('The "slaves" configuration key will be renamed to "replicas" in doctrine-bundle 3.0. "slaves" is deprecated since doctrine-bundle 2.2.', '2.2')
)
->useAttributeAsKey('name')
->prototype('array');
$this->configureDbalDriverNode($slaveNode);
// dbal >= 2.11
$replicaNode = $connectionNode
->children()
->arrayNode('replicas')
->useAttributeAsKey('name')
->prototype('array');
$this->configureDbalDriverNode($replicaNode);
$shardNode = $connectionNode
->children()
->arrayNode('shards')
->prototype('array');
$shardNode
->children()
->integerNode('id')
->min(1)
->isRequired()
->end()
->end();
$this->configureDbalDriverNode($shardNode);
return $node;
}
/**
* Adds config keys related to params processed by the DBAL drivers
*
* These keys are available for replica configurations too.
*/
private function configureDbalDriverNode(ArrayNodeDefinition $node): void
{
$node
->validate()
->always(static function (array $values) {
if (! isset($values['url'])) {
return $values;
}
$urlConflictingOptions = ['host' => true, 'port' => true, 'user' => true, 'password' => true, 'path' => true, 'dbname' => true, 'unix_socket' => true, 'memory' => true];
$urlConflictingValues = array_keys(array_intersect_key($values, $urlConflictingOptions));
if ($urlConflictingValues) {
$tail = count($urlConflictingValues) > 1 ? sprintf('or "%s" options', array_pop($urlConflictingValues)) : 'option';
trigger_deprecation(
'doctrine/doctrine-bundle',
'2.4',
'Setting the "doctrine.dbal.%s" %s while the "url" one is defined is deprecated',
implode('", "', $urlConflictingValues),
$tail
);
}
return $values;
})
->end()
->children()
->scalarNode('url')->info('A URL with connection information; any parameter value parsed from this string will override explicitly set parameters')->end()
->scalarNode('dbname')->end()
->scalarNode('host')->info('Defaults to "localhost" at runtime.')->end()
->scalarNode('port')->info('Defaults to null at runtime.')->end()
->scalarNode('user')->info('Defaults to "root" at runtime.')->end()
->scalarNode('password')->info('Defaults to null at runtime.')->end()
->booleanNode('override_url')->setDeprecated(...$this->getDeprecationMsg('The "doctrine.dbal.override_url" configuration key is deprecated.', '2.4'))->end()
->scalarNode('dbname_suffix')->end()
->scalarNode('application_name')->end()
->scalarNode('charset')->end()
->scalarNode('path')->end()
->booleanNode('memory')->end()
->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end()
->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end()
->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if omitted)')->end()
->booleanNode('service')
->info('True to use SERVICE_NAME as connection parameter instead of SID for Oracle')
->end()
->scalarNode('servicename')
->info(
'Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter ' .
'for Oracle depending on the service parameter.'
)
->end()
->scalarNode('sessionMode')
->info('The session mode to use for the oci8 driver')
->end()
->scalarNode('server')
->info('The name of a running database server to connect to for SQL Anywhere.')
->end()
->scalarNode('default_dbname')
->info(
'Override the default database (postgres) to connect to for PostgreSQL connexion.'
)
->end()
->scalarNode('sslmode')
->info(
'Determines whether or with what priority a SSL TCP/IP connection will be negotiated with ' .
'the server for PostgreSQL.'
)
->end()
->scalarNode('sslrootcert')
->info(
'The name of a file containing SSL certificate authority (CA) certificate(s). ' .
'If the file exists, the server\'s certificate will be verified to be signed by one of these authorities.'
)
->end()
->scalarNode('sslcert')
->info(
'The path to the SSL client certificate file for PostgreSQL.'
)
->end()
->scalarNode('sslkey')
->info(
'The path to the SSL client key file for PostgreSQL.'
)
->end()
->scalarNode('sslcrl')
->info(
'The file name of the SSL certificate revocation list for PostgreSQL.'
)
->end()
->booleanNode('pooled')->info('True to use a pooled server with the oci8/pdo_oracle driver')->end()
->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end()
->booleanNode('use_savepoints')->info('Use savepoints for nested transactions')->end()
->scalarNode('instancename')
->info(
'Optional parameter, complete whether to add the INSTANCE_NAME parameter in the connection.' .
' It is generally used to connect to an Oracle RAC server to select the name' .
' of a particular instance.'
)
->end()
->scalarNode('connectstring')
->info(
'Complete Easy Connect connection descriptor, see https://docs.oracle.com/database/121/NETAG/naming.htm.' .
'When using this option, you will still need to provide the user and password parameters, but the other ' .
'parameters will no longer be used. Note that when using this parameter, the getHost and getPort methods' .
' from Doctrine\DBAL\Connection will no longer function as expected.'
)
->end()
->end()
->beforeNormalization()
->ifTrue(static function ($v) {
return ! isset($v['sessionMode']) && isset($v['session_mode']);
})
->then(static function ($v) {
$v['sessionMode'] = $v['session_mode'];
unset($v['session_mode']);
return $v;
})
->end()
->beforeNormalization()
->ifTrue(static function ($v) {
return ! isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']);
})
->then(static function ($v) {
$v['MultipleActiveResultSets'] = $v['multiple_active_result_sets'];
unset($v['multiple_active_result_sets']);
return $v;
})
->end();
}
/**
* Add the ORM section to configuration tree
*/
private function addOrmSection(ArrayNodeDefinition $node): void
{
$node
->children()
->arrayNode('orm')
->beforeNormalization()
->ifTrue(static function ($v) {
if (! empty($v) && ! class_exists(EntityManager::class)) {
throw new LogicException('The doctrine/orm package is required when the doctrine.orm config is set.');
}
return $v === null || (is_array($v) && ! array_key_exists('entity_managers', $v) && ! array_key_exists('entity_manager', $v));
})
->then(static function ($v) {
$v = (array) $v;
// Key that should not be rewritten to the connection config
$excludedKeys = [
'default_entity_manager' => true,
'auto_generate_proxy_classes' => true,
'proxy_dir' => true,
'proxy_namespace' => true,
'resolve_target_entities' => true,
'resolve_target_entity' => true,
];
$entityManager = [];
foreach ($v as $key => $value) {
if (isset($excludedKeys[$key])) {
continue;
}
$entityManager[$key] = $v[$key];
unset($v[$key]);
}
$v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default';
$v['entity_managers'] = [$v['default_entity_manager'] => $entityManager];
return $v;
})
->end()
->children()
->scalarNode('default_entity_manager')->end()
->scalarNode('auto_generate_proxy_classes')->defaultValue(false)
->info('Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL", "FILE_NOT_EXISTS_OR_CHANGED"')
->validate()
->ifTrue(function ($v) {
$generationModes = $this->getAutoGenerateModes();
if (is_int($v) && in_array($v, $generationModes['values']/*array(0, 1, 2, 3)*/)) {
return false;
}
if (is_bool($v)) {
return false;
}
if (is_string($v)) {
if (in_array(strtoupper($v), $generationModes['names']/*array('NEVER', 'ALWAYS', 'FILE_NOT_EXISTS', 'EVAL', 'FILE_NOT_EXISTS_OR_CHANGED')*/)) {
return false;
}
}
return true;
})
->thenInvalid('Invalid auto generate mode value %s')
->end()
->validate()
->ifString()
->then(static function ($v) {
return constant('Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_' . strtoupper($v));
})
->end()
->end()
->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end()
->scalarNode('proxy_namespace')->defaultValue('Proxies')->end()
->end()
->fixXmlConfig('entity_manager')
->append($this->getOrmEntityManagersNode())
->fixXmlConfig('resolve_target_entity', 'resolve_target_entities')
->append($this->getOrmTargetEntityResolverNode())
->end()
->end();
}
/**
* Return ORM target entity resolver node
*/
private function getOrmTargetEntityResolverNode(): NodeDefinition
{
$treeBuilder = new TreeBuilder('resolve_target_entities');
$node = $treeBuilder->getRootNode();
$node
->useAttributeAsKey('interface')
->prototype('scalar')
->cannotBeEmpty()
->end();
return $node;
}
/**
* Return ORM entity listener node
*/
private function getOrmEntityListenersNode(): NodeDefinition
{
$treeBuilder = new TreeBuilder('entity_listeners');
$node = $treeBuilder->getRootNode();
$normalizer = static function ($mappings) {
$entities = [];
foreach ($mappings as $entityClass => $mapping) {
$listeners = [];
foreach ($mapping as $listenerClass => $listenerEvent) {
$events = [];
foreach ($listenerEvent as $eventType => $eventMapping) {
if ($eventMapping === null) {
$eventMapping = [null];
}
foreach ($eventMapping as $method) {
$events[] = [
'type' => $eventType,
'method' => $method,
];
}
}
$listeners[] = [
'class' => $listenerClass,
'event' => $events,
];
}
$entities[] = [
'class' => $entityClass,
'listener' => $listeners,
];
}
return ['entities' => $entities];
};
$node
->beforeNormalization()
// Yaml normalization
->ifTrue(static function ($v) {
return is_array(reset($v)) && is_string(key(reset($v)));
})
->then($normalizer)
->end()
->fixXmlConfig('entity', 'entities')
->children()
->arrayNode('entities')
->useAttributeAsKey('class')
->prototype('array')
->fixXmlConfig('listener')
->children()
->arrayNode('listeners')
->useAttributeAsKey('class')
->prototype('array')
->fixXmlConfig('event')
->children()
->arrayNode('events')
->prototype('array')
->children()
->scalarNode('type')->end()
->scalarNode('method')->defaultNull()->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end();
return $node;
}
/**
* Return ORM entity manager node
*/
private function getOrmEntityManagersNode(): ArrayNodeDefinition
{
$treeBuilder = new TreeBuilder('entity_managers');
$node = $treeBuilder->getRootNode();
$node
->requiresAtLeastOneElement()
->useAttributeAsKey('name')
->prototype('array')
->addDefaultsIfNotSet()
->append($this->getOrmCacheDriverNode('query_cache_driver'))
->append($this->getOrmCacheDriverNode('metadata_cache_driver'))
->append($this->getOrmCacheDriverNode('result_cache_driver'))
->append($this->getOrmEntityListenersNode())
->children()
->scalarNode('connection')->end()
->scalarNode('class_metadata_factory_name')->defaultValue(ClassMetadataFactory::class)->end()
->scalarNode('default_repository_class')->defaultValue(EntityRepository::class)->end()
->scalarNode('auto_mapping')->defaultFalse()->end()
->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end()
->scalarNode('quote_strategy')->defaultValue('doctrine.orm.quote_strategy.default')->end()
->scalarNode('entity_listener_resolver')->defaultNull()->end()
->scalarNode('repository_factory')->defaultValue('doctrine.orm.container_repository_factory')->end()
->end()
->children()
->arrayNode('second_level_cache')
->children()
->append($this->getOrmCacheDriverNode('region_cache_driver'))
->scalarNode('region_lock_lifetime')->defaultValue(60)->end()
->booleanNode('log_enabled')->defaultValue($this->debug)->end()
->scalarNode('region_lifetime')->defaultValue(3600)->end()
->booleanNode('enabled')->defaultValue(true)->end()
->scalarNode('factory')->end()
->end()
->fixXmlConfig('region')
->children()
->arrayNode('regions')
->useAttributeAsKey('name')
->prototype('array')
->children()
->append($this->getOrmCacheDriverNode('cache_driver'))
->scalarNode('lock_path')->defaultValue('%kernel.cache_dir%/doctrine/orm/slc/filelock')->end()
->scalarNode('lock_lifetime')->defaultValue(60)->end()
->scalarNode('type')->defaultValue('default')->end()
->scalarNode('lifetime')->defaultValue(0)->end()
->scalarNode('service')->end()
->scalarNode('name')->end()
->end()
->end()
->end()
->end()
->fixXmlConfig('logger')
->children()
->arrayNode('loggers')
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('name')->end()
->scalarNode('service')->end()
->end()
->end()
->end()
->end()
->end()
->end()
->fixXmlConfig('hydrator')
->children()
->arrayNode('hydrators')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('mapping')
->children()
->arrayNode('mappings')
->useAttributeAsKey('name')
->prototype('array')
->beforeNormalization()
->ifString()
->then(static function ($v) {
return ['type' => $v];
})
->end()
->treatNullLike([])
->treatFalseLike(['mapping' => false])
->performNoDeepMerging()
->children()
->scalarNode('mapping')->defaultValue(true)->end()
->scalarNode('type')->end()
->scalarNode('dir')->end()
->scalarNode('alias')->end()
->scalarNode('prefix')->end()
->booleanNode('is_bundle')->end()
->end()
->end()
->end()
->arrayNode('dql')
->fixXmlConfig('string_function')
->fixXmlConfig('numeric_function')
->fixXmlConfig('datetime_function')
->children()
->arrayNode('string_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('numeric_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->arrayNode('datetime_functions')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->end()
->end()
->end()
->end()
->fixXmlConfig('filter')
->children()
->arrayNode('filters')
->info('Register SQL Filters in the entity manager')
->useAttributeAsKey('name')
->prototype('array')
->beforeNormalization()
->ifString()
->then(static function ($v) {
return ['class' => $v];
})
->end()
->beforeNormalization()
// The content of the XML node is returned as the "value" key so we need to rename it
->ifTrue(static function ($v) {
return is_array($v) && isset($v['value']);
})
->then(static function ($v) {
$v['class'] = $v['value'];
unset($v['value']);
return $v;
})
->end()
->fixXmlConfig('parameter')
->children()
->scalarNode('class')->isRequired()->end()
->booleanNode('enabled')->defaultFalse()->end()
->arrayNode('parameters')
->useAttributeAsKey('name')
->prototype('variable')->end()
->end()
->end()
->end()
->end()
->end()
->end();
return $node;
}
/**
* Return a ORM cache driver node for an given entity manager
*/
private function getOrmCacheDriverNode(string $name): ArrayNodeDefinition
{
$treeBuilder = new TreeBuilder($name);
$node = $treeBuilder->getRootNode();
$node
->beforeNormalization()
->ifString()
->then(static function ($v): array {
return ['type' => $v];
})
->end()
->children()
->scalarNode('type')->defaultNull()->end()
->scalarNode('id')->end()
->scalarNode('pool')->end()
->end();
if ($name !== 'metadata_cache_driver') {
$node->addDefaultsIfNotSet();
}
return $node;
}
/**
* Find proxy auto generate modes for their names and int values
*
* @return array{names: list<string>, values: list<int>}
*/
private function getAutoGenerateModes(): array
{
$constPrefix = 'AUTOGENERATE_';
$prefixLen = strlen($constPrefix);
$refClass = new ReflectionClass(AbstractProxyFactory::class);
$constsArray = $refClass->getConstants();
$namesArray = [];
$valuesArray = [];
foreach ($constsArray as $key => $value) {
if (strpos($key, $constPrefix) !== 0) {
continue;
}
$namesArray[] = substr($key, $prefixLen);
$valuesArray[] = (int) $value;
}
return [
'names' => $namesArray,
'values' => $valuesArray,
];
}
/**
* Returns the correct deprecation param's as an array for setDeprecated.
*
* Symfony/Config v5.1 introduces a deprecation notice when calling
* setDeprecation() with less than 3 args and the getDeprecation method was
* introduced at the same time. By checking if getDeprecation() exists,
* we can determine the correct param count to use when calling setDeprecated.
*
* @return list<string>|array{0:string, 1: numeric-string, string}
*/
private function getDeprecationMsg(string $message, string $version): array
{
if (method_exists(BaseNode::class, 'getDeprecation')) {
return [
'doctrine/doctrine-bundle',
$version,
$message,
];
}
return [$message];
}
}

File diff suppressed because it is too large Load Diff