Unverified Commit 8e94ef48 authored by alexpott's avatar alexpott

Issue #2998662 by Sam152, dhirendra.mishra, amateescu, Eli-T: Saving a tagged...

Issue #2998662 by Sam152, dhirendra.mishra, amateescu, Eli-T: Saving a tagged article in staged workspace causes fatal exception

(cherry picked from commit e417c7f2)
parent 9d47e1d6
......@@ -70,4 +70,18 @@ public function entityTypeBuild(array &$entity_types) {
}
}
/**
* Alters field plugin definitions.
*
* @param array[] $definitions
* An array of field plugin definitions.
*
* @see hook_field_info_alter()
*/
public function fieldInfoAlter(&$definitions) {
if (isset($definitions['entity_reference'])) {
$definitions['entity_reference']['constraints']['EntityReferenceSupportedNewEntities'] = [];
}
}
}
<?php
namespace Drupal\workspaces\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* The entity reference supported new entities constraint.
*
* @Constraint(
* id = "EntityReferenceSupportedNewEntities",
* label = @Translation("Entity Reference Supported New Entities", context = "Validation"),
* )
*/
class EntityReferenceSupportedNewEntitiesConstraint extends Constraint {
/**
* The default violation message.
*
* @var string
*/
public $message = '%collection_label can only be created in the default workspace.';
}
<?php
namespace Drupal\workspaces\Plugin\Validation\Constraint;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\workspaces\WorkspaceManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Checks if new entities created for entity reference fields are supported.
*/
class EntityReferenceSupportedNewEntitiesConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
/**
* The workspace manager.
*
* @var \Drupal\workspaces\WorkspaceManagerInterface
*/
protected $workspaceManager;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Creates a new EntityReferenceSupportedNewEntitiesConstraintValidator instance.
*/
public function __construct(WorkspaceManagerInterface $workspaceManager, EntityTypeManagerInterface $entityTypeManager) {
$this->workspaceManager = $workspaceManager;
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('workspaces.manager'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function validate($value, Constraint $constraint) {
if ($this->workspaceManager->getActiveWorkspace()->isDefaultWorkspace()) {
return;
}
$target_entity_type_id = $value->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type');
$target_entity_type = $this->entityTypeManager->getDefinition($target_entity_type_id);
if ($value->hasNewEntity() && !$this->workspaceManager->isEntityTypeSupported($target_entity_type)) {
$this->context->addViolation($constraint->message, ['%collection_label' => $target_entity_type->getCollectionLabel()]);
}
}
}
<?php
namespace Drupal\Tests\workspaces\Kernel;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\entity_test\Entity\EntityTestMulRevPub;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;
/**
* @coversDefaultClass \Drupal\workspaces\Plugin\Validation\Constraint\EntityReferenceSupportedNewEntitiesConstraintValidator
* @group workspaces
*/
class EntityReferenceSupportedNewEntitiesConstraintValidatorTest extends KernelTestBase {
use UserCreationTrait;
use WorkspaceTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'system',
'user',
'workspaces',
'entity_test',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
$this->createUser();
$fields['supported_reference'] = BaseFieldDefinition::create('entity_reference')->setSetting('target_type', 'entity_test_mulrevpub');
$fields['unsupported_reference'] = BaseFieldDefinition::create('entity_reference')->setSetting('target_type', 'entity_test');
$this->container->get('state')->set('entity_test_mulrevpub.additional_base_field_definitions', $fields);
$this->installEntitySchema('entity_test_mulrevpub');
$this->initializeWorkspacesModule();
}
/**
* @covers ::validate
*/
public function testNewEntitiesAllowedInDefaultWorkspace() {
$entity = EntityTestMulRevPub::create([
'unsupported_reference' => [
'entity' => EntityTest::create([]),
],
'supported_reference' => [
'entity' => EntityTest::create([]),
],
]);
$this->assertCount(0, $entity->validate());
}
/**
* @covers ::validate
*/
public function testNewEntitiesForbiddenInNonDefaultWorkspace() {
$this->switchToWorkspace('stage');
$entity = EntityTestMulRevPub::create([
'unsupported_reference' => [
'entity' => EntityTest::create([]),
],
'supported_reference' => [
'entity' => EntityTestMulRevPub::create([]),
],
]);
$violations = $entity->validate();
$this->assertCount(1, $violations);
$this->assertEquals('<em class="placeholder">Test entity entities</em> can only be created in the default workspace.', $violations[0]->getMessage());
}
}
......@@ -14,7 +14,6 @@
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\views\Tests\ViewResultAssertionTrait;
use Drupal\views\Views;
use Drupal\workspaces\Entity\Workspace;
/**
* Tests a complete deployment scenario across different workspaces.
......@@ -28,6 +27,7 @@ class WorkspaceIntegrationTest extends KernelTestBase {
use NodeCreationTrait;
use UserCreationTrait;
use ViewResultAssertionTrait;
use WorkspaceTestTrait;
/**
* The entity type manager.
......@@ -36,20 +36,6 @@ class WorkspaceIntegrationTest extends KernelTestBase {
*/
protected $entityTypeManager;
/**
* The workspaces manager.
*
* @var \Drupal\workspaces\WorkspaceManagerInterface
*/
protected $workspacesManager;
/**
* An array of test workspaces, keyed by workspace ID.
*
* @var \Drupal\workspaces\WorkspaceInterface[]
*/
protected $workspaces = [];
/**
* Creation timestamp that should be incremented for each new entity.
*
......@@ -100,35 +86,6 @@ protected function setUp() {
$this->createNode(['title' => 'live - 2 - r2 - unpublished', 'created' => $this->createdTimestamp++, 'status' => FALSE]);
}
/**
* Enables the Workspaces module and creates two workspaces.
*/
protected function initializeWorkspacesModule() {
// Enable the Workspaces module here instead of the static::$modules array
// so we can test it with default content.
$this->enableModules(['workspaces']);
$this->container = \Drupal::getContainer();
$this->entityTypeManager = \Drupal::entityTypeManager();
$this->workspacesManager = \Drupal::service('workspaces.manager');
$this->installEntitySchema('workspace');
$this->installEntitySchema('workspace_association');
// Create two workspaces by default, 'live' and 'stage'.
$this->workspaces['live'] = Workspace::create(['id' => 'live']);
$this->workspaces['live']->save();
$this->workspaces['stage'] = Workspace::create(['id' => 'stage']);
$this->workspaces['stage']->save();
$permissions = [
'administer nodes',
'create workspace',
'edit any workspace',
'view any workspace',
];
$this->setCurrentUser($this->createUser($permissions));
}
/**
* Tests various scenarios for creating and deploying content in workspaces.
*/
......@@ -523,7 +480,7 @@ public function testExecuteInWorkspaceContext() {
$this->switchToWorkspace('live');
$storage = $this->entityTypeManager->getStorage('node');
$this->assertEquals('live', $this->workspacesManager->getActiveWorkspace()->id());
$this->assertEquals('live', $this->workspaceManager->getActiveWorkspace()->id());
$live_node = $storage->loadUnchanged($node->id());
$this->assertEquals('live node 1', $live_node->title->value);
......@@ -534,8 +491,8 @@ public function testExecuteInWorkspaceContext() {
$this->assertEquals([$live_node->getRevisionId() => $node->id()], $result);
// Try the same assertions in the context of the 'stage' workspace.
$this->workspacesManager->executeInWorkspace('stage', function () use ($node, $storage) {
$this->assertEquals('stage', $this->workspacesManager->getActiveWorkspace()->id());
$this->workspaceManager->executeInWorkspace('stage', function () use ($node, $storage) {
$this->assertEquals('stage', $this->workspaceManager->getActiveWorkspace()->id());
$stage_node = $storage->loadUnchanged($node->id());
$this->assertEquals('stage node 1', $stage_node->title->value);
......@@ -548,7 +505,7 @@ public function testExecuteInWorkspaceContext() {
// Check that the 'stage' workspace was not persisted by the workspace
// manager.
$this->assertEquals('live', $this->workspacesManager->getActiveWorkspace()->id());
$this->assertEquals('live', $this->workspaceManager->getActiveWorkspace()->id());
}
/**
......@@ -740,18 +697,6 @@ protected function assertWorkspaceAssociation(array $expected, $entity_type_id)
}
}
/**
* Sets a given workspace as active.
*
* @param string $workspace_id
* The ID of the workspace to switch to.
*/
protected function switchToWorkspace($workspace_id) {
// Switch the test runner's context to the specified workspace.
$workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id);
\Drupal::service('workspaces.manager')->setActiveWorkspace($workspace);
}
/**
* Flattens the expectations array defined by testWorkspaces().
*
......
<?php
namespace Drupal\Tests\workspaces\Kernel;
use Drupal\workspaces\Entity\Workspace;
/**
* A trait with common workspaces testing functionality.
*/
trait WorkspaceTestTrait {
/**
* The workspaces manager.
*
* @var \Drupal\workspaces\WorkspaceManagerInterface
*/
protected $workspaceManager;
/**
* An array of test workspaces, keyed by workspace ID.
*
* @var \Drupal\workspaces\WorkspaceInterface[]
*/
protected $workspaces = [];
/**
* Enables the Workspaces module and creates two workspaces.
*/
protected function initializeWorkspacesModule() {
// Enable the Workspaces module here instead of the static::$modules array
// so we can test it with default content.
$this->enableModules(['workspaces']);
$this->container = \Drupal::getContainer();
$this->entityTypeManager = \Drupal::entityTypeManager();
$this->workspaceManager = \Drupal::service('workspaces.manager');
$this->installEntitySchema('workspace');
$this->installEntitySchema('workspace_association');
// Create two workspaces by default, 'live' and 'stage'.
$this->workspaces['live'] = Workspace::create(['id' => 'live']);
$this->workspaces['live']->save();
$this->workspaces['stage'] = Workspace::create(['id' => 'stage']);
$this->workspaces['stage']->save();
$permissions = array_intersect([
'administer nodes',
'create workspace',
'edit any workspace',
'view any workspace',
], array_keys($this->container->get('user.permissions')->getPermissions()));
$this->setCurrentUser($this->createUser($permissions));
}
/**
* Sets a given workspace as active.
*
* @param string $workspace_id
* The ID of the workspace to switch to.
*/
protected function switchToWorkspace($workspace_id) {
// Switch the test runner's context to the specified workspace.
$workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id);
\Drupal::service('workspaces.manager')->setActiveWorkspace($workspace);
}
}
......@@ -56,6 +56,15 @@ function workspaces_form_alter(&$form, FormStateInterface $form_state, $form_id)
->formAlter($form, $form_state, $form_id);
}
/**
* Implements hook_field_info_alter().
*/
function workspaces_field_info_alter(&$definitions) {
\Drupal::service('class_resolver')
->getInstanceFromDefinition(EntityTypeInfo::class)
->fieldInfoAlter($definitions);
}
/**
* Implements hook_entity_load().
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment