New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/context #27
Feature/context #27
Changes from all commits
2a30648
4e6b267
1ae3cf8
3604f98
486113c
6f4adcc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Contains \Drupal\rules\Context\Context. | ||
*/ | ||
|
||
namespace Drupal\rules\Context; | ||
|
||
use Drupal\Core\Entity\ContentEntityInterface; | ||
use Drupal\Core\TypedData\TypedDataInterface; | ||
|
||
/** | ||
* A context class for Rules. | ||
*/ | ||
class Context implements ContextInterface { | ||
|
||
/** | ||
* The data associated with the context. | ||
* | ||
* @var \Drupal\Core\TypedData\TypedDataInterface | ||
*/ | ||
protected $contextData; | ||
|
||
/** | ||
* The definition to which a context must conform. | ||
* | ||
* @var \Drupal\rules\Context\ContextDefinitionInterface | ||
*/ | ||
protected $contextDefinition; | ||
|
||
/** | ||
* Sets the contextDefinition for us without needing to call the setter. | ||
*/ | ||
public function __construct(ContextDefinitionInterface $context_definition) { | ||
$this->contextDefinition = $context_definition; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextValue() { | ||
// Special case entities. | ||
// @todo: Remove once entities do not implemented TypedDataInterface any | ||
// more. | ||
if ($this->contextData instanceof ContentEntityInterface) { | ||
return $this->contextData; | ||
} | ||
return $this->contextData->getValue(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function setContextValue($value) { | ||
if ($value instanceof TypedDataInterface) { | ||
return $this->setContextData($value); | ||
} | ||
else { | ||
return $this->setContextData(\Drupal::typedDataManager()->create($this->contextDefinition->getDataDefinition(), $value)); | ||
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextData() { | ||
return $this->getContextData; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function setContextData(TypedDataInterface $data) { | ||
$this->contextData = $data; | ||
return $this; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextDefinition() { | ||
return $this->contextDefinition; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function setContextDefinition(array $context_definition) { | ||
$this->contextDefinition = $context_definition; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getConstraints() { | ||
return $this->contextDefinition->getConstraints(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validate() { | ||
return $this->getContextData()->validate(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Contains \Drupal\rules\Context\ContextAwarePluginBase. | ||
*/ | ||
|
||
namespace Drupal\rules\Context; | ||
|
||
use Drupal\Component\Plugin\Exception\ContextException; | ||
use Drupal\Component\Plugin\PluginBase; | ||
use Symfony\Component\Validator\ConstraintViolationList; | ||
|
||
/** | ||
* Base class for plugins that are context aware. | ||
*/ | ||
abstract class ContextAwarePluginBase extends PluginBase implements ContextAwarePluginInterface { | ||
|
||
/** | ||
* The contexts of this plugin. | ||
* | ||
* @var \Drupal\rules\Context\ContextInterface[] | ||
*/ | ||
protected $contexts; | ||
|
||
/** | ||
* The context definitions of this plugin. | ||
* | ||
* @var \Drupal\rules\Context\ContextDefinitionInterface[] | ||
*/ | ||
protected $contextDefinitions; | ||
|
||
/** | ||
* Defines the needed context of this plugin. | ||
* | ||
* @todo: Can we make this abstract somehow? | ||
* | ||
* @return \Drupal\rules\Context\ContextDefinitionInterface[] | ||
* The array of context definitions, keyed by context name. | ||
*/ | ||
public static function contextDefinitions() { | ||
return []; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextDefinitions() { | ||
if (!isset($this->contextDefinitions)) { | ||
$this->contextDefinitions = static::contextDefinitions(); | ||
} | ||
return $this->contextDefinitions; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextDefinition($name) { | ||
$definitions = $this->getContextDefinitions(); | ||
if (empty($definitions[$name])) { | ||
throw new ContextException("The $name context is not a valid context."); | ||
} | ||
return $definitions[$name]; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContexts() { | ||
// Make sure all context objects are initialized. | ||
foreach ($this->getContextDefinitions() as $name => $definition) { | ||
$this->getContext($name); | ||
} | ||
return $this->contexts; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContext($name) { | ||
// Check for a valid context value. | ||
if (!isset($this->context[$name])) { | ||
$this->context[$name] = new Context($this->getContextDefinition($name)); | ||
} | ||
return $this->context[$name]; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextValues() { | ||
$values = array(); | ||
foreach ($this->getContextDefinitions() as $name => $definition) { | ||
$values[$name] = isset($this->context[$name]) ? $this->context[$name]->getContextValue() : NULL; | ||
} | ||
return $values; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getContextValue($name) { | ||
return $this->getContext($name)->getContextValue(); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function setContextValue($name, $value) { | ||
$this->getContext($name)->setContextValue($value); | ||
return $this; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validateContexts() { | ||
$violations = new ConstraintViolationList(); | ||
// @todo: Implement symfony validator API to let the validator traverse | ||
// and set property paths accordingly. | ||
|
||
foreach ($this->getContexts() as $name => $context) { | ||
$violations->addAll($context->validate()); | ||
} | ||
return $violations; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
|
||
/** | ||
* @file | ||
* Contains \Drupal\rules\Context\ContextAwarePluginInterface. | ||
*/ | ||
|
||
namespace Drupal\rules\Context; | ||
|
||
use \Drupal\Component\Plugin\ContextAwarePluginInterface as CoreContextAwarePluginInterface; | ||
|
||
/** | ||
* Interface for Rules-context aware plugins. | ||
*/ | ||
interface ContextAwarePluginInterface extends CoreContextAwarePluginInterface { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure I understand why most of the functions that already declared in CoreContextAwarePluginInterface are redeclared here, but I guess it's because you need to return different types than the parent interface. I don't think that's a safe idea: that would make the two interfaces not swappable and basically makes them hidden-ly incompatible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the goal would be to get our interface in core. For now, that's what we can do easily. |
||
|
||
/** | ||
* Gets the context definitions of the plugin. | ||
* | ||
* @return \Drupal\rules\Context\ContextDefinitionInterface[] | ||
* The array of context definitions, keyed by context name. | ||
*/ | ||
public function getContextDefinitions(); | ||
|
||
/** | ||
* Gets a specific context definition of the plugin. | ||
* | ||
* @param string $name | ||
* The name of the context in the plugin definition. | ||
* | ||
* @throws \Drupal\Component\Plugin\Exception\ContextException | ||
* If the requested context is not defined. | ||
* | ||
* @return \Drupal\rules\Context\ContextDefinitionInterface | ||
* The definition against which the context value must validate. | ||
*/ | ||
public function getContextDefinition($name); | ||
|
||
/** | ||
* Gets the defined contexts. | ||
* | ||
* @return \Drupal\rules\Context\ContextInterface[] | ||
* The set context objects. | ||
*/ | ||
public function getContexts(); | ||
|
||
/** | ||
* Gets a defined context. | ||
* | ||
* @param string $name | ||
* The name of the context in the plugin configuration. | ||
* | ||
* @throws \Drupal\Component\Plugin\Exception\ContextException | ||
* If the requested context is not defined. | ||
* | ||
* @return \Drupal\rules\Context\ContextInterface | ||
* The context object. | ||
*/ | ||
public function getContext($name); | ||
|
||
/** | ||
* Validates the set values for the defined contexts. | ||
* | ||
* @return \Symfony\Component\Validator\ConstraintViolationListInterface | ||
* A list of constraint violations. If the list is empty, validation | ||
* succeeded. | ||
*/ | ||
public function validateContexts(); | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for else here.