Unverified Commit 9d47e1d6 authored by larowlan's avatar larowlan Committed by alexpott

Issue #2968452 by amateescu, timmillwood, jeqq, alexpott, Fabianx: Add a way...

Issue #2968452 by amateescu, timmillwood, jeqq, alexpott, Fabianx: Add a way to execute a function in the context of a specific workspace

(cherry picked from commit bc3348bb)
parent faa28e8e
......@@ -167,6 +167,31 @@ public function getActiveWorkspace() {
* {@inheritdoc}
*/
public function setActiveWorkspace(WorkspaceInterface $workspace) {
$this->doSwitchWorkspace($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;
}
}
return $this;
}
/**
* Switches the current workspace.
*
* @param \Drupal\workspaces\WorkspaceInterface $workspace
* The workspace to set as active.
*
* @throws \Drupal\workspaces\WorkspaceAccessException
* Thrown when the current user doesn't have access to view the workspace.
*/
protected function doSwitchWorkspace(WorkspaceInterface $workspace) {
// 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()) {
......@@ -179,22 +204,29 @@ 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;
}
}
$supported_entity_types = $this->getSupportedEntityTypes();
foreach ($supported_entity_types as $supported_entity_type) {
$this->entityTypeManager->getStorage($supported_entity_type->id())->resetCache();
}
}
return $this;
/**
* {@inheritdoc}
*/
public function executeInWorkspace($workspace_id, callable $function) {
/** @var \Drupal\workspaces\WorkspaceInterface $workspace */
$workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id);
if (!$workspace) {
throw new \InvalidArgumentException('The ' . $workspace_id . ' workspace does not exist.');
}
$previous_active_workspace = $this->getActiveWorkspace();
$this->doSwitchWorkspace($workspace);
$result = $function();
$this->doSwitchWorkspace($previous_active_workspace);
return $result;
}
/**
......
......@@ -49,6 +49,19 @@ public function getActiveWorkspace();
*/
public function setActiveWorkspace(WorkspaceInterface $workspace);
/**
* Executes the given callback function in the context of a workspace.
*
* @param string $workspace_id
* The ID of a workspace.
* @param callable $function
* The callback to be executed.
*
* @return mixed
* The callable's return value.
*/
public function executeInWorkspace($workspace_id, callable $function);
/**
* Determines whether runtime entity operations should be altered.
*
......
......@@ -36,6 +36,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.
*
......@@ -102,6 +109,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');
......@@ -492,6 +500,57 @@ public function testDisallowedEntityCRUDInNonDefaultWorkspace() {
$entity_test->delete();
}
/**
* @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([$live_node->getRevisionId() => $node->id()], $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([$stage_node->getRevisionId() => $stage_node->id()], $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.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment