Problem/Motivation

The workspaces module doesn't alter the latest (translation affected) revision entity queries at the moment. This is because the "locking" protection provided by EntityWorkspaceConflictConstraint prevents an entity that's tracked in a workspace from being edited in Live or in another workspace. However, both #3486378: [Plan] Allow for / implement simplified content workflow with workspaces and #3438083: Ability to edit content in Live while it’s also being edited in other workspaces seek to bypass/remove that restriction. We need to ensure that the queries that are involved are properly altered.

Proposed resolution

Latest revision entity queries and \Drupal\Core\Entity\TranslatableRevisionableStorageInterface::getLatestTranslationAffectedRevisionId() should return the latest workspace-specific revisions. EntityRepositoryInterface::getActive() and EntityRepositoryInterface::getActiveMultiple() are two major use-cases for those type of queries.

The only impact on existing sites is that entity queries will function properly when the locking protection mentioned above is bypassed in custom code.

Remaining tasks

Review.

User interface changes

Nope.

API changes

Nope.

Data model changes

Nope.

Release notes snippet

Entity queries for latest (translation affected) revisions will now return the latest workspace-specific revision when executed inside a workspace.

Issue fork drupal-3045177

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

amateescu created an issue. See original summary.

amateescu’s picture

Status: Active » Needs review
StatusFileSize
new950 bytes
new1.83 KB

This should do it :)

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

manuel garcia’s picture

Status: Needs review » Reviewed & tested by the community

Fix is simple enough and comes with test coverage.

Using workspaces both the users and developers should expect to always be working with entities for the current workspace.

@amateescu walked me through this in slack, and it makes sense for workspaces to do this, and it shouldn't cause any side-effects.

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

The last submitted patch, 2: 3045177-test-only.patch, failed testing. View results

amateescu’s picture

StatusFileSize
new1.83 KB

Re-uploading the full patch because the testbot keeps retesting the test-only one.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Random fail, queued a re-test.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

yogeshmpawar’s picture

Status: Needs work » Reviewed & tested by the community

All looks good so setting back to RTBC! Tests failure is not related (see #3055648: Frequent random fail in \Drupal\Tests\media_library\FunctionalJavascript\MediaLibraryTest).

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Random fail.

catch’s picture

Status: Reviewed & tested by the community » Needs review

So I can see the reasons for doing this, but are there cases where non-workspace-aware code could be querying the latest revision and expects to get the actual most recent revision rather than the workspace-specific one?

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

I thought about that quite a bit and I think that code that is non-workspace-aware assumes a linear versioning history, but, since workspaces introduces parallel versioning, my conclusion was that returning the latest revisions from a (possibly) different branch is not the expected outcome in a non-default workspace context.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record, +Needs release note

#22 is a good argument although seems hard to predict. Let's add both a change record and a release note mention regardless - CNW for that.

amateescu’s picture

Issue summary: View changes
Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs change record, -Needs release note

Good point :) Added a CR https://www.drupal.org/node/3064221 and copied its text to the release note snippet.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 3045177-10.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
amateescu’s picture

This is just a normal bug so maybe it doesn't need to be a stable blocker.

gábor hojtsy’s picture

Status: Reviewed & tested by the community » Needs review

Hm, why is this built against 8.7.x and not 8.8.x?

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

Because it's a simple bug that needs to be fixed in both branches :)

gábor hojtsy’s picture

Version: 8.7.x-dev » 8.8.x-dev
gábor hojtsy’s picture

Ok then, I queued a test on 8.8.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

jasonawant’s picture

Hi, I came across this while investigating what I think is a related issue. I've referenced this issue from #3088341: Add ability to query on most recent language specific revision. I suspect there may be a example found in workspace entity query to borrow and apply to query for the an entity translation most recent revision.

krzysztof domański’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new4.06 KB

This patch #10 broke SQLite and PostgreSQL.

1) Drupal\Tests\workspaces\Functional\WorkspaceConcurrentEditingTest::testConcurrentEditing
Failed asserting that true is false.

Queued a test against to expose the fails.

build:
  assessment:
    testing:
      run_tests.functional:
        types: 'PHPUnit-Functional'
        testgroups: '--class "Drupal\Tests\workspaces\Functional\WorkspaceConcurrentEditingTest"'
        suppress-deprecations: false
        halt-on-fail: false
        repeat: 10
krzysztof domański’s picture

StatusFileSize
new4.09 KB

This time with concurrency: 1.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new1.95 KB
new776 bytes

Very good catch @Krzysztof Domański, fixed that :)

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

The change is minor, so setting it back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 38: 3045177-38.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Postponed

Since @catch is still not 100% convinced about doing this, let's postpone it until we get more reports from people that might be affected by it.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Darren Oh made their first commit to this issue’s fork.

darren oh’s picture

darren oh’s picture

Status: Postponed » Needs review

catch was just asking a question. This change is necessary to ensure predictable behavior with code that is not workspace-aware. I am currently trying to set up workspaces for a major client, and a blocker is that the edit tab does not load the revision for the current workspace by default.

darren oh’s picture

darren oh’s picture

amateescu’s picture

Status: Needs review » Needs work

@Darren Oh, I think you're the first one to actually bump into this problem that was only theoretical so far, so I'm wondering if you can share any more info about the code that is not workspace-aware and it was loading the wrong revision :)

As for the MR, let's switch the order in the condition and check for isEntityTypeSupported() before hasActiveWorkspace(), see #3395626: Fix workspace-support check in entity queries for a recent example why this matters.

darren oh’s picture

Sure I can share more info. If you have multiple workspaces, the first workspace in which a node is edited blocks editing in all other workspaces because the edit tab always loads the most recent revision. You'll get a message saying the node is being edited in another workspace and changes cannot be saved. The expected behavior is that the most recent live revision is loaded and copied to the current workspace.

amateescu’s picture

The expected behavior is that the most recent live revision is loaded and copied to the current workspace.

That's not the expected behavior in core at the moment. Editing the same entity in different workspaces requires a conflict resolution solution, which doesn't exist in core (yet?), that's why we actively prevent it.

If you'd like to give editors the ability to edit the same entity in different workspaces, with the (important!) caveat that whichever workspace is published last "wins" (i.e. the changes from the previously-published workspace will be lost), I'd suggest to override the plugin class of the EntityWorkspaceConflict constraint with a custom one.

darren oh’s picture

I did override the EntityWorkspaceConflict constraint. Also had to apply the fix from this issue.

amateescu’s picture

There must be something else at play then, because I tried the snippet below and the following steps:

1. edit a node in a workspace, save
2. edit the node in Live, save
3. create a new workspace, and editing the node showed me the revision created in step 2.

--- a/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityWorkspaceConflictConstraintValidator.php
+++ b/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityWorkspaceConflictConstraintValidator.php
@@ -79,6 +79,7 @@ public static function create(ContainerInterface $container) {
    * {@inheritdoc}
    */
   public function validate($entity, Constraint $constraint) {
+    return;
     /** @var \Drupal\Core\Entity\EntityInterface $entity */
     if (isset($entity) && !$entity->isNew()) {
       $active_workspace = $this->workspaceManager->getActiveWorkspace();
amateescu’s picture

Status: Needs work » Postponed (maintainer needs more info)

amateescu changed the visibility of the branch 3045177-test-only to hidden.

amateescu’s picture

Status: Postponed (maintainer needs more info) » Needs review

While working on #3486378: [Plan] Allow for / implement simplified content workflow with workspaces, it turned out that this is very much needed for that issue, and for #3438083: Ability to edit content in Live while it’s also being edited in other workspaces as well.

Pushed an update to also handle latest translation affected revisions.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

amateescu’s picture

Status: Needs work » Needs review
Issue tags: +no-needs-review-bot

The bot is trying to apply the 11.1.x MR to 11.x

catch’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

The MR needs to be against 11.x since that's the target for commits, the bot isn't wrong there.

This could use an issue summary about why it needs to be done and what the impact is.

amateescu’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs issue summary update

The bot is confused when there are multiple MRs. 6681 (3045177-workspace-specific-latest-revision) is the one for 11.x. Updated the IS.

fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Looks great to me!

Had just one question, but that is minor.

Tests also make sense.

FWIW, here is a test summary by AI:

This is a kernel test for Drupal's Workspaces module, specifically testing how entity revisions are managed in different workspaces and languages. Let's break it down:

**1. Key Components:**
- **Workspace Context:** Tests how entities behave when edited in different workspaces ('ham', 'cheese') vs Live environment
- **Multilingual Support:** Tests with English (en) and Romanian (ro) languages
- **Two Entity Types:**
- `entity_test_revpub`: Revisionable, non-translatable entity
- `entity_test_mulrevpub`: Revisionable AND translatable entity

**2. Test Flow:**

**A. Non-translatable Entity Test:**
1. Creates initial entity in Live
2. Creates revisions in workspaces:
- 'ham' workspace revision
- 'cheese' workspace revision
- New Live revision
3. Verifications:
- Each workspace sees its own revision
- Live sees the latest Live revision
- Workspaces maintain their revisions even after Live updates

**B. Translatable Entity Test:**
1. Creates multilingual entity with EN/RO translations in Live
2. Tests workspace-specific translations:
- Creates RO translation revision in 'ham'
- Creates RO translation revision in 'cheese'
- Creates new RO translation in Live
3. Verifications:
- Correct workspace-specific RO translations are returned
- Language context (en/ro) is respected
- Workspace revisions remain isolated from each other and Live

**3. Key Technical Checks:**
- `EntityRepository::getActive()` correctly resolves:
- Workspace context (which revision is active in which workspace)
- Language context (which translation to show)
- Revision tracking across workspaces
- Workspace switching mechanics (`switchToWorkspace()`/`switchToLive()`)
- Proper isolation of workspace-specific revisions

**4. Why This Matters:**
- Ensures content editors in different workspaces don't interfere with each other
- Validates proper version control for multilingual content
- Maintains data integrity when publishing from workspaces to Live
- Tests core Workspaces module functionality at the storage layer

The test uses kernel-level testing (without full HTTP stack) to validate these low-level entity operations efficiently.

oily made their first commit to this issue’s fork.

oily’s picture

Edited code to enhance clarity.

oily’s picture

Issue summary: View changes

Edited issue summary.

oily’s picture

Where it states 'The only impact on existing sites is that entity queries will function properly if the locking protection mentioned above was bypassed in custom code.' in the issue summary should that be 'The only impact on existing sites is that entity queries will not function properly if the locking protection mentioned above was bypassed in custom code.'?

darren oh’s picture

No, Drupal was relying on the locking mechanism to hide this bug from users. Existing sites that bypass the locking mechanism in custom code will now work properly without needing additional workarounds.

oily’s picture

@darran oh Great! MR seems good to me.

oily’s picture

Rebased.

catch’s picture

Status: Reviewed & tested by the community » Needs review

One question on the MR.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

Replied to the MR comment. It seems that the number of MRs here causes some confusion, so here's a quick breakdown for them:

11.x -> MR !6681
11.1.x -> MR !10971
10.5.x (and below) -> MR !10973

And to reply to that comment here as well, note that in the 11.x MR the hook implementation is in the proper place: core/modules/workspaces/src/Hook/EntityOperations.php

OOP hooks made it very "fun" to work on the Worskspaces module :)

catch’s picture

Status: Reviewed & tested by the community » Needs review

Sorry I completely missed that was the 11.1 MR. However I left one more question on the 11.x MR about an explanatory comment and possibly additional test coverage.

amateescu changed the visibility of the branch 3045177-10.5.x to hidden.

amateescu’s picture

Updated both the 11.x and 11.1.x MRs to expand that comment, and added explicit test coverage.

darren oh’s picture

Status: Needs review » Reviewed & tested by the community
darren oh’s picture

Issue summary: View changes

  • catch committed 55fbe8ac on 11.x
    Issue #3045177 by amateescu, darren oh, oily, krzysztof domański, catch...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 11.x, thanks!

If there were not already 11.1.x and 10.5.x MRs, given this doesn't cleanly cherry-pick, I would have just marked this fixed against 11.x.

In this case there are already backport MRs ready, but this is a non-trivial change and it's not impossible something somewhere could be relying on the existing behaviour (checking if there's a newer revision in a different workspace, maybe?), so I'm still going to leave it fixed in 11.x and not backport - site can download the diff from the 11.1 or 10.5 MRs if they need it before they update. Can possible be persuaded to backport to 10.5.x if it turns out this is needed for contrib compatibility with both 10.x and 11.x but even then probably not to the patch releases.

amateescu’s picture

A quick followup is needed here: #3504057: The active variant of an entity in the Live workspace should be the default revision

I forgot we need to apply the same principle of this issue for latest revision / EntityRepository::getActive() in Live.

Status: Fixed » Closed (fixed)

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

amateescu’s picture

Opened another followup, this time a performance issue.