diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php index c0a8747495b92d149ce21a10d610c0a5283bcdce..2a5554257134f868374d2eb7e49429cb91daffd7 100644 --- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php @@ -113,7 +113,16 @@ private function parseDefinitions($content, $file) throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); } + // Some extensions split up their dependencies into multiple files. + if (isset($content['_provider'])) { + $provider = $content['_provider']; + } + else { + $basename = basename($file); + list($provider, ) = explode('.', $basename, 2); + } foreach ($content['services'] as $id => $service) { + $service['tags'][] = ['name' => '_provider', 'provider' => $provider]; $this->parseDefinition($id, $service, $file); } } diff --git a/core/modules/rest/src/Plugin/views/style/Serializer.php b/core/modules/rest/src/Plugin/views/style/Serializer.php index 71bb5111bb51bfac4a7e2448e1802164f391e542..7e9b4331ef0099e015fa14352917ca7cf37f918b 100644 --- a/core/modules/rest/src/Plugin/views/style/Serializer.php +++ b/core/modules/rest/src/Plugin/views/style/Serializer.php @@ -47,6 +47,13 @@ class Serializer extends StylePluginBase implements CacheableDependencyInterface */ protected $formats = array(); + /** + * The serialization format providers, keyed by format. + * + * @var string[] + */ + protected $formatProviders; + /** * {@inheritdoc} */ @@ -56,19 +63,21 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->get('serializer'), - $container->getParameter('serializer.formats') + $container->getParameter('serializer.formats'), + $container->getParameter('serializer.format_providers') ); } /** * Constructs a Plugin object. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, SerializerInterface $serializer, array $serializer_formats) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, SerializerInterface $serializer, array $serializer_formats, array $serializer_format_providers) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->definition = $plugin_definition + $configuration; $this->serializer = $serializer; $this->formats = $serializer_formats; + $this->formatProviders = $serializer_format_providers; } /** @@ -91,7 +100,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { '#type' => 'checkboxes', '#title' => $this->t('Accepted request formats'), '#description' => $this->t('Request formats that will be allowed in responses. If none are selected all formats will be allowed.'), - '#options' => array_combine($this->formats, $this->formats), + '#options' => $this->getFormatOptions(), '#default_value' => $this->options['formats'], ); } @@ -167,4 +176,30 @@ public function getCacheTags() { return []; } + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + $formats = $this->getFormats(); + $providers = array_intersect_key($this->formatProviders, array_flip($formats)); + // The plugin always uses services from the serialization module. + $providers[] = 'serialization'; + + $dependencies += ['module' => []]; + $dependencies['module'] = array_merge($dependencies['module'], $providers); + return $dependencies; + } + + /** + * Returns an array of format options + * + * @return string[] + * An array of format options. Both key and value are the same. + */ + protected function getFormatOptions() { + $formats = array_keys($this->formatProviders); + return array_combine($formats, $formats); + } + } diff --git a/core/modules/rest/tests/src/Kernel/Views/StyleSerializerKernelTest.php b/core/modules/rest/tests/src/Kernel/Views/StyleSerializerKernelTest.php new file mode 100644 index 0000000000000000000000000000000000000000..829d08bb1880f4dc0f630ff55be175e9cc46a466 --- /dev/null +++ b/core/modules/rest/tests/src/Kernel/Views/StyleSerializerKernelTest.php @@ -0,0 +1,61 @@ +getDisplay('rest_export_1'); + + $display['display_options']['defaults']['style'] = FALSE; + $display['display_options']['style']['type'] = 'serializer'; + $display['display_options']['style']['options']['formats'] = ['json', 'xml']; + $view->save(); + + $view->calculateDependencies(); + $this->assertEquals(['module' => ['rest', 'serialization', 'user']], $view->getDependencies()); + + \Drupal::service('module_installer')->install(['hal']); + + $view = View::load('test_serializer_display_entity'); + $display = &$view->getDisplay('rest_export_1'); + $display['display_options']['style']['options']['formats'] = ['json', 'xml', 'hal_json']; + $view->save(); + + $view->calculateDependencies(); + $this->assertEquals(['module' => ['hal', 'rest', 'serialization', 'user']], $view->getDependencies()); + } + +} diff --git a/core/modules/rest/tests/src/Unit/Plugin/views/style/SerializerTest.php b/core/modules/rest/tests/src/Unit/Plugin/views/style/SerializerTest.php index 16f103337623db35627f5de66f57f63cd6f1136c..f9753b734342c11bd708cf7f80ff41b50dba99e3 100644 --- a/core/modules/rest/tests/src/Unit/Plugin/views/style/SerializerTest.php +++ b/core/modules/rest/tests/src/Unit/Plugin/views/style/SerializerTest.php @@ -68,7 +68,7 @@ public function testSerializerReceivesOptions() { ->willReturn() ->shouldBeCalled(); - $view_serializer_style = new Serializer([], 'dummy_serializer', [], $mock_serializer->reveal(), ['json', 'xml']); + $view_serializer_style = new Serializer([], 'dummy_serializer', [], $mock_serializer->reveal(), ['json', 'xml'], ['json' => 'serialization', 'xml' => 'serialization']); $view_serializer_style->options = ['formats' => ['xml', 'json']]; $view_serializer_style->view = $this->view; $view_serializer_style->displayHandler = $this->displayHandler; diff --git a/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php b/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php index e1f73d77a38ebae0833eccc02cbd363b649814b2..f4611f3fc1a529cfa1476cb0ffc66902db6ea59c 100644 --- a/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php +++ b/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php @@ -40,10 +40,17 @@ public function process(ContainerBuilder $container) { // Find all serialization formats known. $formats = array(); - foreach ($container->findTaggedServiceIds('encoder') as $attributes) { - $formats[] = $attributes[0]['format']; + $format_providers = []; + foreach ($container->findTaggedServiceIds('encoder') as $service_id => $attributes) { + $format = $attributes[0]['format']; + $formats[] = $format; + + if ($provider_tag = $container->getDefinition($service_id)->getTag('_provider')) { + $format_providers[$format] = $provider_tag[0]['provider']; + } } $container->setParameter('serializer.formats', $formats); + $container->setParameter('serializer.format_providers', $format_providers); } /** diff --git a/core/modules/serialization/src/Tests/RegisterSerializationClassesCompilerPassTest.php b/core/modules/serialization/src/Tests/RegisterSerializationClassesCompilerPassTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6406bbbaef174a8d6ee842bb682c7cfa04144d7c --- /dev/null +++ b/core/modules/serialization/src/Tests/RegisterSerializationClassesCompilerPassTest.php @@ -0,0 +1,45 @@ +setDefinition('serializer', new Definition(Serializer::class, [[], []])); + + $definition = new Definition('TestClass'); + $definition->addTag('encoder', ['format' => 'xml']); + $definition->addTag('_provider', ['provider' => 'test_provider_a']); + $container->setDefinition('encoder_1', $definition); + + $definition = new Definition('TestClass'); + $definition->addTag('encoder', ['format' => 'json']); + $definition->addTag('_provider', ['provider' => 'test_provider_a']); + $container->setDefinition('encoder_2', $definition); + + $definition = new Definition('TestClass'); + $definition->addTag('encoder', ['format' => 'hal_json']); + $definition->addTag('_provider', ['provider' => 'test_provider_b']); + $container->setDefinition('encoder_3', $definition); + + $compiler_pass = new RegisterSerializationClassesCompilerPass(); + $compiler_pass->process($container); + + $this->assertEquals(['xml', 'json', 'hal_json'], $container->getParameter('serializer.formats')); + $this->assertEquals(['xml' => 'test_provider_a', 'json' => 'test_provider_a', 'hal_json' => 'test_provider_b'], $container->getParameter('serializer.format_providers')); + } + +} diff --git a/core/modules/views/views.install b/core/modules/views/views.install index 37d03b63a6a15289254eeffcf32fe5e7f9826029..ba2b49df7a9b05902ff60ce28131a96e7e543ed0 100644 --- a/core/modules/views/views.install +++ b/core/modules/views/views.install @@ -363,3 +363,19 @@ function views_update_8005() { /** * @} End of "addtogroup updates-8.1.0". */ + +/** + * @addtogroup updates-8.2.0 + * @{ + */ + +/** + * Rebuild the container to add a new container parameter. + */ +function views_update_8006() { + // Empty update to cause a cache rebuild so that the container is rebuilt. +} + +/** + * @} End of "addtogroup updates-8.2.0". + */ diff --git a/core/modules/views/views.post_update.php b/core/modules/views/views.post_update.php index 2d670c2af91b35e59e1e0e9dba401f7e2b3aa63c..e82b6c801bef0fefae289a7a5a5722c682c7772b 100644 --- a/core/modules/views/views.post_update.php +++ b/core/modules/views/views.post_update.php @@ -182,3 +182,26 @@ function views_post_update_taxonomy_index_tid() { /** * @} End of "addtogroup updates-8.1.x". */ + +/** + * @addtogroup updates-8.2.x + * @{ + */ + +/** + * Fix views with serializer dependencies. + */ +function views_post_update_serializer_dependencies() { + $views = View::loadMultiple(); + array_walk($views, function(View $view) { + $old_dependencies = $view->getDependencies(); + $new_dependencies = $view->calculateDependencies()->getDependencies(); + if ($old_dependencies !== $new_dependencies) { + $view->save(); + } + }); +} + +/** + * @} End of "addtogroup updates-8.2.x". + */ diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1a9dc667f71fce050d6753e8891e00d2c8c4839c --- /dev/null +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php @@ -0,0 +1,43 @@ + $yml, + ]); + + $builder = new ContainerBuilder(); + $yaml_file_loader = new YamlFileLoader($builder); + $yaml_file_loader->load('vfs://drupal/modules/example/example.yml'); + + $this->assertEquals(['_provider' => [['provider' => 'example']]], $builder->getDefinition('example_service')->getTags()); + } + +}