Issue #3081587 by seanB, shaal, phenaproxima, webchick, Berdir, Gábor Hojtsy, plach: Multilingual content is shown double in the media library view

merge-requests/55/head
webchick 2019-10-10 00:11:57 -07:00
parent 5c7c2617cd
commit 713ea1f37c
4 changed files with 536 additions and 1 deletions

View File

@ -364,6 +364,49 @@ display:
group_items: { }
entity_type: media
plugin_id: media_status
langcode:
id: langcode
table: media_field_data
field: langcode
relationship: none
group_type: group
admin_label: ''
operator: in
value: { }
group: 1
exposed: true
expose:
operator_id: langcode_op
label: Language
description: ''
use_operator: false
operator: langcode_op
identifier: langcode
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
anonymous: '0'
administrator: '0'
reduce: false
operator_limit_selection: false
operator_list: { }
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: media
entity_field: langcode
plugin_id: language
sorts:
created:
id: created
@ -941,6 +984,46 @@ display:
entity_type: media
entity_field: name
plugin_id: string
default_langcode:
id: default_langcode
table: media_field_data
field: default_langcode
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
operator_limit_selection: false
operator_list: { }
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: media
entity_field: default_langcode
plugin_id: boolean
filter_groups:
operator: AND
groups:
@ -1005,6 +1088,7 @@ display:
plugin_id: display_link
empty: true
css_class: 'media-library-view js-media-library-view media-library-view--widget'
rendering_language: '***LANGUAGE_language_interface***'
cache_metadata:
max-age: -1
contexts:
@ -1188,6 +1272,46 @@ display:
entity_type: media
entity_field: name
plugin_id: string
default_langcode:
id: default_langcode
table: media_field_data
field: default_langcode
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
operator_limit_selection: false
operator_list: { }
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: media
entity_field: default_langcode
plugin_id: boolean
filter_groups:
operator: AND
groups:
@ -1252,10 +1376,10 @@ display:
plugin_id: display_link
empty: true
css_class: 'media-library-view js-media-library-view media-library-view--widget'
rendering_language: '***LANGUAGE_language_interface***'
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args

View File

@ -176,6 +176,7 @@ function media_library_post_update_table_display() {
$table_display->overrideOption('access', $grid_display->getOption('access'));
$table_display->overrideOption('filters', $grid_display->getOption('filters'));
$table_display->overrideOption('arguments', $grid_display->getOption('arguments'));
$table_display->overrideOption('rendering_language', $grid_display->getOption('rendering_language'));
// Also override the sorts and pager if the grid display has overrides.
$defaults = $grid_display->getOption('defaults');
@ -613,3 +614,163 @@ function media_library_post_update_default_administrative_list_to_table_display(
$view->storage->save();
}
}
/**
* Add langcode filters to media library view displays.
*/
function media_library_post_update_add_langcode_filters() {
$view = Views::getView('media_library');
if (!$view) {
return;
}
// Fetch the filters from the default display and add the new 'langcode'
// filter if it does not yet exist.
$default_display = $view->getDisplay();
$filters = $default_display->getOption('filters');
$added_langcode = FALSE;
if (!isset($filters['langcode'])) {
$filters['langcode'] = [
'id' => 'langcode',
'table' => 'media_field_data',
'field' => 'langcode',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'operator' => 'in',
'value' => [],
'group' => 1,
'exposed' => TRUE,
'expose' => [
'use_operator' => FALSE,
'remember' => FALSE,
'operator_id' => 'langcode_op',
'multiple' => FALSE,
'description' => '',
'required' => FALSE,
'reduce' => FALSE,
'label' => 'Language',
'operator_limit_selection' => FALSE,
'operator' => 'langcode_op',
'identifier' => 'langcode',
'operator_list' => [],
'remember_roles' => [
'administrator' => '0',
'authenticated' => 'authenticated',
'anonymous' => '0',
],
],
'is_grouped' => FALSE,
'group_info' => [
'widget' => 'select',
'group_items' => [],
'multiple' => FALSE,
'description' => '',
'default_group_multiple' => [],
'default_group' => 'All',
'label' => '',
'identifier' => '',
'optional' => TRUE,
'remember' => FALSE,
],
'entity_type' => 'media',
'entity_field' => 'langcode',
'plugin_id' => 'language',
];
$default_display->setOption('filters', $filters);
$added_langcode = TRUE;
}
$added_default_langcode_displays = [];
foreach (['widget', 'widget_table'] as $display_id) {
// Check if the display still exists, or else skip it.
if (!$view->displayHandlers->has($display_id)) {
continue;
}
$view->setDisplay($display_id);
$display = $view->getDisplay();
// Fetch the filters from the display and add the 'default_langcode' filter
// if it does not yet exist.
$filters = $display->getOption('filters');
if (!isset($filters['default_langcode'])) {
$filters['default_langcode'] = [
'id' => 'default_langcode',
'table' => 'media_field_data',
'field' => 'default_langcode',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'operator' => '=',
'value' => '1',
'group' => 1,
'exposed' => FALSE,
'expose' => [
'use_operator' => FALSE,
'remember' => FALSE,
'operator_id' => '',
'multiple' => FALSE,
'description' => '',
'required' => FALSE,
'label' => '',
'operator_limit_selection' => FALSE,
'operator' => '',
'identifier' => '',
'operator_list' => [],
'remember_roles' => [
RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID,
],
],
'is_grouped' => FALSE,
'group_info' => [
'widget' => 'select',
'group_items' => [],
'multiple' => FALSE,
'description' => '',
'default_group_multiple' => [],
'default_group' => 'All',
'label' => '',
'identifier' => '',
'optional' => TRUE,
'remember' => FALSE,
],
'entity_type' => 'media',
'entity_field' => 'default_langcode',
'plugin_id' => 'boolean',
];
$display->setOption('filters', $filters);
// Change the rendering language of the rows to the interface language.
$display->setOption('rendering_language', '***LANGUAGE_language_interface***');
$added_default_langcode_displays[] = $view->storage->get('display')[$display_id]['display_title'];
}
}
if ($added_langcode && $added_default_langcode_displays) {
$view->save();
return t("The 'Language' filter was added to the default display of the %label view and the 'Default translation' filter was added to the following displays: %displays", [
'%label' => $view->storage->label(),
'%displays' => implode(', ', $added_default_langcode_displays),
]);
}
if ($added_langcode) {
$view->save();
return t("The 'Language' filter was added to the default display of the %label view.", [
'%label' => $view->storage->label(),
'%displays' => implode(', ', $added_default_langcode_displays),
]);
}
if ($added_default_langcode_displays) {
$view->save();
return t("The 'Default translation' filter was added to the following %label view displays: %displays", [
'%label' => $view->storage->label(),
'%displays' => implode(', ', $added_default_langcode_displays),
]);
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace Drupal\Tests\media_library\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the media library module updates for the langcode filters.
*
* @group media_library
* @group legacy
*/
class MediaLibraryUpdateViewLangcodeFiltersTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
__DIR__ . '/../../../../../media/tests/fixtures/update/drupal-8.4.0-media_installed.php',
__DIR__ . '/../../../fixtures/update/drupal-8.7.2-media_library_installed.php',
];
}
/**
* Tests that the langcode filters are added to the media library view.
*
* @see media_library_post_update_add_langcode_filters()
*/
public function testMediaLibraryViewStatusExtraFilter() {
$config = $this->config('views.view.media_library');
// We don't have any language filters yet for all displays.
$this->assertNull($config->get('display.default.display_options.filters.langcode'));
$this->assertNull($config->get('display.default.display_options.filters.default_langcode'));
$this->assertNull($config->get('display.widget.display_options.filters.langcode'));
$this->assertNull($config->get('display.widget.display_options.filters.default_langcode'));
$this->assertNull($config->get('display.widget_table.display_options.filters.langcode'));
$this->assertNull($config->get('display.widget_table.display_options.filters.default_langcode'));
// The rendering language should not be set for the displays.
$this->assertNull($config->get('display.default.display_options.rendering_language'));
$this->assertNull($config->get('display.widget.display_options.rendering_language'));
$this->assertNull($config->get('display.widget_table.display_options.rendering_language'));
$this->runUpdates();
$config = $this->config('views.view.media_library');
// The update should add the langcode filter to the default display only.
$this->assertNull($config->get('display.widget.display_options.filters.langcode'));
$this->assertNull($config->get('display.widget_table.display_options.filters.langcode'));
$default_langcode_filter = $config->get('display.default.display_options.filters.langcode');
$this->assertInternalType('array', $default_langcode_filter);
$this->assertSame('langcode', $default_langcode_filter['field']);
$this->assertSame('media', $default_langcode_filter['entity_type']);
$this->assertSame('language', $default_langcode_filter['plugin_id']);
$this->assertSame('langcode', $default_langcode_filter['id']);
$this->assertTrue($default_langcode_filter['exposed']);
// The update should add the default_langcode filter to the widget displays
// only.
$this->assertNull($config->get('display.default.display_options.filters.default_langcode'));
foreach (['widget', 'widget_table'] as $display_id) {
$filter = $config->get('display.' . $display_id . '.display_options.filters.default_langcode');
$this->assertInternalType('array', $filter);
$this->assertSame('default_langcode', $filter['field']);
$this->assertSame('media', $filter['entity_type']);
$this->assertSame('boolean', $filter['plugin_id']);
$this->assertSame('default_langcode', $filter['id']);
$this->assertFalse($filter['exposed']);
}
// The default display should use the default rendering language, which is
// the language of the content.
$this->assertNull($config->get('display.default.display_options.rendering_language'));
// The rendering language of the row should be set to the interface
// language.
$this->assertSame('***LANGUAGE_language_interface***', $config->get('display.widget.display_options.rendering_language'));
$this->assertSame('***LANGUAGE_language_interface***', $config->get('display.widget_table.display_options.rendering_language'));
}
}

View File

@ -0,0 +1,168 @@
<?php
namespace Drupal\Tests\media_library\FunctionalJavascript;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\file\Entity\File;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\media\Entity\Media;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
use Drupal\Tests\TestFileCreationTrait;
/**
* Tests media library for translatable media.
*
* @group media_library
*/
class TranslationsTest extends WebDriverTestBase {
use EntityReferenceTestTrait;
use MediaTypeCreationTrait;
use TestFileCreationTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'content_translation',
'field',
'media',
'media_library',
'node',
'views',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create some languages.
foreach (['nl', 'es'] as $langcode) {
ConfigurableLanguage::createFromLangcode($langcode)->save();
}
// Create an image media type and article node type.
$this->createMediaType('image', ['id' => 'image']);
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
// Make the media translatable and ensure the change is picked up.
\Drupal::service('content_translation.manager')->setEnabled('media', 'image', TRUE);
// Create a media reference field on articles.
$this->createEntityReferenceField(
'node',
'article',
'field_media',
'Media',
'media',
'default',
['target_bundles' => ['image']],
FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
);
// Add the media field to the form display.
\Drupal::service('entity_display.repository')->getFormDisplay('node', 'article')
->setComponent('field_media', ['type' => 'media_library_widget'])
->save();
// Create a file to user for our images.
$image = File::create([
'uri' => $this->getTestFiles('image')[0]->uri,
]);
$image->setPermanent();
$image->save();
// Create a translated and untranslated media item in each language.
$media_items = [
['nl' => 'Eekhoorn', 'es' => 'Ardilla'],
['es' => 'Zorro', 'nl' => 'Vos'],
['nl' => 'Hert'],
['es' => 'Tejón'],
];
foreach ($media_items as $translations) {
$default_langcode = key($translations);
$default_name = array_shift($translations);
$media = Media::create([
'name' => $default_name,
'bundle' => 'image',
'field_media_image' => $image,
'langcode' => $default_langcode,
]);
foreach ($translations as $langcode => $name) {
$media->addTranslation($langcode, ['name' => $name]);
}
$media->save();
}
$user = $this->drupalCreateUser([
'access administration pages',
'access content',
'access media overview',
'edit own article content',
'create article content',
'administer media',
]);
$this->drupalLogin($user);
}
/**
* Tests the media library widget shows all media only once.
*/
public function testMediaLibraryTranslations() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
// All translations should be shown in the administration overview,
// regardless of the interface language.
$this->drupalGet('nl/admin/content/media-grid');
$assert_session->elementsCount('css', '.media-library-item', 6);
$media_items = $page->findAll('css', '.media-library-item__name');
$media_names = [];
foreach ($media_items as $media_item) {
$media_names[] = $media_item->getText();
}
sort($media_names);
$this->assertSame(['Ardilla', 'Eekhoorn', 'Hert', 'Tejón', 'Vos', 'Zorro'], $media_names);
$this->drupalGet('es/admin/content/media-grid');
$assert_session->elementsCount('css', '.media-library-item', 6);
$media_items = $page->findAll('css', '.media-library-item__name');
$media_names = [];
foreach ($media_items as $media_item) {
$media_names[] = $media_item->getText();
}
sort($media_names);
$this->assertSame(['Ardilla', 'Eekhoorn', 'Hert', 'Tejón', 'Vos', 'Zorro'], $media_names);
// All media should only be shown once, and should be shown in the interface
// language.
$this->drupalGet('nl/node/add/article');
$assert_session->elementExists('css', '.media-library-open-button[name^="field_media"]')->click();
$assert_session->waitForText('Add or select media');
$assert_session->elementsCount('css', '.media-library-item', 4);
$media_items = $page->findAll('css', '.media-library-item__name');
$media_names = [];
foreach ($media_items as $media_item) {
$media_names[] = $media_item->getText();
}
sort($media_names);
$this->assertSame(['Eekhoorn', 'Hert', 'Tejón', 'Vos'], $media_names);
$this->drupalGet('es/node/add/article');
$assert_session->elementExists('css', '.media-library-open-button[name^="field_media"]')->click();
$assert_session->waitForText('Add or select media');
$assert_session->elementsCount('css', '.media-library-item', 4);
$media_items = $page->findAll('css', '.media-library-item__name');
$media_names = [];
foreach ($media_items as $media_item) {
$media_names[] = $media_item->getText();
}
sort($media_names);
$this->assertSame(['Ardilla', 'Hert', 'Tejón', 'Zorro'], $media_names);
}
}