Issue #3216107 by amateescu, adriancid, alexpott, Fabianx: Workspace association data is not updated when an entity is deleted

merge-requests/3240/head
catch 2023-01-13 09:49:25 +00:00
parent 231e771847
commit b13dae8bd0
4 changed files with 96 additions and 6 deletions

View File

@ -214,16 +214,31 @@ class WorkspaceAssociation implements WorkspaceAssociationInterface {
/**
* {@inheritdoc}
*/
public function deleteAssociations($workspace_id, $entity_type_id = NULL, $entity_ids = NULL) {
$query = $this->database->delete(static::TABLE)
->condition('workspace', $workspace_id);
public function deleteAssociations($workspace_id = NULL, $entity_type_id = NULL, $entity_ids = NULL, $revision_ids = NULL) {
if (!$workspace_id && !$entity_type_id) {
throw new \InvalidArgumentException('A workspace ID or an entity type ID must be provided.');
}
$query = $this->database->delete(static::TABLE);
if ($workspace_id) {
$query->condition('workspace', $workspace_id);
}
if ($entity_type_id) {
if (!$entity_ids && !$revision_ids) {
throw new \InvalidArgumentException('A list of entity IDs or revision IDs must be provided for an entity type.');
}
$query->condition('target_entity_type_id', $entity_type_id, '=');
if ($entity_ids) {
$query->condition('target_entity_id', $entity_ids, 'IN');
}
if ($revision_ids) {
$query->condition('target_entity_revision_id', $revision_ids, 'IN');
}
}
$query->execute();

View File

@ -97,16 +97,22 @@ interface WorkspaceAssociationInterface {
/**
* Deletes all the workspace association records for the given workspace.
*
* @param string $workspace_id
* A workspace entity ID.
* @param string|null $workspace_id
* (optional) A workspace entity ID. Defaults to NULL.
* @param string|null $entity_type_id
* (optional) The target entity type of the associations to delete. Defaults
* to NULL.
* @param int[]|string[]|null $entity_ids
* (optional) The target entity IDs of the associations to delete. Defaults
* to NULL.
* @param int[]|string[]|null $revision_ids
* (optional) The target entity revision IDs of the associations to delete.
* Defaults to NULL.
*
* @throws \InvalidArgumentException
* If neither $workspace_id nor $entity_type_id arguments were provided.
*/
public function deleteAssociations($workspace_id, $entity_type_id = NULL, $entity_ids = NULL);
public function deleteAssociations($workspace_id = NULL, $entity_type_id = NULL, $entity_ids = NULL, $revision_ids = NULL);
/**
* Initializes a workspace with all the associations of its parent.

View File

@ -367,6 +367,55 @@ class WorkspaceIntegrationTest extends KernelTestBase {
$this->assertEmpty($workspace_publisher->getDifferringRevisionIdsOnSource());
}
/**
* Tests the workspace association data integrity for entity CRUD operations.
*
* @covers ::workspaces_entity_presave
* @covers ::workspaces_entity_insert
* @covers ::workspaces_entity_delete
* @covers ::workspaces_entity_revision_delete
*/
public function testWorkspaceAssociationDataIntegrity() {
$this->initializeWorkspacesModule();
// Check the initial empty state.
$expected_workspace_association = ['stage' => []];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
// Add a new unpublished node in 'stage' and check that new revision is
// tracked in the workspace association data.
$this->switchToWorkspace('stage');
$unpublished_node = $this->createNode(['title' => 'stage - 3 - r3 - unpublished', 'created' => $this->createdTimestamp++, 'status' => FALSE]);
$expected_workspace_association = ['stage' => [3]];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
// Add a new revision for the unpublished node.
$unpublished_node->title = 'stage - 3 - r4 - unpublished';
$unpublished_node->save();
$expected_workspace_association = ['stage' => [4]];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
// Delete the unpublished node and check that the association data has been
// updated.
$unpublished_node->delete();
$expected_workspace_association = ['stage' => []];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
// Add a new published node in 'stage' and check that new workspace-specific
// revision is tracked in the workspace association data. Note that revision
// '5' has been created as an unpublished default revision in Live, so it is
// not tracked.
$this->createNode(['title' => 'stage - 4 - r6 - published', 'created' => $this->createdTimestamp++, 'status' => TRUE]);
$expected_workspace_association = ['stage' => [6]];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
// Delete revision '6' and check that the workspace association does not
// track it anymore.
$this->entityTypeManager->getStorage('node')->deleteRevision(6);
$expected_workspace_association = ['stage' => []];
$this->assertWorkspaceAssociation($expected_workspace_association, 'node');
}
/**
* Tests entity tracking in workspace descendants.
*/

View File

@ -143,6 +143,26 @@ function workspaces_entity_predelete(EntityInterface $entity) {
->entityPredelete($entity);
}
/**
* Implements hook_entity_delete().
*/
function workspaces_entity_delete(EntityInterface $entity) {
if (\Drupal::service('workspaces.manager')->isEntityTypeSupported($entity->getEntityType())) {
\Drupal::service('workspaces.association')
->deleteAssociations(NULL, $entity->getEntityTypeId(), [$entity->id()]);
}
}
/**
* Implements hook_entity_revision_delete().
*/
function workspaces_entity_revision_delete(EntityInterface $entity) {
if (\Drupal::service('workspaces.manager')->isEntityTypeSupported($entity->getEntityType())) {
\Drupal::service('workspaces.association')
->deleteAssociations(NULL, $entity->getEntityTypeId(), [$entity->id()], [$entity->getRevisionId()]);
}
}
/**
* Implements hook_entity_access().
*