Issue #2476563 by Gábor Hojtsy, penyaskito, amateescu: Entity operations links tied to original entity language, ignore everything else
parent
400baf1609
commit
1ae0ed8796
|
@ -386,6 +386,8 @@ abstract class ConfigEntityBase extends Entity implements ConfigEntityInterface
|
|||
* {@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);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?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 @@ namespace Drupal\config_test;
|
|||
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 @@ class ConfigTestForm extends EntityForm {
|
|||
'#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 @@ namespace Drupal\views\Plugin\views\field;
|
|||
|
||||
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 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
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 @@ class EntityOperations extends FieldPluginBase {
|
|||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('entity.manager')
|
||||
$container->get('entity.manager'),
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -98,7 +113,7 @@ class EntityOperations extends FieldPluginBase {
|
|||
* {@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 @@ class EntityOperations extends FieldPluginBase {
|
|||
* {@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 @@ namespace Drupal\views\Tests\Handler;
|
|||
|
||||
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 @@ class EntityUrlTest extends UnitTestCase {
|
|||
$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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue