vendor/api-platform/core/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php line 907
<?php/** This file is part of the API Platform project.** (c) Kévin Dunglas <dunglas@gmail.com>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/declare(strict_types=1);namespace ApiPlatform\Symfony\Bundle\DependencyInjection;use ApiPlatform\Api\FilterInterface as LegacyFilterInterface;use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface;use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface;use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter as DoctrineMongoDbOdmAbstractFilter;use ApiPlatform\Doctrine\Odm\State\LinksHandlerInterface as OdmLinksHandlerInterface;use ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension;use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension;use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface as DoctrineQueryCollectionExtensionInterface;use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter as DoctrineOrmAbstractFilter;use ApiPlatform\Doctrine\Orm\State\LinksHandlerInterface as OrmLinksHandlerInterface;use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface;use ApiPlatform\GraphQl\Error\ErrorHandlerInterface;use ApiPlatform\GraphQl\Resolver\MutationResolverInterface;use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface;use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;use ApiPlatform\GraphQl\Type\Definition\TypeInterface as GraphQlTypeInterface;use ApiPlatform\Metadata\ApiResource;use ApiPlatform\Metadata\FilterInterface;use ApiPlatform\Metadata\UriVariableTransformerInterface;use ApiPlatform\Metadata\UrlGeneratorInterface;use ApiPlatform\Metadata\Util\Inflector;use ApiPlatform\State\ApiResource\Error;use ApiPlatform\State\ProcessorInterface;use ApiPlatform\State\ProviderInterface;use ApiPlatform\Symfony\GraphQl\Resolver\Factory\DataCollectorResolverFactory;use ApiPlatform\Symfony\Validator\Exception\ValidationException;use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface;use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface;use Doctrine\Persistence\ManagerRegistry;use phpDocumentor\Reflection\DocBlockFactoryInterface;use PHPStan\PhpDocParser\Parser\PhpDocParser;use Ramsey\Uuid\Uuid;use Symfony\Component\Config\FileLocator;use Symfony\Component\Config\Resource\DirectoryResource;use Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\DependencyInjection\ContainerInterface;use Symfony\Component\DependencyInjection\Definition;use Symfony\Component\DependencyInjection\Exception\RuntimeException;use Symfony\Component\DependencyInjection\Extension\Extension;use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;use Symfony\Component\DependencyInjection\Reference;use Symfony\Component\Finder\Finder;use Symfony\Component\HttpClient\ScopingHttpClient;use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;use Symfony\Component\Uid\AbstractUid;use Symfony\Component\Validator\Validator\ValidatorInterface;use Symfony\Component\Yaml\Yaml;use Twig\Environment;/*** The extension of this bundle.** @author Kévin Dunglas <dunglas@gmail.com>*/final class ApiPlatformExtension extends Extension implements PrependExtensionInterface{/*** {@inheritdoc}*/public function prepend(ContainerBuilder $container): void{if (isset($container->getExtensions()['framework'])) {$container->prependExtensionConfig('framework', ['serializer' => ['enabled' => true,],]);$container->prependExtensionConfig('framework', ['property_info' => ['enabled' => true,],]);}if (isset($container->getExtensions()['lexik_jwt_authentication'])) {$container->prependExtensionConfig('lexik_jwt_authentication', ['api_platform' => ['enabled' => true,],]);}}/*** {@inheritdoc}*/public function load(array $configs, ContainerBuilder $container): void{$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));$configuration = new Configuration();$config = $this->processConfiguration($configuration, $configs);if (!$config['formats']) {trigger_deprecation('api-platform/core', '3.2', 'Setting the "formats" section will be mandatory in API Platform 4.');$config['formats'] = ['jsonld' => ['mime_types' => ['application/ld+json']],// Note that in API Platform 4 this will be removed as it was used for documentation only and are is now present in the docsFormats'json' => ['mime_types' => ['application/json']], // Swagger support];}$formats = $this->getFormats($config['formats']);$patchFormats = $this->getFormats($config['patch_formats']);$errorFormats = $this->getFormats($config['error_formats']);$docsFormats = $this->getFormats($config['docs_formats']);$jsonSchemaFormats = $config['jsonschema_formats'];if (!$jsonSchemaFormats) {foreach (array_keys($formats) as $f) {// Distinct JSON-based formats must have names that start with 'json'if (str_starts_with($f, 'json')) {$jsonSchemaFormats[$f] = true;}}}if (!isset($errorFormats['json'])) {$errorFormats['json'] = ['application/problem+json', 'application/json'];}if (!isset($errorFormats['jsonproblem'])) {$errorFormats['jsonproblem'] = ['application/problem+json'];}if ($this->isConfigEnabled($container, $config['graphql']) && !isset($formats['json'])) {trigger_deprecation('api-platform/core', '3.2', 'Add the "json" format to the configuration to use GraphQL.');$formats['json'] = ['application/json'];}// Backward Compatibility layerif (isset($formats['jsonapi']) && !isset($patchFormats['jsonapi'])) {$patchFormats['jsonapi'] = ['application/vnd.api+json'];}if (isset($docsFormats['json']) && !isset($docsFormats['jsonopenapi'])) {trigger_deprecation('api-platform/core', '3.2', 'The "json" format is too broad, use ["jsonopenapi" => ["application/vnd.openapi+json"]] instead.');$docsFormats['jsonopenapi'] = ['application/vnd.openapi+json'];}$this->registerCommonConfiguration($container, $config, $loader, $formats, $patchFormats, $errorFormats, $docsFormats, $jsonSchemaFormats);$this->registerMetadataConfiguration($container, $config, $loader);$this->registerOAuthConfiguration($container, $config);$this->registerOpenApiConfiguration($container, $config, $loader);$this->registerSwaggerConfiguration($container, $config, $loader);$this->registerJsonApiConfiguration($formats, $loader, $config);$this->registerJsonLdHydraConfiguration($container, $formats, $loader, $config);$this->registerJsonHalConfiguration($formats, $loader);$this->registerJsonProblemConfiguration($errorFormats, $loader);$this->registerGraphQlConfiguration($container, $config, $loader);$this->registerCacheConfiguration($container);$this->registerDoctrineOrmConfiguration($container, $config, $loader);$this->registerDoctrineMongoDbOdmConfiguration($container, $config, $loader);$this->registerHttpCacheConfiguration($container, $config, $loader);$this->registerValidatorConfiguration($container, $config, $loader);$this->registerDataCollectorConfiguration($container, $config, $loader);$this->registerMercureConfiguration($container, $config, $loader);$this->registerMessengerConfiguration($container, $config, $loader);$this->registerElasticsearchConfiguration($container, $config, $loader);$this->registerSecurityConfiguration($container, $config, $loader);$this->registerMakerConfiguration($container, $config, $loader);$this->registerArgumentResolverConfiguration($loader);$container->registerForAutoconfiguration(FilterInterface::class)->addTag('api_platform.filter');$container->registerForAutoconfiguration(LegacyFilterInterface::class)->addTag('api_platform.filter');$container->registerForAutoconfiguration(ProviderInterface::class)->addTag('api_platform.state_provider');$container->registerForAutoconfiguration(ProcessorInterface::class)->addTag('api_platform.state_processor');$container->registerForAutoconfiguration(UriVariableTransformerInterface::class)->addTag('api_platform.uri_variables.transformer');if (!$container->has('api_platform.state.item_provider')) {$container->setAlias('api_platform.state.item_provider', 'api_platform.state_provider.object');}$this->registerInflectorConfiguration($config);}private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats, array $docsFormats, array $jsonSchemaFormats): void{$loader->load('symfony/events.xml');$loader->load('symfony/controller.xml');$loader->load('api.xml');$loader->load('state.xml');$loader->load('filter.xml');if (class_exists(Uuid::class)) {$loader->load('ramsey_uuid.xml');}if (class_exists(AbstractUid::class)) {$loader->load('symfony/uid.xml');}// TODO: remove in 4.x$container->setParameter('api_platform.event_listeners_backward_compatibility_layer', $config['event_listeners_backward_compatibility_layer']);$loader->load('legacy/events.xml');$container->setParameter('api_platform.enable_entrypoint', $config['enable_entrypoint']);$container->setParameter('api_platform.enable_docs', $config['enable_docs']);$container->setParameter('api_platform.keep_legacy_inflector', $config['keep_legacy_inflector']);$container->setParameter('api_platform.title', $config['title']);$container->setParameter('api_platform.description', $config['description']);$container->setParameter('api_platform.version', $config['version']);$container->setParameter('api_platform.show_webby', $config['show_webby']);$container->setParameter('api_platform.url_generation_strategy', $config['defaults']['url_generation_strategy'] ?? UrlGeneratorInterface::ABS_PATH);$container->setParameter('api_platform.exception_to_status', $config['exception_to_status']);$container->setParameter('api_platform.formats', $formats);$container->setParameter('api_platform.patch_formats', $patchFormats);$container->setParameter('api_platform.error_formats', $errorFormats);$container->setParameter('api_platform.docs_formats', $docsFormats);$container->setParameter('api_platform.jsonschema_formats', $jsonSchemaFormats);$container->setParameter('api_platform.eager_loading.enabled', $this->isConfigEnabled($container, $config['eager_loading']));$container->setParameter('api_platform.eager_loading.max_joins', $config['eager_loading']['max_joins']);$container->setParameter('api_platform.eager_loading.fetch_partial', $config['eager_loading']['fetch_partial']);$container->setParameter('api_platform.eager_loading.force_eager', $config['eager_loading']['force_eager']);$container->setParameter('api_platform.collection.exists_parameter_name', $config['collection']['exists_parameter_name']);$container->setParameter('api_platform.collection.order', $config['collection']['order']);$container->setParameter('api_platform.collection.order_parameter_name', $config['collection']['order_parameter_name']);$container->setParameter('api_platform.collection.order_nulls_comparison', $config['collection']['order_nulls_comparison']);$container->setParameter('api_platform.collection.pagination.enabled', $config['defaults']['pagination_enabled'] ?? true);$container->setParameter('api_platform.collection.pagination.partial', $config['defaults']['pagination_partial'] ?? false);$container->setParameter('api_platform.collection.pagination.client_enabled', $config['defaults']['pagination_client_enabled'] ?? false);$container->setParameter('api_platform.collection.pagination.client_items_per_page', $config['defaults']['pagination_client_items_per_page'] ?? false);$container->setParameter('api_platform.collection.pagination.client_partial', $config['defaults']['pagination_client_partial'] ?? false);$container->setParameter('api_platform.collection.pagination.items_per_page', $config['defaults']['pagination_items_per_page'] ?? 30);$container->setParameter('api_platform.collection.pagination.maximum_items_per_page', $config['defaults']['pagination_maximum_items_per_page'] ?? null);$container->setParameter('api_platform.collection.pagination.page_parameter_name', $config['defaults']['pagination_page_parameter_name'] ?? $config['collection']['pagination']['page_parameter_name']);$container->setParameter('api_platform.collection.pagination.enabled_parameter_name', $config['defaults']['pagination_enabled_parameter_name'] ?? $config['collection']['pagination']['enabled_parameter_name']);$container->setParameter('api_platform.collection.pagination.items_per_page_parameter_name', $config['defaults']['pagination_items_per_page_parameter_name'] ?? $config['collection']['pagination']['items_per_page_parameter_name']);$container->setParameter('api_platform.collection.pagination.partial_parameter_name', $config['defaults']['pagination_partial_parameter_name'] ?? $config['collection']['pagination']['partial_parameter_name']);$container->setParameter('api_platform.collection.pagination', $this->getPaginationDefaults($config['defaults'] ?? [], $config['collection']['pagination']));$container->setParameter('api_platform.handle_symfony_errors', $config['handle_symfony_errors'] ?? false);$container->setParameter('api_platform.http_cache.etag', $config['defaults']['cache_headers']['etag'] ?? true);$container->setParameter('api_platform.http_cache.max_age', $config['defaults']['cache_headers']['max_age'] ?? null);$container->setParameter('api_platform.http_cache.shared_max_age', $config['defaults']['cache_headers']['shared_max_age'] ?? null);$container->setParameter('api_platform.http_cache.vary', $config['defaults']['cache_headers']['vary'] ?? ['Accept']);$container->setParameter('api_platform.http_cache.public', $config['defaults']['cache_headers']['public'] ?? $config['http_cache']['public']);$container->setParameter('api_platform.http_cache.invalidation.max_header_length', $config['defaults']['cache_headers']['invalidation']['max_header_length'] ?? $config['http_cache']['invalidation']['max_header_length']);$container->setParameter('api_platform.http_cache.invalidation.xkey.glue', $config['defaults']['cache_headers']['invalidation']['xkey']['glue'] ?? $config['http_cache']['invalidation']['xkey']['glue']);$container->setAlias('api_platform.path_segment_name_generator', $config['path_segment_name_generator']);if ($config['name_converter']) {$container->setAlias('api_platform.name_converter', $config['name_converter']);}$container->setParameter('api_platform.asset_package', $config['asset_package']);$container->setParameter('api_platform.defaults', $this->normalizeDefaults($config['defaults'] ?? []));$container->setParameter('api_platform.rfc_7807_compliant_errors', $config['defaults']['extra_properties']['rfc_7807_compliant_errors'] ?? false);if ($container->getParameter('kernel.debug')) {$container->removeDefinition('api_platform.serializer.mapping.cache_class_metadata_factory');}}/*** This method will be removed in 3.0 when "defaults" will be the regular configuration path for the pagination.*/private function getPaginationDefaults(array $defaults, array $collectionPaginationConfiguration): array{$paginationOptions = [];foreach ($defaults as $key => $value) {if (!str_starts_with($key, 'pagination_')) {continue;}$paginationOptions[str_replace('pagination_', '', $key)] = $value;}return array_merge($collectionPaginationConfiguration, $paginationOptions);}private function normalizeDefaults(array $defaults): array{$normalizedDefaults = ['extra_properties' => $defaults['extra_properties'] ?? []];unset($defaults['extra_properties']);$rc = new \ReflectionClass(ApiResource::class);$publicProperties = [];foreach ($rc->getConstructor()->getParameters() as $param) {$publicProperties[$param->getName()] = true;}$nameConverter = new CamelCaseToSnakeCaseNameConverter();foreach ($defaults as $option => $value) {if (isset($publicProperties[$nameConverter->denormalize($option)])) {$normalizedDefaults[$option] = $value;continue;}$normalizedDefaults['extra_properties'][$option] = $value;}return $normalizedDefaults;}private function registerMetadataConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{[$xmlResources, $yamlResources] = $this->getResourcesToWatch($container, $config);$container->setParameter('api_platform.class_name_resources', $this->getClassNameResources());$loader->load('metadata/resource_name.xml');$loader->load('metadata/property_name.xml');if (!empty($config['resource_class_directories'])) {$container->setParameter('api_platform.resource_class_directories', array_merge($config['resource_class_directories'],$container->getParameter('api_platform.resource_class_directories')));}// V3 metadata$loader->load('metadata/xml.xml');$loader->load('metadata/links.xml');$loader->load('metadata/property.xml');$loader->load('metadata/resource.xml');$loader->load('metadata/operation.xml');$container->getDefinition('api_platform.metadata.resource_extractor.xml')->replaceArgument(0, $xmlResources);$container->getDefinition('api_platform.metadata.property_extractor.xml')->replaceArgument(0, $xmlResources);if (class_exists(PhpDocParser::class) || interface_exists(DocBlockFactoryInterface::class)) {$loader->load('metadata/php_doc.xml');}if (class_exists(Yaml::class)) {$loader->load('metadata/yaml.xml');$container->getDefinition('api_platform.metadata.resource_extractor.yaml')->replaceArgument(0, $yamlResources);$container->getDefinition('api_platform.metadata.property_extractor.yaml')->replaceArgument(0, $yamlResources);}}private function getClassNameResources(): array{return [Error::class,ValidationException::class,];}private function getBundlesResourcesPaths(ContainerBuilder $container, array $config): array{$bundlesResourcesPaths = [];foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {$dirname = $bundle['path'];$paths = ["$dirname/ApiResource","$dirname/src/ApiResource",];foreach (['.yaml', '.yml', '.xml', ''] as $extension) {$paths[] = "$dirname/Resources/config/api_resources$extension";$paths[] = "$dirname/config/api_resources$extension";}if ($this->isConfigEnabled($container, $config['doctrine'])) {$paths[] = "$dirname/Entity";$paths[] = "$dirname/src/Entity";}if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {$paths[] = "$dirname/Document";$paths[] = "$dirname/src/Document";}foreach ($paths as $path) {if ($container->fileExists($path, false)) {$bundlesResourcesPaths[] = $path;}}}return $bundlesResourcesPaths;}private function getResourcesToWatch(ContainerBuilder $container, array $config): array{$paths = array_unique(array_merge($this->getBundlesResourcesPaths($container, $config), $config['mapping']['paths']));if (!$config['mapping']['paths']) {$projectDir = $container->getParameter('kernel.project_dir');foreach (["$projectDir/config/api_platform", "$projectDir/src/ApiResource"] as $dir) {if (is_dir($dir)) {$paths[] = $dir;}}if ($this->isConfigEnabled($container, $config['doctrine']) && is_dir($doctrinePath = "$projectDir/src/Entity")) {$paths[] = $doctrinePath;}if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm']) && is_dir($documentPath = "$projectDir/src/Document")) {$paths[] = $documentPath;}}$resources = ['yml' => [], 'xml' => [], 'dir' => []];foreach ($paths as $path) {if (is_dir($path)) {foreach (Finder::create()->followLinks()->files()->in($path)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) {$resources['yaml' === ($extension = $file->getExtension()) ? 'yml' : $extension][] = $file->getRealPath();}$resources['dir'][] = $path;$container->addResource(new DirectoryResource($path, '/\.(xml|ya?ml|php)$/'));continue;}if ($container->fileExists($path, false)) {if (!preg_match('/\.(xml|ya?ml)$/', (string) $path, $matches)) {throw new RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & YAML.', $path));}$resources['yaml' === $matches[1] ? 'yml' : $matches[1]][] = $path;continue;}throw new RuntimeException(sprintf('Could not open file or directory "%s".', $path));}$container->setParameter('api_platform.resource_class_directories', $resources['dir']);return [$resources['xml'], $resources['yml']];}private function registerOAuthConfiguration(ContainerBuilder $container, array $config): void{if (!$config['oauth']) {return;}$container->setParameter('api_platform.oauth.enabled', $this->isConfigEnabled($container, $config['oauth']));$container->setParameter('api_platform.oauth.clientId', $config['oauth']['clientId']);$container->setParameter('api_platform.oauth.clientSecret', $config['oauth']['clientSecret']);$container->setParameter('api_platform.oauth.type', $config['oauth']['type']);$container->setParameter('api_platform.oauth.flow', $config['oauth']['flow']);$container->setParameter('api_platform.oauth.tokenUrl', $config['oauth']['tokenUrl']);$container->setParameter('api_platform.oauth.authorizationUrl', $config['oauth']['authorizationUrl']);$container->setParameter('api_platform.oauth.refreshUrl', $config['oauth']['refreshUrl']);$container->setParameter('api_platform.oauth.scopes', $config['oauth']['scopes']);$container->setParameter('api_platform.oauth.pkce', $config['oauth']['pkce']);if ($container->hasDefinition('api_platform.swagger_ui.action')) {$container->getDefinition('api_platform.swagger_ui.action')->setArgument(10, $config['oauth']['pkce']);}}/*** Registers the Swagger, ReDoc and Swagger UI configuration.*/private function registerSwaggerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{foreach (array_keys($config['swagger']['api_keys']) as $keyName) {if (!preg_match('/^[a-zA-Z0-9._-]+$/', $keyName)) {trigger_deprecation('api-platform/core', '3.1', sprintf('The swagger api_keys key "%s" is not valid with OpenAPI 3.1 it should match "^[a-zA-Z0-9._-]+$"', $keyName));}}$container->setParameter('api_platform.swagger.versions', $config['swagger']['versions']);if (!$config['enable_swagger'] && $config['enable_swagger_ui']) {throw new RuntimeException('You can not enable the Swagger UI without enabling Swagger, fix this by enabling swagger via the configuration "enable_swagger: true".');}if (!$config['enable_swagger']) {return;}$loader->load('openapi.xml');$loader->load('swagger_ui.xml');$loader->load('legacy/swagger_ui.xml');if (!$config['enable_swagger_ui'] && !$config['enable_re_doc']) {// Remove the listener but keep the controller to allow customizing the path of the UI$container->removeDefinition('api_platform.swagger.listener.ui');}$container->setParameter('api_platform.enable_swagger_ui', $config['enable_swagger_ui']);$container->setParameter('api_platform.enable_re_doc', $config['enable_re_doc']);$container->setParameter('api_platform.swagger.api_keys', $config['swagger']['api_keys']);if ($config['openapi']['swagger_ui_extra_configuration'] && $config['swagger']['swagger_ui_extra_configuration']) {throw new RuntimeException('You can not set "swagger_ui_extra_configuration" twice - in "openapi" and "swagger" section.');}$container->setParameter('api_platform.swagger_ui.extra_configuration', $config['openapi']['swagger_ui_extra_configuration'] ?: $config['swagger']['swagger_ui_extra_configuration']);}private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader, array $config): void{if (!isset($formats['jsonapi'])) {return;}$loader->load('jsonapi.xml');$loader->load('legacy/jsonapi.xml');}private function registerJsonLdHydraConfiguration(ContainerBuilder $container, array $formats, XmlFileLoader $loader, array $config): void{if (!isset($formats['jsonld'])) {return;}$loader->load('jsonld.xml');$loader->load('legacy/hydra.xml');$loader->load('hydra.xml');if (!$container->has('api_platform.json_schema.schema_factory')) {$container->removeDefinition('api_platform.hydra.json_schema.schema_factory');}if (!$config['enable_docs']) {$container->removeDefinition('api_platform.hydra.listener.response.add_link_header');$container->removeDefinition('api_platform.hydra.processor.link');}}private function registerJsonHalConfiguration(array $formats, XmlFileLoader $loader): void{if (!isset($formats['jsonhal'])) {return;}$loader->load('hal.xml');}private function registerJsonProblemConfiguration(array $errorFormats, XmlFileLoader $loader): void{if (!isset($errorFormats['jsonproblem'])) {return;}$loader->load('problem.xml');}private function registerGraphQlConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{$enabled = $this->isConfigEnabled($container, $config['graphql']);$graphqlIntrospectionEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['introspection']);$graphiqlEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['graphiql']);$graphqlPlayGroundEnabled = $enabled && $this->isConfigEnabled($container, $config['graphql']['graphql_playground']);if ($graphqlPlayGroundEnabled) {trigger_deprecation('api-platform/core', '3.1', 'GraphQL Playground is deprecated and will be removed in API Platform 4.0. Only GraphiQL will be available in the future. Set api_platform.graphql.graphql_playground to false in the configuration to remove this deprecation.');}$container->setParameter('api_platform.graphql.enabled', $enabled);$container->setParameter('api_platform.graphql.introspection.enabled', $graphqlIntrospectionEnabled);$container->setParameter('api_platform.graphql.graphiql.enabled', $graphiqlEnabled);$container->setParameter('api_platform.graphql.graphql_playground.enabled', $graphqlPlayGroundEnabled);$container->setParameter('api_platform.graphql.collection.pagination', $config['graphql']['collection']['pagination']);if (!$enabled) {return;}$container->setParameter('api_platform.graphql.default_ide', $config['graphql']['default_ide']);$container->setParameter('api_platform.graphql.nesting_separator', $config['graphql']['nesting_separator']);$loader->load('graphql.xml');// @phpstan-ignore-next-line because PHPStan uses the container of the test env cache and in test the parameter kernel.bundles always contains the key TwigBundleif (!class_exists(Environment::class) || !isset($container->getParameter('kernel.bundles')['TwigBundle'])) {if ($graphiqlEnabled || $graphqlPlayGroundEnabled) {throw new RuntimeException(sprintf('GraphiQL and GraphQL Playground interfaces depend on Twig. Please activate TwigBundle for the %s environnement or disable GraphiQL and GraphQL Playground.', $container->getParameter('kernel.environment')));}$container->removeDefinition('api_platform.graphql.action.graphiql');$container->removeDefinition('api_platform.graphql.action.graphql_playground');}$container->registerForAutoconfiguration(QueryItemResolverInterface::class)->addTag('api_platform.graphql.resolver');$container->registerForAutoconfiguration(QueryCollectionResolverInterface::class)->addTag('api_platform.graphql.resolver');$container->registerForAutoconfiguration(MutationResolverInterface::class)->addTag('api_platform.graphql.resolver');$container->registerForAutoconfiguration(GraphQlTypeInterface::class)->addTag('api_platform.graphql.type');$container->registerForAutoconfiguration(ErrorHandlerInterface::class)->addTag('api_platform.graphql.error_handler');/* TODO: remove these in 4.x only one resolver factory is used and we're using providers/processors */if ($config['event_listeners_backward_compatibility_layer'] ?? true) {// @TODO: API Platform 3.3 trigger_deprecation('api-platform/core', '3.3', 'In API Platform 4 only one factory "api_platform.graphql.resolver.factory.item" will remain. Stages are deprecated in favor of using a provider/processor.');// + deprecate every service from legacy/graphql.xml$loader->load('legacy/graphql.xml');if (!$container->getParameter('kernel.debug')) {return;}$requestStack = new Reference('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE);$collectionDataCollectorResolverFactory = (new Definition(DataCollectorResolverFactory::class))->setDecoratedService('api_platform.graphql.resolver.factory.collection')->setArguments([new Reference('api_platform.graphql.data_collector.resolver.factory.collection.inner'), $requestStack]);$itemDataCollectorResolverFactory = (new Definition(DataCollectorResolverFactory::class))->setDecoratedService('api_platform.graphql.resolver.factory.item')->setArguments([new Reference('api_platform.graphql.data_collector.resolver.factory.item.inner'), $requestStack]);$itemMutationDataCollectorResolverFactory = (new Definition(DataCollectorResolverFactory::class))->setDecoratedService('api_platform.graphql.resolver.factory.item_mutation')->setArguments([new Reference('api_platform.graphql.data_collector.resolver.factory.item_mutation.inner'), $requestStack]);$itemSubscriptionDataCollectorResolverFactory = (new Definition(DataCollectorResolverFactory::class))->setDecoratedService('api_platform.graphql.resolver.factory.item_subscription')->setArguments([new Reference('api_platform.graphql.data_collector.resolver.factory.item_subscription.inner'), $requestStack]);$container->addDefinitions(['api_platform.graphql.data_collector.resolver.factory.collection' => $collectionDataCollectorResolverFactory,'api_platform.graphql.data_collector.resolver.factory.item' => $itemDataCollectorResolverFactory,'api_platform.graphql.data_collector.resolver.factory.item_mutation' => $itemMutationDataCollectorResolverFactory,'api_platform.graphql.data_collector.resolver.factory.item_subscription' => $itemSubscriptionDataCollectorResolverFactory,]);}}private function registerCacheConfiguration(ContainerBuilder $container): void{if (!$container->hasParameter('kernel.debug') || !$container->getParameter('kernel.debug')) {$container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer');}}private function registerDoctrineOrmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$this->isConfigEnabled($container, $config['doctrine'])) {return;}// For older versions of doctrine bridge this allows autoconfiguration for filtersif (!$container->has(ManagerRegistry::class)) {$container->setAlias(ManagerRegistry::class, 'doctrine');}$container->registerForAutoconfiguration(QueryItemExtensionInterface::class)->addTag('api_platform.doctrine.orm.query_extension.item');$container->registerForAutoconfiguration(DoctrineQueryCollectionExtensionInterface::class)->addTag('api_platform.doctrine.orm.query_extension.collection');$container->registerForAutoconfiguration(DoctrineOrmAbstractFilter::class);$container->registerForAutoconfiguration(OrmLinksHandlerInterface::class)->addTag('api_platform.doctrine.orm.links_handler');$loader->load('doctrine_orm.xml');if ($this->isConfigEnabled($container, $config['eager_loading'])) {return;}$container->removeAlias(EagerLoadingExtension::class);$container->removeDefinition('api_platform.doctrine.orm.query_extension.eager_loading');$container->removeAlias(FilterEagerLoadingExtension::class);$container->removeDefinition('api_platform.doctrine.orm.query_extension.filter_eager_loading');}private function registerDoctrineMongoDbOdmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {return;}$container->registerForAutoconfiguration(AggregationItemExtensionInterface::class)->addTag('api_platform.doctrine_mongodb.odm.aggregation_extension.item');$container->registerForAutoconfiguration(AggregationCollectionExtensionInterface::class)->addTag('api_platform.doctrine_mongodb.odm.aggregation_extension.collection');$container->registerForAutoconfiguration(DoctrineMongoDbOdmAbstractFilter::class)->setBindings(['$managerRegistry' => new Reference('doctrine_mongodb')]);$container->registerForAutoconfiguration(OdmLinksHandlerInterface::class)->addTag('api_platform.doctrine.odm.links_handler');$loader->load('doctrine_mongodb_odm.xml');}private function registerHttpCacheConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{$loader->load('http_cache.xml');$loader->load('legacy/http_cache.xml');if (!$this->isConfigEnabled($container, $config['http_cache']['invalidation'])) {return;}if ($this->isConfigEnabled($container, $config['doctrine'])) {$loader->load('doctrine_orm_http_cache_purger.xml');}$loader->load('http_cache_purger.xml');$loader->load('legacy/http_cache_purger.xml');foreach ($config['http_cache']['invalidation']['scoped_clients'] as $client) {$definition = $container->getDefinition($client);$definition->addTag('api_platform.http_cache.http_client');}if (!($urls = $config['http_cache']['invalidation']['urls'])) {$urls = $config['http_cache']['invalidation']['varnish_urls'];}foreach ($urls as $key => $url) {$definition = new Definition(ScopingHttpClient::class, [new Reference('http_client'), $url, ['base_uri' => $url] + $config['http_cache']['invalidation']['request_options']]);$definition->setFactory([ScopingHttpClient::class, 'forBaseUri']);$definition->addTag('api_platform.http_cache.http_client');$container->setDefinition('api_platform.invalidation_http_client.'.$key, $definition);}$serviceName = $config['http_cache']['invalidation']['purger'];if (!$container->hasDefinition('api_platform.http_cache.purger')) {$container->setAlias('api_platform.http_cache.purger', $serviceName);}}/*** Normalizes the format from config to the one accepted by Symfony HttpFoundation.*/private function getFormats(array $configFormats): array{$formats = [];foreach ($configFormats as $format => $value) {foreach ($value['mime_types'] as $mimeType) {$formats[$format][] = $mimeType;}}return $formats;}private function registerValidatorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (interface_exists(ValidatorInterface::class)) {$loader->load('metadata/validator.xml');$loader->load('symfony/validator.xml');if ($this->isConfigEnabled($container, $config['graphql'])) {$loader->load('graphql/validator.xml');}$container->registerForAutoconfiguration(ValidationGroupsGeneratorInterface::class)->addTag('api_platform.validation_groups_generator');$container->registerForAutoconfiguration(PropertySchemaRestrictionMetadataInterface::class)->addTag('api_platform.metadata.property_schema_restriction');$loader->load('legacy/validator.xml');}if (!$config['validator']) {return;}$container->setParameter('api_platform.validator.serialize_payload_fields', $config['validator']['serialize_payload_fields']);$container->setParameter('api_platform.validator.query_parameter_validation', $config['validator']['query_parameter_validation']);if (!$config['validator']['query_parameter_validation']) {$container->removeDefinition('api_platform.listener.view.validate_query_parameters');$container->removeDefinition('api_platform.validator.query_parameter_validator');}}private function registerDataCollectorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$config['enable_profiler']) {return;}$loader->load('data_collector.xml');if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) {$loader->load('debug.xml');}}private function registerMercureConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$this->isConfigEnabled($container, $config['mercure'])) {return;}$container->setParameter('api_platform.mercure.include_type', $config['mercure']['include_type']);$loader->load('legacy/mercure.xml');$loader->load('mercure.xml');if ($this->isConfigEnabled($container, $config['doctrine'])) {$loader->load('doctrine_orm_mercure_publisher.xml');}if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {$loader->load('doctrine_odm_mercure_publisher.xml');}if ($this->isConfigEnabled($container, $config['graphql'])) {$loader->load('graphql_mercure.xml');}}private function registerMessengerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$this->isConfigEnabled($container, $config['messenger'])) {return;}$loader->load('messenger.xml');}private function registerElasticsearchConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{$enabled = $this->isConfigEnabled($container, $config['elasticsearch']);$container->setParameter('api_platform.elasticsearch.enabled', $enabled);if (!$enabled) {return;}$clientClass = class_exists(\Elasticsearch\Client::class) ? \Elasticsearch\Client::class : \Elastic\Elasticsearch\Client::class;$clientDefinition = new Definition($clientClass);$container->setDefinition('api_platform.elasticsearch.client', $clientDefinition);$container->registerForAutoconfiguration(RequestBodySearchCollectionExtensionInterface::class)->addTag('api_platform.elasticsearch.request_body_search_extension.collection');$container->setParameter('api_platform.elasticsearch.hosts', $config['elasticsearch']['hosts']);$loader->load('elasticsearch.xml');// @phpstan-ignore-next-lineif (\Elasticsearch\Client::class === $clientClass) {$loader->load('legacy/elasticsearch.xml');$container->setParameter('api_platform.elasticsearch.mapping', $config['elasticsearch']['mapping']);$container->setDefinition('api_platform.elasticsearch.client_for_metadata', $clientDefinition);}}private function registerSecurityConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{/** @var string[] $bundles */$bundles = $container->getParameter('kernel.bundles');if (!isset($bundles['SecurityBundle'])) {return;}$loader->load('security.xml');$loader->load('legacy/security.xml');if (interface_exists(ValidatorInterface::class)) {$loader->load('symfony/security_validator.xml');}if ($this->isConfigEnabled($container, $config['graphql'])) {$loader->load('graphql/security.xml');}}private function registerOpenApiConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{$container->setParameter('api_platform.openapi.termsOfService', $config['openapi']['termsOfService']);$container->setParameter('api_platform.openapi.contact.name', $config['openapi']['contact']['name']);$container->setParameter('api_platform.openapi.contact.url', $config['openapi']['contact']['url']);$container->setParameter('api_platform.openapi.contact.email', $config['openapi']['contact']['email']);$container->setParameter('api_platform.openapi.license.name', $config['openapi']['license']['name']);$container->setParameter('api_platform.openapi.license.url', $config['openapi']['license']['url']);$loader->load('json_schema.xml');}private function registerMakerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void{if (!$this->isConfigEnabled($container, $config['maker'])) {return;}$loader->load('maker.xml');}private function registerArgumentResolverConfiguration(XmlFileLoader $loader): void{$loader->load('argument_resolver.xml');}private function registerInflectorConfiguration(array $config): void{if ($config['keep_legacy_inflector']) {Inflector::keepLegacyInflector(true);trigger_deprecation('api-platform/core', '3.2', 'Using doctrine/inflector is deprecated since API Platform 3.2 and will be removed in API Platform 4. Use symfony/string instead. Run "composer require symfony/string" and set "keep_legacy_inflector" to false in config.');} else {Inflector::keepLegacyInflector(false);}}}