summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2018-07-13 12:26:50 (GMT)
committerNathaniel Catchpole2018-07-13 12:26:50 (GMT)
commit099f4146a5d04b12196ff2962a27fbb045cf2af4 (patch)
tree8f919db9c7820597d685e3b997ff96b2fd73320b
parent14a769b7580317bd3d690449c9222492e9308c72 (diff)
Issue #2932462 by phenaproxima, japerry, tim.plunkett: Add EntityContextDefinition for the 80% use case
-rw-r--r--core/lib/Drupal/Core/Annotation/ContextDefinition.php28
-rw-r--r--core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php130
-rw-r--r--core/lib/Drupal/Core/Plugin/Context/ContextProviderInterface.php4
-rw-r--r--core/lib/Drupal/Core/Plugin/Context/EntityContext.php62
-rw-r--r--core/lib/Drupal/Core/Plugin/Context/EntityContextDefinition.php114
-rw-r--r--core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php8
-rw-r--r--core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php11
-rw-r--r--core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php6
-rw-r--r--core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php9
-rw-r--r--core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php8
-rw-r--r--core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php4
-rw-r--r--core/modules/node/src/ContextProvider/NodeRouteContext.php7
-rw-r--r--core/modules/system/tests/modules/plugin_test/src/Plugin/MockBlockManager.php7
-rw-r--r--core/modules/user/src/ContextProvider/CurrentUserContext.php5
-rw-r--r--core/modules/views/src/Plugin/views/argument_validator/Entity.php6
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/Condition/ConditionTestDualUserTest.php11
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/Condition/OptionalContextConditionTest.php8
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php4
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/ContextPluginTest.php4
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php5
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/FactoryTest.php5
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php5
-rw-r--r--core/tests/Drupal/KernelTests/Core/Plugin/PluginTestBase.php10
-rw-r--r--core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php229
-rw-r--r--core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php79
-rw-r--r--core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionIsSatisfiedTest.php308
26 files changed, 749 insertions, 328 deletions
diff --git a/core/lib/Drupal/Core/Annotation/ContextDefinition.php b/core/lib/Drupal/Core/Annotation/ContextDefinition.php
index 0439752..9e28d5a 100644
--- a/core/lib/Drupal/Core/Annotation/ContextDefinition.php
+++ b/core/lib/Drupal/Core/Annotation/ContextDefinition.php
@@ -116,11 +116,37 @@ class ContextDefinition extends Plugin {
if (isset($values['class']) && !in_array('Drupal\Core\Plugin\Context\ContextDefinitionInterface', class_implements($values['class']))) {
throw new \Exception('ContextDefinition class must implement \Drupal\Core\Plugin\Context\ContextDefinitionInterface.');
}
- $class = isset($values['class']) ? $values['class'] : 'Drupal\Core\Plugin\Context\ContextDefinition';
+
+ $class = $this->getDefinitionClass($values);
$this->definition = new $class($values['value'], $values['label'], $values['required'], $values['multiple'], $values['description'], $values['default_value']);
}
/**
+ * Determines the context definition class to use.
+ *
+ * If the annotation specifies a specific context definition class, we use
+ * that. Otherwise, we use \Drupal\Core\Plugin\Context\EntityContextDefinition
+ * if the data type starts with 'entity:', since it contains specialized logic
+ * specific to entities. Otherwise, we fall back to the generic
+ * \Drupal\Core\Plugin\Context\ContextDefinition class.
+ *
+ * @param array $values
+ * The annotation values.
+ *
+ * @return string
+ * The fully-qualified name of the context definition class.
+ */
+ protected function getDefinitionClass(array $values) {
+ if (isset($values['class'])) {
+ return $values['class'];
+ }
+ if (strpos($values['value'], 'entity:') === 0) {
+ return 'Drupal\Core\Plugin\Context\EntityContextDefinition';
+ }
+ return 'Drupal\Core\Plugin\Context\ContextDefinition';
+ }
+
+ /**
* Returns the value of an annotation.
*
* @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface
diff --git a/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php b/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php
index cb90fd4..458c740 100644
--- a/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php
+++ b/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php
@@ -3,11 +3,6 @@
namespace Drupal\Core\Plugin\Context;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
-use Drupal\Core\Entity\ContentEntityStorageInterface;
-use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
-use Drupal\Core\Entity\Plugin\Validation\Constraint\BundleConstraint;
-use Drupal\Core\Entity\Plugin\Validation\Constraint\EntityTypeConstraint;
-use Drupal\Core\Entity\TypedData\EntityDataDefinition;
use Drupal\Core\TypedData\TypedDataTrait;
/**
@@ -15,7 +10,10 @@ use Drupal\Core\TypedData\TypedDataTrait;
*/
class ContextDefinition implements ContextDefinitionInterface {
- use DependencySerializationTrait;
+ use DependencySerializationTrait {
+ __sleep as traitSleep;
+ __wakeup as traitWakeup;
+ }
use TypedDataTrait;
@@ -73,6 +71,38 @@ class ContextDefinition implements ContextDefinitionInterface {
protected $constraints = [];
/**
+ * An EntityContextDefinition instance, for backwards compatibility.
+ *
+ * If this context is created with a data type that starts with 'entity:',
+ * this property will be an instance of EntityContextDefinition, and certain
+ * methods of this object will delegate to their overridden counterparts in
+ * $this->entityContextDefinition.
+ *
+ * This property should be kept private so that it is only accessible to this
+ * class for backwards compatibility reasons. It will be removed in Drupal 9.
+ *
+ * @deprecated
+ * Constructing a context definition for an entity type (i.e., the data type
+ * begins with 'entity:') is deprecated in Drupal 8.6.0. Instead, use
+ * the static factory methods of EntityContextDefinition to create context
+ * definitions for entity types, or the static ::create() method of this
+ * class for any other data type. See https://www.drupal.org/node/2976400
+ * for more information.
+ *
+ * @see ::__construct()
+ * @see ::__sleep()
+ * @see ::__wakeup()
+ * @see ::getConstraintObjects()
+ * @see ::getSampleValues()
+ * @see ::initializeEntityContextDefinition()
+ * @see https://www.drupal.org/node/2932462
+ * @see https://www.drupal.org/node/2976400
+ *
+ * @var \Drupal\Core\Plugin\Context\EntityContextDefinition
+ */
+ private $entityContextDefinition;
+
+ /**
* Creates a new context definition.
*
* @param string $data_type
@@ -111,6 +141,11 @@ class ContextDefinition implements ContextDefinitionInterface {
$this->isMultiple = $multiple;
$this->description = $description;
$this->defaultValue = $default_value;
+
+ if (strpos($data_type, 'entity:') === 0 && !($this instanceof EntityContextDefinition)) {
+ @trigger_error('Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use ' . __NAMESPACE__ . '\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.', E_USER_DEPRECATED);
+ $this->initializeEntityContextDefinition();
+ }
}
/**
@@ -274,7 +309,12 @@ class ContextDefinition implements ContextDefinitionInterface {
$values = [$context->getContextData()];
}
elseif ($definition instanceof self) {
- $values = $definition->getSampleValues();
+ if ($this->entityContextDefinition) {
+ $values = $this->entityContextDefinition->getSampleValues();
+ }
+ else {
+ $values = $definition->getSampleValues();
+ }
}
else {
$values = [];
@@ -309,33 +349,6 @@ class ContextDefinition implements ContextDefinitionInterface {
* The set of typed data object.
*/
protected function getSampleValues() {
- // @todo Move the entity specific logic out of this class in
- // https://www.drupal.org/node/2932462.
- // Get the constraints from the context's definition.
- $constraints = $this->getConstraintObjects();
- // If constraints include EntityType, we generate an entity or adapter.
- if (!empty($constraints['EntityType']) && $constraints['EntityType'] instanceof EntityTypeConstraint) {
- $entity_type_manager = \Drupal::entityTypeManager();
- $entity_type_id = $constraints['EntityType']->type;
- $storage = $entity_type_manager->getStorage($entity_type_id);
- // If the storage can generate a sample entity we might delegate to that.
- if ($storage instanceof ContentEntityStorageInterface) {
- if (!empty($constraints['Bundle']) && $constraints['Bundle'] instanceof BundleConstraint) {
- foreach ($constraints['Bundle']->bundle as $bundle) {
- // We have a bundle, we are bundleable and we can generate a sample.
- yield EntityAdapter::createFromEntity($storage->createWithSampleValues($bundle));
- }
- return;
- }
- }
-
- // Either no bundle, or not bundleable, so generate an entity adapter.
- $definition = EntityDataDefinition::create($entity_type_id);
- yield new EntityAdapter($definition);
- return;
- }
-
- // No entity related constraints, so generate a basic typed data object.
yield $this->getTypedDataManager()->create($this->getDataDefinition());
}
@@ -346,16 +359,13 @@ class ContextDefinition implements ContextDefinitionInterface {
* A list of applied constraints for the context definition.
*/
protected function getConstraintObjects() {
- $constraint_definitions = $this->getConstraints();
-
- // @todo Move the entity specific logic out of this class in
- // https://www.drupal.org/node/2932462.
- // If the data type is an entity, manually add one to the constraints array.
- if (strpos($this->getDataType(), 'entity:') === 0) {
- $entity_type_id = substr($this->getDataType(), 7);
- $constraint_definitions['EntityType'] = ['type' => $entity_type_id];
+ // If the backwards compatibility layer is present, delegate to that.
+ if ($this->entityContextDefinition) {
+ return $this->entityContextDefinition->getConstraintObjects();
}
+ $constraint_definitions = $this->getConstraints();
+
$validation_constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager();
$constraints = [];
foreach ($constraint_definitions as $constraint_name => $constraint_definition) {
@@ -365,4 +375,40 @@ class ContextDefinition implements ContextDefinitionInterface {
return $constraints;
}
+ /**
+ * Implements magic __sleep() method.
+ */
+ public function __sleep() {
+ return array_diff($this->traitSleep(), ['entityContextDefinition']);
+ }
+
+ /**
+ * Implements magic __wakeup() method.
+ */
+ public function __wakeup() {
+ $this->traitWakeup();
+
+ if (strpos($this->getDataType(), 'entity:') === 0) {
+ $this->initializeEntityContextDefinition();
+ }
+ }
+
+ /**
+ * Initializes $this->entityContextDefinition for backwards compatibility.
+ *
+ * This method should be kept private so that it is only accessible to this
+ * class for backwards compatibility reasons. It will be removed in Drupal 9.
+ *
+ * @deprecated
+ */
+ private function initializeEntityContextDefinition() {
+ $this->entityContextDefinition = EntityContextDefinition::create()
+ ->setDataType($this->getDataType())
+ ->setLabel($this->getLabel())
+ ->setRequired($this->isRequired())
+ ->setMultiple($this->isMultiple())
+ ->setDescription($this->getDescription())
+ ->setDefaultValue($this->getDefaultValue());
+ }
+
}
diff --git a/core/lib/Drupal/Core/Plugin/Context/ContextProviderInterface.php b/core/lib/Drupal/Core/Plugin/Context/ContextProviderInterface.php
index 77075e8..3083bc9 100644
--- a/core/lib/Drupal/Core/Plugin/Context/ContextProviderInterface.php
+++ b/core/lib/Drupal/Core/Plugin/Context/ContextProviderInterface.php
@@ -27,7 +27,7 @@ interface ContextProviderInterface {
* $node = ...
*
* // Set that specific node as the value of the 'node' context.
- * $context = new Context(new ContextDefinition('entity:node'), $node);
+ * $context = EntityContext::fromEntity($node);
* return ['node' => $context];
* @endcode
*
@@ -62,7 +62,7 @@ interface ContextProviderInterface {
* // can be configured to use it. When the plugin, for example a block,
* // needs to evaluate the context, the value of this context will be
* // supplied by getRuntimeContexts().
- * $context = new Context(new ContextDefinition('entity:node'));
+ * $context = EntityContext::fromEntityTypeId('node');
* return ['node' => $context];
* @endcode
*
diff --git a/core/lib/Drupal/Core/Plugin/Context/EntityContext.php b/core/lib/Drupal/Core/Plugin/Context/EntityContext.php
new file mode 100644
index 0000000..131360d
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Context/EntityContext.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\Core\Plugin\Context;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+
+/**
+ * Class to provide a specific entity context.
+ */
+class EntityContext extends Context {
+
+ /**
+ * Gets a context from an entity type ID.
+ *
+ * @param string $entity_type_id
+ * Entity type ID from which a definition will be derived.
+ * @param string $label
+ * (optional) The label of the context.
+ *
+ * @return static
+ */
+ public static function fromEntityTypeId($entity_type_id, $label = NULL) {
+ $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
+ return static::fromEntityType($entity_type, $label);
+ }
+
+ /**
+ * Gets a context from an entity type.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+ * Entity type from which a definition will be derived.
+ * @param string $label
+ * (optional) The label of the context.
+ *
+ * @return static
+ */
+ public static function fromEntityType(EntityTypeInterface $entity_type, $label = NULL) {
+ $definition = EntityContextDefinition::fromEntityType($entity_type);
+ if ($label) {
+ $definition->setLabel($label);
+ }
+ return new static($definition);
+ }
+
+ /**
+ * Gets a context object from an entity.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * Entity that provides a context.
+ * @param string $label
+ * (optional) The label of the context.
+ *
+ * @return \Drupal\Core\Plugin\Context\EntityContext
+ */
+ public static function fromEntity(EntityInterface $entity, $label = NULL) {
+ $context = static::fromEntityType($entity->getEntityType(), $label);
+ $context->setContextValue($entity);
+ return $context;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Plugin/Context/EntityContextDefinition.php b/core/lib/Drupal/Core/Plugin/Context/EntityContextDefinition.php
new file mode 100644
index 0000000..0e45f10
--- /dev/null
+++ b/core/lib/Drupal/Core/Plugin/Context/EntityContextDefinition.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace Drupal\Core\Plugin\Context;
+
+use Drupal\Core\Entity\ContentEntityStorageInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
+use Drupal\Core\Entity\Plugin\Validation\Constraint\BundleConstraint;
+use Drupal\Core\Entity\TypedData\EntityDataDefinition;
+
+/**
+ * Defines a class to provide entity context definitions.
+ */
+class EntityContextDefinition extends ContextDefinition {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($data_type = 'any', $label = NULL, $required = TRUE, $multiple = FALSE, $description = NULL, $default_value = NULL) {
+ // Prefix the data type with 'entity:' so that this class can be constructed
+ // like so: new EntityContextDefinition('node')
+ if (strpos($data_type, 'entity:') !== 0) {
+ $data_type = "entity:$data_type";
+ }
+ parent::__construct($data_type, $label, $required, $multiple, $description, $default_value);
+ }
+
+ /**
+ * Returns the entity type ID of this context.
+ *
+ * @return string
+ * The entity type ID.
+ */
+ protected function getEntityTypeId() {
+ // The data type is the entity type ID prefixed by 'entity:' (7 characters).
+ return substr($this->getDataType(), 7);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getConstraintObjects() {
+ if (!$this->getConstraint('EntityType')) {
+ $this->addConstraint('EntityType', [
+ 'type' => $this->getEntityTypeId(),
+ ]);
+ }
+ return parent::getConstraintObjects();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getSampleValues() {
+ // Get the constraints from the context's definition.
+ $constraints = $this->getConstraintObjects();
+ $entity_type_manager = \Drupal::entityTypeManager();
+ $entity_type_id = $this->getEntityTypeId();
+ $storage = $entity_type_manager->getStorage($entity_type_id);
+ // If the storage can generate a sample entity we might delegate to that.
+ if ($storage instanceof ContentEntityStorageInterface) {
+ if (!empty($constraints['Bundle']) && $constraints['Bundle'] instanceof BundleConstraint) {
+ foreach ($constraints['Bundle']->getBundleOption() as $bundle) {
+ // We have a bundle, we are bundleable and we can generate a sample.
+ yield EntityAdapter::createFromEntity($storage->createWithSampleValues($bundle));
+ }
+ return;
+ }
+ }
+
+ // Either no bundle, or not bundleable, so generate an entity adapter.
+ $definition = EntityDataDefinition::create($entity_type_id);
+ yield new EntityAdapter($definition);
+ }
+
+ /**
+ * Creates a context definition from a given entity type ID.
+ *
+ * @param string $entity_type_id
+ * The entity type ID from which to derive a context definition.
+ *
+ * @return static
+ */
+ public static function fromEntityTypeId($entity_type_id) {
+ $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
+ return static::fromEntityType($entity_type);
+ }
+
+ /**
+ * Creates a context definition from a given entity type.
+ *
+ * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+ * The entity type from which to derive a context definition.
+ *
+ * @return static
+ */
+ public static function fromEntityType(EntityTypeInterface $entity_type) {
+ return new static('entity:' . $entity_type->id(), $entity_type->getLabel());
+ }
+
+ /**
+ * Creates a context definition from a given entity object.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * The entity from which to derive a context definition.
+ *
+ * @return static
+ */
+ public static function fromEntity(EntityInterface $entity) {
+ return static::fromEntityType($entity->getEntityType());
+ }
+
+}
diff --git a/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php b/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php
index 9ca8132..dc89d5c 100644
--- a/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php
+++ b/core/modules/block/tests/modules/block_test/src/ContextProvider/MultipleStaticContext.php
@@ -4,9 +4,8 @@ namespace Drupal\block_test\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Session\AccountInterface;
/**
@@ -47,9 +46,8 @@ class MultipleStaticContext implements ContextProviderInterface {
public function getRuntimeContexts(array $unqualified_context_ids) {
$current_user = $this->userStorage->load($this->account->id());
- $context1 = new Context(new ContextDefinition('entity:user', 'User A'), $current_user);
-
- $context2 = new Context(new ContextDefinition('entity:user', 'User B'), $current_user);
+ $context1 = EntityContext::fromEntity($current_user, 'User A');
+ $context2 = EntityContext::fromEntity($current_user, 'User B');
$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['user']);
diff --git a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
index 4df6afe..ff34290 100644
--- a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -5,8 +5,7 @@ namespace Drupal\layout_builder\Entity;
use Drupal\Core\Entity\Entity\EntityViewDisplay as BaseEntityViewDisplay;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
@@ -137,6 +136,7 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
public function buildMultiple(array $entities) {
$build_list = parent::buildMultiple($entities);
+ /** @var \Drupal\Core\Entity\EntityInterface $entity */
foreach ($entities as $id => $entity) {
$sections = $this->getRuntimeSections($entity);
if ($sections) {
@@ -150,9 +150,10 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
// Bypass ::getContexts() in order to use the runtime entity, not a
// sample entity.
$contexts = $this->contextRepository()->getAvailableContexts();
- // @todo Use EntityContextDefinition after resolving
- // https://www.drupal.org/node/2932462.
- $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()])), $entity);
+ $label = new TranslatableMarkup('@entity being viewed', [
+ '@entity' => $entity->getEntityType()->getSingularLabel(),
+ ]);
+ $contexts['layout_builder.entity'] = EntityContext::fromEntity($entity, $label);
foreach ($sections as $delta => $section) {
$build_list[$id]['_layout_builder'][$delta] = $section->toRenderArray($contexts);
}
diff --git a/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php b/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php
index 71b9c1e..3e15fcd 100644
--- a/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php
+++ b/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php
@@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityTypeRepositoryInterface;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Field\FormatterPluginManager;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -118,9 +118,7 @@ class FieldBlockDeriver extends DeriverBase implements ContainerDeriverInterface
// unavailable to place in the block UI.
$derivative['_block_ui_hidden'] = !$field_definition->isDisplayConfigurable('view');
- // @todo Use EntityContextDefinition after resolving
- // https://www.drupal.org/node/2932462.
- $context_definition = new ContextDefinition('entity:' . $entity_type_id, $entity_type_labels[$entity_type_id], TRUE);
+ $context_definition = EntityContextDefinition::fromEntityTypeId($entity_type_id)->setLabel($entity_type_labels[$entity_type_id]);
$context_definition->addConstraint('Bundle', [$bundle]);
$derivative['context'] = [
'entity' => $context_definition,
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
index c21492a..a795f18 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
@@ -8,9 +8,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Url;
use Drupal\field_ui\FieldUI;
use Drupal\layout_builder\DefaultsSectionStorageInterface;
@@ -255,12 +253,9 @@ class DefaultsSectionStorage extends SectionStorageBase implements ContainerFact
public function getContexts() {
$display = $this->getDisplay();
$entity = $this->sampleEntityGenerator->get($display->getTargetEntityTypeId(), $display->getTargetBundle());
- $context_label = new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()]);
- // @todo Use EntityContextDefinition after resolving
- // https://www.drupal.org/node/2932462.
$contexts = [];
- $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", $context_label), $entity);
+ $contexts['layout_builder.entity'] = EntityContext::fromEntity($entity);
return $contexts;
}
diff --git a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
index db38b12..0da2947 100644
--- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
@@ -8,9 +8,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Url;
use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
use Drupal\layout_builder\OverridesSectionStorageInterface;
@@ -213,9 +211,7 @@ class OverridesSectionStorage extends SectionStorageBase implements ContainerFac
*/
public function getContexts() {
$entity = $this->getEntity();
- // @todo Use EntityContextDefinition after resolving
- // https://www.drupal.org/node/2932462.
- $contexts['layout_builder.entity'] = new Context(new ContextDefinition("entity:{$entity->getEntityTypeId()}", new TranslatableMarkup('@entity being viewed', ['@entity' => $entity->getEntityType()->getLabel()])), $entity);
+ $contexts['layout_builder.entity'] = EntityContext::fromEntity($entity);
return $contexts;
}
diff --git a/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php b/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php
index d77a239..d5246a0 100644
--- a/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php
+++ b/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php
@@ -10,7 +10,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterPluginManager;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Session\AccountInterface;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\layout_builder\Plugin\Block\FieldBlock;
@@ -207,7 +207,7 @@ class FieldBlockTest extends EntityKernelTestBase {
'admin_label' => 'Test Block',
'bundles' => ['entity_test'],
'context' => [
- 'entity' => new ContextDefinition('entity:entity_test', 'Test', TRUE),
+ 'entity' => EntityContextDefinition::fromEntityTypeId('entity_test')->setLabel('Test'),
],
];
$formatter_manager = $this->prophesize(FormatterPluginManager::class);
diff --git a/core/modules/node/src/ContextProvider/NodeRouteContext.php b/core/modules/node/src/ContextProvider/NodeRouteContext.php
index 2e10a8a..8f0acd7 100644
--- a/core/modules/node/src/ContextProvider/NodeRouteContext.php
+++ b/core/modules/node/src/ContextProvider/NodeRouteContext.php
@@ -4,8 +4,9 @@ namespace Drupal\node\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\Entity\Node;
use Drupal\Core\StringTranslation\StringTranslationTrait;
@@ -39,7 +40,7 @@ class NodeRouteContext implements ContextProviderInterface {
*/
public function getRuntimeContexts(array $unqualified_context_ids) {
$result = [];
- $context_definition = new ContextDefinition('entity:node', NULL, FALSE);
+ $context_definition = EntityContextDefinition::create('node')->setRequired(FALSE);
$value = NULL;
if (($route_object = $this->routeMatch->getRouteObject()) && ($route_contexts = $route_object->getOption('parameters')) && isset($route_contexts['node'])) {
if ($node = $this->routeMatch->getParameter('node')) {
@@ -65,7 +66,7 @@ class NodeRouteContext implements ContextProviderInterface {
* {@inheritdoc}
*/
public function getAvailableContexts() {
- $context = new Context(new ContextDefinition('entity:node', $this->t('Node from URL')));
+ $context = EntityContext::fromEntityTypeId('node', $this->t('Node from URL'));
return ['node' => $context];
}
diff --git a/core/modules/system/tests/modules/plugin_test/src/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/src/Plugin/MockBlockManager.php
index 78a02a9..de9fc33 100644
--- a/core/modules/system/tests/modules/plugin_test/src/Plugin/MockBlockManager.php
+++ b/core/modules/system/tests/modules/plugin_test/src/Plugin/MockBlockManager.php
@@ -7,6 +7,7 @@ use Drupal\Component\Plugin\Discovery\StaticDiscovery;
use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
use Drupal\Component\Plugin\Factory\ReflectionFactory;
use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
/**
* Defines a plugin manager used by Plugin API derivative unit tests.
@@ -140,7 +141,11 @@ class MockBlockManager extends PluginManagerBase {
// a TranslatableMarkup and we will do assertEqual() checks on arrays that
// include ContextDefinition objects, and var_export() has problems
// printing TranslatableMarkup objects.
- return new ContextDefinition($data_type, (string) $label, $required);
+ $class = ContextDefinition::class;
+ if (strpos($data_type, 'entity:') === 0) {
+ $class = EntityContextDefinition::class;
+ }
+ return new $class($data_type, (string) $label, $required);
}
}
diff --git a/core/modules/user/src/ContextProvider/CurrentUserContext.php b/core/modules/user/src/ContextProvider/CurrentUserContext.php
index aacc5f7..5e17569 100644
--- a/core/modules/user/src/ContextProvider/CurrentUserContext.php
+++ b/core/modules/user/src/ContextProvider/CurrentUserContext.php
@@ -4,9 +4,8 @@ namespace Drupal\user\ContextProvider;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
@@ -56,7 +55,7 @@ class CurrentUserContext implements ContextProviderInterface {
$current_user->_skipProtectedUserFieldConstraint = TRUE;
}
- $context = new Context(new ContextDefinition('entity:user', $this->t('Current user')), $current_user);
+ $context = EntityContext::fromEntity($current_user, $this->t('Current user'));
$cacheability = new CacheableMetadata();
$cacheability->setCacheContexts(['user']);
$context->addCacheableDependency($cacheability);
diff --git a/core/modules/views/src/Plugin/views/argument_validator/Entity.php b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
index 896d24b..befbbe7 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/Entity.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
@@ -5,7 +5,7 @@ namespace Drupal\views\Plugin\views\argument_validator;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -233,7 +233,9 @@ class Entity extends ArgumentValidatorPluginBase {
* {@inheritdoc}
*/
public function getContextDefinition() {
- return new ContextDefinition('entity:' . $this->definition['entity_type'], $this->argument->adminLabel(), FALSE);
+ return EntityContextDefinition::fromEntityTypeId($this->definition['entity_type'])
+ ->setLabel($this->argument->adminLabel())
+ ->setRequired(FALSE);
}
}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ConditionTestDualUserTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ConditionTestDualUserTest.php
index 5d57d57..b0aece9 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ConditionTestDualUserTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ConditionTestDualUserTest.php
@@ -2,8 +2,7 @@
namespace Drupal\KernelTests\Core\Plugin\Condition;
-use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
@@ -66,8 +65,7 @@ class ConditionTestDualUserTest extends KernelTestBase {
'user1' => 'anonymous',
'user2' => 'anonymous',
]);
- $definition = new ContextDefinition('entity:user');
- $contexts['anonymous'] = new Context($definition, $this->anonymous);
+ $contexts['anonymous'] = EntityContext::fromEntity($this->anonymous);
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
$this->assertTrue($condition->execute());
}
@@ -83,9 +81,8 @@ class ConditionTestDualUserTest extends KernelTestBase {
'user1' => 'anonymous',
'user2' => 'authenticated',
]);
- $definition = new ContextDefinition('entity:user');
- $contexts['anonymous'] = new Context($definition, $this->anonymous);
- $contexts['authenticated'] = new Context($definition, $this->authenticated);
+ $contexts['anonymous'] = EntityContext::fromEntity($this->anonymous);
+ $contexts['authenticated'] = EntityContext::fromEntity($this->authenticated);
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
$this->assertFalse($condition->execute());
}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/OptionalContextConditionTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/OptionalContextConditionTest.php
index 96c8bac..e0a4a09 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/OptionalContextConditionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/OptionalContextConditionTest.php
@@ -3,7 +3,8 @@
namespace Drupal\KernelTests\Core\Plugin\Condition;
use Drupal\Core\Plugin\Context\Context;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
@@ -44,7 +45,7 @@ class OptionalContextConditionTest extends KernelTestBase {
->setContextMapping([
'node' => 'node',
]);
- $definition = new ContextDefinition('entity:node');
+ $definition = EntityContextDefinition::fromEntityTypeId('node');
$contexts['node'] = (new Context($definition));
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
$this->assertTrue($condition->execute());
@@ -61,9 +62,8 @@ class OptionalContextConditionTest extends KernelTestBase {
->setContextMapping([
'node' => 'node',
]);
- $definition = new ContextDefinition('entity:node');
$node = Node::create(['type' => 'example']);
- $contexts['node'] = new Context($definition, $node);
+ $contexts['node'] = EntityContext::fromEntity($node);
\Drupal::service('context.handler')->applyContextMapping($condition, $contexts);
$this->assertFalse($condition->execute());
}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php
index 3df71cb..842f76b 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php
@@ -2,8 +2,8 @@
namespace Drupal\KernelTests\Core\Plugin;
-use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\KernelTests\KernelTestBase;
@@ -30,7 +30,7 @@ class ContextDefinitionTest extends KernelTestBase {
// Assert that these violations do not prevent it from satisfying the
// requirements of another object.
$requirement = new ContextDefinition('any');
- $context = new Context(new ContextDefinition('entity:entity_test'), $value);
+ $context = EntityContext::fromEntity($value);
$this->assertTrue($requirement->isSatisfiedBy($context));
}
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/ContextPluginTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/ContextPluginTest.php
index a9ec4b8..8a1fa48 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/ContextPluginTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/ContextPluginTest.php
@@ -3,7 +3,7 @@
namespace Drupal\KernelTests\Core\Plugin;
use Drupal\Component\Plugin\Exception\ContextException;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
@@ -45,7 +45,7 @@ class ContextPluginTest extends KernelTestBase {
}
// Test the getContextDefinitions() method.
- $user_context_definition = ContextDefinition::create('entity:user')->setLabel(t('User'));
+ $user_context_definition = EntityContextDefinition::fromEntityTypeId('user')->setLabel(t('User'));
$this->assertEqual($plugin->getContextDefinitions()['user']->getLabel(), $user_context_definition->getLabel());
// Test the getContextDefinition() method for a valid context.
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php
index 251abbf..519d737 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/DerivativeTest.php
@@ -10,6 +10,11 @@ namespace Drupal\KernelTests\Core\Plugin;
class DerivativeTest extends PluginTestBase {
/**
+ * {@inheritdoc}
+ */
+ public static $modules = ['node', 'user'];
+
+ /**
* Tests getDefinitions() and getDefinition() with a derivativeDecorator.
*/
public function testDerivativeDecorator() {
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/FactoryTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/FactoryTest.php
index 50da5cf..ed77929 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/FactoryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/FactoryTest.php
@@ -12,6 +12,11 @@ use Drupal\Component\Plugin\Exception\ExceptionInterface;
class FactoryTest extends PluginTestBase {
/**
+ * {@inheritdoc}
+ */
+ public static $modules = ['node', 'user'];
+
+ /**
* Test that DefaultFactory can create a plugin instance.
*/
public function testDefaultFactory() {
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php
index 454165d..20ba65c 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/InspectionTest.php
@@ -10,6 +10,11 @@ namespace Drupal\KernelTests\Core\Plugin;
class InspectionTest extends PluginTestBase {
/**
+ * {@inheritdoc}
+ */
+ public static $modules = ['node', 'user'];
+
+ /**
* Ensure the test plugins correctly implement getPluginId() and getPluginDefinition().
*/
public function testInspection() {
diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/PluginTestBase.php b/core/tests/Drupal/KernelTests/Core/Plugin/PluginTestBase.php
index fac49b2..1d3734f 100644
--- a/core/tests/Drupal/KernelTests/Core/Plugin/PluginTestBase.php
+++ b/core/tests/Drupal/KernelTests/Core/Plugin/PluginTestBase.php
@@ -2,7 +2,7 @@
namespace Drupal\KernelTests\Core\Plugin;
-use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\KernelTests\KernelTestBase;
use Drupal\plugin_test\Plugin\TestPluginManager;
use Drupal\plugin_test\Plugin\MockBlockManager;
@@ -93,7 +93,7 @@ abstract class PluginTestBase extends KernelTestBase {
'label' => 'User name',
'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
'context' => [
- 'user' => new ContextDefinition('entity:user', 'User'),
+ 'user' => EntityContextDefinition::fromEntityTypeId('user')->setLabel('User'),
],
],
'user_name_optional' => [
@@ -101,7 +101,7 @@ abstract class PluginTestBase extends KernelTestBase {
'label' => 'User name optional',
'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
'context' => [
- 'user' => new ContextDefinition('entity:user', 'User', FALSE),
+ 'user' => EntityContextDefinition::fromEntityTypeId('user')->setLabel('User')->setRequired(FALSE),
],
],
'string_context' => [
@@ -114,8 +114,8 @@ abstract class PluginTestBase extends KernelTestBase {
'label' => 'Complex context',
'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock',
'context' => [
- 'user' => new ContextDefinition('entity:user', 'User'),
- 'node' => new ContextDefinition('entity:node', 'Node'),
+ 'user' => EntityContextDefinition::fromEntityTypeId('user')->setLabel('User'),
+ 'node' => EntityContextDefinition::fromEntityTypeId('node')->setLabel('Node'),
],
],
];
diff --git a/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php b/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php
index ce33d7f..c93e77d 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php
@@ -5,13 +5,6 @@ namespace Drupal\Tests\Core\Plugin\Context;
use Drupal\Core\Cache\NullBackend;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Entity\ContentEntityStorageInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\Core\Entity\EntityType;
-use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
-use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
@@ -28,27 +21,6 @@ use Prophecy\Argument;
class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
/**
- * The entity type manager.
- *
- * @var \Drupal\Core\Entity\EntityTypeManagerInterface
- */
- protected $entityTypeManager;
-
- /**
- * The entity manager.
- *
- * @var \Drupal\Core\Entity\EntityManagerInterface
- */
- protected $entityManager;
-
- /**
- * The entity type bundle info.
- *
- * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
- */
- protected $entityTypeBundleInfo;
-
- /**
* {@inheritdoc}
*/
protected function setUp() {
@@ -57,7 +29,6 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
$namespaces = new \ArrayObject([
'Drupal\\Core\\TypedData' => $this->root . '/core/lib/Drupal/Core/TypedData',
'Drupal\\Core\\Validation' => $this->root . '/core/lib/Drupal/Core/Validation',
- 'Drupal\\Core\\Entity' => $this->root . '/core/lib/Drupal/Core/Entity',
]);
$cache_backend = new NullBackend('cache');
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
@@ -71,21 +42,13 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
$type_data_manager = new TypedDataManager($namespaces, $cache_backend, $module_handler->reveal(), $class_resolver->reveal());
$type_data_manager->setValidationConstraintManager(new ConstraintManager($namespaces, $cache_backend, $module_handler->reveal()));
- $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
- $this->entityManager = $this->prophesize(EntityManagerInterface::class);
-
- $this->entityTypeBundleInfo = $this->prophesize(EntityTypeBundleInfoInterface::class);
-
$container = new ContainerBuilder();
$container->set('typed_data_manager', $type_data_manager);
- $container->set('entity_type.manager', $this->entityTypeManager->reveal());
- $container->set('entity.manager', $this->entityManager->reveal());
- $container->set('entity_type.bundle.info', $this->entityTypeBundleInfo->reveal());
\Drupal::setContainer($container);
}
/**
- * Asserts that the requirement is satisfied as expected.
+ * Tests that context requirements is satisfied as expected.
*
* @param bool $expected
* The expected outcome.
@@ -95,13 +58,7 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
* The context definition to check.
* @param mixed $value
* (optional) The value to set on the context, defaults to NULL.
- */
- protected function assertRequirementIsSatisfied($expected, ContextDefinition $requirement, ContextDefinition $definition, $value = NULL) {
- $context = new Context($definition, $value);
- $this->assertSame($expected, $requirement->isSatisfiedBy($context));
- }
-
- /**
+ *
* @covers ::isSatisfiedBy
* @covers ::getSampleValues
* @covers ::getConstraintObjects
@@ -109,22 +66,8 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
* @dataProvider providerTestIsSatisfiedBy
*/
public function testIsSatisfiedBy($expected, ContextDefinition $requirement, ContextDefinition $definition, $value = NULL) {
- $entity_storage = $this->prophesize(EntityStorageInterface::class);
- $content_entity_storage = $this->prophesize(ContentEntityStorageInterface::class);
- $this->entityTypeManager->getStorage('test_config')->willReturn($entity_storage->reveal());
- $this->entityTypeManager->getStorage('test_content')->willReturn($content_entity_storage->reveal());
- $this->entityManager->getDefinitions()->willReturn([
- 'test_config' => new EntityType(['id' => 'test_config']),
- 'test_content' => new EntityType(['id' => 'test_content']),
- ]);
- $this->entityTypeBundleInfo->getBundleInfo('test_config')->willReturn([
- 'test_config' => ['label' => 'test_config'],
- ]);
- $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
- 'test_content' => ['label' => 'test_content'],
- ]);
-
- $this->assertRequirementIsSatisfied($expected, $requirement, $definition, $value);
+ $context = new Context($definition, $value);
+ $this->assertSame($expected, $requirement->isSatisfiedBy($context));
}
/**
@@ -167,36 +110,6 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
new ContextDefinition('any'),
5,
];
-
- // Entities without bundles.
- $data['content entity, matching type, no value'] = [
- TRUE,
- new ContextDefinition('entity:test_content'),
- new ContextDefinition('entity:test_content'),
- ];
- $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
- $entity->getIterator()->willReturn(new \ArrayIterator([]));
- $entity->getCacheContexts()->willReturn([]);
- $entity->getCacheTags()->willReturn([]);
- $entity->getCacheMaxAge()->willReturn(0);
- $entity->getEntityTypeId()->willReturn('test_content');
- $data['content entity, matching type, correct value'] = [
- TRUE,
- new ContextDefinition('entity:test_content'),
- new ContextDefinition('entity:test_content'),
- $entity->reveal(),
- ];
- $data['content entity, incorrect manual constraint'] = [
- TRUE,
- new ContextDefinition('entity:test_content'),
- (new ContextDefinition('entity:test_content'))->addConstraint('EntityType', 'test_config'),
- ];
- $data['config entity, matching type, no value'] = [
- TRUE,
- new ContextDefinition('entity:test_config'),
- new ContextDefinition('entity:test_config'),
- ];
-
// Inherited context definition class.
$data['both any, inherited context requirement definition'] = [
TRUE,
@@ -207,138 +120,4 @@ class ContextDefinitionIsSatisfiedTest extends UnitTestCase {
return $data;
}
- /**
- * @covers ::isSatisfiedBy
- * @covers ::getSampleValues
- * @covers ::getConstraintObjects
- *
- * @dataProvider providerTestIsSatisfiedByGenerateBundledEntity
- */
- public function testIsSatisfiedByGenerateBundledEntity($expected, array $requirement_bundles, array $candidate_bundles, array $bundles_to_instantiate = NULL) {
- // If no bundles are explicitly specified, instantiate all bundles.
- if (!$bundles_to_instantiate) {
- $bundles_to_instantiate = $candidate_bundles;
- }
-
- $content_entity_storage = $this->prophesize(ContentEntityStorageInterface::class);
- foreach ($bundles_to_instantiate as $bundle) {
- $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
- $entity->getEntityTypeId()->willReturn('test_content');
- $entity->getIterator()->willReturn(new \ArrayIterator([]));
- $entity->bundle()->willReturn($bundle);
- $content_entity_storage->createWithSampleValues($bundle)
- ->willReturn($entity->reveal())
- ->shouldBeCalled();
- }
-
- $this->entityTypeManager->getStorage('test_content')->willReturn($content_entity_storage->reveal());
- $this->entityManager->getDefinitions()->willReturn([
- 'test_content' => new EntityType(['id' => 'test_content']),
- ]);
-
- $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
- 'first_bundle' => ['label' => 'First bundle'],
- 'second_bundle' => ['label' => 'Second bundle'],
- 'third_bundle' => ['label' => 'Third bundle'],
- ]);
-
- $requirement = new ContextDefinition('entity:test_content');
- if ($requirement_bundles) {
- $requirement->addConstraint('Bundle', $requirement_bundles);
- }
- $definition = (new ContextDefinition('entity:test_content'))->addConstraint('Bundle', $candidate_bundles);
- $this->assertRequirementIsSatisfied($expected, $requirement, $definition);
- }
-
- /**
- * Provides test data for ::testIsSatisfiedByGenerateBundledEntity().
- */
- public function providerTestIsSatisfiedByGenerateBundledEntity() {
- $data = [];
- $data['no requirement'] = [
- TRUE,
- [],
- ['first_bundle'],
- ];
- $data['single requirement'] = [
- TRUE,
- ['first_bundle'],
- ['first_bundle'],
- ];
- $data['single requirement, multiple candidates, satisfies last candidate'] = [
- TRUE,
- ['third_bundle'],
- ['first_bundle', 'second_bundle', 'third_bundle'],
- ];
- $data['single requirement, multiple candidates, satisfies first candidate'] = [
- TRUE,
- ['first_bundle'],
- ['first_bundle', 'second_bundle', 'third_bundle'],
- // Once the first match is found, subsequent candidates are not checked.
- ['first_bundle'],
- ];
- $data['unsatisfied requirement'] = [
- FALSE,
- ['second_bundle'],
- ['first_bundle', 'third_bundle'],
- ];
- $data['multiple requirements'] = [
- TRUE,
- ['first_bundle', 'second_bundle'],
- ['first_bundle'],
- ];
- return $data;
- }
-
- /**
- * @covers ::isSatisfiedBy
- * @covers ::getSampleValues
- * @covers ::getConstraintObjects
- *
- * @dataProvider providerTestIsSatisfiedByPassBundledEntity
- */
- public function testIsSatisfiedByPassBundledEntity($expected, $requirement_constraint) {
- $this->entityManager->getDefinitions()->willReturn([
- 'test_content' => new EntityType(['id' => 'test_content']),
- ]);
- $this->entityTypeManager->getStorage('test_content')->shouldNotBeCalled();
-
- $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
- 'first_bundle' => ['label' => 'First bundle'],
- 'second_bundle' => ['label' => 'Second bundle'],
- 'third_bundle' => ['label' => 'Third bundle'],
- ]);
-
- $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
- $entity->getEntityTypeId()->willReturn('test_content');
- $entity->getIterator()->willReturn(new \ArrayIterator([]));
- $entity->getCacheContexts()->willReturn([]);
- $entity->getCacheTags()->willReturn([]);
- $entity->getCacheMaxAge()->willReturn(0);
- $entity->bundle()->willReturn('third_bundle');
-
- $requirement = new ContextDefinition('entity:test_content');
- if ($requirement_constraint) {
- $requirement->addConstraint('Bundle', $requirement_constraint);
- }
- $definition = new ContextDefinition('entity:test_content');
- $this->assertRequirementIsSatisfied($expected, $requirement, $definition, $entity->reveal());
- }
-
- /**
- * Provides test data for ::testIsSatisfiedByPassBundledEntity().
- */
- public function providerTestIsSatisfiedByPassBundledEntity() {
- $data = [];
- $data[] = [TRUE, []];
- $data[] = [FALSE, ['first_bundle']];
- $data[] = [FALSE, ['second_bundle']];
- $data[] = [TRUE, ['third_bundle']];
- $data[] = [TRUE, ['first_bundle', 'second_bundle', 'third_bundle']];
- $data[] = [FALSE, ['first_bundle', 'second_bundle']];
- $data[] = [TRUE, ['first_bundle', 'third_bundle']];
- $data[] = [TRUE, ['second_bundle', 'third_bundle']];
- return $data;
- }
-
}
diff --git a/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php b/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php
new file mode 100644
index 0000000..1a14692
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Drupal\Tests\Core\Plugin\Context;
+
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Plugin\Context\ContextDefinition
+ *
+ * @group Plugin
+ * @group legacy
+ */
+class EntityContextDefinitionDeprecationTest extends UnitTestCase {
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ // Mock container services needed for constraint validation.
+ $constraint_manager = $this->prophesize('\Drupal\Core\Validation\ConstraintManager');
+ $constraint_manager->create(Argument::type('string'), Argument::any())->willReturn(TRUE);
+
+ $typed_data_manager = $this->prophesize('\Drupal\Core\TypedData\TypedDataManagerInterface');
+ $typed_data_manager->getValidationConstraintManager()->willReturn($constraint_manager->reveal());
+
+ $validator = $this->prophesize('\Symfony\Component\Validator\Validator\ValidatorInterface')
+ ->reveal();
+ $typed_data_manager->getValidator()->willReturn($validator);
+
+ $container = new ContainerBuilder();
+ $container->set('typed_data_manager', $typed_data_manager->reveal());
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information.
+ */
+ public function testDeprecationNotice() {
+ $definition = new ContextDefinition('entity:node');
+ // The code paths we're testing are private and protected, so use reflection
+ // to manipulate protected properties.
+ $reflector = new \ReflectionObject($definition);
+
+ // Ensure that the BC object was created correctly.
+ $this->assertTrue($reflector->hasProperty('entityContextDefinition'));
+ $property = $reflector->getProperty('entityContextDefinition');
+ $property->setAccessible(TRUE);
+ $this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition));
+
+ // Ensure that getConstraintObjects() adds the EntityType constraint.
+ $method = $reflector->getMethod('getConstraintObjects');
+ $method->setAccessible(TRUE);
+ $this->assertArrayHasKey('EntityType', $method->invoke($definition));
+
+ // Ensure that the BC object's getSampleValues() method is called during
+ // validation.
+ $bc_mock = $this->getMockBuilder(EntityContextDefinition::class)
+ ->setMethods(['getSampleValues'])
+ ->getMock();
+
+ $bc_mock->expects($this->atLeastOnce())
+ ->method('getSampleValues')
+ ->willReturn([]);
+ $property->setValue($definition, $bc_mock);
+ $definition->isSatisfiedBy(new Context($definition));
+
+ // Ensure that the BC layer survives serialization and unserialization.
+ $definition = unserialize(serialize($definition));
+ $this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition));
+ }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionIsSatisfiedTest.php b/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionIsSatisfiedTest.php
new file mode 100644
index 0000000..1552c12
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionIsSatisfiedTest.php
@@ -0,0 +1,308 @@
+<?php
+
+namespace Drupal\Tests\Core\Plugin\Context;
+
+use Drupal\Core\Cache\NullBackend;
+use Drupal\Core\DependencyInjection\ClassResolverInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\ContentEntityStorageInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityType;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Plugin\Context\EntityContextDefinition;
+use Drupal\Core\TypedData\TypedDataManager;
+use Drupal\Core\Validation\ConstraintManager;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Argument;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Plugin\Context\EntityContextDefinition
+ * @group Plugin
+ */
+class EntityContextDefinitionIsSatisfiedTest extends UnitTestCase {
+
+ /**
+ * The entity type manager.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+ */
+ protected $entityTypeManager;
+
+ /**
+ * The entity manager.
+ *
+ * @var \Drupal\Core\Entity\EntityManagerInterface
+ */
+ protected $entityManager;
+
+ /**
+ * The entity type bundle info.
+ *
+ * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
+ */
+ protected $entityTypeBundleInfo;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp() {
+ parent::setUp();
+
+ $namespaces = new \ArrayObject([
+ 'Drupal\\Core\\TypedData' => $this->root . '/core/lib/Drupal/Core/TypedData',
+ 'Drupal\\Core\\Validation' => $this->root . '/core/lib/Drupal/Core/Validation',
+ 'Drupal\\Core\\Entity' => $this->root . '/core/lib/Drupal/Core/Entity',
+ ]);
+ $cache_backend = new NullBackend('cache');
+ $module_handler = $this->prophesize(ModuleHandlerInterface::class);
+
+ $class_resolver = $this->prophesize(ClassResolverInterface::class);
+ $class_resolver->getInstanceFromDefinition(Argument::type('string'))->will(function ($arguments) {
+ $class_name = $arguments[0];
+ return new $class_name();
+ });
+
+ $type_data_manager = new TypedDataManager($namespaces, $cache_backend, $module_handler->reveal(), $class_resolver->reveal());
+ $type_data_manager->setValidationConstraintManager(new ConstraintManager($namespaces, $cache_backend, $module_handler->reveal()));
+
+ $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class);
+ $this->entityManager = $this->prophesize(EntityManagerInterface::class);
+
+ $this->entityTypeBundleInfo = $this->prophesize(EntityTypeBundleInfoInterface::class);
+
+ $container = new ContainerBuilder();
+ $container->set('typed_data_manager', $type_data_manager);
+ $container->set('entity_type.manager', $this->entityTypeManager->reveal());
+ $container->set('entity.manager', $this->entityManager->reveal());
+ $container->set('entity_type.bundle.info', $this->entityTypeBundleInfo->reveal());
+ \Drupal::setContainer($container);
+ }
+
+ /**
+ * Asserts that the requirement is satisfied as expected.
+ *
+ * @param bool $expected
+ * The expected outcome.
+ * @param \Drupal\Core\Plugin\Context\EntityContextDefinition $requirement
+ * The requirement to check against.
+ * @param \Drupal\Core\Plugin\Context\EntityContextDefinition $definition
+ * The context definition to check.
+ * @param mixed $value
+ * (optional) The value to set on the context, defaults to NULL.
+ */
+ protected function assertRequirementIsSatisfied($expected, EntityContextDefinition $requirement, EntityContextDefinition $definition, $value = NULL) {
+ $context = new EntityContext($definition, $value);
+ $this->assertSame($expected, $requirement->isSatisfiedBy($context));
+ }
+
+ /**
+ * @covers ::isSatisfiedBy
+ * @covers ::getSampleValues
+ * @covers ::getConstraintObjects
+ *
+ * @dataProvider providerTestIsSatisfiedBy
+ */
+ public function testIsSatisfiedBy($expected, EntityContextDefinition $requirement, EntityContextDefinition $definition, $value = NULL) {
+ $entity_storage = $this->prophesize(EntityStorageInterface::class);
+ $content_entity_storage = $this->prophesize(ContentEntityStorageInterface::class);
+ $this->entityTypeManager->getStorage('test_config')->willReturn($entity_storage->reveal());
+ $this->entityTypeManager->getStorage('test_content')->willReturn($content_entity_storage->reveal());
+ $this->entityManager->getDefinitions()->willReturn([
+ 'test_config' => new EntityType(['id' => 'test_config']),
+ 'test_content' => new EntityType(['id' => 'test_content']),
+ ]);
+ $this->entityTypeBundleInfo->getBundleInfo('test_config')->willReturn([
+ 'test_config' => ['label' => 'test_config'],
+ ]);
+ $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
+ 'test_content' => ['label' => 'test_content'],
+ ]);
+
+ $this->assertRequirementIsSatisfied($expected, $requirement, $definition, $value);
+ }
+
+ /**
+ * Provides test data for ::testIsSatisfiedBy().
+ */
+ public function providerTestIsSatisfiedBy() {
+ $data = [];
+
+ $content = new EntityType(['id' => 'test_content']);
+ $config = new EntityType(['id' => 'test_config']);
+
+ // Entities without bundles.
+ $data['content entity, matching type, no value'] = [
+ TRUE,
+ EntityContextDefinition::fromEntityType($content),
+ EntityContextDefinition::fromEntityType($content),
+ ];
+ $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
+ $entity->getIterator()->willReturn(new \ArrayIterator([]));
+ $entity->getCacheContexts()->willReturn([]);
+ $entity->getCacheTags()->willReturn([]);
+ $entity->getCacheMaxAge()->willReturn(0);
+ $entity->getEntityTypeId()->willReturn('test_content');
+ $data['content entity, matching type, correct value'] = [
+ TRUE,
+ EntityContextDefinition::fromEntityType($content),
+ EntityContextDefinition::fromEntityType($content),
+ $entity->reveal(),
+ ];
+ $data['content entity, incorrect manual constraint'] = [
+ TRUE,
+ EntityContextDefinition::fromEntityType($content),
+ EntityContextDefinition::fromEntityType($content)->addConstraint('EntityType', 'test_config'),
+ ];
+ $data['config entity, matching type, no value'] = [
+ TRUE,
+ EntityContextDefinition::fromEntityType($config),
+ EntityContextDefinition::fromEntityType($config),
+ ];
+
+ return $data;
+ }
+
+ /**
+ * @covers ::isSatisfiedBy
+ * @covers ::getSampleValues
+ * @covers ::getConstraintObjects
+ *
+ * @dataProvider providerTestIsSatisfiedByGenerateBundledEntity
+ */
+ public function testIsSatisfiedByGenerateBundledEntity($expected, array $requirement_bundles, array $candidate_bundles, array $bundles_to_instantiate = NULL) {
+ // If no bundles are explicitly specified, instantiate all bundles.
+ if (!$bundles_to_instantiate) {
+ $bundles_to_instantiate = $candidate_bundles;
+ }
+
+ $content_entity_storage = $this->prophesize(ContentEntityStorageInterface::class);
+ foreach ($bundles_to_instantiate as $bundle) {
+ $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
+ $entity->getEntityTypeId()->willReturn('test_content');
+ $entity->getIterator()->willReturn(new \ArrayIterator([]));
+ $entity->bundle()->willReturn($bundle);
+ $content_entity_storage->createWithSampleValues($bundle)
+ ->willReturn($entity->reveal())
+ ->shouldBeCalled();
+ }
+
+ $entity_type = new EntityType(['id' => 'test_content']);
+
+ $this->entityTypeManager->getStorage('test_content')->willReturn($content_entity_storage->reveal());
+ $this->entityManager->getDefinitions()->willReturn([
+ 'test_content' => $entity_type,
+ ]);
+
+ $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
+ 'first_bundle' => ['label' => 'First bundle'],
+ 'second_bundle' => ['label' => 'Second bundle'],
+ 'third_bundle' => ['label' => 'Third bundle'],
+ ]);
+
+ $requirement = EntityContextDefinition::fromEntityType($entity_type);
+ if ($requirement_bundles) {
+ $requirement->addConstraint('Bundle', $requirement_bundles);
+ }
+ $definition = EntityContextDefinition::fromEntityType($entity_type)->addConstraint('Bundle', $candidate_bundles);
+ $this->assertRequirementIsSatisfied($expected, $requirement, $definition);
+ }
+
+ /**
+ * Provides test data for ::testIsSatisfiedByGenerateBundledEntity().
+ */
+ public function providerTestIsSatisfiedByGenerateBundledEntity() {
+ $data = [];
+ $data['no requirement'] = [
+ TRUE,
+ [],
+ ['first_bundle'],
+ ];
+ $data['single requirement'] = [
+ TRUE,
+ ['first_bundle'],
+ ['first_bundle'],
+ ];
+ $data['single requirement, multiple candidates, satisfies last candidate'] = [
+ TRUE,
+ ['third_bundle'],
+ ['first_bundle', 'second_bundle', 'third_bundle'],
+ ];
+ $data['single requirement, multiple candidates, satisfies first candidate'] = [
+ TRUE,
+ ['first_bundle'],
+ ['first_bundle', 'second_bundle', 'third_bundle'],
+ // Once the first match is found, subsequent candidates are not checked.
+ ['first_bundle'],
+ ];
+ $data['unsatisfied requirement'] = [
+ FALSE,
+ ['second_bundle'],
+ ['first_bundle', 'third_bundle'],
+ ];
+ $data['multiple requirements'] = [
+ TRUE,
+ ['first_bundle', 'second_bundle'],
+ ['first_bundle'],
+ ];
+ return $data;
+ }
+
+ /**
+ * @covers ::isSatisfiedBy
+ * @covers ::getSampleValues
+ * @covers ::getConstraintObjects
+ *
+ * @dataProvider providerTestIsSatisfiedByPassBundledEntity
+ */
+ public function testIsSatisfiedByPassBundledEntity($expected, $requirement_constraint) {
+ $entity_type = new EntityType(['id' => 'test_content']);
+ $this->entityManager->getDefinitions()->willReturn([
+ 'test_content' => $entity_type,
+ ]);
+ $this->entityTypeManager->getDefinition('test_content')->willReturn($entity_type);
+ $this->entityTypeManager->getStorage('test_content')->shouldNotBeCalled();
+
+ $this->entityTypeBundleInfo->getBundleInfo('test_content')->willReturn([
+ 'first_bundle' => ['label' => 'First bundle'],
+ 'second_bundle' => ['label' => 'Second bundle'],
+ 'third_bundle' => ['label' => 'Third bundle'],
+ ]);
+
+ $entity = $this->prophesize(ContentEntityInterface::class)->willImplement(\IteratorAggregate::class);
+ $entity->getEntityTypeId()->willReturn('test_content');
+ $entity->getIterator()->willReturn(new \ArrayIterator([]));
+ $entity->getCacheContexts()->willReturn([]);
+ $entity->getCacheTags()->willReturn([]);
+ $entity->getCacheMaxAge()->willReturn(0);
+ $entity->bundle()->willReturn('third_bundle');
+
+ $requirement = EntityContextDefinition::fromEntityTypeId('test_content');
+ if ($requirement_constraint) {
+ $requirement->addConstraint('Bundle', $requirement_constraint);
+ }
+ $definition = EntityContextDefinition::fromEntityTypeId('test_content');
+ $this->assertRequirementIsSatisfied($expected, $requirement, $definition, $entity->reveal());
+ }
+
+ /**
+ * Provides test data for ::testIsSatisfiedByPassBundledEntity().
+ */
+ public function providerTestIsSatisfiedByPassBundledEntity() {
+ $data = [];
+ $data[] = [TRUE, []];
+ $data[] = [FALSE, ['first_bundle']];
+ $data[] = [FALSE, ['second_bundle']];
+ $data[] = [TRUE, ['third_bundle']];
+ $data[] = [TRUE, ['first_bundle', 'second_bundle', 'third_bundle']];
+ $data[] = [FALSE, ['first_bundle', 'second_bundle']];
+ $data[] = [TRUE, ['first_bundle', 'third_bundle']];
+ $data[] = [TRUE, ['second_bundle', 'third_bundle']];
+ return $data;
+ }
+
+}