summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2018-11-13 17:49:25 (GMT)
committerAlex Pott2018-11-13 17:49:32 (GMT)
commit8e94ef486ced9c0a618fd9e87e6b42d04490d6d9 (patch)
treeb38861a5144481f3cbdec4dba365e495bcd8f339
parent9d47e1d656fdc9edd881ea0f4d19795fa468aa9a (diff)
Issue #2998662 by Sam152, dhirendra.mishra, amateescu, Eli-T: Saving a tagged article in staged workspace causes fatal exception
(cherry picked from commit e417c7f2fd9a1d865d85690e4830d51bae74399e)
-rw-r--r--core/modules/workspaces/src/EntityTypeInfo.php14
-rw-r--r--core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php24
-rw-r--r--core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php65
-rw-r--r--core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php81
-rw-r--r--core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php65
-rw-r--r--core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php67
-rw-r--r--core/modules/workspaces/workspaces.module9
7 files changed, 265 insertions, 60 deletions
diff --git a/core/modules/workspaces/src/EntityTypeInfo.php b/core/modules/workspaces/src/EntityTypeInfo.php
index 3b91f84..5495c7f 100644
--- a/core/modules/workspaces/src/EntityTypeInfo.php
+++ b/core/modules/workspaces/src/EntityTypeInfo.php
@@ -70,4 +70,18 @@ class EntityTypeInfo implements ContainerInjectionInterface {
}
}
+ /**
+ * 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'] = [];
+ }
+ }
+
}
diff --git a/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php b/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php
new file mode 100644
index 0000000..894e343
--- /dev/null
+++ b/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php
@@ -0,0 +1,24 @@
+<?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.';
+
+}
diff --git a/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php b/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php
new file mode 100644
index 0000000..11083df
--- /dev/null
+++ b/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php
@@ -0,0 +1,65 @@
+<?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()]);
+ }
+ }
+
+}
diff --git a/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php b/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php
new file mode 100644
index 0000000..5cef79d
--- /dev/null
+++ b/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php
@@ -0,0 +1,81 @@
+<?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());
+ }
+
+}
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
index f4f76e6..39c365b 100644
--- a/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php
@@ -14,7 +14,6 @@ use Drupal\Tests\node\Traits\NodeCreationTrait;
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.
@@ -37,20 +37,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.
*
* @var int
@@ -101,35 +87,6 @@ class WorkspaceIntegrationTest extends KernelTestBase {
}
/**
- * 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.
*/
public function testWorkspaces() {
@@ -523,7 +480,7 @@ class WorkspaceIntegrationTest extends KernelTestBase {
$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 @@ class WorkspaceIntegrationTest extends KernelTestBase {
$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 @@ class WorkspaceIntegrationTest extends KernelTestBase {
// 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());
}
/**
@@ -741,18 +698,6 @@ class WorkspaceIntegrationTest extends KernelTestBase {
}
/**
- * 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().
*
* @param array $expected
diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php
new file mode 100644
index 0000000..13cff6a
--- /dev/null
+++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php
@@ -0,0 +1,67 @@
+<?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);
+ }
+
+}
diff --git a/core/modules/workspaces/workspaces.module b/core/modules/workspaces/workspaces.module
index f279c43..3e816d2 100644
--- a/core/modules/workspaces/workspaces.module
+++ b/core/modules/workspaces/workspaces.module
@@ -57,6 +57,15 @@ function workspaces_form_alter(&$form, FormStateInterface $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().
*/
function workspaces_entity_load(array &$entities, $entity_type_id) {