Problem/Motivation
As pointed out in #2784921-112: Add Workspaces experimental module point 1, having a Live (default) workspace entity is not desirable. It's also problematic when uninstalling the Workspace module, as can be seen in #3059824: TypeError: Argument 1 passed to Drupal\workspaces\WorkspaceListBuilder::buildRow() must implement interface Drupal\Core\Entity\EntityInterface, null given.
Proposed resolution
Remove the Live (default) workspace and change the concept model for switching to the Live version of the site by switching out of the current workspace.
Remaining tasks
Reviews.
User interface changes
The workspace switcher block does not have Live as an option anymore, and a Switch to Live action button has been added instead.
Before - in the Live version of the site

Before - in the Stage workspace

After - in the Live version of the site

After - in the Stage workspace

API changes
API additions:
- three new methods on WorkspaceManagerInterface: hasActiveWorkspace(), switchToLive() and executeOutsideWorkspace().
- one new method on WorkspaceNegotiatorInterface: unsetActiveWorkspace()
Data model changes
There is no 'live' workspace entity anymore.
Release notes snippet
There is no concept of a "Live" (default) workspace anymore. Switching to the live version of the site is now accomplished by switching out of the current workspace.
| Comment | File | Size | Author |
|---|---|---|---|
| #29 | interdiff-29.txt | 2.12 KB | amateescu |
| #29 | 2935780-29.patch | 59.34 KB | amateescu |
| #28 | interdiff-28.txt | 621 bytes | amateescu |
| #28 | 2935780-28.patch | 57.55 KB | amateescu |
Comments
Comment #2
amateescu commentedI tried to do it with the patch attached, but it's really not that simple because loading entities also relies on db queries on various code paths, and the number of hacks needed to have it available during db or entity queries would go through the roof :/
Comment #3
amateescu commentedComment #4
fabianx commentedI think per the comment:
This can be closed now as fixed or not?
Comment #5
amateescu commentedThe context of that comment was about the Live workspace returned by
\Drupal\workspace\Negotiator\DefaultWorkspaceNegotiator. However, that in-memory "live" workspace is only returned when we don't have its in-storage representation. For example when we want to uninstall the module, we need to remove all the workspace entities from storage, including the Live one.We currently still create a Live workspace in storage, see
workspace_install().Comment #7
amateescu commentedFix component following module rename.
Comment #8
sam152 commentedThe only other approach I can see for this is to not have a live workspace entity at all. From a mental model point of view, instead of switching to "Live" you would essentially switch out of "Stage". That may also clean up some of
WorkspaceInterface, for examplepublishmakes no sense for the live workspace, andisDefaultWorkspacewould become irrelevant.This seems like a pretty big shift though, so I suppose the question should be: has there been any kind of significant issue or risk with the installed live workspace disappearing or being deleted? How recoverable is workspaces if that is deleted?
Comment #10
amateescu commentedI just closed an issue which shows that the current situation is actually a bug: #3059824: TypeError: Argument 1 passed to Drupal\workspaces\WorkspaceListBuilder::buildRow() must implement interface Drupal\Core\Entity\EntityInterface, null given, so re-classifying and adding credit to @kunalkursija for creating that issue with very helpful steps to reproduce.
Comment #12
amateescu commentedComment #13
amateescu commented@Sam152, your idea from #8 makes perfect sense, and I think it's exactly what we should do :)
Comment #14
amateescu commentedAdded a change record https://www.drupal.org/node/3071527 and removed a few unneeded redirects to the front page.
Comment #15
manuel garcia commentedJust a quick review / feelings after a first read of the patch:
While it's true that this is what submitting this form does, I cant stop thinking about the difference is between deactivating a workspace vs switching to live.
Deactivating the workspace is what is actually happening in the system, in the code.
Switching to live is what the user actually wants to do, what the action means for the user anyway.
So I think naming everything as the user action would make sense to me. When someone tries to look for the form's code, it would be easier to find if it was called
SwitchToLiveWorkspaceFormor something along those lines, but as I said, an argument could be made for keeping it like this - thoughts?This form description would also change if we decide to change the class name.
If not, I think
Provides a form to deactivate a workspace.could be clearer.Comment #16
amateescu commented@Manuel Garcia, thanks for taking a look!
The funny thing is that I started this patch with a
SwitchToLiveFormas you suggested, but went with the "deactivate" approach in the end because I thought it would be easier to take advantage of theworkspace.viewentity access operation.However, after thinking it through a bit, I think we need a very simple "has active workspace" access check for that form, so that's what I implemented in this new patch.
Comment #17
amateescu commentedFixed a copy/pasta mistake :/
Comment #18
amateescu commentedWrote a proper issue summary.
Comment #19
manuel garcia commentedYay!
While it makes sense to clean up, I can't shake this question out of my head: can this be dangerous for sites live using this workspace?
Also, should we bother checking that we indeed loaded the live workspace before trying to delete it?
Comment #20
amateescu commentedI don't think there's a problem with deleting this workspace because users who have it set in their session by the workspace negotiator, on the next request when we try to load it from the workspace storage we won't get any result, and as a result the negotiator will return NULL and the workspace manager will fall back to the live version of site, which is exactly the expected outcome for those users.
Good point, done :)
Comment #21
manuel garcia commentedThanks @amateescu for the explanation, makes sense.
Patch is looking pretty good to me, just a couple more questions:
Do we need an update path test for this? My guess is it isn’t necessary, since we are just deleting one entity, but well doesn’t hurt to ask I suppose.
Comment #22
amateescu commentedRe #21:
1. I don't think we need an update path test because the update function either removes the
liveworkspace if it exists, or it doesn't :) There's nothing really to test..2. Good point, added two sections to the CR: "API additions" and "Deprecations".
Comment #23
manuel garcia commentedRe #22:
1. Yup, I can't think of anything else to test either by looking at the post_update function. The only fear I had with it was explained on
#22#20.2. Thanks, had a read and the new sections are clear.
Does this need documenting in the CR?
Comment #24
amateescu commentedOf course! Added that new method to the IS and the change record :)
Comment #25
manuel garcia commentedThanks @amateescu - we now have a clear patch, a detailed CR and IS, so I'm RTBCing since I can't think of anything else to improve or that should be added.
Comment #26
amateescu commentedMarking as a stable blocker.
Comment #27
catchOverall looks like a good simplification, couple of small things below:
Minor but do we really need to validate what's in routing yaml? And if so why not assert() to tell module developers they did something wrong?
Minor again, should $function be $callable?
The naming seems a bit ambivalent in that it could also mean 'is there an active workspace on the site', but I don't have a better idea.
However I think the return could be:
TRUE if a workspace is active, FALSE otherwise.Only other idea would be reversing it to something like isLive()?
Comment #28
amateescu commentedYup, this special Live workspace was bugging me since you and Fabian pointed it out in the reviews for the initial workspaces patch :)
Re #27:
I copied this approach from
\Drupal\user\Access\LoginStatusCheck::access()and I think the added benefit offilter_var()is that it also converts the variable to an actual boolean value so we can do a strict type check below.I used
$functionto match the existingexecuteInWorkspace()method, but I don't have any strong preference about it. Just that we should rename both at the same time :)I like the
hasActiveWorkspace()name because it pairs very well with theget|setActiveWorkspace()methods, and because it denotes that the code within a condition needs to cater for an "exceptional" case, when the site is not in the usual/default state.However, if other folks have a different opinion or suggestion, I'm happy to go with the majority preference.
Comment #29
amateescu commentedDid a self-review and found a couple more things that should be cleaned up.
Comment #31
catch#28 1, 2, and 3 are all fair enough.
Committed d881bd0 and pushed to 8.8.x. Thanks!
Comment #33
rodrigoaguileraThe change record was still in draft state so I published it