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\ContextAwarePluginInterface;
use Drupal\Component\Plugin\Exception\ContextException; use Drupal\Component\Plugin\Exception\ContextException;
use Drupal\Component\Utility\String; 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. * Provides methods to handle sets of contexts.
*/ */
class ContextHandler implements ContextHandlerInterface { 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} * {@inheritdoc}
*/ */
@ -47,37 +27,8 @@ class ContextHandler implements ContextHandlerInterface {
return TRUE; 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. // 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} * {@inheritdoc}
*/ */
public function getMatchingContexts(array $contexts, DataDefinitionInterface $definition) { public function getMatchingContexts(array $contexts, ContextDefinitionInterface $definition) {
return array_filter($contexts, function (ContextInterface $context) use ($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 the data types do not match, this context is invalid unless the
if ($definition->getDataType() != $context_definition->getDataType()) { // expected data type is any, which means all data types are supported.
if ($definition->getDataType() != 'any' && $definition->getDataType() != $context_definition->getDataType()) {
return FALSE; return FALSE;
} }
// If any constraint does not match, this context is invalid. // 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) { foreach ($definition->getConstraints() as $constraint_name => $constraint) {
if ($context_definition->getConstraint($constraint_name) != $constraint) { if ($context_definition->getConstraint($constraint_name) != $constraint) {
return FALSE; return FALSE;

View File

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

View File

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