summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Rowlands2018-11-08 09:29:47 (GMT)
committerAlex Pott2018-11-13 16:17:06 (GMT)
commit9d47e1d656fdc9edd881ea0f4d19795fa468aa9a (patch)
treead58b563dba847a08aa629b232fa0a972e4ae47d
parentfaa28e8e08415c4904202c71d97c087530d511b0 (diff)
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 bc3348bb455c48f6b9db305be37a960e2b1011b1)
-rw-r--r--core/modules/workspaces/src/WorkspaceManager.php54
-rw-r--r--core/modules/workspaces/src/WorkspaceManagerInterface.php13
-rw-r--r--core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php59
3 files changed, 115 insertions, 11 deletions
diff --git a/core/modules/workspaces/src/WorkspaceManager.php b/core/modules/workspaces/src/WorkspaceManager.php
index faa5f8f..0fe39f5 100644
--- a/core/modules/workspaces/src/WorkspaceManager.php
+++ b/core/modules/workspaces/src/WorkspaceManager.php
@@ -167,6 +167,31 @@ class WorkspaceManager implements WorkspaceManagerInterface {
* {@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 @@ class WorkspaceManager implements WorkspaceManagerInterface {
$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;
}
/**
diff --git a/core/modules/workspaces/src/WorkspaceManagerInterface.php b/core/modules/workspaces/src/WorkspaceManagerInterface.php
index 9ce720b..006a2bd 100644
--- a/core/modules/workspaces/src/WorkspaceManagerInterface.php
+++ b/core/modules/workspaces/src/WorkspaceManagerInterface.php
@@ -50,6 +50,19 @@ interface WorkspaceManagerInterface {
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.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
index 9d77cdf..f4f76e6 100644
--- a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
@@ -37,6 +37,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[]
@@ -102,6 +109,7 @@ class WorkspaceIntegrationTest extends KernelTestBase {
$this->enableModules(['workspaces']);
$this->container = \Drupal::getContainer();
$this->entityTypeManager = \Drupal::entityTypeManager();
+ $this->workspacesManager = \Drupal::service('workspaces.manager');
$this->installEntitySchema('workspace');
$this->installEntitySchema('workspace_association');
@@ -493,6 +501,57 @@ class WorkspaceIntegrationTest extends KernelTestBase {
}
/**
+ * @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.
*
* @param array $expected