Problem/Motivation

This was proposed by @FabianX in #2784921-151: Add Workspaces experimental module.10:

+++ b/core/modules/workspace/src/Plugin/RepositoryHandler/LiveRepositoryHandler.php
@@ -0,0 +1,196 @@
+      // Get the latest revision IDs for all the entities that are tracked by
+      // the source workspace.
+      $query = $this->entityTypeManager
+        ->getStorage($entity_type_id)
+        ->getQuery()
+        ->condition($entity_type->getKey('id'), $tracked_revisions, 'IN')
+        ->latestRevision();

While this current is not a problem, if we ever wanted to also act on latestRevision() (I get that comment now), we should explicitly specify to override the currently active workspace, so that we compare with whatever workspace we want to compare against (currently default / live):

e.g.

In cps we have:

cps_override_changeset('published');

// ...

cps_override_changeset(NULL);

---

For better code flow I would suggest to use a closure:

$this->workspaceManager->executeInWorkspace(::DEFAULT_WORKSPACE, function() {
  // Do queries and entity operations against the live site.
});

We tried to avoid that in CPS at first, but it ended up to be necessary and useful.

Proposed resolution

Add a executeInWorkspace() method to the workspace manager which receives two arguments, a workspace ID and a closure.

Remaining tasks

TBD.

User interface changes

Nope.

API changes

Nope.

Data model changes

Nope.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

amateescu created an issue. See original summary.

amateescu’s picture

Project: Workspace » Drupal core
Version: 8.x-2.x-dev » 8.6.x-dev
Component: Code » workspace.module
amateescu’s picture

Title: Consider adding a way to quickly change workspaces » Add a way to quickly execute a function in the context of a specific workspace
Status: Active » Needs review
FileSize
2.08 KB

@FabianX, is this what you had in mind?

timmillwood’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
+++ b/core/modules/workspace/src/WorkspaceManager.php
@@ -200,6 +200,25 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) {
+    $previous_active_workspace = $this->activeWorkspace;
+    $this->activeWorkspace = $workspace;
...
+    $this->activeWorkspace = $previous_active_workspace;

I think this should use the getActiveWorkspace() and setActiveWorkspace() methods, then we can remove the duplicate access check too.

amateescu’s picture

I did not use those methods on purpose because they're doing quite some additional work. For example, WorkspaceManager::setActiveWorkspace() also calls setActiveWorkspace() on the negotiators in order to persist that workspace, and we don't really want do to that.

timmillwood’s picture

Wouldn't we want it to persist until we switch it back :)

Fabianx’s picture

Yes, that is what I had in mind:

We absolutely need to use something like setActiveWorkspace though, because we for example need to clear the (in-memory) entity cache before switching.

See:

cps_override_changeset()

I however don't think we should inform negotiators of a changed workspace - as that really should not persist - even if the operation inside errors out (unexpected to the user).

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

amateescu’s picture

Component: workspace.module » workspaces.module

Fix component following module rename.

amateescu’s picture

Title: Add a way to quickly execute a function in the context of a specific workspace » Add a way to execute a function in the context of a specific workspace
Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
6.9 KB
6.76 KB

Added a way to not persist the workspace in setActiveWorkspace() and test coverage. We should good to go here :)

jeqq’s picture

Status: Needs review » Needs work
+++ b/core/modules/workspaces/src/WorkspaceManager.php
@@ -200,6 +202,25 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) {
+    return $this;

Shouldn't it return here what $function() returns?

amateescu’s picture

Status: Needs work » Needs review
FileSize
6.95 KB
1.23 KB

Very good point! Let's do that.

jeqq’s picture

Status: Needs review » Reviewed & tested by the community

Looks good.

The last submitted patch, 3: 2968452.patch, failed testing. View results

Sam152’s picture

This would have been a neat area that #2982949: Introduce CallableResolver to help standardise the DX and error handling for callbacks across various subsystems could have helped provide some utility. Vanilla callables need bridges to container injected classes to be unit testable. That's stalled for now though, so this issue is fine as it is.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
@@ -491,6 +499,57 @@ public function testDisallowedEntityCRUDInNonDefaultWorkspace() {
+    $this->assertEquals([3 => 3], $result);

can we use $(live|stage)_node->(revisionId|id)() here to avoid fragility in the test and make it explicit what these integers represent?

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
7.02 KB
1.17 KB

Sure thing! Moving back to RTBC because it's a very simple change :)

alexpott’s picture

+++ b/core/modules/workspaces/src/WorkspaceManager.php
@@ -166,7 +166,7 @@ public function getActiveWorkspace() {
-  public function setActiveWorkspace(WorkspaceInterface $workspace) {
+  public function setActiveWorkspace(WorkspaceInterface $workspace, $persist = TRUE) {

Are we sure that we want to expose the persist option as API? I think that might lead to errors.

amateescu’s picture

I don't see why not, it could be actually useful IMO. A theoretical use case could be a custom workspace negotiator or link used in an email that only allows a user to see a single page in the context of a given workspace, without persisting it if the user navigates away from that page.

Sam152’s picture

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/workspaces/src/WorkspaceManager.php
@@ -200,6 +202,25 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) {
+    $this->setActiveWorkspace($workspace, FALSE);
...
+    $this->setActiveWorkspace($previous_active_workspace, FALSE);

I'm with alexpott on this. Let's not make persist part of the public API until we have a need for it.

We can make the elements of setActiveWorkspace that do the switching (but not the persisting) a separate protected function (such as doSwitchWorkspace) and then call that from executeInWorkspace, that way we keep the surface smaller

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
6.88 KB
3.75 KB

Okay :)

larowlan’s picture

Status: Reviewed & tested by the community » Fixed

Committed bc3348b and pushed to 8.7.x. Thanks!

  • larowlan committed bc3348b on 8.7.x
    Issue #2968452 by amateescu, timmillwood, jeqq, alexpott, Fabianx: Add a...
amateescu’s picture

Version: 8.7.x-dev » 8.6.x-dev
Status: Fixed » Reviewed & tested by the community

Since Workspaces is experimental, I think this can be backported to 8.6.x, even more since it blocks a bug fix. #2998414: Workspaces fails to deploy content in fields that required dedicated table storage

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Yeah as an experimental module we should backport this.

  • alexpott committed 9d47e1d on 8.6.x authored by larowlan
    Issue #2968452 by amateescu, timmillwood, jeqq, alexpott, Fabianx: Add a...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.