Commit 1ae0ed87 authored by catch's avatar catch

Issue #2476563 by Gábor Hojtsy, penyaskito, amateescu: Entity operations links...

Issue #2476563 by Gábor Hojtsy, penyaskito, amateescu: Entity operations links tied to original entity language, ignore everything else
parent 400baf16
......@@ -386,6 +386,8 @@ public function calculateDependencies() {
* {@inheritdoc}
*/
public function urlInfo($rel = 'edit-form', array $options = []) {
// Unless language was already provided, avoid setting an explicit language.
$options += ['language' => NULL];
return parent::urlInfo($rel, $options);
}
......
<?php
/**
* @file
* Definition of Drupal\config\Tests\ConfigEntityListMultilingualTest.
*/
namespace Drupal\config\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Tests the listing of configuration entities in a multilingual scenario.
*
* @group config
*/
class ConfigEntityListMultilingualTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('config_test', 'language', 'block');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Delete the override config_test entity. It is not required by this test.
\Drupal::entityManager()->getStorage('config_test')->load('override')->delete();
ConfigurableLanguage::createFromLangcode('hu')->save();
$this->drupalPlaceBlock('local_actions_block');
}
/**
* Tests the listing UI with different language scenarios.
*/
function testListUI() {
// Log in as an administrative user to access the full menu trail.
$this->drupalLogin($this->drupalCreateUser(array('access administration pages', 'administer site configuration')));
// Get the list page.
$this->drupalGet('admin/structure/config_test');
$this->assertLinkByHref('admin/structure/config_test/manage/dotted.default');
// Add a new entity using the action link.
$this->clickLink('Add test configuration');
$edit = array(
'label' => 'Antilop',
'id' => 'antilop',
'langcode' => 'hu',
);
$this->drupalPostForm(NULL, $edit, t('Save'));
// Ensure that operations for editing the Hungarian entity appear in English.
$this->assertLinkByHref('admin/structure/config_test/manage/antilop');
// Get the list page in Hungarian and assert Hungarian admin links
// regardless of language of config entities.
$this->drupalGet('hu/admin/structure/config_test');
$this->assertLinkByHref('hu/admin/structure/config_test/manage/dotted.default');
$this->assertLinkByHref('hu/admin/structure/config_test/manage/antilop');
}
}
......@@ -10,6 +10,7 @@
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -126,6 +127,13 @@ public function form(array $form, FormStateInterface $form_state) {
'#access' => !empty($size),
);
$form['langcode'] = array(
'#type' => 'language_select',
'#title' => t('Language'),
'#languages' => LanguageInterface::STATE_ALL,
'#default_value' => $entity->language()->getId(),
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
......
......@@ -9,7 +9,9 @@
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Routing\RedirectDestinationTrait;
use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -22,6 +24,7 @@
*/
class EntityOperations extends FieldPluginBase {
use EntityTranslationRenderTrait;
use RedirectDestinationTrait;
/**
......@@ -31,6 +34,13 @@ class EntityOperations extends FieldPluginBase {
*/
protected $entityManager;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* Constructor.
*
......@@ -42,10 +52,14 @@ class EntityOperations extends FieldPluginBase {
* The plugin implementation definition.
* @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, array $plugin_definition, EntityManagerInterface $entity_manager) {
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityManager = $entity_manager;
$this->languageManager = $language_manager;
}
/**
......@@ -56,7 +70,8 @@ public static function create(ContainerInterface $container, array $configuratio
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity.manager')
$container->get('entity.manager'),
$container->get('language_manager')
);
}
......@@ -98,7 +113,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
* {@inheritdoc}
*/
public function render(ResultRow $values) {
$entity = $this->getEntity($values);
$entity = $this->getEntityTranslation($this->getEntity($values), $values);
$operations = $this->entityManager->getListBuilder($entity->getEntityTypeId())->getOperations($entity);
if ($this->options['destination']) {
foreach ($operations as &$operation) {
......@@ -120,8 +135,39 @@ public function render(ResultRow $values) {
* {@inheritdoc}
*/
public function query() {
// There is nothing to ensure or add for this handler, so we purposefully do
// nothing here and do not call parent::query() either.
// We purposefully do not call parent::query() because we do not want the
// default query behavior for Views fields. Instead, let the entity
// translation renderer provide the correct query behavior.
if ($this->languageManager->isMultilingual()) {
$this->getEntityTranslationRenderer()->query($this->query, $this->relationship);
}
}
/**
* {@inheritdoc}
*/
public function getEntityTypeId() {
return $this->getEntityType();
}
/**
* {@inheritdoc}
*/
protected function getEntityManager() {
return $this->entityManager;
}
/**
* {@inheritdoc}
*/
protected function getLanguageManager() {
return $this->languageManager;
}
/**
* {@inheritdoc}
*/
protected function getView() {
return $this->view;
}
}
......@@ -9,6 +9,8 @@
use Drupal\Core\Url;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
/**
* Tests the core Drupal\views\Plugin\views\field\EntityOperations handler.
......@@ -29,30 +31,62 @@ class FieldEntityOperationsTest extends HandlerTestBase {
*
* @var array
*/
public static $modules = array('entity_test');
public static $modules = array('node', 'language');
function setUp() {
parent::setUp();
// Create Article content type.
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
/**
* Tests entity operations field.
*/
public function testEntityOperations() {
// Create some test entities.
// Add languages and refresh the container so the entity manager will have
// fresh data.
ConfigurableLanguage::createFromLangcode('hu')->save();
ConfigurableLanguage::createFromLangcode('es')->save();
$this->rebuildContainer();
// Create some test entities. Every other entity is Hungarian while all
// have a Spanish translation.
$entities = array();
for ($i = 0; $i < 5; $i++) {
EntityTest::create(array(
'name' => $this->randomString(),
))->save();
$entity = Node::create([
'title' => $this->randomString(),
'type' => 'article',
'langcode' => $i % 2 === 0 ? 'hu' : 'en',
]);
$entity->save();
$translation = $entity->addTranslation('es');
$translation->set('title', $entity->getTitle() . ' in Spanish');
$translation->save();
$entities[$i] = $entity;
}
$entities = EntityTest::loadMultiple();
$admin_user = $this->drupalCreateUser(array('access administration pages', 'administer entity_test content'));
$this->drupalLogin($admin_user);
$admin_user = $this->drupalCreateUser(array('access administration pages', 'administer nodes', 'bypass node access'));
$this->drupalLogin($this->rootUser);
$this->drupalGet('test-entity-operations');
/** @var $entity \Drupal\entity_test\Entity\EntityTest */
foreach ($entities as $entity) {
$operations = \Drupal::entityManager()->getListBuilder('entity_test')->getOperations($entity);
foreach ($operations as $operation) {
$expected_destination = Url::fromUri('internal:/test-entity-operations')->toString();
$result = $this->xpath('//ul[contains(@class, dropbutton)]/li/a[contains(@href, :path) and text()=:title]', array(':path' => $operation['url']->toString() . '?destination=' . $expected_destination, ':title' => $operation['title']));
$this->assertEqual(count($result), 1, t('Found entity @operation link with destination parameter.', array('@operation' => $operation['title'])));
/** @var \Drupal\Core\Language\LanguageInterface $language */
foreach ($entity->getTranslationLanguages() as $language) {
$entity = $entity->getTranslation($language->getId());
$operations = \Drupal::entityManager()->getListBuilder('node')->getOperations($entity);
$this->assertTrue(count($operations) > 0, 'There are operations.');
foreach ($operations as $operation) {
$expected_destination = Url::fromUri('internal:/test-entity-operations')->toString();
$result = $this->xpath('//ul[contains(@class, dropbutton)]/li/a[@href=:path and text()=:title]', array(':path' => $operation['url']->toString() . '?destination=' . $expected_destination, ':title' => $operation['title']));
$this->assertEqual(count($result), 1, t('Found entity @operation link with destination parameter.', array('@operation' => $operation['title'])));
// Entities which were created in Hungarian should link to the Hungarian
// edit form, others to the English one (which has no path prefix here).
$base_path = \Drupal::request()->getBasePath();
$parts = explode('/', str_replace($base_path, '', $operation['url']->toString()));
$expected_prefix = ($language->getId() != 'en' ? $language->getId() : 'node');
$this->assertEqual($parts[1], $expected_prefix, 'Entity operation links to the correct language for the entity.');
}
}
}
}
......
......@@ -2,13 +2,13 @@ langcode: en
status: true
dependencies:
module:
- entity_test
- node
id: test_entity_operations
label: test_entity_operations
module: views
description: ''
tag: ''
base_table: entity_test
base_table: node_field_data
base_field: id
core: 8.x
display:
......@@ -35,60 +35,29 @@ display:
row:
type: fields
fields:
name:
id: name
table: entity_test
field: name
relationship: none
group_type: group
admin_label: ''
label: ''
title:
id: title
table: node_field_data
field: title
label: Title
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
entity_type: entity_test
entity_field: name
entity_type: node
entity_field: title
type: string
settings:
link_to_entity: true
plugin_id: field
operations:
id: operations
table: entity_test
table: node
field: operations
relationship: none
group_type: group
......
......@@ -24,6 +24,13 @@ class EntityOperationsUnitTest extends UnitTestCase {
*/
protected $entityManager;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $languageManager;
/**
* The plugin under test.
*
......@@ -38,13 +45,14 @@ class EntityOperationsUnitTest extends UnitTestCase {
*/
public function setUp() {
$this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
$this->languageManager = $this->getMock('\Drupal\Core\Language\LanguageManagerInterface');
$configuration = array();
$plugin_id = $this->randomMachineName();
$plugin_definition = array(
'title' => $this->randomMachineName(),
);
$this->plugin = new EntityOperations($configuration, $plugin_id, $plugin_definition, $this->entityManager);
$this->plugin = new EntityOperations($configuration, $plugin_id, $plugin_definition, $this->entityManager, $this->languageManager);
$redirect_service = $this->getMock('Drupal\Core\Routing\RedirectDestinationInterface');
$redirect_service->expects($this->any())
......
......@@ -66,10 +66,13 @@ public function testUrlInfo($entity_class, $link_template, $expected, $langcode
$this->assertEquals($langcode, $uri->getOption('language')->getId());
}
else {
// The expected langcode for a config entity is 'en', because it sets the
// value as default property.
$expected_langcode = $entity instanceof ConfigEntityInterface ? 'en' : LanguageInterface::LANGCODE_NOT_SPECIFIED;
$this->assertEquals($expected_langcode, $uri->getOption('language')->getId());
if ($entity instanceof ConfigEntityInterface) {
// Config entities do not provide a language with their URIs.
$this->assertEquals(NULL, $uri->getOption('language'));
}
else {
$this->assertEquals(LanguageInterface::LANGCODE_NOT_SPECIFIED, $uri->getOption('language')->getId());
}
}
}
......
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