Ability to edit content in live workspace when it has been edited in other workspaces

Created on 4 April 2024, 10 months ago

Problem/Motivation

Currently if a node has been edited in a non-live workspace, it cannot be edited in live.

If you go to the edit form, you see the following message:

The content is being edited in the Stage workspace. As a result, your changes cannot be saved.

This message comes from EntityWorkspaceConflictConstraint, which seems to be basically unchanged since #2784921: Add Workspaces experimental module β†’ .

A common use case for workspaces is to prepare a large number of changes ahead of a major change such as a product launch or rebrand.
If a node has been edited in a workspace for that reason, and there's an urgent change needed on one of those nodes, content editors are blocked from changing it in live.

Steps to reproduce

Proposed resolution

tbc - may depend on discussion in #2867707: WI: Phase H: Conflict management and local workspace merging support β†’

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

✨ Feature request
Status

Active

Version

11.0 πŸ”₯

Component
WorkspacesΒ  β†’

Last updated about 18 hours ago

No maintainer
Created by

πŸ‡¬πŸ‡§United Kingdom malcomio

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @malcomio
  • πŸ‡¬πŸ‡§United Kingdom malcomio

    This limitation of workspaces isn't obvious from the documentation - I've added some info to https://www.drupal.org/docs/8/core/modules/workspace/using-workspaces β†’

  • Status changed to Postponed 10 months ago
  • πŸ‡ΊπŸ‡ΈUnited States djdevin Philadelphia

    In our case, merging wasn't necessary, all derivatives are based off of the currently published version so it wasn't a big deal.

    This functionality is also necessary for a situation like this:

    - Live site
    - Promo A
    - Promo A takedown
    - Promo B

    Otherwise you have to wait until the Promo A takedown to start working on the next promo

    I removed the constraint then added a hook_entity_prepare_form that would swap out the entity version. When editing, Drupal only loads the most recent revision. It seems to work alright, I'm not sure of any caveats. The order of versioning is kinda wonky since the latest version might not be the content that is going to go out, but just don't look at the revisions page!

    It might be useful to add a column on that page to show that a revision belongs to which workspace.

    
    /**
     * Implements hook_entity_prepare_form().
     *
     * Replace the form's entity with one that is associated with the current
     * workspace.
     *
     * Workspace already replaces the entity being viewed based on the workspace.
     * But edit forms always load the most recent revision.
     *
     * This is based on Drupal\workspaces\EntityOperations::entityPreload, altered
     * to work in hook_entity_prepare_form().
     */
    function custom_entity_prepare_form(EntityInterface &$entity, $operation, FormStateInterface $form_state) {
      if ($operation == 'edit') {
        $entityTypeManager = \Drupal::entityTypeManager();
        $workspaceManager = \Drupal::service('workspaces.manager');
        $workspaceAssociation = \Drupal::service('workspaces.association');
    
        // Only run if the entity type can belong to a workspace and we are in a
        // non-default workspace.
        if (!$workspaceManager->shouldAlterOperations($entityTypeManager->getDefinition($entity->getEntityTypeId()))) {
          return;
        }
    
        // Get a list of revision IDs for entities that have a revision set for the
        // current active workspace. If an entity has multiple revisions set for a
        // workspace, only the one with the highest ID is returned.
        if ($tracked_entities = $workspaceAssociation->getTrackedEntities($workspaceManager->getActiveWorkspace()->id(), $entity->getEntityTypeId(), [$entity->id()])) {
          /** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
          $storage = $entityTypeManager->getStorage($entity->getEntityTypeId());
    
          $vid = key($tracked_entities[$entity->getEntityTypeId()]);
    
          // Swap out the entity.
          $entity = $storage->loadRevision($vid);
    
          // Just an indicator we could use in form_alter.
          $form_state->set('pur_workflow_entity_prepare_form', TRUE);
        }
      }
    }
    
    [...]
    
    /**
     * Implements hook_validation_constraint_alter().
     *
     * Replace the default workspace constraint with one that does nothing.
     */
    function custom_validation_constraint_alter(array &$definitions) {
      if (isset($definitions['EntityWorkspaceConflict'])) {
        $definitions['EntityWorkspaceConflict']['class'] = CustomEntityWorkspaceConflictConstraint::class;
      }
    }
    
    
    
  • I'd say this is rather a blocker for any big organization to ever consider to use Workspace, big organizations constantly update their live instance, so this should be available only as an opt-in option.

  • πŸ‡ΊπŸ‡ΈUnited States djdevin Philadelphia

    I fixed a few issues from my PoC in #4 and published it here: https://www.drupal.org/project/workspaces_parallel β†’

    Caveat, there is no reintegration so any live changes just get overwritten when you publish (only content that was edited within the Workspace).

  • πŸ‡ΊπŸ‡ΈUnited States djdevin Philadelphia
  • πŸ‡ΊπŸ‡ΈUnited States djdevin Philadelphia
  • Pipeline finished with Failed
    2 months ago
    Total: 140s
    #345318
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Seems to have pipeline errors

    Going to post into #workspaces too

  • Pipeline finished with Failed
    about 2 months ago
    Total: 282s
    #358024
  • πŸ‡ΊπŸ‡ΈUnited States djdevin Philadelphia

    The discard issue is fixed if you use WSE in combination with this change, because then it gets all the revisions associated with a Workspace and not just the ones since the current version.

    πŸ“Œ Simplify getAssociatedRevisions() and getAssociatedInitialRevisions() from core Active

Production build 0.71.5 2024