diff --git a/core/modules/workspaces/src/WorkspaceManager.php b/core/modules/workspaces/src/WorkspaceManager.php index 4ec554c..fb609f1 100644 --- a/core/modules/workspaces/src/WorkspaceManager.php +++ b/core/modules/workspaces/src/WorkspaceManager.php @@ -166,7 +166,7 @@ public function getActiveWorkspace() { /** * {@inheritdoc} */ - public function setActiveWorkspace(WorkspaceInterface $workspace) { + public function setActiveWorkspace(WorkspaceInterface $workspace, $persist = TRUE) { // If the current user doesn't have access to view the workspace, they // shouldn't be allowed to switch to it. if (!$workspace->access('view') && !$workspace->isDefaultWorkspace()) { @@ -180,12 +180,14 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) { $this->activeWorkspace = $workspace; // Set the workspace on the proper negotiator. - $request = $this->requestStack->getCurrentRequest(); - foreach ($this->negotiatorIds as $negotiator_id) { - $negotiator = $this->classResolver->getInstanceFromDefinition($negotiator_id); - if ($negotiator->applies($request)) { - $negotiator->setActiveWorkspace($workspace); - break; + if ($persist) { + $request = $this->requestStack->getCurrentRequest(); + foreach ($this->negotiatorIds as $negotiator_id) { + $negotiator = $this->classResolver->getInstanceFromDefinition($negotiator_id); + if ($negotiator->applies($request)) { + $negotiator->setActiveWorkspace($workspace); + break; + } } } @@ -201,17 +203,17 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) { * {@inheritdoc} */ public function executeInWorkspace($workspace_id, callable $function) { - /** @var \Drupal\workspace\WorkspaceInterface $workspace */ + /** @var \Drupal\workspaces\WorkspaceInterface $workspace */ $workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id); - if (!$workspace || (!$workspace->isDefaultWorkspace() && !$workspace->access('view'))) { - throw new WorkspaceAccessException('The user does not have permission to view that workspace.'); + if (!$workspace) { + throw new \InvalidArgumentException('The ' . $workspace_id . ' workspace does not exist.'); } - $previous_active_workspace = $this->activeWorkspace; - $this->activeWorkspace = $workspace; + $previous_active_workspace = $this->getActiveWorkspace(); + $this->setActiveWorkspace($workspace, FALSE); $function(); - $this->activeWorkspace = $previous_active_workspace; + $this->setActiveWorkspace($previous_active_workspace, FALSE); return $this; } diff --git a/core/modules/workspaces/src/WorkspaceManagerInterface.php b/core/modules/workspaces/src/WorkspaceManagerInterface.php index 5ef9fbf..7cc3494 100644 --- a/core/modules/workspaces/src/WorkspaceManagerInterface.php +++ b/core/modules/workspaces/src/WorkspaceManagerInterface.php @@ -41,13 +41,16 @@ public function getActiveWorkspace(); * * @param \Drupal\workspaces\WorkspaceInterface $workspace * The workspace to set as active. + * @param bool $persist + * (optional) Whether the new active workspace should be persisted by the + * workspace negotiator. Defaults to TRUE. * * @return $this * * @throws \Drupal\workspaces\WorkspaceAccessException * Thrown when the current user doesn't have access to view the workspace. */ - public function setActiveWorkspace(WorkspaceInterface $workspace); + public function setActiveWorkspace(WorkspaceInterface $workspace, $persist = TRUE); /** * Executes the given callback function in the context of a workspace. diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php index 7854402..d61d378 100644 --- a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php +++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php @@ -35,6 +35,13 @@ class WorkspaceIntegrationTest extends KernelTestBase { protected $entityTypeManager; /** + * The workspaces manager. + * + * @var \Drupal\workspaces\WorkspaceManagerInterface + */ + protected $workspacesManager; + + /** * An array of test workspaces, keyed by workspace ID. * * @var \Drupal\workspaces\WorkspaceInterface[] @@ -100,6 +107,7 @@ protected function initializeWorkspacesModule() { $this->enableModules(['workspaces']); $this->container = \Drupal::getContainer(); $this->entityTypeManager = \Drupal::entityTypeManager(); + $this->workspacesManager = \Drupal::service('workspaces.manager'); $this->installEntitySchema('workspace'); $this->installEntitySchema('workspace_association'); @@ -491,6 +499,57 @@ public function testDisallowedEntityCRUDInNonDefaultWorkspace() { } /** + * @covers \Drupal\workspaces\WorkspaceManager::executeInWorkspace + */ + public function testExecuteInWorkspaceContext() { + $this->initializeWorkspacesModule(); + + // Create an entity in the default workspace. + $this->switchToWorkspace('live'); + $node = $this->createNode([ + 'title' => 'live node 1', + ]); + $node->save(); + + // Switch to the 'stage' workspace and change some values for the referenced + // entities. + $this->switchToWorkspace('stage'); + $node->title->value = 'stage node 1'; + $node->save(); + + // Switch back to the default workspace and run the baseline assertions. + $this->switchToWorkspace('live'); + $storage = $this->entityTypeManager->getStorage('node'); + + $this->assertEquals('live', $this->workspacesManager->getActiveWorkspace()->id()); + + $live_node = $storage->loadUnchanged($node->id()); + $this->assertEquals('live node 1', $live_node->title->value); + + $result = $storage->getQuery() + ->condition('title', 'live node 1') + ->execute(); + $this->assertEquals([3 => 3], $result); + + // Try the same assertions in the context of the 'stage' workspace. + $this->workspacesManager->executeInWorkspace('stage', function () use ($node, $storage) { + $this->assertEquals('stage', $this->workspacesManager->getActiveWorkspace()->id()); + + $stage_node = $storage->loadUnchanged($node->id()); + $this->assertEquals('stage node 1', $stage_node->title->value); + + $result = $storage->getQuery() + ->condition('title', 'stage node 1') + ->execute(); + $this->assertEquals([4 => 3], $result); + }); + + // Check that the 'stage' workspace was not persisted by the workspace + // manager. + $this->assertEquals('live', $this->workspacesManager->getActiveWorkspace()->id()); + } + + /** * Checks entity load, entity queries and views results for a test scenario. * * @param array $expected