Commit 5c386edc authored by alexpott's avatar alexpott

Issue #2664880 by vasi, dawehner, clemens.tolboom: DataEntityRow doesn't respect translations

parent c2cbf733
......@@ -2,7 +2,11 @@
namespace Drupal\rest\Plugin\views\row;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
use Drupal\views\Plugin\views\row\RowPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin which displays entities as raw data.
......@@ -18,16 +22,97 @@
*/
class DataEntityRow extends RowPluginBase {
use EntityTranslationRenderTrait;
/**
* {@inheritdoc}
*/
protected $usesOptions = FALSE;
/**
* Contains the entity type of this row plugin instance.
*
* @var \Drupal\Core\Entity\EntityTypeInterface
*/
protected $entityType;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
public $entityManager;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* {@inheritdoc}
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* The language manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->languageManager = $language_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('entity.manager'), $container->get('language_manager'));
}
/**
* {@inheritdoc}
*/
public function render($row) {
return $row->_entity;
return $this->getEntityTranslation($row->_entity, $row);
}
/**
* {@inheritdoc}
*/
public function getEntityTypeId() {
return $this->view->getBaseEntityType()->id();
}
/**
* {@inheritdoc}
*/
protected function getEntityManager() {
return $this->entityManager;
}
/**
* {@inheritdoc}
*/
protected function getLanguageManager() {
return $this->languageManager;
}
/**
* {@inheritdoc}
*/
protected function getView() {
return $this->view;
}
/**
* {@inheritdoc}
*/
public function query() {
parent::query();
$this->getEntityTranslationRenderer()->query($this->view->getQuery());
}
}
......@@ -7,6 +7,7 @@
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
use Drupal\views\Entity\View;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
......@@ -38,14 +39,14 @@ class StyleSerializerTest extends PluginTestBase {
*
* @var array
*/
public static $modules = array('views_ui', 'entity_test', 'hal', 'rest_test_views', 'node', 'text', 'field');
public static $modules = array('views_ui', 'entity_test', 'hal', 'rest_test_views', 'node', 'text', 'field', 'language');
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = array('test_serializer_display_field', 'test_serializer_display_entity', 'test_serializer_node_display_field', 'test_serializer_node_exposed_filter');
public static $testViews = array('test_serializer_display_field', 'test_serializer_display_entity', 'test_serializer_display_entity_translated', 'test_serializer_node_display_field', 'test_serializer_node_exposed_filter');
/**
* A user with administrative privileges to look at test entity and configure views.
......@@ -750,4 +751,38 @@ public function testRestViewExposedFilter() {
$this->assertEqual($result, $expected, 'Querying a view with a starts with exposed filter on the title returns nodes whose title starts with value provided.');
$this->assertCacheContexts($cache_contexts);
}
/**
* Test multilingual entity rows.
*/
public function testMulEntityRows() {
// Create some languages.
ConfigurableLanguage::createFromLangcode('l1')->save();
ConfigurableLanguage::createFromLangcode('l2')->save();
// Create an entity with no translations.
$storage = \Drupal::entityTypeManager()->getStorage('entity_test_mul');
$storage->create(['langcode' => 'l1', 'name' => 'mul-none'])->save();
// Create some entities with translations.
$entity = $storage->create(['langcode' => 'l1', 'name' => 'mul-l1-orig']);
$entity->save();
$entity->addTranslation('l2', ['name' => 'mul-l1-l2'])->save();
$entity = $storage->create(['langcode' => 'l2', 'name' => 'mul-l2-orig']);
$entity->save();
$entity->addTranslation('l1', ['name' => 'mul-l2-l1'])->save();
// Get the names of the output.
$json = $this->drupalGetWithFormat('test/serialize/translated_entity', 'json');
$decoded = $this->container->get('serializer')->decode($json, 'hal_json');
$names = [];
foreach ($decoded as $item) {
$names[] = $item['name'][0]['value'];
}
sort($names);
// Check that the names are correct.
$expected = ['mul-l1-l2', 'mul-l1-orig', 'mul-l2-l1', 'mul-l2-orig', 'mul-none'];
$this->assertIdentical($names, $expected, 'The translated content was found in the JSON.');
}
}
langcode: en
status: true
dependencies:
module:
- entity_test
- rest
id: test_serializer_display_entity_translated
label: 'Test serialize translated entity rows'
module: rest
description: ''
tag: ''
base_table: entity_test_mul_property_data
base_field: id
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
style:
type: serializer
row:
type: data_entity
title: 'Test serialize translated entity rows'
rendering_language: '***LANGUAGE_entity_translation***'
arguments: { }
rest_export_1:
display_plugin: rest_export
id: rest_export_1
display_title: serializer
position: null
display_options:
defaults:
access: false
path: test/serialize/translated_entity
......@@ -2669,11 +2669,8 @@ protected function buildRenderingLanguageOptions() {
* TRUE if the base table is of a translatable entity type, FALSE otherwise.
*/
protected function isBaseTableTranslatable() {
$view_base_table = $this->view->storage->get('base_table');
$views_data = Views::viewsData()->get($view_base_table);
if (!empty($views_data['table']['entity type'])) {
$entity_type_id = $views_data['table']['entity type'];
return \Drupal::entityManager()->getDefinition($entity_type_id)->isTranslatable();
if ($entity_type = $this->view->getBaseEntityType()) {
return $entity_type->isTranslatable();
}
return FALSE;
}
......
......@@ -428,6 +428,13 @@ class ViewExecutable implements \Serializable {
*/
protected $routeProvider;
/**
* The entity type of the base table, if available.
*
* @var \Drupal\Core\Entity\EntityTypeInterface|false
*/
protected $baseEntityType;
/**
* Constructs a new ViewExecutable object.
*
......@@ -961,6 +968,27 @@ public function getBaseTables() {
return $base_tables;
}
/**
* Returns the entity type of the base table, if available.
*
* @return \Drupal\Core\Entity\EntityType|false
* The entity type of the base table, or FALSE if none exists.
*/
public function getBaseEntityType() {
if (!isset($this->baseEntityType)) {
$view_base_table = $this->storage->get('base_table');
$views_data = $this->viewsData->get($view_base_table);
if (!empty($views_data['table']['entity type'])) {
$entity_type_id = $views_data['table']['entity type'];
$this->baseEntityType = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
}
else {
$this->baseEntityType = FALSE;
}
}
return $this->baseEntityType;
}
/**
* Runs the preQuery() on all active handlers.
*/
......@@ -2036,7 +2064,13 @@ public function destroy() {
$defaults = $reflection->getDefaultProperties();
// The external dependencies should not be reset. This is not generated by
// the execution of a view.
unset($defaults['storage'], $defaults['user'], $defaults['request'], $defaults['routeProvider']);
unset(
$defaults['storage'],
$defaults['user'],
$defaults['request'],
$defaults['routeProvider'],
$defaults['viewsData']
);
foreach ($defaults as $property => $default) {
$this->{$property} = $default;
......
......@@ -351,7 +351,13 @@ protected function assertViewDestroy($view) {
$reflection = new \ReflectionClass($view);
$defaults = $reflection->getDefaultProperties();
// The storage and user should remain.
unset($defaults['storage'], $defaults['user'], $defaults['request'], $defaults['routeProvider']);
unset(
$defaults['storage'],
$defaults['user'],
$defaults['request'],
$defaults['routeProvider'],
$defaults['viewsData']
);
foreach ($defaults as $property => $default) {
$this->assertIdentical($this->getProtectedProperty($view, $property), $default);
......
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