class ContextDefinition
Same name in this branch
- 8.x-3.x src/Context/Annotation/ContextDefinition.php \Drupal\rules\Context\Annotation\ContextDefinition
Extends the core context definition class with useful methods.
This class overrides the core ContextDefinition to provide Rules-specific functionality, but also to preserve the Drupal 8 behavior of ContextDefinition without triggering deprecated code. Specifically, in Rules we need to be able to create a ContextDefinition for ANY typed data object, without prior knowledge of what that type is; we need to be able to say new ContextDefinition($type) or ContextDefinition::create($type) where $type may be 'integer', or 'string', or 'entity:node' etc.
This worked in Drupal 8, but in Drupal 9 we now have to use different classes for different types. Thus the core ContextDefinition::create($type) will work ONLY for non-entity types, and we have to use a different way to create context definitions for entities. This is a problem because now there is no factory method to create context definitions, and we have to test each type and just "know" the correct class to use for that type to create a context definition.
This Drupal 9 behavior is unworkable in a module like Rules where we rely on introspection and reflection to manipulate typed data. Without some way to programmatically create a context definition for an arbitrary data type, Rules will not work.
To work around this, we override the core ContextDefinition's __construct() and create() methods. In the parent::__construct(), there is an explicit assert that prevents ContextDefinition from being used for an entity. We remove that here - the __construct() method of this class is otherwise identical to the parent. We also override the core ContextDefinition's create() method to create a Rules version of EntityContextDefinition when ContextDefinition is created for an entity type. This is necessary because the core EntityContextDefinition doesn't have the necessary Rules extensions and there is no multiple inheritance in PHP so we have to extend ContextDefinition and EntityContextDefinition separately.
This is a poor solution that will work for existing core Rules use-cases, as EntityContextDefinition is never used directly in Rules, but this may not work for modules that extend Rules. A proper and permanent solution will require a change to core Drupal.
Hierarchy
- class \Drupal\Core\Plugin\Context\ContextDefinition implements \Drupal\Core\Plugin\Context\ContextDefinitionInterface uses \Drupal\Core\DependencyInjection\DependencySerializationTrait, \Drupal\Core\TypedData\TypedDataTrait
- class \Drupal\rules\Context\ContextDefinition extends \Drupal\Core\Plugin\Context\ContextDefinition implements \Drupal\rules\Context\ContextDefinitionInterface
Expanded class hierarchy of ContextDefinition
See also
\Drupal\rules\Context\EntityContextDefinition
https://www.drupal.org/project/rules/issues/3161582
https://www.drupal.org/project/drupal/issues/3126747
22 files declare their use of ContextDefinition
- AutocompleteTest.php in tests/
src/ Kernel/ Engine/ AutocompleteTest.php - AutoSaveTest.php in tests/
src/ Unit/ Integration/ Engine/ AutoSaveTest.php - ConfigEntityTest.php in tests/
src/ Kernel/ ConfigEntityTest.php - ContextDefinition.php in src/
Context/ Annotation/ ContextDefinition.php - ContextIntegrationTest.php in tests/
src/ Kernel/ ContextIntegrationTest.php
File
-
src/
Context/ ContextDefinition.php, line 52
Namespace
Drupal\rules\ContextView source
class ContextDefinition extends ContextDefinitionCore implements ContextDefinitionInterface {
/**
* {@inheritdoc}
*/
public function __construct($data_type = 'any', $label = NULL, $required = TRUE, $multiple = FALSE, $description = NULL, $default_value = NULL) {
$this->dataType = $data_type;
$this->label = $label;
$this->isRequired = $required;
$this->isMultiple = $multiple;
$this->description = $description;
$this->defaultValue = $default_value;
}
/**
* The created context definition object.
*/
public static function create($data_type = 'any') {
if (strpos($data_type, 'entity:') === 0) {
return new EntityContextDefinition($data_type);
}
return new static($data_type);
}
/**
* The mapping of config export keys to internal properties.
*
* @var array
*/
protected static $nameMap = [
'type' => 'dataType',
'label' => 'label',
'description' => 'description',
'multiple' => 'isMultiple',
'required' => 'isRequired',
'default_value' => 'defaultValue',
'constraints' => 'constraints',
'getter' => 'getter',
'allow_null' => 'allowNull',
'assignment_restriction' => 'assignmentRestriction',
];
/**
* Name of getter function for this context variable.
*
* Only applicable for events.
*
* @var string
*/
protected $getter = NULL;
/**
* Whether the context value is allowed to be NULL or not.
*
* @var bool
*/
protected $allowNull = FALSE;
/**
* The assignment restriction of this context.
*
* @var string|null
*
* @see \Drupal\rules\Context\ContextDefinitionInterface::getAssignmentRestriction()
*/
protected $assignmentRestriction = NULL;
/**
* {@inheritdoc}
*/
public function toArray() {
$values = [];
$defaults = get_class_vars(__CLASS__);
foreach (static::$nameMap as $key => $property_name) {
// Only export values for non-default properties.
if ($this->{$property_name} !== $defaults[$property_name]) {
$values[$key] = $this->{$property_name};
}
}
return $values;
}
/**
* Creates a definition object from an exported array of values.
*
* @param array $values
* The array of values, as returned by toArray().
*
* @return static
* The created definition.
*
* @throws \Drupal\Component\Plugin\Exception\ContextException
* If the required classes are not implemented.
*/
public static function createFromArray(array $values) {
if (isset($values['class']) && !in_array(ContextDefinitionInterface::class, class_implements($values['class']))) {
throw new ContextException('ContextDefinition class must implement ' . ContextDefinitionInterface::class . '.');
}
// Default to Rules context definition class.
$values['class'] = $values['class'] ?? ContextDefinition::class;
if (!isset($values['value'])) {
$values['value'] = 'any';
}
$definition = $values['class']::create($values['value']);
foreach (array_intersect_key(static::$nameMap, $values) as $key => $name) {
$definition->{$name} = $values[$key];
}
return $definition;
}
/**
* {@inheritdoc}
*/
public function hasGetter() {
return !is_null($this->getter);
}
/**
* {@inheritdoc}
*/
public function getGetter() {
return $this->getter;
}
/**
* {@inheritdoc}
*/
public function isAllowedNull() {
return $this->allowNull;
}
/**
* {@inheritdoc}
*/
public function setAllowNull($null_allowed) {
$this->allowNull = $null_allowed;
return $this;
}
/**
* {@inheritdoc}
*/
public function getAssignmentRestriction() {
return $this->assignmentRestriction;
}
/**
* {@inheritdoc}
*/
public function setAssignmentRestriction($restriction) {
$this->assignmentRestriction = $restriction;
return $this;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Member alias | Overriden Title | Overrides |
---|---|---|---|---|---|---|
ContextDefinition::$allowNull | protected | property | Whether the context value is allowed to be NULL or not. | |||
ContextDefinition::$assignmentRestriction | protected | property | The assignment restriction of this context. | |||
ContextDefinition::$constraints | protected | property | An array of constraints. | |||
ContextDefinition::$dataType | protected | property | The data type of the data. | |||
ContextDefinition::$defaultValue | protected | property | The default value. | |||
ContextDefinition::$description | protected | property | The human-readable description. | |||
ContextDefinition::$getter | protected | property | Name of getter function for this context variable. | |||
ContextDefinition::$isMultiple | protected | property | Whether the data is multi-valued, i.e. a list of data items. | |||
ContextDefinition::$isRequired | protected | property | Determines whether a data value is required. | |||
ContextDefinition::$label | protected | property | The human-readable label. | |||
ContextDefinition::$nameMap | protected static | property | The mapping of config export keys to internal properties. | |||
ContextDefinition::addConstraint | public | function | Adds a validation constraint. | Overrides ContextDefinitionInterface::addConstraint | ||
ContextDefinition::create | public static | function | The created context definition object. | Overrides ContextDefinition::create | ||
ContextDefinition::createFromArray | public static | function | Creates a definition object from an exported array of values. | |||
ContextDefinition::dataTypeMatches | protected | function | Checks if this definition's data type matches that of the given context. | |||
ContextDefinition::getAssignmentRestriction | public | function | Determines if this context has an assignment restriction. | Overrides ContextDefinitionInterface::getAssignmentRestriction | ||
ContextDefinition::getConstraint | public | function | Gets a validation constraint. | Overrides ContextDefinitionInterface::getConstraint | ||
ContextDefinition::getConstraintObjects | protected | function | Extracts an array of constraints for a context definition object. | 1 | ||
ContextDefinition::getConstraints | public | function | Gets an array of validation constraints. | Overrides ContextDefinitionInterface::getConstraints | ||
ContextDefinition::getDataDefinition | public | function | Returns the data definition of the defined context. | Overrides ContextDefinitionInterface::getDataDefinition | ||
ContextDefinition::getDataType | public | function | Gets the data type needed by the context. | Overrides ContextDefinitionInterface::getDataType | ||
ContextDefinition::getDefaultValue | public | function | Gets the default value for this context definition. | Overrides ContextDefinitionInterface::getDefaultValue | ||
ContextDefinition::getDescription | public | function | Gets a human readable description. | Overrides ContextDefinitionInterface::getDescription | ||
ContextDefinition::getGetter | public | function | ||||
ContextDefinition::getLabel | public | function | Gets a human readable label. | Overrides ContextDefinitionInterface::getLabel | ||
ContextDefinition::getSampleValues | protected | function | Returns typed data objects representing this context definition. | 1 | ||
ContextDefinition::hasGetter | public | function | ||||
ContextDefinition::isAllowedNull | public | function | Determines if the context value is allowed to be NULL. | Overrides ContextDefinitionInterface::isAllowedNull | ||
ContextDefinition::isMultiple | public | function | Determines whether the data is multi-valued, i.e. a list of data items. | Overrides ContextDefinitionInterface::isMultiple | ||
ContextDefinition::isRequired | public | function | Determines whether the context is required. | Overrides ContextDefinitionInterface::isRequired | ||
ContextDefinition::isSatisfiedBy | public | function | Determines if this definition is satisfied by a context object. | Overrides ContextDefinitionInterface::isSatisfiedBy | ||
ContextDefinition::setAllowNull | public | function | Sets the "allow NULL value" behavior. | Overrides ContextDefinitionInterface::setAllowNull | ||
ContextDefinition::setAssignmentRestriction | public | function | Sets the assignment restriction mode for this context. | Overrides ContextDefinitionInterface::setAssignmentRestriction | ||
ContextDefinition::setConstraints | public | function | Sets the array of validation constraints. | Overrides ContextDefinitionInterface::setConstraints | ||
ContextDefinition::setDataType | public | function | Sets the data type needed by the context. | Overrides ContextDefinitionInterface::setDataType | ||
ContextDefinition::setDefaultValue | public | function | Sets the default data value. | Overrides ContextDefinitionInterface::setDefaultValue | ||
ContextDefinition::setDescription | public | function | Sets the human readable description. | Overrides ContextDefinitionInterface::setDescription | ||
ContextDefinition::setLabel | public | function | Sets the human readable label. | Overrides ContextDefinitionInterface::setLabel | ||
ContextDefinition::setMultiple | public | function | Sets whether the data is multi-valued. | Overrides ContextDefinitionInterface::setMultiple | ||
ContextDefinition::setRequired | public | function | Sets whether the data is required. | Overrides ContextDefinitionInterface::setRequired | ||
ContextDefinition::toArray | public | function | Exports the definition as an array. | Overrides ContextDefinitionInterface::toArray | ||
ContextDefinition::__construct | public | function | Constructs a new context definition object. | Overrides ContextDefinition::__construct | ||
ContextDefinitionInterface::ASSIGNMENT_RESTRICTION_INPUT | constant | Constants for the context assignment restriction mode. | ||||
ContextDefinitionInterface::ASSIGNMENT_RESTRICTION_SELECTOR | constant | |||||
DependencySerializationTrait::$_entityStorages | protected | property | ||||
DependencySerializationTrait::$_serviceIds | protected | property | ||||
DependencySerializationTrait::__sleep | public | function | Aliased as: traitSleep | 1 | ||
DependencySerializationTrait::__wakeup | public | function | 2 | |||
TypedDataTrait::$typedDataManager | protected | property | The typed data manager used for creating the data types. | |||
TypedDataTrait::getTypedDataManager | public | function | Gets the typed data manager. | 2 | ||
TypedDataTrait::setTypedDataManager | public | function | Sets the typed data manager. | 2 |