vendor/api-platform/core/src/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php line 266

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the API Platform project.
  4. *
  5. * (c) Kévin Dunglas <dunglas@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. declare(strict_types=1);
  11. namespace ApiPlatform\Symfony\Bundle\DependencyInjection;
  12. use ApiPlatform\Api\FilterInterface;
  13. use ApiPlatform\Api\UrlGeneratorInterface;
  14. use ApiPlatform\Core\Annotation\ApiResource as ApiResourceAnnotation;
  15. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractContextAwareFilter as DoctrineOrmAbstractContextAwareFilter;
  16. use ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Extension\RequestBodySearchCollectionExtensionInterface as LegacyRequestBodySearchCollectionExtensionInterface;
  17. use ApiPlatform\Core\DataPersister\DataPersisterInterface;
  18. use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
  19. use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
  20. use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
  21. use ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface;
  22. use ApiPlatform\Core\DataTransformer\DataTransformerInterface;
  23. use ApiPlatform\Doctrine\Odm\Extension\AggregationCollectionExtensionInterface;
  24. use ApiPlatform\Doctrine\Odm\Extension\AggregationItemExtensionInterface;
  25. use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter as DoctrineMongoDbOdmAbstractFilter;
  26. use ApiPlatform\Doctrine\Orm\Extension\EagerLoadingExtension;
  27. use ApiPlatform\Doctrine\Orm\Extension\FilterEagerLoadingExtension;
  28. use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface as DoctrineQueryCollectionExtensionInterface;
  29. use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;
  30. use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter as DoctrineOrmAbstractFilter;
  31. use ApiPlatform\Elasticsearch\Extension\RequestBodySearchCollectionExtensionInterface;
  32. use ApiPlatform\GraphQl\Error\ErrorHandlerInterface;
  33. use ApiPlatform\GraphQl\Resolver\MutationResolverInterface;
  34. use ApiPlatform\GraphQl\Resolver\QueryCollectionResolverInterface;
  35. use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
  36. use ApiPlatform\GraphQl\Type\Definition\TypeInterface as GraphQlTypeInterface;
  37. use ApiPlatform\Metadata\ApiResource;
  38. use ApiPlatform\State\ProcessorInterface;
  39. use ApiPlatform\State\ProviderInterface;
  40. use ApiPlatform\Symfony\Validator\Metadata\Property\Restriction\PropertySchemaRestrictionMetadataInterface;
  41. use ApiPlatform\Symfony\Validator\ValidationGroupsGeneratorInterface;
  42. use Doctrine\Common\Annotations\Annotation;
  43. use Doctrine\Persistence\ManagerRegistry;
  44. use phpDocumentor\Reflection\DocBlockFactoryInterface;
  45. use Ramsey\Uuid\Uuid;
  46. use Symfony\Component\Cache\Adapter\ArrayAdapter;
  47. use Symfony\Component\Config\FileLocator;
  48. use Symfony\Component\Config\Resource\DirectoryResource;
  49. use Symfony\Component\DependencyInjection\ContainerBuilder;
  50. use Symfony\Component\DependencyInjection\Definition;
  51. use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  52. use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
  53. use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
  54. use Symfony\Component\DependencyInjection\Reference;
  55. use Symfony\Component\Finder\Finder;
  56. use Symfony\Component\HttpClient\ScopingHttpClient;
  57. use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  58. use Symfony\Component\Mercure\Discovery;
  59. use Symfony\Component\Mercure\HubRegistry;
  60. use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
  61. use Symfony\Component\Uid\AbstractUid;
  62. use Symfony\Component\Validator\Validator\ValidatorInterface;
  63. use Symfony\Component\Yaml\Yaml;
  64. /**
  65. * The extension of this bundle.
  66. *
  67. * @author Kévin Dunglas <dunglas@gmail.com>
  68. */
  69. final class ApiPlatformExtension extends Extension implements PrependExtensionInterface
  70. {
  71. public function prepend(ContainerBuilder $container): void
  72. {
  73. if (isset($container->getExtensions()['framework'])) {
  74. $container->prependExtensionConfig('framework', [
  75. 'serializer' => [
  76. 'enabled' => true,
  77. ],
  78. ]);
  79. $container->prependExtensionConfig('framework', [
  80. 'property_info' => [
  81. 'enabled' => true,
  82. ],
  83. ]);
  84. }
  85. }
  86. public function load(array $configs, ContainerBuilder $container): void
  87. {
  88. $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
  89. $configuration = new Configuration();
  90. $config = $this->processConfiguration($configuration, $configs);
  91. $formats = $this->getFormats($config['formats']);
  92. $patchFormats = $this->getFormats($config['patch_formats']);
  93. $errorFormats = $this->getFormats($config['error_formats']);
  94. // Backward Compatibility layer
  95. if (isset($formats['jsonapi']) && !isset($patchFormats['jsonapi'])) {
  96. $patchFormats['jsonapi'] = ['application/vnd.api+json'];
  97. }
  98. $this->registerCommonConfiguration($container, $config, $loader, $formats, $patchFormats, $errorFormats);
  99. $this->registerMetadataConfiguration($container, $config, $loader);
  100. $this->registerOAuthConfiguration($container, $config);
  101. $this->registerOpenApiConfiguration($container, $config, $loader);
  102. $this->registerSwaggerConfiguration($container, $config, $loader);
  103. $this->registerJsonApiConfiguration($formats, $loader);
  104. $this->registerJsonLdHydraConfiguration($container, $formats, $loader, $config);
  105. $this->registerJsonHalConfiguration($formats, $loader, $config);
  106. $this->registerJsonProblemConfiguration($errorFormats, $loader);
  107. $this->registerGraphQlConfiguration($container, $config, $loader);
  108. $this->registerLegacyBundlesConfiguration($container, $config, $loader);
  109. $this->registerCacheConfiguration($container);
  110. $this->registerDoctrineOrmConfiguration($container, $config, $loader);
  111. $this->registerDoctrineMongoDbOdmConfiguration($container, $config, $loader);
  112. $this->registerHttpCacheConfiguration($container, $config, $loader);
  113. $this->registerValidatorConfiguration($container, $config, $loader);
  114. $this->registerDataCollectorConfiguration($container, $config, $loader);
  115. $this->registerMercureConfiguration($container, $config, $loader);
  116. $this->registerMessengerConfiguration($container, $config, $loader);
  117. $this->registerElasticsearchConfiguration($container, $config, $loader);
  118. $this->registerDataTransformerConfiguration($container);
  119. $this->registerSecurityConfiguration($container, $loader, $config);
  120. $this->registerMakerConfiguration($container, $config, $loader);
  121. $this->registerArgumentResolverConfiguration($container, $loader, $config);
  122. $this->registerLegacyServices($container, $config, $loader);
  123. $this->registerUpgradeCommandConfiguration($container, $loader, $config);
  124. // TODO: remove in 3.x
  125. $container->registerForAutoconfiguration(DataPersisterInterface::class)
  126. ->addTag('api_platform.data_persister');
  127. $container->registerForAutoconfiguration(ItemDataProviderInterface::class)
  128. ->addTag('api_platform.item_data_provider');
  129. $container->registerForAutoconfiguration(CollectionDataProviderInterface::class)
  130. ->addTag('api_platform.collection_data_provider');
  131. $container->registerForAutoconfiguration(SubresourceDataProviderInterface::class)
  132. ->addTag('api_platform.subresource_data_provider');
  133. $container->registerForAutoconfiguration(FilterInterface::class)
  134. ->addTag('api_platform.filter');
  135. $container->registerForAutoconfiguration(ProviderInterface::class)
  136. ->addTag('api_platform.state_provider');
  137. $container->registerForAutoconfiguration(ProcessorInterface::class)
  138. ->addTag('api_platform.state_processor');
  139. }
  140. private function registerCommonConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader, array $formats, array $patchFormats, array $errorFormats): void
  141. {
  142. $loader->load('api.xml');
  143. $loader->load('v3/state.xml');
  144. if ($config['metadata_backward_compatibility_layer']) {
  145. $loader->load('legacy/api.xml');
  146. $loader->load('legacy/data_provider.xml');
  147. $loader->load('legacy/backward_compatibility.xml');
  148. } else {
  149. $loader->load('v3/api.xml');
  150. $loader->load('legacy/data_provider.xml');
  151. $loader->load('v3/backward_compatibility.xml');
  152. }
  153. $loader->load('data_persister.xml');
  154. $loader->load('data_provider.xml');
  155. $loader->load('filter.xml');
  156. if ($container->hasDefinition('api_platform.operation_method_resolver')) {
  157. $container->getDefinition('api_platform.operation_method_resolver')
  158. ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.'));
  159. }
  160. if ($container->hasDefinition('api_platform.formats_provider')) {
  161. $container->getDefinition('api_platform.formats_provider')
  162. ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%service_id%" service is deprecated since API Platform 2.5.'));
  163. $container->getAlias('ApiPlatform\Core\Api\OperationAwareFormatsProviderInterface')
  164. ->setDeprecated(...$this->buildDeprecationArgs('2.5', 'The "%alias_id%" alias is deprecated since API Platform 2.5.'));
  165. }
  166. if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) {
  167. $container->getDefinition('api_platform.operation_path_resolver.underscore')
  168. ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.underscore" instead.'));
  169. }
  170. if ($container->hasDefinition('api_platform.operation_path_resolver.underscore')) {
  171. $container->getDefinition('api_platform.operation_path_resolver.dash')
  172. ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since API Platform 2.1 and will be removed in 3.0. Use "api_platform.path_segment_name_generator.dash" instead.'));
  173. }
  174. $container->getDefinition('api_platform.filters')
  175. ->setDeprecated(...$this->buildDeprecationArgs('2.1', 'The "%service_id%" service is deprecated since 2.1 and will be removed in 3.0. Use the "api_platform.filter_locator" service instead.'));
  176. if (class_exists(Uuid::class)) {
  177. $loader->load('ramsey_uuid.xml');
  178. if ($container->hasDefinition('api_platform.identifier.uuid_normalizer')) {
  179. $container->getDefinition('api_platform.identifier.uuid_normalizer')
  180. ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.ramsey_uuid.uri_variables.transformer.uuid" service instead.'));
  181. }
  182. }
  183. if (class_exists(AbstractUid::class)) {
  184. $loader->load('symfony_uid.xml');
  185. if ($container->hasDefinition('api_platform.identifier.symfony_ulid_normalizer')) {
  186. $container->getDefinition('api_platform.identifier.symfony_ulid_normalizer')
  187. ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.symfony.uri_variables.transformer.ulid" service instead.'));
  188. }
  189. if ($container->hasDefinition('api_platform.identifier.symfony_uuid_normalizer')) {
  190. $container->getDefinition('api_platform.identifier.symfony_uuid_normalizer')
  191. ->setDeprecated(...$this->buildDeprecationArgs('2.7', 'The "%service_id%" service is deprecated since 2.7 and will be removed in 3.0. Use the "api_platform.symfony.uri_variables.transformer.uuid" service instead.'));
  192. }
  193. }
  194. $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']);
  195. $container->setParameter('api_platform.enable_entrypoint', $config['enable_entrypoint']);
  196. $container->setParameter('api_platform.enable_docs', $config['enable_docs']);
  197. $container->setParameter('api_platform.title', $config['title']);
  198. $container->setParameter('api_platform.description', $config['description']);
  199. $container->setParameter('api_platform.version', $config['version']);
  200. $container->setParameter('api_platform.show_webby', $config['show_webby']);
  201. $container->setParameter('api_platform.url_generation_strategy', $config['defaults']['url_generation_strategy'] ?? UrlGeneratorInterface::ABS_PATH);
  202. $container->setParameter('api_platform.exception_to_status', $config['exception_to_status']);
  203. $container->setParameter('api_platform.formats', $formats);
  204. $container->setParameter('api_platform.patch_formats', $patchFormats);
  205. $container->setParameter('api_platform.error_formats', $errorFormats);
  206. // TODO: to remove in 3.0
  207. $container->setParameter('api_platform.allow_plain_identifiers', $config['allow_plain_identifiers']);
  208. $container->setParameter('api_platform.eager_loading.enabled', $this->isConfigEnabled($container, $config['eager_loading']));
  209. $container->setParameter('api_platform.eager_loading.max_joins', $config['eager_loading']['max_joins']);
  210. $container->setParameter('api_platform.eager_loading.fetch_partial', $config['eager_loading']['fetch_partial']);
  211. $container->setParameter('api_platform.eager_loading.force_eager', $config['eager_loading']['force_eager']);
  212. $container->setParameter('api_platform.collection.exists_parameter_name', $config['collection']['exists_parameter_name']);
  213. $container->setParameter('api_platform.collection.order', $config['collection']['order']);
  214. $container->setParameter('api_platform.collection.order_parameter_name', $config['collection']['order_parameter_name']);
  215. $container->setParameter('api_platform.collection.order_nulls_comparison', $config['collection']['order_nulls_comparison']);
  216. $container->setParameter('api_platform.collection.pagination.enabled', $config['defaults']['pagination_enabled'] ?? $this->isConfigEnabled($container, $config['collection']['pagination']));
  217. $container->setParameter('api_platform.collection.pagination.partial', $config['defaults']['pagination_partial'] ?? $config['collection']['pagination']['partial']);
  218. $container->setParameter('api_platform.collection.pagination.client_enabled', $config['defaults']['pagination_client_enabled'] ?? $config['collection']['pagination']['client_enabled']);
  219. $container->setParameter('api_platform.collection.pagination.client_items_per_page', $config['defaults']['pagination_client_items_per_page'] ?? $config['collection']['pagination']['client_items_per_page']);
  220. $container->setParameter('api_platform.collection.pagination.client_partial', $config['defaults']['pagination_client_partial'] ?? $config['collection']['pagination']['client_partial']);
  221. $container->setParameter('api_platform.collection.pagination.items_per_page', $config['defaults']['pagination_items_per_page'] ?? $config['collection']['pagination']['items_per_page']);
  222. $container->setParameter('api_platform.collection.pagination.maximum_items_per_page', $config['defaults']['pagination_maximum_items_per_page'] ?? $config['collection']['pagination']['maximum_items_per_page']);
  223. $container->setParameter('api_platform.collection.pagination.page_parameter_name', $config['defaults']['pagination_page_parameter_name'] ?? $config['collection']['pagination']['page_parameter_name']);
  224. $container->setParameter('api_platform.collection.pagination.enabled_parameter_name', $config['defaults']['pagination_enabled_parameter_name'] ?? $config['collection']['pagination']['enabled_parameter_name']);
  225. $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']);
  226. $container->setParameter('api_platform.collection.pagination.partial_parameter_name', $config['defaults']['pagination_partial_parameter_name'] ?? $config['collection']['pagination']['partial_parameter_name']);
  227. $container->setParameter('api_platform.collection.pagination', $this->getPaginationDefaults($config['defaults'] ?? [], $config['collection']['pagination']));
  228. $container->setParameter('api_platform.http_cache.etag', $config['defaults']['cache_headers']['etag'] ?? $config['http_cache']['etag']);
  229. $container->setParameter('api_platform.http_cache.max_age', $config['defaults']['cache_headers']['max_age'] ?? $config['http_cache']['max_age']);
  230. $container->setParameter('api_platform.http_cache.shared_max_age', $config['defaults']['cache_headers']['shared_max_age'] ?? $config['http_cache']['shared_max_age']);
  231. $container->setParameter('api_platform.http_cache.vary', $config['defaults']['cache_headers']['vary'] ?? $config['http_cache']['vary']);
  232. $container->setParameter('api_platform.http_cache.public', $config['defaults']['cache_headers']['public'] ?? $config['http_cache']['public']);
  233. $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']);
  234. $container->setParameter('api_platform.http_cache.invalidation.xkey.glue', $config['defaults']['cache_headers']['invalidation']['xkey']['glue'] ?? $config['http_cache']['invalidation']['xkey']['glue']);
  235. $container->setAlias('api_platform.operation_path_resolver.default', $config['default_operation_path_resolver']);
  236. $container->setAlias('api_platform.path_segment_name_generator', $config['path_segment_name_generator']);
  237. if ($config['name_converter']) {
  238. $container->setAlias('api_platform.name_converter', $config['name_converter']);
  239. }
  240. $container->setParameter('api_platform.asset_package', $config['asset_package']);
  241. $container->setParameter('api_platform.defaults', $this->normalizeDefaults($config['defaults'] ?? [], $config['metadata_backward_compatibility_layer'] ?? false));
  242. }
  243. /**
  244. * This method will be removed in 3.0 when "defaults" will be the regular configuration path for the pagination.
  245. */
  246. private function getPaginationDefaults(array $defaults, array $collectionPaginationConfiguration): array
  247. {
  248. $paginationOptions = [];
  249. foreach ($defaults as $key => $value) {
  250. if (!str_starts_with($key, 'pagination_')) {
  251. continue;
  252. }
  253. $paginationOptions[str_replace('pagination_', '', $key)] = $value;
  254. }
  255. return array_merge($collectionPaginationConfiguration, $paginationOptions);
  256. }
  257. private function normalizeDefaults(array $defaults, bool $compatibility = false): array
  258. {
  259. $key = $compatibility ? 'attributes' : 'extra_properties';
  260. $normalizedDefaults = [$key => $defaults[$key] ?? []];
  261. unset($defaults[$key]);
  262. $publicProperties = [];
  263. if ($compatibility) {
  264. [$publicProperties] = ApiResourceAnnotation::getConfigMetadata();
  265. } else {
  266. $rc = new \ReflectionClass(ApiResource::class);
  267. foreach ($rc->getConstructor()->getParameters() as $param) {
  268. $publicProperties[$param->getName()] = true;
  269. }
  270. }
  271. $nameConverter = new CamelCaseToSnakeCaseNameConverter();
  272. foreach ($defaults as $option => $value) {
  273. if (isset($publicProperties[$nameConverter->denormalize($option)])) {
  274. $normalizedDefaults[$option] = $value;
  275. continue;
  276. }
  277. $normalizedDefaults[$key][$option] = $value;
  278. }
  279. return $normalizedDefaults;
  280. }
  281. private function registerMetadataConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  282. {
  283. [$xmlResources, $yamlResources] = $this->getResourcesToWatch($container, $config);
  284. $loader->load('metadata/resource_name.xml');
  285. $loader->load('metadata/property_name.xml');
  286. if (!empty($config['resource_class_directories'])) {
  287. $container->setParameter('api_platform.resource_class_directories', array_merge(
  288. $config['resource_class_directories'], $container->getParameter('api_platform.resource_class_directories')
  289. ));
  290. }
  291. $loader->load('legacy/metadata.xml');
  292. $container->getDefinition('api_platform.metadata.extractor.xml.legacy')->replaceArgument(0, $xmlResources);
  293. if (class_exists(Annotation::class)) {
  294. $loader->load('legacy/metadata_annotation.xml');
  295. }
  296. if (interface_exists(DocBlockFactoryInterface::class)) {
  297. $loader->load('legacy/metadata_php_doc.xml');
  298. }
  299. if (class_exists(Yaml::class)) {
  300. $loader->load('legacy/metadata_yaml.xml');
  301. $container->getDefinition('api_platform.metadata.extractor.yaml.legacy')->replaceArgument(0, $yamlResources);
  302. if ($config['metadata_backward_compatibility_layer']) {
  303. $loader->load('legacy/metadata_yaml_backward_compatibility.xml');
  304. }
  305. }
  306. // Load the legacy metadata as well
  307. if ($config['metadata_backward_compatibility_layer']) {
  308. $loader->load('legacy/metadata_backward_compatibility.xml');
  309. return;
  310. }
  311. // V3 metadata
  312. $loader->load('metadata/xml.xml');
  313. $loader->load('metadata/links.xml');
  314. $loader->load('metadata/property.xml');
  315. $loader->load('metadata/resource.xml');
  316. $loader->load('v3/metadata.xml');
  317. $container->getDefinition('api_platform.metadata.resource_extractor.xml')->replaceArgument(0, $xmlResources);
  318. $container->getDefinition('api_platform.metadata.property_extractor.xml')->replaceArgument(0, $xmlResources);
  319. if (interface_exists(DocBlockFactoryInterface::class)) {
  320. $loader->load('metadata/php_doc.xml');
  321. }
  322. if (class_exists(Yaml::class)) {
  323. $loader->load('metadata/yaml.xml');
  324. $container->getDefinition('api_platform.metadata.resource_extractor.yaml')->replaceArgument(0, $yamlResources);
  325. $container->getDefinition('api_platform.metadata.property_extractor.yaml')->replaceArgument(0, $yamlResources);
  326. }
  327. }
  328. private function getBundlesResourcesPaths(ContainerBuilder $container, array $config): array
  329. {
  330. $bundlesResourcesPaths = [];
  331. foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
  332. $paths = [];
  333. $dirname = $bundle['path'];
  334. foreach (['.yaml', '.yml', '.xml', ''] as $extension) {
  335. $paths[] = "$dirname/Resources/config/api_resources$extension";
  336. }
  337. if ($this->isConfigEnabled($container, $config['doctrine'])) {
  338. $paths[] = "$dirname/Entity";
  339. }
  340. if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {
  341. $paths[] = "$dirname/Document";
  342. }
  343. foreach ($paths as $path) {
  344. if ($container->fileExists($path, false)) {
  345. $bundlesResourcesPaths[] = $path;
  346. }
  347. }
  348. }
  349. return $bundlesResourcesPaths;
  350. }
  351. private function getResourcesToWatch(ContainerBuilder $container, array $config): array
  352. {
  353. $paths = array_unique(array_merge($this->getBundlesResourcesPaths($container, $config), $config['mapping']['paths']));
  354. // Flex structure (only if nothing specified)
  355. $projectDir = $container->getParameter('kernel.project_dir');
  356. if (!$paths && is_dir($dir = "$projectDir/config/api_platform")) {
  357. $paths = [$dir];
  358. }
  359. $resources = ['yml' => [], 'xml' => [], 'dir' => []];
  360. foreach ($paths as $path) {
  361. if (is_dir($path)) {
  362. foreach (Finder::create()->followLinks()->files()->in($path)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) {
  363. $resources['yaml' === ($extension = $file->getExtension()) ? 'yml' : $extension][] = $file->getRealPath();
  364. }
  365. $resources['dir'][] = $path;
  366. $container->addResource(new DirectoryResource($path, '/\.(xml|ya?ml|php)$/'));
  367. continue;
  368. }
  369. if ($container->fileExists($path, false)) {
  370. if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) {
  371. throw new RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & YAML.', $path));
  372. }
  373. $resources['yaml' === $matches[1] ? 'yml' : $matches[1]][] = $path;
  374. continue;
  375. }
  376. throw new RuntimeException(sprintf('Could not open file or directory "%s".', $path));
  377. }
  378. $container->setParameter('api_platform.resource_class_directories', $resources['dir']);
  379. return [$resources['xml'], $resources['yml']];
  380. }
  381. private function registerOAuthConfiguration(ContainerBuilder $container, array $config): void
  382. {
  383. if (!$config['oauth']) {
  384. return;
  385. }
  386. $container->setParameter('api_platform.oauth.enabled', $this->isConfigEnabled($container, $config['oauth']));
  387. $container->setParameter('api_platform.oauth.clientId', $config['oauth']['clientId']);
  388. $container->setParameter('api_platform.oauth.clientSecret', $config['oauth']['clientSecret']);
  389. $container->setParameter('api_platform.oauth.type', $config['oauth']['type']);
  390. $container->setParameter('api_platform.oauth.flow', $config['oauth']['flow']);
  391. $container->setParameter('api_platform.oauth.tokenUrl', $config['oauth']['tokenUrl']);
  392. $container->setParameter('api_platform.oauth.authorizationUrl', $config['oauth']['authorizationUrl']);
  393. $container->setParameter('api_platform.oauth.refreshUrl', $config['oauth']['refreshUrl']);
  394. $container->setParameter('api_platform.oauth.scopes', $config['oauth']['scopes']);
  395. $container->setParameter('api_platform.oauth.pkce', $config['oauth']['pkce']);
  396. if ($container->hasDefinition('api_platform.swagger.action.ui')) {
  397. $container->getDefinition('api_platform.swagger.action.ui')->setArgument(27, $config['oauth']['pkce']);
  398. }
  399. if ($container->hasDefinition('api_platform.swagger_ui.action')) {
  400. $container->getDefinition('api_platform.swagger_ui.action')->setArgument(10, $config['oauth']['pkce']);
  401. }
  402. }
  403. /**
  404. * Registers the Swagger, ReDoc and Swagger UI configuration.
  405. */
  406. private function registerSwaggerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  407. {
  408. $container->setParameter('api_platform.swagger.versions', $config['swagger']['versions']);
  409. if (!$config['enable_swagger'] && $config['enable_swagger_ui']) {
  410. throw new RuntimeException('You can not enable the Swagger UI without enabling Swagger, fix this by enabling swagger via the configuration "enable_swagger: true".');
  411. }
  412. if (!$config['enable_swagger']) {
  413. return;
  414. }
  415. $loader->load('openapi.xml');
  416. $loader->load('swagger_ui.xml');
  417. if (!$config['enable_swagger_ui'] && !$config['enable_re_doc']) {
  418. // Remove the listener but keep the controller to allow customizing the path of the UI
  419. $container->removeDefinition('api_platform.swagger.listener.ui');
  420. }
  421. $container->setParameter('api_platform.enable_swagger_ui', $config['enable_swagger_ui']);
  422. $container->setParameter('api_platform.enable_re_doc', $config['enable_re_doc']);
  423. $container->setParameter('api_platform.swagger.api_keys', $config['swagger']['api_keys']);
  424. if ($config['openapi']['swagger_ui_extra_configuration'] && $config['swagger']['swagger_ui_extra_configuration']) {
  425. throw new RuntimeException('You can not set "swagger_ui_extra_configuration" twice - in "openapi" and "swagger" section.');
  426. }
  427. $container->setParameter('api_platform.swagger_ui.extra_configuration', $config['openapi']['swagger_ui_extra_configuration'] ?: $config['swagger']['swagger_ui_extra_configuration']);
  428. if ($config['metadata_backward_compatibility_layer']) {
  429. $loader->load('legacy/swagger.xml');
  430. $loader->load('legacy/openapi.xml');
  431. $loader->load('legacy/swagger_ui.xml');
  432. if (true === $config['openapi']['backward_compatibility_layer']) {
  433. $container->getDefinition('api_platform.swagger.normalizer.documentation')->addArgument($container->getDefinition('api_platform.openapi.normalizer'));
  434. }
  435. return;
  436. }
  437. // for swagger 2 support
  438. $loader->load('legacy/swagger.xml');
  439. $loader->load('v3/openapi.xml');
  440. $loader->load('v3/swagger_ui.xml');
  441. }
  442. private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void
  443. {
  444. if (!isset($formats['jsonapi'])) {
  445. return;
  446. }
  447. $loader->load('jsonapi.xml');
  448. }
  449. private function registerJsonLdHydraConfiguration(ContainerBuilder $container, array $formats, XmlFileLoader $loader, array $config): void
  450. {
  451. if (!isset($formats['jsonld'])) {
  452. return;
  453. }
  454. $loader->load('jsonld.xml');
  455. $loader->load('hydra.xml');
  456. if ($config['metadata_backward_compatibility_layer']) {
  457. $loader->load('legacy/hydra.xml');
  458. } else {
  459. $loader->load('v3/hydra.xml');
  460. }
  461. if (!$container->has('api_platform.json_schema.schema_factory')) {
  462. $container->removeDefinition('api_platform.hydra.json_schema.schema_factory');
  463. }
  464. if (!$config['enable_docs']) {
  465. $container->removeDefinition('api_platform.hydra.listener.response.add_link_header');
  466. }
  467. }
  468. private function registerJsonHalConfiguration(array $formats, XmlFileLoader $loader, array $config): void
  469. {
  470. if (!isset($formats['jsonhal'])) {
  471. return;
  472. }
  473. $loader->load('hal.xml');
  474. if ($config['metadata_backward_compatibility_layer']) {
  475. $loader->load('legacy/hal.xml');
  476. } else {
  477. $loader->load('v3/hal.xml');
  478. }
  479. }
  480. private function registerJsonProblemConfiguration(array $errorFormats, XmlFileLoader $loader): void
  481. {
  482. if (!isset($errorFormats['jsonproblem'])) {
  483. return;
  484. }
  485. $loader->load('problem.xml');
  486. }
  487. private function registerGraphQlConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  488. {
  489. $enabled = $this->isConfigEnabled($container, $config['graphql']);
  490. $container->setParameter('api_platform.graphql.enabled', $enabled);
  491. $container->setParameter('api_platform.graphql.graphiql.enabled', $enabled && $this->isConfigEnabled($container, $config['graphql']['graphiql']));
  492. $container->setParameter('api_platform.graphql.graphql_playground.enabled', $enabled && $this->isConfigEnabled($container, $config['graphql']['graphql_playground']));
  493. $container->setParameter('api_platform.graphql.collection.pagination', $config['graphql']['collection']['pagination']);
  494. if (!$enabled) {
  495. return;
  496. }
  497. $container->setParameter('api_platform.graphql.default_ide', $config['graphql']['default_ide']);
  498. $container->setParameter('api_platform.graphql.nesting_separator', $config['graphql']['nesting_separator']);
  499. $loader->load('graphql.xml');
  500. if ($config['metadata_backward_compatibility_layer']) {
  501. $loader->load('legacy/graphql.xml');
  502. } else {
  503. $loader->load('v3/graphql.xml');
  504. }
  505. $container->registerForAutoconfiguration(QueryItemResolverInterface::class)
  506. ->addTag('api_platform.graphql.query_resolver');
  507. $container->registerForAutoconfiguration(QueryCollectionResolverInterface::class)
  508. ->addTag('api_platform.graphql.query_resolver');
  509. $container->registerForAutoconfiguration(MutationResolverInterface::class)
  510. ->addTag('api_platform.graphql.mutation_resolver');
  511. $container->registerForAutoconfiguration(GraphQlTypeInterface::class)
  512. ->addTag('api_platform.graphql.type');
  513. $container->registerForAutoconfiguration(ErrorHandlerInterface::class)
  514. ->addTag('api_platform.graphql.error_handler');
  515. }
  516. private function registerLegacyBundlesConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  517. {
  518. /** @var string[] $bundles */
  519. $bundles = $container->getParameter('kernel.bundles');
  520. if (isset($bundles['FOSUserBundle']) && $config['enable_fos_user']) {
  521. $loader->load('fos_user.xml');
  522. }
  523. if (isset($bundles['NelmioApiDocBundle']) && $config['enable_nelmio_api_doc']) {
  524. $loader->load('nelmio_api_doc.xml');
  525. $container->getDefinition('api_platform.nelmio_api_doc.annotations_provider')
  526. ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.'));
  527. $container->getDefinition('api_platform.nelmio_api_doc.parser')
  528. ->setDeprecated(...$this->buildDeprecationArgs('2.2', 'The "%service_id%" service is deprecated since API Platform 2.2 and will be removed in 3.0. NelmioApiDocBundle 3 has native support for API Platform.'));
  529. }
  530. }
  531. private function registerCacheConfiguration(ContainerBuilder $container): void
  532. {
  533. if (!$container->hasParameter('kernel.debug') || !$container->getParameter('kernel.debug')) {
  534. $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer');
  535. }
  536. if (!$container->hasParameter('api_platform.metadata_cache')) {
  537. return;
  538. }
  539. @trigger_error('The "api_platform.metadata_cache" parameter is deprecated since version 2.4 and will have no effect in 3.0.', \E_USER_DEPRECATED);
  540. // BC
  541. if (!$container->getParameter('api_platform.metadata_cache') && $container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) {
  542. $container->removeDefinition('api_platform.cache_warmer.cache_pool_clearer');
  543. $container->register('api_platform.cache.metadata.property', ArrayAdapter::class);
  544. $container->register('api_platform.cache.metadata.property.legacy', ArrayAdapter::class);
  545. $container->register('api_platform.cache.metadata.resource', ArrayAdapter::class);
  546. $container->register('api_platform.cache.metadata.resource.legacy', ArrayAdapter::class);
  547. $container->register('api_platform.cache.metadata.resource_collection', ArrayAdapter::class);
  548. $container->register('api_platform.cache.route_name_resolver', ArrayAdapter::class);
  549. $container->register('api_platform.cache.identifiers_extractor', ArrayAdapter::class);
  550. $container->register('api_platform.cache.subresource_operation_factory', ArrayAdapter::class);
  551. $container->register('api_platform.elasticsearch.cache.metadata.document', ArrayAdapter::class);
  552. }
  553. }
  554. private function registerDoctrineOrmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  555. {
  556. if (!$this->isConfigEnabled($container, $config['doctrine'])) {
  557. return;
  558. }
  559. // For older versions of doctrine bridge this allows autoconfiguration for filters
  560. if (!$container->has(ManagerRegistry::class)) {
  561. $container->setAlias(ManagerRegistry::class, 'doctrine');
  562. }
  563. $container->registerForAutoconfiguration(QueryItemExtensionInterface::class)
  564. ->addTag('api_platform.doctrine.orm.query_extension.item');
  565. $container->registerForAutoconfiguration(DoctrineQueryCollectionExtensionInterface::class)
  566. ->addTag('api_platform.doctrine.orm.query_extension.collection');
  567. $container->registerForAutoconfiguration(DoctrineOrmAbstractContextAwareFilter::class)
  568. ->setBindings(['$requestStack' => null]);
  569. $container->registerForAutoconfiguration(DoctrineOrmAbstractFilter::class);
  570. // Legacy namespaces as strings we don't want to load the classes
  571. $container->registerForAutoconfiguration('ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface')
  572. ->addTag('api_platform.doctrine.orm.query_extension.item');
  573. $container->registerForAutoconfiguration('ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\ContextAwareQueryCollectionExtensionInterface')
  574. ->addTag('api_platform.doctrine.orm.query_extension.collection');
  575. $container->registerForAutoconfiguration('ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryCollectionExtensionInterface')
  576. ->addTag('api_platform.doctrine.orm.query_extension.collection');
  577. $loader->load('doctrine_orm.xml');
  578. $loader->load('legacy/doctrine_orm.xml');
  579. if (!$config['metadata_backward_compatibility_layer']) {
  580. $loader->load('v3/doctrine_orm.xml');
  581. }
  582. if ($this->isConfigEnabled($container, $config['eager_loading'])) {
  583. return;
  584. }
  585. $container->removeAlias(EagerLoadingExtension::class);
  586. $container->removeDefinition('api_platform.doctrine.orm.query_extension.eager_loading');
  587. $container->removeAlias(FilterEagerLoadingExtension::class);
  588. $container->removeDefinition('api_platform.doctrine.orm.query_extension.filter_eager_loading');
  589. }
  590. private function registerDoctrineMongoDbOdmConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  591. {
  592. if (!$this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {
  593. return;
  594. }
  595. $container->registerForAutoconfiguration(AggregationItemExtensionInterface::class)
  596. ->addTag('api_platform.doctrine_mongodb.odm.aggregation_extension.item');
  597. $container->registerForAutoconfiguration(AggregationCollectionExtensionInterface::class)
  598. ->addTag('api_platform.doctrine_mongodb.odm.aggregation_extension.collection');
  599. $container->registerForAutoconfiguration(DoctrineMongoDbOdmAbstractFilter::class)
  600. ->setBindings(['$managerRegistry' => new Reference('doctrine_mongodb')]);
  601. $loader->load('doctrine_mongodb_odm.xml');
  602. if (!$config['metadata_backward_compatibility_layer']) {
  603. $loader->load('v3/doctrine_odm.xml');
  604. } else {
  605. $loader->load('legacy/doctrine_odm.xml');
  606. }
  607. }
  608. private function registerHttpCacheConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  609. {
  610. $loader->load('http_cache.xml');
  611. if (!$this->isConfigEnabled($container, $config['http_cache']['invalidation'])) {
  612. return;
  613. }
  614. if ($this->isConfigEnabled($container, $config['doctrine'])) {
  615. $loader->load('doctrine_orm_http_cache_purger.xml');
  616. }
  617. $loader->load('http_cache_purger.xml');
  618. $definitions = [];
  619. foreach ($config['http_cache']['invalidation']['varnish_urls'] as $key => $url) {
  620. $definition = new Definition(ScopingHttpClient::class, [new Reference('http_client'), $url, ['base_uri' => $url] + $config['http_cache']['invalidation']['request_options']]);
  621. $definition->setFactory([ScopingHttpClient::class, 'forBaseUri']);
  622. $definitions[] = $definition;
  623. }
  624. foreach (['api_platform.http_cache.purger.varnish.ban', 'api_platform.http_cache.purger.varnish.xkey'] as $serviceName) {
  625. $container->findDefinition($serviceName)->setArguments([
  626. $definitions,
  627. $config['http_cache']['invalidation']['max_header_length'],
  628. ]);
  629. }
  630. $serviceName = $config['http_cache']['invalidation']['purger'];
  631. $container->setAlias('api_platform.http_cache.purger', $serviceName);
  632. }
  633. /**
  634. * Normalizes the format from config to the one accepted by Symfony HttpFoundation.
  635. */
  636. private function getFormats(array $configFormats): array
  637. {
  638. $formats = [];
  639. foreach ($configFormats as $format => $value) {
  640. foreach ($value['mime_types'] as $mimeType) {
  641. $formats[$format][] = $mimeType;
  642. }
  643. }
  644. return $formats;
  645. }
  646. private function registerValidatorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  647. {
  648. if (interface_exists(ValidatorInterface::class)) {
  649. if ($config['metadata_backward_compatibility_layer']) {
  650. $loader->load('legacy/validator.xml');
  651. } else {
  652. $loader->load('metadata/validator.xml');
  653. $loader->load('symfony/validator.xml');
  654. }
  655. $container->registerForAutoconfiguration(ValidationGroupsGeneratorInterface::class)
  656. ->addTag('api_platform.validation_groups_generator')
  657. ->setPublic(true); // this line should be removed in 3.0
  658. $container->registerForAutoconfiguration(PropertySchemaRestrictionMetadataInterface::class)
  659. ->addTag('api_platform.metadata.property_schema_restriction');
  660. }
  661. if (!$config['validator']) {
  662. return;
  663. }
  664. $container->setParameter('api_platform.validator.serialize_payload_fields', $config['validator']['serialize_payload_fields']);
  665. $container->setParameter('api_platform.validator.query_parameter_validation', $config['validator']['query_parameter_validation']);
  666. if (!$config['validator']['query_parameter_validation']) {
  667. $container->removeDefinition('api_platform.listener.view.validate_query_parameters');
  668. $container->removeDefinition('api_platform.validator.query_parameter_validator');
  669. }
  670. }
  671. private function registerDataCollectorConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  672. {
  673. if (!$config['enable_profiler']) {
  674. return;
  675. }
  676. if ($config['metadata_backward_compatibility_layer']) {
  677. $loader->load('legacy/data_collector.xml');
  678. } else {
  679. $loader->load('v3/data_collector.xml');
  680. }
  681. if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) {
  682. $loader->load('debug.xml');
  683. if ($config['metadata_backward_compatibility_layer']) {
  684. $loader->load('legacy/debug.xml');
  685. } else {
  686. $loader->load('v3/debug.xml');
  687. }
  688. }
  689. }
  690. private function registerMercureConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  691. {
  692. if (!$this->isConfigEnabled($container, $config['mercure'])) {
  693. return;
  694. }
  695. $loader->load('mercure.xml');
  696. if (!class_exists(Discovery::class)) {
  697. $container->getDefinition('api_platform.mercure.listener.response.add_link_header')->setArgument(1, $config['mercure']['hub_url'] ?? '%mercure.default_hub%');
  698. }
  699. if ($this->isConfigEnabled($container, $config['doctrine'])) {
  700. if ($config['metadata_backward_compatibility_layer']) {
  701. $loader->load('legacy/doctrine_orm_mercure_publisher.xml');
  702. } else {
  703. $loader->load('v3/doctrine_orm_mercure_publisher.xml');
  704. }
  705. if (class_exists(HubRegistry::class)) {
  706. $container->getDefinition('api_platform.doctrine.orm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class));
  707. }
  708. }
  709. if ($this->isConfigEnabled($container, $config['doctrine_mongodb_odm'])) {
  710. if ($config['metadata_backward_compatibility_layer']) {
  711. $loader->load('legacy/doctrine_odm_mercure_publisher.xml');
  712. } else {
  713. $loader->load('v3/doctrine_odm_mercure_publisher.xml');
  714. }
  715. if (class_exists(HubRegistry::class)) {
  716. $container->getDefinition('api_platform.doctrine_mongodb.odm.listener.mercure.publish')->setArgument(6, new Reference(HubRegistry::class));
  717. }
  718. }
  719. if ($this->isConfigEnabled($container, $config['graphql'])) {
  720. if ($config['metadata_backward_compatibility_layer']) {
  721. $loader->load('legacy/graphql_mercure.xml');
  722. } else {
  723. $loader->load('v3/graphql_mercure.xml');
  724. }
  725. if (class_exists(HubRegistry::class)) {
  726. $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument(new Reference(HubRegistry::class));
  727. } else {
  728. $container->getDefinition('api_platform.graphql.subscription.mercure_iri_generator')->addArgument($config['mercure']['hub_url'] ?? '%mercure.default_hub%');
  729. }
  730. }
  731. if ($config['metadata_backward_compatibility_layer']) {
  732. $container->getDefinition('api_platform.mercure.listener.response.add_link_header')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory'));
  733. }
  734. }
  735. private function registerMessengerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  736. {
  737. if (!$this->isConfigEnabled($container, $config['messenger'])) {
  738. return;
  739. }
  740. $loader->load('messenger.xml');
  741. if (!$config['metadata_backward_compatibility_layer']) {
  742. $loader->load('v3/messenger.xml');
  743. }
  744. }
  745. private function registerElasticsearchConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  746. {
  747. $enabled = $this->isConfigEnabled($container, $config['elasticsearch']);
  748. $container->setParameter('api_platform.elasticsearch.enabled', $enabled);
  749. if (!$enabled) {
  750. return;
  751. }
  752. $loader->load('elasticsearch.xml');
  753. $loader->load('legacy/elasticsearch.xml');
  754. if (!$config['metadata_backward_compatibility_layer']) {
  755. $loader->load('v3/elasticsearch.xml');
  756. }
  757. $container->registerForAutoconfiguration(RequestBodySearchCollectionExtensionInterface::class)
  758. ->addTag('api_platform.elasticsearch.request_body_search_extension.collection');
  759. $container->registerForAutoconfiguration(LegacyRequestBodySearchCollectionExtensionInterface::class)
  760. ->addTag('api_platform.elasticsearch.request_body_search_extension.collection');
  761. $container->setParameter('api_platform.elasticsearch.hosts', $config['elasticsearch']['hosts']);
  762. $container->setParameter('api_platform.elasticsearch.mapping', $config['elasticsearch']['mapping']);
  763. }
  764. private function registerDataTransformerConfiguration(ContainerBuilder $container): void
  765. {
  766. $container->registerForAutoconfiguration(DataTransformerInterface::class)
  767. ->addTag('api_platform.data_transformer');
  768. $container->registerForAutoconfiguration(DataTransformerInitializerInterface::class)
  769. ->addTag('api_platform.data_transformer');
  770. }
  771. private function registerSecurityConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void
  772. {
  773. /** @var string[] $bundles */
  774. $bundles = $container->getParameter('kernel.bundles');
  775. if (!isset($bundles['SecurityBundle'])) {
  776. return;
  777. }
  778. $loader->load('security.xml');
  779. if ($config['metadata_backward_compatibility_layer']) {
  780. $container->getDefinition('api_platform.security.listener.request.deny_access')->setArgument(0, new Reference('api_platform.metadata.resource.metadata_factory'));
  781. }
  782. }
  783. private function registerOpenApiConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  784. {
  785. $container->setParameter('api_platform.openapi.termsOfService', $config['openapi']['termsOfService']);
  786. $container->setParameter('api_platform.openapi.contact.name', $config['openapi']['contact']['name']);
  787. $container->setParameter('api_platform.openapi.contact.url', $config['openapi']['contact']['url']);
  788. $container->setParameter('api_platform.openapi.contact.email', $config['openapi']['contact']['email']);
  789. $container->setParameter('api_platform.openapi.license.name', $config['openapi']['license']['name']);
  790. $container->setParameter('api_platform.openapi.license.url', $config['openapi']['license']['url']);
  791. $loader->load('json_schema.xml');
  792. if ($config['metadata_backward_compatibility_layer']) {
  793. $loader->load('legacy/json_schema.xml');
  794. } else {
  795. $loader->load('v3/json_schema.xml');
  796. }
  797. }
  798. private function registerMakerConfiguration(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  799. {
  800. if (!$this->isConfigEnabled($container, $config['maker'])) {
  801. return;
  802. }
  803. $loader->load('maker.xml');
  804. }
  805. private function registerArgumentResolverConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void
  806. {
  807. if ($config['metadata_backward_compatibility_layer']) {
  808. return;
  809. }
  810. $loader->load('argument_resolver.xml');
  811. }
  812. private function registerLegacyServices(ContainerBuilder $container, array $config, XmlFileLoader $loader): void
  813. {
  814. $container->setParameter('api_platform.metadata_backward_compatibility_layer', $config['metadata_backward_compatibility_layer']);
  815. $loader->load('legacy/identifiers.xml');
  816. if (!$config['metadata_backward_compatibility_layer']) {
  817. $loader->load('symfony.xml');
  818. }
  819. }
  820. private function registerUpgradeCommandConfiguration(ContainerBuilder $container, XmlFileLoader $loader, array $config): void
  821. {
  822. $loader->load('legacy/upgrade.xml');
  823. }
  824. private function buildDeprecationArgs(string $version, string $message): array
  825. {
  826. return method_exists(Definition::class, 'getDeprecation')
  827. ? ['api-platform/core', $version, $message]
  828. : [true, $message];
  829. }
  830. }
  831. class_alias(ApiPlatformExtension::class, \ApiPlatform\Core\Bridge\Symfony\Bundle\DependencyInjection\ApiPlatformExtension::class);