Skip to content
Snippets Groups Projects
Commit 392d6084 authored by catch's avatar catch
Browse files

Issue #3300639 by amateescu, acrazyanimal, smustgrave: Improve and add...

Issue #3300639 by amateescu, acrazyanimal, smustgrave: Improve and add explicit test coverage for the workspace conflict validator

(cherry picked from commit 8f28c48d)
parent 2076c3d9
No related branches found
No related tags found
24 merge requests!11185Issue #3477324 by andypost, alexpott: Fix usage of str_getcsv() and fgetcsv() for PHP 8.4,!10602Issue #3438769 by vinmayiswamy, antonnavi, michelle, amateescu: Sub workspace does not clear,!10301Issue #3469309 by mstrelan, smustgrave, moshe weitzman: Use one-time login...,!10187Issue #3487488 by dakwamine: ExtensionMimeTypeGuesser::guessMimeType must support file names with "0" (zero) like foo.0.zip,!9944Issue #3483353: Consider making the createCopy config action optionally fail...,!9929Issue #3445469 by pooja_sharma, smustgrave: Add additional test coverage for...,!9787Resolve issue 3479427 - bootstrap barrio issue under Windows,!9742Issue #3463908 by catch, quietone: Split OptionsFieldUiTest into two,!9526Issue #3458177 by mondrake, catch, quietone, godotislate, longwave, larowlan,...,!8738Issue #3424162 by camilledavis, dineshkumarbollu, smustgrave: Claro...,!8704Make greek characters available in ckeditor5,!8597Draft: Issue #3442259 by catch, quietone, dww: Reduce time of Migrate Upgrade tests...,!8533Issue #3446962 by kim.pepper: Remove incorrectly added...,!8517Issue #3443748 by NexusNovaz, smustgrave: Testcase creates false positive,!8325Update file Sort.php,!8095Expose document root on install,!7930Resolve #3427374 "Taxonomytid viewsargumentdefault plugin",!7627Issue #3439440 by nicxvan, Binoli Lalani, longwave: Remove country support from DateFormatter,!7445Issue #3440169: When using drupalGet(), provide an associative array for $headers,!7401#3271894 Fix documented StreamWrapperInterface return types for realpath() and dirname(),!7384Add constraints to system.advisories,!6502Draft: Resolve #2938524 "Plach testing issue",!38582585169-10.1.x,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key
Pipeline #131621 passed with warnings
Pipeline: drupal

#131659

    Pipeline: drupal

    #131648

      Pipeline: drupal

      #131642

        +1
        ......@@ -21,6 +21,6 @@ class EntityWorkspaceConflictConstraint extends SymfonyConstraint {
        *
        * @var string
        */
        public $message = 'The content is being edited in the %label workspace. As a result, your changes cannot be saved.';
        public $message = 'The content is being edited in the @label workspace. As a result, your changes cannot be saved.';
        }
        ......@@ -13,55 +13,17 @@
        /**
        * Validates the EntityWorkspaceConflict constraint.
        *
        * @internal
        */
        class EntityWorkspaceConflictConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
        /**
        * The entity type manager.
        *
        * @var \Drupal\Core\Entity\EntityTypeManagerInterface
        */
        protected $entityTypeManager;
        /**
        * The workspace manager service.
        *
        * @var \Drupal\workspaces\WorkspaceManagerInterface
        */
        protected $workspaceManager;
        /**
        * The workspace association service.
        *
        * @var \Drupal\workspaces\WorkspaceAssociationInterface
        */
        protected $workspaceAssociation;
        /**
        * The workspace repository service.
        *
        * @var \Drupal\workspaces\WorkspaceRepositoryInterface
        */
        protected $workspaceRepository;
        /**
        * Constructs an EntityUntranslatableFieldsConstraintValidator object.
        *
        * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
        * The entity type manager service.
        * @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
        * The workspace manager service.
        * @param \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association
        * The workspace association service.
        * @param \Drupal\workspaces\WorkspaceRepositoryInterface $workspace_repository
        * The Workspace repository service.
        */
        public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, WorkspaceAssociationInterface $workspace_association, WorkspaceRepositoryInterface $workspace_repository) {
        $this->entityTypeManager = $entity_type_manager;
        $this->workspaceManager = $workspace_manager;
        $this->workspaceAssociation = $workspace_association;
        $this->workspaceRepository = $workspace_repository;
        }
        public function __construct(
        protected readonly EntityTypeManagerInterface $entityTypeManager,
        protected readonly WorkspaceManagerInterface $workspaceManager,
        protected readonly WorkspaceAssociationInterface $workspaceAssociation,
        protected readonly WorkspaceRepositoryInterface $workspaceRepository,
        ) {}
        /**
        * {@inheritdoc}
        ......@@ -83,22 +45,18 @@ public function validate($entity, Constraint $constraint) {
        if (isset($entity) && !$entity->isNew()) {
        $active_workspace = $this->workspaceManager->getActiveWorkspace();
        // Get the latest revision of the entity in order to check if it's being
        // edited in a different workspace.
        $latest_revision = $this->workspaceManager->executeOutsideWorkspace(function () use ($entity) {
        /** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
        $storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
        return $storage->loadRevision($storage->getLatestRevisionId($entity->id()));
        });
        // If the latest revision of the entity is tracked in a workspace, it can
        // only be edited in that workspace or one of its descendants.
        if ($latest_revision_workspace = $latest_revision->workspace->entity) {
        $descendants_and_self = $this->workspaceRepository->getDescendantsAndSelf($latest_revision_workspace->id());
        // If the entity is tracked in a workspace, it can only be edited in
        // that workspace or one of its descendants.
        if ($tracking_workspace_ids = $this->workspaceAssociation->getEntityTrackingWorkspaceIds($entity)) {
        $first_tracking_workspace_id = reset($tracking_workspace_ids);
        $descendants_and_self = $this->workspaceRepository->getDescendantsAndSelf($first_tracking_workspace_id);
        if (!$active_workspace || !in_array($active_workspace->id(), $descendants_and_self, TRUE)) {
        $workspace = $this->entityTypeManager->getStorage('workspace')
        ->load($first_tracking_workspace_id);
        $this->context->buildViolation($constraint->message)
        ->setParameter('%label', $latest_revision_workspace->label())
        ->setParameter('@label', $workspace->label())
        ->addViolation();
        }
        }
        ......
        ......@@ -308,7 +308,8 @@ public function getEntityTrackingWorkspaceIds(RevisionableInterface $entity) {
        $query = $this->database->select(static::TABLE)
        ->fields(static::TABLE, ['workspace'])
        ->condition('target_entity_type_id', $entity->getEntityTypeId())
        ->condition('target_entity_id', $entity->id());
        ->condition('target_entity_id', $entity->id())
        ->orderBy('target_entity_revision_id', 'DESC');
        return $query->execute()->fetchCol();
        }
        ......
        <?php
        declare(strict_types=1);
        namespace Drupal\Tests\workspaces\Kernel;
        use Drupal\Core\Entity\EntityInterface;
        use Drupal\Core\Entity\EntityTypeManagerInterface;
        use Drupal\entity_test\Entity\EntityTestMulRevPub;
        use Drupal\KernelTests\KernelTestBase;
        use Drupal\Tests\user\Traits\UserCreationTrait;
        use Drupal\workspaces\Entity\Workspace;
        /**
        * @coversDefaultClass \Drupal\workspaces\Plugin\Validation\Constraint\EntityWorkspaceConflictConstraintValidator
        * @group workspaces
        */
        class EntityWorkspaceConflictConstraintValidatorTest extends KernelTestBase {
        use UserCreationTrait;
        use WorkspaceTestTrait;
        /**
        * {@inheritdoc}
        */
        protected static $modules = [
        'entity_test',
        'path_alias',
        'system',
        'user',
        'workspaces',
        ];
        /**
        * The entity type manager.
        */
        protected EntityTypeManagerInterface $entityTypeManager;
        /**
        * {@inheritdoc}
        */
        protected function setUp(): void {
        parent::setUp();
        $this->entityTypeManager = \Drupal::entityTypeManager();
        $this->installSchema('workspaces', ['workspace_association']);
        $this->installEntitySchema('entity_test_mulrevpub');
        $this->installEntitySchema('workspace');
        $this->installEntitySchema('user');
        $this->createUser();
        }
        /**
        * @covers ::validate
        */
        public function testNewEntitiesAllowedInDefaultWorkspace(): void {
        // Create two top-level workspaces and a second-level one.
        $stage = Workspace::create(['id' => 'stage', 'label' => 'Stage']);
        $stage->save();
        $dev = Workspace::create(['id' => 'dev', 'label' => 'Dev', 'parent' => 'stage']);
        $dev->save();
        $other = Workspace::create(['id' => 'other', 'label' => 'Other']);
        $other->save();
        // Create an entity in Live, and check that the validation is skipped.
        $entity = EntityTestMulRevPub::create();
        $this->assertCount(0, $entity->validate());
        $entity->save();
        $entity = $this->reloadEntity($entity);
        $this->assertCount(0, $entity->validate());
        // Edit the entity in Stage.
        $this->switchToWorkspace('stage');
        $entity->save();
        $entity = $this->reloadEntity($entity);
        $this->assertCount(0, $entity->validate());
        $expected_message = 'The content is being edited in the Stage workspace. As a result, your changes cannot be saved.';
        // Check that the entity can no longer be edited in Live.
        $this->switchToLive();
        $entity = $this->reloadEntity($entity);
        $violations = $entity->validate();
        $this->assertCount(1, $violations);
        $this->assertSame($expected_message, (string) $violations->get(0)->getMessage());
        // Check that the entity can no longer be edited in another top-level
        // workspace.
        $this->switchToWorkspace('other');
        $entity = $this->reloadEntity($entity);
        $violations = $entity->validate();
        $this->assertCount(1, $violations);
        $this->assertSame($expected_message, (string) $violations->get(0)->getMessage());
        // Check that the entity can still be edited in a sub-workspace of Stage.
        $this->switchToWorkspace('dev');
        $entity = $this->reloadEntity($entity);
        $this->assertCount(0, $entity->validate());
        // Edit the entity in Dev.
        $this->switchToWorkspace('dev');
        $entity->save();
        $entity = $this->reloadEntity($entity);
        $this->assertCount(0, $entity->validate());
        $expected_message = 'The content is being edited in the Dev workspace. As a result, your changes cannot be saved.';
        // Check that the entity can no longer be edited in Live.
        $this->switchToLive();
        $entity = $this->reloadEntity($entity);
        $violations = $entity->validate();
        $this->assertCount(1, $violations);
        $this->assertSame($expected_message, (string) $violations->get(0)->getMessage());
        // Check that the entity can no longer be edited in the parent workspace.
        $this->switchToWorkspace('stage');
        $entity = $this->reloadEntity($entity);
        $violations = $entity->validate();
        $this->assertCount(1, $violations);
        $this->assertSame($expected_message, (string) $violations->get(0)->getMessage());
        // Check that the entity can no longer be edited in another top-level
        // workspace.
        $this->switchToWorkspace('other');
        $entity = $this->reloadEntity($entity);
        $violations = $entity->validate();
        $this->assertCount(1, $violations);
        $this->assertSame($expected_message, (string) $violations->get(0)->getMessage());
        }
        /**
        * Reloads the given entity from the storage and returns it.
        *
        * @param \Drupal\Core\Entity\EntityInterface $entity
        * The entity to be reloaded.
        *
        * @return \Drupal\Core\Entity\EntityInterface
        * The reloaded entity.
        */
        protected function reloadEntity(EntityInterface $entity): EntityInterface {
        $storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
        $storage->resetCache([$entity->id()]);
        return $storage->load($entity->id());
        }
        }
        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