Commit 491554b1 authored by alexpott's avatar alexpott

Issue #1996130 by dawehner, damiankloip, dagmar, marthinal, clemens.tolboom,...

Issue #1996130 by dawehner, damiankloip, dagmar, marthinal, clemens.tolboom, Nitesh Sethia: REST views: not adding dependencies on Serializer providers
parent 7c0adf9e
......@@ -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);
}
}
......
......@@ -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);
}
}
<?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());
}
}
......@@ -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;
......
......@@ -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);
}
/**
......
<?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'));
}
}
......@@ -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".
*/
......@@ -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".
*/
<?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());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment