summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2016-05-27 11:13:13 (GMT)
committerAlex Pott2016-05-27 11:13:13 (GMT)
commit491554b1809c14157545fb3c2450656b262c4a10 (patch)
tree599c6cf552d73a2d4bd892270042e3a29d8f4364
parent7c0adf9e2941d20d69d11aa5f56d65e729ea8734 (diff)
Issue #1996130 by dawehner, damiankloip, dagmar, marthinal, clemens.tolboom, Nitesh Sethia: REST views: not adding dependencies on Serializer providers
-rw-r--r--core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php9
-rw-r--r--core/modules/rest/src/Plugin/views/style/Serializer.php41
-rw-r--r--core/modules/rest/tests/src/Kernel/Views/StyleSerializerKernelTest.php61
-rw-r--r--core/modules/rest/tests/src/Unit/Plugin/views/style/SerializerTest.php2
-rw-r--r--core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php11
-rw-r--r--core/modules/serialization/src/Tests/RegisterSerializationClassesCompilerPassTest.php45
-rw-r--r--core/modules/views/views.install16
-rw-r--r--core/modules/views/views.post_update.php23
-rw-r--r--core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php43
9 files changed, 245 insertions, 6 deletions
diff --git a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
index c0a8747..2a55542 100644
--- a/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
+++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
@@ -113,7 +113,16 @@ class YamlFileLoader
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 71bb511..7e9b433 100644
--- a/core/modules/rest/src/Plugin/views/style/Serializer.php
+++ b/core/modules/rest/src/Plugin/views/style/Serializer.php
@@ -48,6 +48,13 @@ class Serializer extends StylePluginBase implements CacheableDependencyInterface
protected $formats = array();
/**
+ * The serialization format providers, keyed by format.
+ *
+ * @var string[]
+ */
+ protected $formatProviders;
+
+ /**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
@@ -56,19 +63,21 @@ class Serializer extends StylePluginBase implements CacheableDependencyInterface
$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 @@ class Serializer extends StylePluginBase implements CacheableDependencyInterface
'#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 @@ class Serializer extends StylePluginBase implements CacheableDependencyInterface
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 0000000..829d08b
--- /dev/null
+++ b/core/modules/rest/tests/src/Kernel/Views/StyleSerializerKernelTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace Drupal\Tests\rest\Kernel\Views;
+
+use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
+use Drupal\views\Entity\View;
+use Drupal\views\Tests\ViewTestData;
+
+/**
+ * @coversDefaultClass \Drupal\rest\Plugin\views\style\Serializer
+ * @group views
+ */
+class StyleSerializerKernelTest extends ViewsKernelTestBase {
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $testViews = ['test_serializer_display_entity'];
+
+ /**
+ * {@inheritdoc}
+ */
+ public static $modules = ['rest_test_views', 'serialization', 'rest'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp($import_test_views = TRUE) {
+ parent::setUp($import_test_views);
+
+ ViewTestData::createTestViews(get_class($this), ['rest_test_views']);
+ }
+
+ /**
+ * @covers ::calculateDependencies
+ */
+ public function testCalculateDepenencies() {
+ /** @var \Drupal\views\Entity\View $view */
+ $view = View::load('test_serializer_display_entity');
+ $display = &$view->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 16f1033..f9753b7 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 @@ class SerializerTest extends UnitTestCase {
->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 e1f73d7..f4611f3 100644
--- a/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php
+++ b/core/modules/serialization/src/RegisterSerializationClassesCompilerPass.php
@@ -40,10 +40,17 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
// 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 0000000..6406bbb
--- /dev/null
+++ b/core/modules/serialization/src/Tests/RegisterSerializationClassesCompilerPassTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Drupal\serialization\Tests;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\serialization\RegisterSerializationClassesCompilerPass;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\Serializer\Serializer;
+
+/**
+ * @coversDefaultClass \Drupal\serialization\RegisterSerializationClassesCompilerPass
+ * @group serialization
+ */
+class RegisterSerializationClassesCompilerPassTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers ::process
+ */
+ public function testEncoders() {
+ $container = new ContainerBuilder();
+ $container->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 37d03b6..ba2b49d 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 2d670c2..e82b6c8 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 0000000..1a9dc66
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\Tests\Core\DependencyInjection;
+
+use Drupal\Component\FileCache\FileCacheFactory;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\DependencyInjection\YamlFileLoader;
+use org\bovigo\vfs\vfsStream;
+
+/**
+ * @coversDefaultClass \Drupal\Core\DependencyInjection\YamlFileLoader
+ * @group DependencyInjection
+ */
+class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ FileCacheFactory::setPrefix('example');
+ }
+
+ public function testParseDefinitionsWithProvider() {
+ $yml = <<<YAML
+services:
+ example_service:
+ class: \Drupal\Core\ExampleClass
+YAML;
+
+ vfsStream::setup('drupal', NULL, [
+ 'modules/example/example.yml' => $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());
+ }
+
+}