From fdac75b8b05f3b9dcc60d0b72ab5b038fcd7e7a8 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Tue, 30 Apr 2024 12:35:53 +0100 Subject: [PATCH] Issue #3273461 by amateescu, smustgrave, alexpott: Add pagination to the workspace manage page (cherry picked from commit f7950eb418e016a7ff172aeee72f33015fc10fd2) --- .../workspaces/src/WorkspaceAssociation.php | 28 ++++++++++++++++++- .../src/WorkspaceAssociationInterface.php | 18 ++++++++++++ .../workspaces/src/WorkspaceViewBuilder.php | 25 ++++++++++++----- .../tests/src/Functional/WorkspaceTest.php | 17 +++++++++++ 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/core/modules/workspaces/src/WorkspaceAssociation.php b/core/modules/workspaces/src/WorkspaceAssociation.php index 1ccab7ebb7d..426314ac433 100644 --- a/core/modules/workspaces/src/WorkspaceAssociation.php +++ b/core/modules/workspaces/src/WorkspaceAssociation.php @@ -3,6 +3,7 @@ namespace Drupal\workspaces; use Drupal\Core\Database\Connection; +use Drupal\Core\Database\Query\PagerSelectExtender; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\RevisionableInterface; use Drupal\Core\Entity\Sql\SqlContentEntityStorage; @@ -47,7 +48,7 @@ class WorkspaceAssociation implements WorkspaceAssociationInterface, EventSubscr * A multidimensional array of entity IDs that are associated to a workspace. * * The first level keys are workspace IDs, the second level keys are entity - * * type IDs, and the third level array are entity IDs, keyed by revision IDs. + * type IDs, and the third level array are entity IDs, keyed by revision IDs. * * @var array */ @@ -188,6 +189,31 @@ class WorkspaceAssociation implements WorkspaceAssociationInterface, EventSubscr return $tracked_revisions; } + /** + * {@inheritdoc} + */ + public function getTrackedEntitiesForListing($workspace_id, int $pager_id = NULL, int|false $limit = 50): array { + $query = $this->database->select(static::TABLE) + ->extend(PagerSelectExtender::class) + ->limit($limit); + if ($pager_id) { + $query->element($pager_id); + } + + $query + ->fields(static::TABLE, ['target_entity_type_id', 'target_entity_id', 'target_entity_revision_id']) + ->orderBy('target_entity_type_id', 'ASC') + ->orderBy('target_entity_revision_id', 'DESC') + ->condition('workspace', $workspace_id); + + $tracked_revisions = []; + foreach ($query->execute() as $record) { + $tracked_revisions[$record->target_entity_type_id][$record->target_entity_revision_id] = $record->target_entity_id; + } + + return $tracked_revisions; + } + /** * {@inheritdoc} */ diff --git a/core/modules/workspaces/src/WorkspaceAssociationInterface.php b/core/modules/workspaces/src/WorkspaceAssociationInterface.php index b6f4faacc3b..a8b9216f577 100644 --- a/core/modules/workspaces/src/WorkspaceAssociationInterface.php +++ b/core/modules/workspaces/src/WorkspaceAssociationInterface.php @@ -53,6 +53,24 @@ interface WorkspaceAssociationInterface { */ public function getTrackedEntities($workspace_id, $entity_type_id = NULL, $entity_ids = NULL); + /** + * Retrieves a paged list of entities tracked by a given workspace. + * + * @param string $workspace_id + * The ID of the workspace. + * @param int|null $pager_id + * (optional) A pager ID. Defaults to NULL. + * @param int|false $limit + * (optional) An integer specifying the number of elements per page. If + * passed a false value (FALSE, 0, NULL), the pager is disabled. Defaults to + * 50. + * + * @return array + * Returns a multidimensional array where the first level keys are entity + * type IDs and the values are an array of entity IDs keyed by revision IDs. + */ + public function getTrackedEntitiesForListing($workspace_id, int $pager_id = NULL, int|false $limit = 50): array; + /** * Retrieves all content revisions tracked by a given workspace. * diff --git a/core/modules/workspaces/src/WorkspaceViewBuilder.php b/core/modules/workspaces/src/WorkspaceViewBuilder.php index 9f329ba7d37..50ecd8ea5a7 100644 --- a/core/modules/workspaces/src/WorkspaceViewBuilder.php +++ b/core/modules/workspaces/src/WorkspaceViewBuilder.php @@ -42,6 +42,11 @@ class WorkspaceViewBuilder extends EntityViewBuilder { */ protected $bundleInfo; + /** + * The number of entities to display on the workspace manage page. + */ + protected int|false $limit = 50; + /** * {@inheritdoc} */ @@ -69,7 +74,13 @@ class WorkspaceViewBuilder extends EntityViewBuilder { 'operations' => $this->t('Operations'), ]; foreach ($entities as $build_id => $entity) { + // Display the number of entities changed in the workspace regardless of + // how many of them are listed on each page. + $changes_count = []; $all_tracked_entities = $this->workspaceAssociation->getTrackedEntities($entity->id()); + foreach ($all_tracked_entities as $entity_type_id => $tracked_entity_ids) { + $changes_count[$entity_type_id] = $this->entityTypeManager->getDefinition($entity_type_id)->getCountLabel(count($tracked_entity_ids)); + } $build[$build_id]['changes']['overview'] = [ '#type' => 'item', @@ -82,13 +93,8 @@ class WorkspaceViewBuilder extends EntityViewBuilder { '#empty' => $this->t('This workspace has no changes.'), ]; - $changes_count = []; - foreach ($all_tracked_entities as $entity_type_id => $tracked_entities) { - // Ensure that newest revisions are displayed at the top. - krsort($tracked_entities); - - $changes_count[$entity_type_id] = $this->entityTypeManager->getDefinition($entity_type_id)->getCountLabel(count($tracked_entities)); - + $paged_tracked_entities = $this->workspaceAssociation->getTrackedEntitiesForListing($entity->id(), $build_id, $this->limit); + foreach ($paged_tracked_entities as $entity_type_id => $tracked_entities) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); if ($this->entityTypeManager->hasHandler($entity_type_id, 'list_builder')) { $list_builder = $this->entityTypeManager->getListBuilder($entity_type_id); @@ -166,6 +172,11 @@ class WorkspaceViewBuilder extends EntityViewBuilder { if ($changes_count) { $build[$build_id]['changes']['overview']['#markup'] = implode(', ', $changes_count); } + + $build[$build_id]['pager'] = [ + '#type' => 'pager', + '#element' => $build_id, + ]; } } diff --git a/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php b/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php index a4c492c6f72..9a25f492677 100644 --- a/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php +++ b/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php @@ -215,6 +215,23 @@ class WorkspaceTest extends BrowserTestBase { $assert_session->linkExists('Node 1'); $assert_session->linkExists('Node 2'); $assert_session->linkExists('Term 1'); + + // Create 50 more nodes to test the pagination. + for ($i = 3; $i < 53; $i++) { + $this->createNodeThroughUi('Node ' . $i, 'test'); + } + + $this->drupalGet($test_1->toUrl()->toString()); + $assert_session->pageTextContains('52 content items'); + $assert_session->pageTextContains('1 taxonomy term'); + $assert_session->linkExists('Node 52'); + $assert_session->linkExists('Node 3'); + $assert_session->linkNotExists('Term 1'); + + $this->drupalGet($test_1->toUrl()->toString(), ['query' => ['page' => '1']]); + $assert_session->linkExists('Node 1'); + $assert_session->linkExists('Node 2'); + $assert_session->linkExists('Term 1'); } /**