Unverified Commit 4d6098cd authored by Alex Pott's avatar Alex Pott
Browse files

fix: #2722307 Move translation based conditions into database query on revisions overview page

By: mkalkbrenner
By: catch
By: berdir
By: yoroy
By: acbramley
By: smustgrave
By: liam morland
By: quietone
By: alexpott
(cherry picked from commit aab88182)
parent 990c5fe0
Loading
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -210,25 +210,29 @@ protected function loadRevisions(RevisionableInterface $entity) {
    $entityStorage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
    assert($entityStorage instanceof RevisionableStorageInterface);

    $result = $entityStorage->getQuery()
    $query = $entityStorage->getQuery()
      ->accessCheck(FALSE)
      ->allRevisions()
      ->condition($entityType->getKey('id'), $entity->id())
      ->sort($entityType->getKey('revision'), 'DESC')
      ->pager(self::REVISIONS_PER_PAGE)
      ->execute();
      ->pager(self::REVISIONS_PER_PAGE);

    // Only show revisions that are affected by the language that is being
    // displayed.
    if ($translatable) {
      $query->condition($entityType->getKey('langcode'), $entity->language()->getId())
        ->condition($entityType->getKey('revision_translation_affected'), '1');
    }

    $result = $query->execute();

    $currentLangcode = $this->languageManager
      ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
      ->getId();
    foreach ($entityStorage->loadMultipleRevisions(array_keys($result)) as $revision) {
      // Only show revisions that are affected by the language that is being
      // displayed.
      if (!$translatable || ($revision->hasTranslation($currentLangcode) && $revision->getTranslation($currentLangcode)->isRevisionTranslationAffected())) {
      yield ($translatable ? $revision->getTranslation($currentLangcode) : $revision);
    }
  }
  }

  /**
   * Generates an overview table of revisions of an entity.
+86 −85
Original line number Diff line number Diff line
@@ -148,9 +148,6 @@ public function revisionOverview(NodeInterface $node) {
    foreach ($this->getRevisionIds($node, $node_storage) as $vid) {
      /** @var \Drupal\node\NodeInterface $revision */
      $revision = $node_storage->loadRevision($vid);
      // Only show revisions that are affected by the language that is being
      // displayed.
      if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
      $username = [
        '#theme' => 'username',
        '#account' => $revision->getRevisionUser(),
@@ -164,16 +161,16 @@ public function revisionOverview(NodeInterface $node) {
      // current language will be the same of the current default revision in
      // this case.
      $is_current_revision = $revision->isDefaultRevision() || (!$current_revision_displayed && $revision->wasDefaultRevision());
        if (!$is_current_revision) {
      if ($is_current_revision) {
        $link = $node->toLink($date)->toString();
        $current_revision_displayed = TRUE;
      }
      else {
        $link = Link::fromTextAndUrl($date, new Url('entity.node.revision', [
          'node' => $node->id(),
          'node_revision' => $vid,
        ]))->toString();
      }
        else {
          $link = $node->toLink($date)->toString();
          $current_revision_displayed = TRUE;
        }

      $row = [];
      $column = [
@@ -242,7 +239,6 @@ public function revisionOverview(NodeInterface $node) {
        $rows[] = $row;
      }
    }
    }

    $build['node_revisions_table'] = [
      '#theme' => 'table',
@@ -275,6 +271,8 @@ public function addPageTitle(NodeTypeInterface $node_type) {
  /**
   * Gets a list of node revision IDs for a specific node.
   *
   * Only returns revisions that are affected by the $node language.
   *
   * @param \Drupal\node\NodeInterface $node
   *   The node entity.
   * @param \Drupal\node\NodeStorageInterface $node_storage
@@ -284,11 +282,14 @@ public function addPageTitle(NodeTypeInterface $node_type) {
   *   Node revision IDs (in descending order).
   */
  protected function getRevisionIds(NodeInterface $node, NodeStorageInterface $node_storage) {
    $entityType = $node->getEntityType();
    $result = $node_storage->getQuery()
      ->accessCheck(TRUE)
      ->allRevisions()
      ->condition($node->getEntityType()->getKey('id'), $node->id())
      ->sort($node->getEntityType()->getKey('revision'), 'DESC')
      ->condition($entityType->getKey('langcode'), $node->language()->getId())
      ->condition($entityType->getKey('revision_translation_affected'), '1')
      ->condition($entityType->getKey('id'), $node->id())
      ->sort($entityType->getKey('revision'), 'DESC')
      ->pager(50)
      ->execute();
    return array_keys($result);
+50 −6
Original line number Diff line number Diff line
@@ -144,36 +144,31 @@ public function testNodeRevisionsTabWithDefaultRevision(): void {

    // Create the node.
    $node = $this->drupalCreateNode();
    $storage = \Drupal::entityTypeManager()->getStorage($node->getEntityTypeId());

    // Create a new revision based on the default revision.
    // Revision 2.
    $node = $storage->load($node->id());
    $node->setNewRevision(TRUE);
    $node->save();

    // Revision 3.
    $node = $storage->load($node->id());
    $node->setNewRevision(TRUE);
    $node->save();

    // Revision 4.
    // Trigger translation changes in order to show the revision.
    $node = $storage->load($node->id());
    $node->setTitle($this->randomString());
    $node->isDefaultRevision(FALSE);
    $node->setNewRevision(TRUE);
    $node->save();

    // Revision 5.
    $node = $storage->load($node->id());
    $node->isDefaultRevision(FALSE);
    $node->setNewRevision(TRUE);
    $node->save();

    $node_id = $node->id();

    $this->drupalGet('node/' . $node_id . '/revisions');
    $this->drupalGet($node->toUrl('version-history'));

    // Verify that the latest affected revision having been a default revision
    // is displayed as the current one.
@@ -194,6 +189,55 @@ public function testNodeRevisionsTabWithDefaultRevision(): void {
    $this->assertSession()->linkByHrefNotExists('/node/' . $node_id . '/revisions/5/revert');
  }

  /**
   * Tests the revision tab paginates correctly with affected translations.
   */
  public function testNodeRevisionsTabPagerAffectedTranslations(): void {
    $this->drupalLogin($this->editor);

    $node = $this->drupalCreateNode();

    // Create 49 revisions with translation changes so there are a total of 50
    // including the initial revision.
    for ($i = 1; $i < 50; $i++) {
      $node->setTitle($this->randomString())
        ->setRevisionLogMessage('translation change ' . $i);
      $node->isDefaultRevision(FALSE);
      $node->setNewRevision(TRUE);
      $node->save();
    }
    // Create 50 revisions without translation changes.
    for ($i = 0; $i < 50; $i++) {
      $node->isDefaultRevision(FALSE);
      $node->setNewRevision(TRUE);
      $node->save();
    }

    // There should be the initial 50 revisions and no pager as the
    // non-affecting revisions are filtered out before pagination.
    $this->drupalGet($node->toUrl('version-history'));
    $assert = $this->assertSession();
    $assert->pageTextContains('translation change 49');
    $assert->elementsCount('css', '.node-revision-table tbody tr', 50);
    $assert->elementNotExists('css', '.pager');

    // Create another translation affecting revision.
    $node->setTitle($this->randomString())
      ->setRevisionLogMessage('translation change 50');
    $node->isDefaultRevision(FALSE);
    $node->setNewRevision(TRUE);
    $node->save();

    // There should now be a pager, and the current revision should be on the
    // second page.
    $this->drupalGet($node->toUrl('version-history'));
    $assert->elementExists('css', '.pager');
    $assert->elementNotExists('css', '.revision-current');
    $this->clickLink('Page 2');
    $assert->elementsCount('css', '.node-revision-table tbody tr', 1);
    $assert->elementExists('css', '.revision-current');
  }

  /**
   * Checks the Revisions tab.
   *
+8 −1
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

use Drupal\Core\Entity\Attribute\ContentEntityType;
use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider;
use Drupal\Core\Entity\Routing\RevisionHtmlRouteProvider;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
@@ -37,7 +38,10 @@
      'delete' => EntityTestDeleteForm::class,
    ],
    'views_data' => EntityViewsData::class,
    'route_provider' => ['html' => DefaultHtmlRouteProvider::class],
    'route_provider' => [
      'html' => DefaultHtmlRouteProvider::class,
      'revision' => RevisionHtmlRouteProvider::class,
    ],
  ],
  links: [
    'add-form' => '/entity_test_mulrev/add/{type}',
@@ -46,6 +50,9 @@
    'delete-form' => '/entity_test/delete/entity_test_mulrev/{entity_test_mulrev}',
    'edit-form' => '/entity_test_mulrev/manage/{entity_test_mulrev}/edit',
    'revision' => '/entity_test_mulrev/{entity_test_mulrev}/revision/{entity_test_mulrev_revision}/view',
    'revision-delete-form' => '/entity_test_mulrev/{entity_test_mulrev}/revision/{entity_test_mulrev_revision}/delete',
    'revision-revert-form' => '/entity_test_mulrev/{entity_test_mulrev}/revision/{entity_test_mulrev_revision}/revert',
    'version-history' => '/entity_test_mulrev/{entity_test_mulrev}/revisions',
  ],
  admin_permission: 'administer entity_test content',
  base_table: 'entity_test_mulrev',
+11 −3
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
namespace Drupal\FunctionalTests\Entity;

use Drupal\Core\Entity\Controller\VersionHistoryController;
use Drupal\entity_test\Entity\EntityTestMulRev;
use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\entity_test_revlog\Entity\EntityTestWithRevisionLog;
use Drupal\Tests\BrowserTestBase;
@@ -316,9 +317,9 @@ public function testOperationDeleteRevision(): void {
   * Test revisions are paginated.
   */
  public function testRevisionsPagination(): void {
    /** @var \Drupal\entity_test\Entity\EntityTestRev $entity */
    $entity = EntityTestRev::create([
      'type' => 'entity_test_rev',
    /** @var \Drupal\entity_test\Entity\EntityTestMulRev $entity */
    $entity = EntityTestMulRev::create([
      'type' => 'entity_test_mulrev',
      'name' => 'view all revisions,view revision',
    ]);
    $entity->save();
@@ -333,6 +334,13 @@ public function testRevisionsPagination(): void {
      $entity->setName('view all revisions,view revision,' . $i)->save();
    }

    // Create revisions without translation changes to ensure these do not
    // affect pagination.
    for ($i = 0; $i < VersionHistoryController::REVISIONS_PER_PAGE; $i++) {
      $entity->setNewRevision(TRUE);
      $entity->save();
    }

    $this->drupalGet($entity->toUrl('version-history'));
    $this->assertSession()->elementsCount('css', 'table tbody tr', VersionHistoryController::REVISIONS_PER_PAGE);
    $this->assertSession()->elementExists('css', '.pager');