Commit bd724091 authored by catch's avatar catch

Issue #2983958 by Sam152, zolt_toth, amateescu, olivier.br, jibran,...

Issue #2983958 by Sam152, zolt_toth, amateescu, olivier.br, jibran, greggmarshall: Users expect the "latest translation affected revision" not the "latest revision" in the views UI when moderating content
parent d553a65e
......@@ -501,10 +501,10 @@ display:
entity_type: node
plugin_id: entity_operations
filters:
latest_revision:
id: latest_revision
latest_translation_affected_revision:
id: latest_translation_affected_revision
table: node_revision
field: latest_revision
field: latest_translation_affected_revision
relationship: none
group_type: group
admin_label: ''
......@@ -537,7 +537,7 @@ display:
default_group_multiple: { }
group_items: { }
entity_type: node
plugin_id: latest_revision
plugin_id: latest_translation_affected_revision
title:
id: title
table: node_field_revision
......
......@@ -7,6 +7,7 @@
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
use Drupal\Core\Site\Settings;
use Drupal\views\Entity\View;
use Drupal\workflows\Entity\Workflow;
/**
......@@ -110,3 +111,30 @@ function content_moderation_post_update_set_default_moderation_state(&$sandbox)
return FALSE;
});
}
/**
* Set the filter on the moderation view to be the latest translation affected.
*/
function content_moderation_post_update_set_views_filter_latest_translation_affected_revision(&$sandbox) {
$original_plugin_name = 'latest_revision';
$new_plugin_name = 'latest_translation_affected_revision';
// Check that views is installed and the moderated content view exists.
if (\Drupal::moduleHandler()->moduleExists('views') && $view = View::load('moderated_content')) {
$display = &$view->getDisplay('default');
if (!isset($display['display_options']['filters'][$original_plugin_name])) {
return;
}
$translation_affected_filter = [
'id' => $new_plugin_name,
'field' => $new_plugin_name,
'plugin_id' => $new_plugin_name,
] + $display['display_options']['filters'][$original_plugin_name];
$display['display_options']['filters'] = [$new_plugin_name => $translation_affected_filter] + $display['display_options']['filters'];
unset($display['display_options']['filters'][$original_plugin_name]);
$view->save();
}
}
<?php
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\views\Entity\View;
/**
* Tests the upgrade path for updating the moderated content view.
*
* @group Update
* @group legacy
*
* @see content_moderation_post_update_set_views_filter_latest_translation_affected_revision()
*/
class ModeratedContentViewLatestRevisionUpdateTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
__DIR__ . '/../../fixtures/update/drupal-8.4.0-content_moderation_installed.php',
__DIR__ . '/../../fixtures/update/drupal-8.5.0-content_moderation_installed.php',
];
}
/**
* Tests updating the moderated content view.
*/
public function testUpdateModeratedContentView() {
$display = View::load('moderated_content')->getDisplay('default');
$this->assertArrayHasKey('latest_revision', $display['display_options']['filters']);
$this->assertArrayNotHasKey('latest_translation_affected_revision', $display['display_options']['filters']);
$this->runUpdates();
$display = View::load('moderated_content')->getDisplay('default');
$this->assertArrayNotHasKey('latest_revision', $display['display_options']['filters']);
$this->assertArrayHasKey('latest_translation_affected_revision', $display['display_options']['filters']);
}
}
......@@ -2,6 +2,8 @@
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
......@@ -24,7 +26,13 @@ class ModeratedContentViewTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['content_moderation', 'node', 'views'];
public static $modules = [
'content_moderation',
'node',
'views',
'language',
'content_translation',
];
/**
* {@inheritdoc}
......@@ -128,4 +136,34 @@ public function testModeratedContentPage() {
$assert_sesison->linkByHrefNotExists('node/' . $nodes['draft_article']->id() . '/edit');
}
/**
* Test the moderated content page with multilingual content.
*/
public function testModeratedContentPageMultilingual() {
ConfigurableLanguage::createFromLangcode('fr')->save();
$node = $this->drupalCreateNode([
'type' => 'article',
'moderation_state' => 'published',
'title' => 'en article published',
]);
$node->title = 'en draft revision';
$node->moderation_state = 'draft';
$node->save();
$translation = Node::load($node->id())->addTranslation('fr');
$translation->title = 'fr draft revision';
$translation->moderation_state = 'draft';
$translation->save();
$this->drupalLogin($this->adminUser);
// The moderated content view should show both the pending en draft revision
// and the pending fr draft revision.
$this->drupalGet('admin/content/moderated');
$this->assertSession()->linkExists('fr draft revision');
$this->assertSession()->linkExists('en draft revision');
}
}
......@@ -250,6 +250,13 @@ public function getViewsData() {
'help' => $this->t('Restrict the view to only revisions that are the latest revision of their entity.'),
'filter' => ['id' => 'latest_revision'],
];
if ($this->entityType->isTranslatable()) {
$data[$revision_table]['latest_translation_affected_revision'] = [
'title' => $this->t('Is Latest Translation Affected Revision'),
'help' => $this->t('Restrict the view to only revisions that are the latest translation affected revision of their entity.'),
'filter' => ['id' => 'latest_translation_affected_revision'],
];
}
}
$this->addEntityLinks($data[$base_table]);
......
<?php
namespace Drupal\views\Plugin\views\filter;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\views\Plugin\ViewsHandlerManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Filter to show only the latest translation affected revision of an entity.
*
* @ingroup views_filter_handlers
*
* @ViewsFilter("latest_translation_affected_revision")
*/
class LatestTranslationAffectedRevision extends FilterPluginBase implements ContainerFactoryPluginInterface {
/**
* Entity Type Manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Views Handler Plugin Manager.
*
* @var \Drupal\views\Plugin\ViewsHandlerManager
*/
protected $joinHandler;
/**
* Constructs a new LatestRevisionTranslationAffected.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity Type Manager Service.
* @param \Drupal\views\Plugin\ViewsHandlerManager $join_handler
* Views Handler Plugin Manager.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ViewsHandlerManager $join_handler) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
$this->joinHandler = $join_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager'),
$container->get('plugin.manager.views.join')
);
}
/**
* {@inheritdoc}
*/
public function adminSummary() {
}
/**
* {@inheritdoc}
*/
protected function operatorForm(&$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function canExpose() {
return FALSE;
}
/**
* {@inheritdoc}
*/
public function query() {
/** @var \Drupal\views\Plugin\views\query\Sql $query */
$query = $this->query;
$query_base_table = $this->relationship ?: $this->view->storage->get('base_table');
$entity_type = $this->entityTypeManager->getDefinition($this->getEntityType());
$keys = $entity_type->getKeys();
$definition = [
'table' => $query_base_table,
'type' => 'LEFT',
'field' => $keys['id'],
'left_table' => $query_base_table,
'left_field' => $keys['id'],
'extra' => [
['left_field' => $keys['revision'], 'field' => $keys['revision'], 'operator' => '>'],
['left_field' => 'langcode', 'field' => 'langcode', 'operator' => '='],
['field' => 'revision_translation_affected', 'value' => '1', 'operator' => '='],
],
];
$join = $this->joinHandler->createInstance('standard', $definition);
$join_table_alias = $query->addTable($query_base_table, $this->relationship, $join);
$query->addWhere($this->options['group'], "$join_table_alias.{$keys['id']}", NULL, 'IS NULL');
$query->addWhere($this->options['group'], "$query_base_table.revision_translation_affected", '1', '=');
}
}
<?php
namespace Drupal\Tests\views\Functional\Entity;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\Views;
/**
* Tests the 'Latest translation affected revision' filter.
*
* @group views
*/
class LatestTranslationAffectedRevisionTest extends ViewTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_latest_translation_affected_revision_filter'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'node',
'system',
'language',
'content_translation',
];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp();
ConfigurableLanguage::createFromLangcode('fr')->save();
$this->drupalCreateContentType(['type' => 'article']);
}
/**
* Tests the 'Latest revision' filter.
*/
public function testLatestRevisionFilter() {
$node = Node::create([
'title' => 'Original translation - default revision',
'type' => 'test',
]);
$node->save();
$translated = $node->addTranslation('fr', ['title' => 'French translation - default revision']);
$translated->title = 'French translation - default revision';
$translated->save();
$pending = clone $node;
$pending->setNewRevision(TRUE);
$pending->isDefaultRevision(FALSE);
$pending->title = 'Original translation - pending revision';
$pending->save();
$pending_translated = clone $translated;
$pending_translated->setNewRevision(TRUE);
$pending_translated->isDefaultRevision(FALSE);
$pending_translated->title = 'French translation - pending revision';
$pending_translated->save();
$view = Views::getView('test_latest_translation_affected_revision_filter');
$this->executeView($view);
$this->assertIdenticalResultset($view, [
['title' => 'Original translation - pending revision'],
['title' => 'French translation - pending revision'],
], ['title' => 'title']);
}
}
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