diff --git a/src/WseWorkspaceAssociation.php b/src/WseWorkspaceAssociation.php index e667b70e1e72354b57dd8fca6de9a7890bc765ea..b119bf9871c69382d39ab685af0e15b85a2430c0 100644 --- a/src/WseWorkspaceAssociation.php +++ b/src/WseWorkspaceAssociation.php @@ -21,6 +21,26 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; */ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSubscriberInterface { + /** + * 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. + * + * @var array + */ + protected array $associatedRevisions = []; + + /** + * A multidimensional array of entity IDs that were created in 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. + * + * @var array + */ + protected array $associatedInitialRevisions = []; + public function __construct( protected WorkspaceAssociationInterface $innerWorkspaceAssociation, protected EntityTypeManagerInterface $entityTypeManager, @@ -33,6 +53,7 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub */ public function trackEntity(RevisionableInterface $entity, WorkspaceInterface $workspace) { $this->innerWorkspaceAssociation->trackEntity($entity, $workspace); + $this->associatedRevisions = $this->associatedInitialRevisions = []; } /** @@ -128,7 +149,7 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub // Get a list of default revisions tracked by the given workspace, because // they need to be handled differently than pending revisions. - $initial_revision_ids = $this->getAssociatedInitialRevisions($workspace->id(), $entity->getEntityTypeId()); + $initial_revision_ids = $this->getAssociatedInitialRevisions($workspace->id(), $entity->getEntityTypeId(), [$entity->id()]); foreach (array_keys($associated_revisions) as $revision_id) { // If the workspace is tracking the entity's default revision (i.e. the @@ -142,18 +163,6 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub $associated_entity_storage->deleteRevision($revision_id); } } - - // phpcs:disable Drupal.Commenting.InlineComment.SpacingBefore - // $affected_revisions = $associated_entity_storage->loadMultipleRevisions(array_keys($affected_revision_ids)); - // foreach ($affected_revisions as $revision) { - // if ($revision->isDefaultRevision()) { - // $revision->delete(); - // } - // else { - // $associated_entity_storage->deleteRevision($revision->getRevisionId()); - // } - // } - // phpcs:enable Drupal.Commenting.InlineComment.SpacingBefore } /** @@ -190,14 +199,74 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub * {@inheritdoc} */ public function getAssociatedRevisions($workspace_id, $entity_type_id, $entity_ids = NULL) { - return $this->innerWorkspaceAssociation->getAssociatedRevisions($workspace_id, $entity_type_id, $entity_ids); + if (isset($this->associatedRevisions[$workspace_id][$entity_type_id])) { + if ($entity_ids) { + return array_intersect($this->associatedRevisions[$workspace_id][$entity_type_id], $entity_ids); + } + else { + return $this->associatedRevisions[$workspace_id][$entity_type_id]; + } + } + + // WSE ensures that workspaces have unique IDs, so we can simplify core's + // way of retrieving the associated revisions. + $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); + $query = $this->entityTypeManager->getStorage($entity_type_id) + ->getQuery() + ->accessCheck(FALSE) + ->allRevisions() + ->condition($entity_type->get('revision_metadata_keys')['workspace'], $workspace_id, '=') + ->sort($entity_type->getKey('revision'), 'ASC'); + + if ($entity_ids) { + $query->condition($entity_type->getKey('id'), $entity_ids, 'IN'); + } + + $result = $query->execute(); + + // Cache the list of associated entity IDs if the full list was requested. + if (!$entity_ids) { + $this->associatedRevisions[$workspace_id][$entity_type_id] = $result; + } + + return $result; } /** * {@inheritdoc} */ public function getAssociatedInitialRevisions(string $workspace_id, string $entity_type_id, array $entity_ids = []) { - return $this->innerWorkspaceAssociation->getAssociatedInitialRevisions($workspace_id, $entity_type_id, $entity_ids); + if (isset($this->associatedInitialRevisions[$workspace_id][$entity_type_id])) { + if ($entity_ids) { + return array_intersect($this->associatedInitialRevisions[$workspace_id][$entity_type_id], $entity_ids); + } + else { + return $this->associatedInitialRevisions[$workspace_id][$entity_type_id]; + } + } + + // WSE ensures that workspaces have unique IDs, so we can simplify core's + // way of retrieving the associated initial (default) revisions. + $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); + $query = $this->entityTypeManager->getStorage($entity_type_id) + ->getQuery() + ->accessCheck(FALSE) + ->allRevisions() + ->condition($entity_type->get('revision_metadata_keys')['revision_default'], TRUE) + ->condition($entity_type->get('revision_metadata_keys')['workspace'], $workspace_id, '='); + + if ($entity_ids) { + $query->condition($entity_type->getKey('id'), $entity_ids, 'IN'); + } + + $result = $query->execute(); + + // Cache the list of associated entity IDs if the full list was requested. + if (!$entity_ids) { + $this->associatedInitialRevisions[$workspace_id][$entity_type_id] = $result; + } + + return $result; } /** @@ -219,6 +288,7 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub */ public function deleteAssociations($workspace_id = NULL, $entity_type_id = NULL, $entity_ids = NULL, $revision_ids = NULL) { $this->innerWorkspaceAssociation->deleteAssociations($workspace_id, $entity_type_id, $entity_ids); + $this->associatedRevisions = $this->associatedInitialRevisions = []; } /** @@ -226,6 +296,7 @@ class WseWorkspaceAssociation implements WorkspaceAssociationInterface, EventSub */ public function initializeWorkspace(WorkspaceInterface $workspace) { $this->innerWorkspaceAssociation->initializeWorkspace($workspace); + $this->associatedRevisions = $this->associatedInitialRevisions = []; } /**