Issue #2293205 by Berdir | tim.plunkett: Consider removing usage of DataDefinition in ContextHandler.

8.0.x
Alex Pott 2014-09-05 17:15:29 +01:00
parent 5c3b66c8c9
commit 0ede95dd0b
3 changed files with 33 additions and 165 deletions

View File

@ -11,32 +11,12 @@ use Drupal\Component\Plugin\ConfigurablePluginInterface;
use Drupal\Component\Plugin\ContextAwarePluginInterface;
use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Component\Utility\String;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\TypedDataManager;
/**
* Provides methods to handle sets of contexts.
*/
class ContextHandler implements ContextHandlerInterface {
/**
* The typed data manager.
*
* @var \Drupal\Core\TypedData\TypedDataManager
*/
protected $typedDataManager;
/**
* Constructs a new ContextHandler.
*
* @param \Drupal\Core\TypedData\TypedDataManager $typed_data
* The typed data manager.
*/
public function __construct(TypedDataManager $typed_data) {
$this->typedDataManager = $typed_data;
}
/**
* {@inheritdoc}
*/
@ -47,37 +27,8 @@ class ContextHandler implements ContextHandlerInterface {
return TRUE;
}
// Build an array of requirements out of the contexts specified by the
// plugin definition.
$requirements = array();
/** @var $plugin_context \Drupal\Core\Plugin\Context\ContextDefinitionInterface */
foreach ($plugin_definition['context'] as $context_id => $plugin_context) {
$definition = $this->typedDataManager->getDefinition($plugin_context->getDataType());
$definition['type'] = $plugin_context->getDataType();
// If the plugin specifies additional constraints, add them to the
// constraints defined by the plugin type.
if ($plugin_constraints = $plugin_context->getConstraints()) {
// Ensure the array exists before adding in constraints.
if (!isset($definition['constraints'])) {
$definition['constraints'] = array();
}
$definition['constraints'] += $plugin_constraints;
}
// Assume the requirement is required if unspecified.
if (!isset($definition['required'])) {
$definition['required'] = TRUE;
}
// @todo Use context definition objects after
// https://drupal.org/node/2281635.
$requirements[$context_id] = new DataDefinition($definition);
}
// Check the set of contexts against the requirements.
return $this->checkRequirements($contexts, $requirements);
return $this->checkRequirements($contexts, $plugin_definition['context']);
});
}
@ -96,17 +47,17 @@ class ContextHandler implements ContextHandlerInterface {
/**
* {@inheritdoc}
*/
public function getMatchingContexts(array $contexts, DataDefinitionInterface $definition) {
public function getMatchingContexts(array $contexts, ContextDefinitionInterface $definition) {
return array_filter($contexts, function (ContextInterface $context) use ($definition) {
$context_definition = $context->getContextDefinition()->getDataDefinition();
$context_definition = $context->getContextDefinition();
// If the data types do not match, this context is invalid.
if ($definition->getDataType() != $context_definition->getDataType()) {
// If the data types do not match, this context is invalid unless the
// expected data type is any, which means all data types are supported.
if ($definition->getDataType() != 'any' && $definition->getDataType() != $context_definition->getDataType()) {
return FALSE;
}
// If any constraint does not match, this context is invalid.
// @todo This is too restrictive, consider only relying on data types.
foreach ($definition->getConstraints() as $constraint_name => $constraint) {
if ($context_definition->getConstraint($constraint_name) != $constraint) {
return FALSE;

View File

@ -8,7 +8,6 @@
namespace Drupal\Core\Plugin\Context;
use Drupal\Component\Plugin\ContextAwarePluginInterface;
use Drupal\Core\TypedData\DataDefinitionInterface;
/**
* Provides an interface for handling sets of contexts.
@ -53,13 +52,13 @@ interface ContextHandlerInterface {
*
* @param \Drupal\Component\Plugin\Context\ContextInterface[] $contexts
* An array of contexts.
* @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
* @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $definition
* The definition to satisfy.
*
* @return \Drupal\Component\Plugin\Context\ContextInterface[]
* An array of matching contexts.
*/
public function getMatchingContexts(array $contexts, DataDefinitionInterface $definition);
public function getMatchingContexts(array $contexts, ContextDefinitionInterface $definition);
/**
* Prepares a plugin for evaluation.

View File

@ -11,8 +11,6 @@ use Drupal\Component\Plugin\ConfigurablePluginInterface;
use Drupal\Component\Plugin\ContextAwarePluginInterface;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextHandler;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Tests\UnitTestCase;
/**
@ -21,13 +19,6 @@ use Drupal\Tests\UnitTestCase;
*/
class ContextHandlerTest extends UnitTestCase {
/**
* The typed data manager.
*
* @var \Drupal\Core\TypedData\TypedDataManager|\PHPUnit_Framework_MockObject_MockObject
*/
protected $typedDataManager;
/**
* The context handler.
*
@ -43,28 +34,7 @@ class ContextHandlerTest extends UnitTestCase {
protected function setUp() {
parent::setUp();
$this->typedDataManager = $this->getMockBuilder('Drupal\Core\TypedData\TypedDataManager')
->disableOriginalConstructor()
->getMock();
$this->typedDataManager->expects($this->any())
->method('getDefaultConstraints')
->will($this->returnValue(array()));
$this->typedDataManager->expects($this->any())
->method('createDataDefinition')
->will($this->returnValueMap(array(
array('expected_data_type', new DataDefinition(array('type' => 'expected_data_type'))),
array('mismatched_data_type', new DataDefinition(array('type' => 'mismatched_data_type'))),
array('unexpected_data_type', new DataDefinition(array('type' => 'unexpected_data_type'))),
array('empty', new DataDefinition(array())),
array('foo', new DataDefinition(array('type' => 'foo'))),
array('fuzzy', new DataDefinition(array('type' => 'fuzzy'))),
array('specific', new DataDefinition(array('type' => 'foo'))),
)));
$this->contextHandler = new ContextHandler($this->typedDataManager);
$container = new ContainerBuilder();
$container->set('typed_data_manager', $this->typedDataManager);
\Drupal::setContainer($container);
$this->contextHandler = new ContextHandler();
}
/**
@ -80,37 +50,19 @@ class ContextHandlerTest extends UnitTestCase {
* Provides data for testCheckRequirements().
*/
public function providerTestCheckRequirements() {
$requirement_optional = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$requirement_optional->expects($this->atLeastOnce())
->method('isRequired')
->will($this->returnValue(FALSE));
$requirement_optional = new ContextDefinition();
$requirement_optional->setRequired(FALSE);
$requirement_any = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$requirement_any->expects($this->atLeastOnce())
->method('isRequired')
->will($this->returnValue(TRUE));
$requirement_any->expects($this->atLeastOnce())
->method('getDataType')
->will($this->returnValue('any'));
$requirement_any->expects($this->atLeastOnce())
->method('getConstraints')
->will($this->returnValue(array()));
$requirement_any = new ContextDefinition();
$requirement_any->setRequired(TRUE);
$context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
$context_any->expects($this->atLeastOnce())
->method('getContextDefinition')
->will($this->returnValue(new ContextDefinition('empty')));
$requirement_specific = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$requirement_specific->expects($this->atLeastOnce())
->method('isRequired')
->will($this->returnValue(TRUE));
$requirement_specific->expects($this->atLeastOnce())
->method('getDataType')
->will($this->returnValue('foo'));
$requirement_specific->expects($this->atLeastOnce())
->method('getConstraints')
->will($this->returnValue(array('bar' => 'baz')));
$requirement_specific = new ContextDefinition('specific');
$requirement_specific->setConstraints(array('bar' => 'baz'));
$context_constraint_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
$context_constraint_mismatch->expects($this->atLeastOnce())
@ -157,26 +109,10 @@ class ContextHandlerTest extends UnitTestCase {
* Provides data for testGetMatchingContexts().
*/
public function providerTestGetMatchingContexts() {
$requirement_any = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$requirement_any->expects($this->atLeastOnce())
->method('isRequired')
->will($this->returnValue(TRUE));
$requirement_any->expects($this->atLeastOnce())
->method('getDataType')
->will($this->returnValue('any'));
$requirement_any->expects($this->atLeastOnce())
->method('getConstraints')
->will($this->returnValue(array()));
$requirement_specific = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$requirement_specific->expects($this->atLeastOnce())
->method('isRequired')
->will($this->returnValue(TRUE));
$requirement_specific->expects($this->atLeastOnce())
->method('getDataType')
->will($this->returnValue('foo'));
$requirement_specific->expects($this->atLeastOnce())
->method('getConstraints')
->will($this->returnValue(array('bar' => 'baz')));
$requirement_any = new ContextDefinition();
$requirement_specific = new ContextDefinition('specific');
$requirement_specific->setConstraints(array('bar' => 'baz'));
$context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
$context_any->expects($this->atLeastOnce())
@ -218,7 +154,7 @@ class ContextHandlerTest extends UnitTestCase {
*
* @dataProvider providerTestFilterPluginDefinitionsByContexts
*/
public function testFilterPluginDefinitionsByContexts($has_context, $definitions, $expected, $typed_data_definition = NULL) {
public function testFilterPluginDefinitionsByContexts($has_context, $definitions, $expected) {
if ($has_context) {
$context = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
$expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(array('expected_constraint_name' => 'expected_constraint_value'));
@ -231,12 +167,6 @@ class ContextHandlerTest extends UnitTestCase {
$contexts = array();
}
if ($typed_data_definition) {
$this->typedDataManager->expects($this->atLeastOnce())
->method('getDefinition')
->will($this->returnValueMap($typed_data_definition));
}
$this->assertSame($expected, $this->contextHandler->filterPluginDefinitionsByContexts($contexts, $definitions));
}
@ -260,7 +190,7 @@ class ContextHandlerTest extends UnitTestCase {
$plugins = array('expected_plugin' => array('context' => array('context1' => new ContextDefinition('expected_data_type'))));
// Missing context, no plugins available.
$data[] = array(array(), $plugins, array());
$data[] = array(FALSE, $plugins, array());
// Satisfied context, all plugins available.
$data[] = array(TRUE, $plugins, $plugins);
@ -269,42 +199,30 @@ class ContextHandlerTest extends UnitTestCase {
// Mismatched constraints, no plugins available.
$data[] = array(TRUE, $plugins, array());
$optional_mismatched_context_definition = clone $mismatched_context_definition;
$optional_mismatched_context_definition->setRequired(FALSE);
$plugins = array('expected_plugin' => array('context' => array('context1' => $optional_mismatched_context_definition)));
// Optional mismatched constraint, all plugins available.
$data[] = array(FALSE, $plugins, $plugins);
$expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(array('expected_constraint_name' => 'expected_constraint_value'));
$plugins = array('expected_plugin' => array('context' => array('context1' => $expected_context_definition)));
// Satisfied context with constraint, all plugins available.
$data[] = array(TRUE, $plugins, $plugins);
$typed_data = array(array('expected_data_type', TRUE, array('required' => FALSE)));
// Optional unsatisfied context from TypedData, all plugins available.
$data[] = array(FALSE, $plugins, $plugins, $typed_data);
$typed_data = array(array('expected_data_type', TRUE, array('required' => TRUE)));
// Required unsatisfied context from TypedData, no plugins available.
$data[] = array(FALSE, $plugins, array(), $typed_data);
$typed_data = array(array('expected_data_type', TRUE, array('constraints' => array('mismatched_constraint_name' => 'mismatched_constraint_value'), 'required' => FALSE)));
// Optional mismatched constraint from TypedData, all plugins available.
$data[] = array(FALSE, $plugins, $plugins, $typed_data);
$typed_data = array(array('expected_data_type', TRUE, array('constraints' => array('mismatched_constraint_name' => 'mismatched_constraint_value'), 'required' => TRUE)));
// Required mismatched constraint from TypedData, no plugins available.
$data[] = array(FALSE, $plugins, array(), $typed_data);
$typed_data = array(array('expected_data_type', TRUE, array('constraints' => array('expected_constraint_name' => 'expected_constraint_value'))));
// Satisfied constraint from TypedData, all plugins available.
$data[] = array(TRUE, $plugins, $plugins, $typed_data);
$optional_expected_context_definition = clone $expected_context_definition;
$optional_expected_context_definition->setRequired(FALSE);
$plugins = array('expected_plugin' => array('context' => array('context1' => $optional_expected_context_definition)));
// Optional unsatisfied context, all plugins available.
$data[] = array(FALSE, $plugins, $plugins);
$unexpected_context_definition = (new ContextDefinition('unexpected_data_type'))->setConstraints(array('mismatched_constraint_name' => 'mismatched_constraint_value'));
$plugins = array(
'unexpected_plugin' => array('context' => array('context1' => $unexpected_context_definition)),
'expected_plugin' => array('context' => array('context2' => new ContextDefinition('expected_data_type'))),
);
$typed_data = array(
array('unexpected_data_type', TRUE, array()),
array('expected_data_type', TRUE, array('constraints' => array('expected_constraint_name' => 'expected_constraint_value'))),
);
// Context only satisfies one plugin.
$data[] = array(TRUE, $plugins, array('expected_plugin' => $plugins['expected_plugin']), $typed_data);
$data[] = array(TRUE, $plugins, array('expected_plugin' => $plugins['expected_plugin']));
return $data;
}