Skip to content
Snippets Groups Projects
Commit 1754440b authored by catch's avatar catch
Browse files

Issue #3348390 by amateescu, s_leu, Grevil: Improve the way entity forms are...

Issue #3348390 by amateescu, s_leu, Grevil: Improve the way entity forms are "disabled" early when an entity is being edited in a workspace
parent c84365f7
No related branches found
No related tags found
26 merge requests!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8540Issue #3457061: Bootstrap Modal dialog Not closing after 10.3.0 Update,!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8373Issue #3427374 by danflanagan8, Vighneshh: taxonomy_tid ViewsArgumentDefault...,!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #163465 canceled
Pipeline: drupal

#163470

    ...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
    use Drupal\Core\Form\FormInterface; use Drupal\Core\Form\FormInterface;
    use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
    use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
    use Drupal\Core\TypedData\TypedDataManagerInterface;
    use Drupal\workspaces\Plugin\Validation\Constraint\EntityWorkspaceConflictConstraint;
    use Drupal\workspaces\WorkspaceInformationInterface; use Drupal\workspaces\WorkspaceInformationInterface;
    use Drupal\workspaces\WorkspaceManagerInterface; use Drupal\workspaces\WorkspaceManagerInterface;
    use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
    ...@@ -24,7 +26,8 @@ class WorkspacesHtmlEntityFormController extends FormController { ...@@ -24,7 +26,8 @@ class WorkspacesHtmlEntityFormController extends FormController {
    public function __construct( public function __construct(
    protected readonly FormController $entityFormController, protected readonly FormController $entityFormController,
    protected readonly WorkspaceManagerInterface $workspaceManager, protected readonly WorkspaceManagerInterface $workspaceManager,
    protected readonly WorkspaceInformationInterface $workspaceInfo protected readonly WorkspaceInformationInterface $workspaceInfo,
    protected readonly TypedDataManagerInterface $typedDataManager
    ) {} ) {}
    /** /**
    ...@@ -34,16 +37,42 @@ public function getContentResult(Request $request, RouteMatchInterface $route_ma ...@@ -34,16 +37,42 @@ public function getContentResult(Request $request, RouteMatchInterface $route_ma
    $form_arg = $this->getFormArgument($route_match); $form_arg = $this->getFormArgument($route_match);
    $form_object = $this->getFormObject($route_match, $form_arg); $form_object = $this->getFormObject($route_match, $form_arg);
    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $form_object->getEntity(); $entity = $form_object->getEntity();
    if ($this->workspaceInfo->isEntitySupported($entity)) { if ($this->workspaceInfo->isEntitySupported($entity)) {
    $active_workspace = $this->workspaceManager->getActiveWorkspace(); $active_workspace = $this->workspaceManager->getActiveWorkspace();
    // Prepare a minimal render array in case we need to return it.
    $build['#cache']['contexts'] = $entity->getCacheContexts();
    $build['#cache']['tags'] = $entity->getCacheTags();
    $build['#cache']['max-age'] = $entity->getCacheMaxAge();
    // Prevent entities from being edited if they're tracked in workspace.
    if ($form_object->getOperation() !== 'delete') {
    $constraints = array_values(array_filter($entity->getTypedData()->getConstraints(), function ($constraint) {
    return $constraint instanceof EntityWorkspaceConflictConstraint;
    }));
    if (!empty($constraints)) {
    $violations = $this->typedDataManager->getValidator()->validate(
    $entity->getTypedData(),
    $constraints[0]
    );
    if (count($violations)) {
    $build['#markup'] = $violations->get(0)->getMessage();
    return $build;
    }
    }
    }
    // Prevent entities from being deleted in a workspace if they have a // Prevent entities from being deleted in a workspace if they have a
    // published default revision. // published default revision.
    if ($form_object->getOperation() === 'delete' && $active_workspace && !$this->workspaceInfo->isEntityDeletable($entity, $active_workspace)) { if ($form_object->getOperation() === 'delete' && $active_workspace && !$this->workspaceInfo->isEntityDeletable($entity, $active_workspace)) {
    $build['#markup'] = $this->t('This @entity_type_label can only be deleted in the Live workspace.', [ $build['#markup'] = $this->t('This @entity_type_label can only be deleted in the Live workspace.', [
    '@entity_type_label' => $entity->getEntityType()->getSingularLabel(), '@entity_type_label' => $entity->getEntityType()->getSingularLabel(),
    ]); ]);
    return $build; return $build;
    } }
    } }
    ......
    ...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
    use Drupal\Core\Entity\RevisionableInterface; use Drupal\Core\Entity\RevisionableInterface;
    use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
    use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
    use Drupal\workspaces\Plugin\Validation\Constraint\EntityWorkspaceConflictConstraint;
    use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
    /** /**
    ...@@ -319,17 +318,6 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, $f ...@@ -319,17 +318,6 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, $f
    if ($this->workspaceManager->hasActiveWorkspace()) { if ($this->workspaceManager->hasActiveWorkspace()) {
    $form['#entity_builders'][] = [static::class, 'entityFormEntityBuild']; $form['#entity_builders'][] = [static::class, 'entityFormEntityBuild'];
    } }
    // Run the workspace conflict validation constraint when the entity form is
    // being built so we can "disable" it early and display a message to the
    // user, instead of allowing them to enter data that can never be saved.
    foreach ($entity->validate()->getEntityViolations() as $violation) {
    if ($violation->getConstraint() instanceof EntityWorkspaceConflictConstraint) {
    $form['#markup'] = $violation->getMessage();
    $form['#access'] = FALSE;
    continue;
    }
    }
    } }
    /** /**
    ......
    ...@@ -123,6 +123,10 @@ public function testBlocksInWorkspaces(): void { ...@@ -123,6 +123,10 @@ public function testBlocksInWorkspaces(): void {
    $assert_session->pageTextNotContains($second_block_body); $assert_session->pageTextNotContains($second_block_body);
    $assert_session->pageTextContains('The DEFAULT block body'); $assert_session->pageTextContains('The DEFAULT block body');
    // Check the concurrent editing protection on the Layout Builder form.
    $this->drupalGet('/node/1/layout');
    $assert_session->pageTextContains('The content is being edited in the Stage workspace. As a result, your changes cannot be saved.');
    $stage->publish(); $stage->publish();
    $this->drupalGet('node/1'); $this->drupalGet('node/1');
    $assert_session->pageTextNotContains('The DEFAULT block body'); $assert_session->pageTextNotContains('The DEFAULT block body');
    ......
    ...@@ -94,5 +94,5 @@ services: ...@@ -94,5 +94,5 @@ services:
    decorates: controller.entity_form decorates: controller.entity_form
    class: Drupal\workspaces\Controller\WorkspacesHtmlEntityFormController class: Drupal\workspaces\Controller\WorkspacesHtmlEntityFormController
    public: false public: false
    arguments: ['@.inner', '@workspaces.manager', '@workspaces.information'] arguments: ['@.inner', '@workspaces.manager', '@workspaces.information', '@typed_data_manager']
    Drupal\workspaces\Controller\WorkspacesHtmlEntityFormController: '@workspaces.controller.entity_form' Drupal\workspaces\Controller\WorkspacesHtmlEntityFormController: '@workspaces.controller.entity_form'
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment