Commit c5e5ad4a authored by alexpott's avatar alexpott

Issue #2204509 by klausi, Xano, fago: Allow context definitions to specify default values

parent 69ce3554
...@@ -54,11 +54,15 @@ public function getContextValue() { ...@@ -54,11 +54,15 @@ public function getContextValue() {
// Support optional contexts. // Support optional contexts.
if (!isset($this->contextValue)) { if (!isset($this->contextValue)) {
$definition = $this->getContextDefinition(); $definition = $this->getContextDefinition();
if ($definition->isRequired()) { $default_value = $definition->getDefaultValue();
if (!isset($default_value) && $definition->isRequired()) {
$type = $definition->getDataType(); $type = $definition->getDataType();
throw new ContextException(sprintf("The %s context is required and not present.", $type)); throw new ContextException(sprintf("The %s context is required and not present.", $type));
} }
return NULL; // Keep the default value here so that subsequent calls don't have to look
// it up again.
$this->contextValue = $default_value;
} }
return $this->contextValue; return $this->contextValue;
} }
......
...@@ -109,6 +109,24 @@ public function isRequired(); ...@@ -109,6 +109,24 @@ public function isRequired();
*/ */
public function setRequired($required = TRUE); public function setRequired($required = TRUE);
/**
* Provides the default value for this context definition.
*
* @return mixed
* The default value or NULL if no default value is set.
*/
public function getDefaultValue();
/**
* Sets the default data value.
*
* @param mixed $default_value
* The default value to be set or NULL to remove any default value.
*
* @return $this
*/
public function setDefaultValue($default_value);
/** /**
* Returns an array of validation constraints. * Returns an array of validation constraints.
* *
......
...@@ -50,6 +50,16 @@ ...@@ -50,6 +50,16 @@
* } * }
* @endcode * @endcode
* *
* Specifying a default value for the context definition:
* @code
* context = {
* "message" = @ContextDefinition("string",
* label = @Translation("Message"),
* default_value = @Translation("Checkout complete! Thank you for your purchase.")
* )
* }
* @endcode
*
* @see annotation * @see annotation
* *
* @} * @}
...@@ -85,6 +95,8 @@ class ContextDefinition extends Plugin { ...@@ -85,6 +95,8 @@ class ContextDefinition extends Plugin {
* - required: (optional) Whether the context definition is required. * - required: (optional) Whether the context definition is required.
* - multiple: (optional) Whether the context definition is multivalue. * - multiple: (optional) Whether the context definition is multivalue.
* - description: (optional) The UI description of this context definition. * - description: (optional) The UI description of this context definition.
* - default_value: (optional) The default value in case the underlying
* value is not set.
* - class: (optional) A custom ContextDefinitionInterface class. * - class: (optional) A custom ContextDefinitionInterface class.
* *
* @throws \Exception * @throws \Exception
...@@ -95,6 +107,7 @@ public function __construct(array $values) { ...@@ -95,6 +107,7 @@ public function __construct(array $values) {
$values += array( $values += array(
'required' => TRUE, 'required' => TRUE,
'multiple' => FALSE, 'multiple' => FALSE,
'default_value' => NULL,
); );
// Annotation classes extract data from passed annotation classes directly // Annotation classes extract data from passed annotation classes directly
// used in the classes they pass to. // used in the classes they pass to.
...@@ -111,7 +124,7 @@ public function __construct(array $values) { ...@@ -111,7 +124,7 @@ public function __construct(array $values) {
throw new \Exception('ContextDefinition class must implement \Drupal\Core\Plugin\Context\ContextDefinitionInterface.'); throw new \Exception('ContextDefinition class must implement \Drupal\Core\Plugin\Context\ContextDefinitionInterface.');
} }
$class = isset($values['class']) ? $values['class'] : 'Drupal\Core\Plugin\Context\ContextDefinition'; $class = isset($values['class']) ? $values['class'] : 'Drupal\Core\Plugin\Context\ContextDefinition';
$this->definition = new $class($values['value'], $values['label'], $values['required'], $values['multiple'], $values['description']); $this->definition = new $class($values['value'], $values['label'], $values['required'], $values['multiple'], $values['description'], $values['default_value']);
} }
/** /**
......
...@@ -40,11 +40,18 @@ class Context extends ComponentContext implements ContextInterface { ...@@ -40,11 +40,18 @@ class Context extends ComponentContext implements ContextInterface {
public function getContextValue() { public function getContextValue() {
if (!isset($this->contextData)) { if (!isset($this->contextData)) {
$definition = $this->getContextDefinition(); $definition = $this->getContextDefinition();
if ($definition->isRequired()) { $default_value = $definition->getDefaultValue();
if (isset($default_value)) {
// Keep the default value here so that subsequent calls don't have to
// look it up again.
$this->setContextValue($default_value);
}
elseif ($definition->isRequired()) {
$type = $definition->getDataType(); $type = $definition->getDataType();
throw new ContextException(SafeMarkup::format("The @type context is required and not present.", array('@type' => $type))); throw new ContextException(SafeMarkup::format("The @type context is required and not present.", array('@type' => $type)));
} }
return NULL; return $default_value;
} }
return $this->getTypedDataManager()->getCanonicalRepresentation($this->contextData); return $this->getTypedDataManager()->getCanonicalRepresentation($this->contextData);
} }
...@@ -72,6 +79,15 @@ public function getConstraints() { ...@@ -72,6 +79,15 @@ public function getConstraints() {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getContextData() { public function getContextData() {
if (!isset($this->contextData)) {
$definition = $this->getContextDefinition();
$default_value = $definition->getDefaultValue();
if (isset($default_value)) {
// Store the default value so that subsequent calls don't have to look
// it up again.
$this->contextData = $this->getTypedDataManager()->create($definition->getDataDefinition(), $default_value);
}
}
return $this->contextData; return $this->contextData;
} }
......
...@@ -56,6 +56,13 @@ class ContextDefinition implements ContextDefinitionInterface { ...@@ -56,6 +56,13 @@ class ContextDefinition implements ContextDefinitionInterface {
*/ */
protected $isRequired = TRUE; protected $isRequired = TRUE;
/**
* The default value.
*
* @var mixed
*/
protected $defaultValue;
/** /**
* An array of constraints. * An array of constraints.
* *
...@@ -90,15 +97,18 @@ public static function create($data_type = 'any') { ...@@ -90,15 +97,18 @@ public static function create($data_type = 'any') {
* Whether the context definition is required. * Whether the context definition is required.
* @param bool $multiple * @param bool $multiple
* Whether the context definition is multivalue. * Whether the context definition is multivalue.
* @param mixed string|null $description * @param string|null $description
* The description of this context definition for the UI. * The description of this context definition for the UI.
* @param mixed $default_value
* The default value of this definition.
*/ */
public function __construct($data_type = 'any', $label = NULL, $required = TRUE, $multiple = FALSE, $description = NULL) { public function __construct($data_type = 'any', $label = NULL, $required = TRUE, $multiple = FALSE, $description = NULL, $default_value = NULL) {
$this->dataType = $data_type; $this->dataType = $data_type;
$this->label = $label; $this->label = $label;
$this->isRequired = $required; $this->isRequired = $required;
$this->isMultiple = $multiple; $this->isMultiple = $multiple;
$this->description = $description; $this->description = $description;
$this->defaultValue = $default_value;
} }
/** /**
...@@ -176,6 +186,21 @@ public function setRequired($required = TRUE) { ...@@ -176,6 +186,21 @@ public function setRequired($required = TRUE) {
return $this; return $this;
} }
/**
* {@inheritdoc}
*/
public function getDefaultValue() {
return $this->defaultValue;
}
/**
* {@inheritdoc}
*/
public function setDefaultValue($default_value) {
$this->defaultValue = $default_value;
return $this;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace Drupal\Tests\Component\Plugin\Context; namespace Drupal\Tests\Component\Plugin\Context;
use Drupal\Component\Plugin\Context\Context;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
/** /**
...@@ -86,4 +87,20 @@ public function testGetContextValue($expected, $context_value, $is_required, $da ...@@ -86,4 +87,20 @@ public function testGetContextValue($expected, $context_value, $is_required, $da
} }
} }
/**
* @covers ::getContextValue
*/
public function testDefaultValue() {
$mock_definition = $this->getMockBuilder('Drupal\Component\Plugin\Context\ContextDefinitionInterface')
->setMethods(array('getDefaultValue'))
->getMockForAbstractClass();
$mock_definition->expects($this->once())
->method('getDefaultValue')
->willReturn('test');
$context = new Context($mock_definition);
$this->assertEquals('test', $context->getContextValue());
}
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
namespace Drupal\Tests\Core\Plugin\Context; namespace Drupal\Tests\Core\Plugin\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Tests\UnitTestCase; use Drupal\Tests\UnitTestCase;
/** /**
...@@ -205,4 +206,15 @@ public function testGetConstraint($expected, $constraint_array, $constraint) { ...@@ -205,4 +206,15 @@ public function testGetConstraint($expected, $constraint_array, $constraint) {
$this->assertEquals($expected, $mock_context_definition->getConstraint($constraint)); $this->assertEquals($expected, $mock_context_definition->getConstraint($constraint));
} }
/**
* @covers ::getDefaultValue
* @covers ::setDefaultValue
*/
public function testDefaultValue() {
$context_definition = new ContextDefinition();
$this->assertNull($context_definition->getDefaultValue());
$context_definition->setDefaultValue('test');
$this->assertSame('test', $context_definition->getDefaultValue());
}
} }
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Plugin\Context\ContextTest.
*/
namespace Drupal\Tests\Core\Plugin\Context;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Plugin\Context\Context
* @group Plugin
*/
class ContextTest extends UnitTestCase {
/**
* The mocked context definition object.
*
* @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $contextDefinition;
/**
* The mocked Typed Data manager.
*
* @var \Drupal\Core\TypedData\TypedDataManager|\PHPUnit_Framework_MockObject_MockObject
*/
protected $typedDataManager;
/**
* The mocked Typed Data object.
*
* @var \Drupal\Core\TypedData\TypedDataInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $typedData;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$mock_data_definition = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$this->contextDefinition = $this->getMockBuilder('Drupal\Core\Plugin\Context\ContextDefinitionInterface')
->setMethods(array('getDefaultValue', 'getDataDefinition'))
->getMockForAbstractClass();
$this->contextDefinition->expects($this->once())
->method('getDefaultValue')
->willReturn('test');
$this->contextDefinition->expects($this->once())
->method('getDataDefinition')
->willReturn($mock_data_definition);
$this->typedData = $this->getMock('Drupal\Core\TypedData\TypedDataInterface');
$this->typedDataManager = $this->getMockBuilder('Drupal\Core\TypedData\TypedDataManager')
->disableOriginalConstructor()
->setMethods(array('create'))
->getMock();
$this->typedDataManager->expects($this->once())
->method('create')
->with($mock_data_definition, 'test')
->willReturn($this->typedData);
}
/**
* @covers ::getContextValue
*/
public function testDefaultValue() {
$context = new Context($this->contextDefinition);
$context->setTypedDataManager($this->typedDataManager);
$this->assertEquals('test', $context->getContextValue());
}
/**
* @covers ::getContextData
*/
public function testDefaultDataValue() {
$context = new Context($this->contextDefinition);
$context->setTypedDataManager($this->typedDataManager);
$this->assertEquals($this->typedData, $context->getContextData());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment