From 71364b1a81ca6749f66af48c82980dcd6d152d6e Mon Sep 17 00:00:00 2001 From: Dries <dries@buytaert.net> Date: Tue, 12 Feb 2013 15:51:59 -0500 Subject: [PATCH] Issue #1896076 by EclipseGc, fago: Added Contextual Plugins and supporting code. --- .../Component/Plugin/Context/Context.php | 86 ++++++++ .../Plugin/Context/ContextInterface.php | 68 ++++++ .../Plugin/ContextAwarePluginBase.php | 109 ++++++++++ .../Plugin/ContextAwarePluginInterface.php | 91 ++++++++ .../Plugin/Exception/ContextException.php | 15 ++ .../Drupal/Core/Plugin/Context/Context.php | 74 +++++++ .../Core/Plugin/ContextAwarePluginBase.php | 33 +++ .../system/Tests/Plugin/ContextPluginTest.php | 203 ++++++++++++++++++ .../system/Tests/Plugin/PluginTestBase.php | 22 ++ .../plugin_test/Plugin/MockBlockManager.php | 29 +++ .../mock_block/MockComplexContextBlock.php | 24 +++ .../mock_block/MockUserNameBlock.php | 24 +++ .../mock_block/TypedDataStringBlock.php | 23 ++ 13 files changed, 801 insertions(+) create mode 100644 core/lib/Drupal/Component/Plugin/Context/Context.php create mode 100644 core/lib/Drupal/Component/Plugin/Context/ContextInterface.php create mode 100644 core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php create mode 100644 core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php create mode 100644 core/lib/Drupal/Component/Plugin/Exception/ContextException.php create mode 100644 core/lib/Drupal/Core/Plugin/Context/Context.php create mode 100644 core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php create mode 100644 core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php create mode 100644 core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php create mode 100644 core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php create mode 100644 core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php diff --git a/core/lib/Drupal/Component/Plugin/Context/Context.php b/core/lib/Drupal/Component/Plugin/Context/Context.php new file mode 100644 index 000000000000..9f4396b62371 --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/Context/Context.php @@ -0,0 +1,86 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Plugin\Context\Context. + */ + +namespace Drupal\Component\Plugin\Context; + +use Drupal\Component\Plugin\Exception\ContextException; + +/** + * A generic context class for wrapping data a plugin needs to operate. + */ +class Context implements ContextInterface { + + /** + * The value of the context. + * + * @var mixed + */ + protected $contextValue; + + /** + * The definition to which a context must conform. + * + * @var array + */ + protected $contextDefinition; + + /** + * Sets the contextDefinition for us without needing to call the setter. + */ + public function __construct(array $context_definition) { + $this->contextDefinition = $context_definition; + } + + /** + * Implements \Drupal\Component\Plugin\Context\ContextInterface::setContextValue(). + */ + public function setContextValue($value) { + $value = $this->validate($value); + $this->contextValue = $value; + } + + /** + * Implements \Drupal\Component\Plugin\Context\ContextInterface::getContextValue(). + */ + public function getContextValue() { + return $this->contextValue; + } + + /** + * Implements \Drupal\Component\Plugin\Context\ContextInterface::setContextDefinition(). + */ + public function setContextDefinition(array $context_definition) { + $this->contextDefinition = $context_definition; + } + + /** + * Implements \Drupal\Component\Plugin\Context\ContextInterface::getContextDefinition(). + */ + public function getContextDefinition() { + return $this->contextDefinition; + } + + /** + * Implements \Drupal\Component\Plugin\Context\ContextInterface::validate(). + * + * The default validation method only supports instance of checks between the + * contextDefintion and the contextValue. Other formats of context + * definitions can be supported through a subclass. + */ + public function validate($value) { + // Check to make sure we have a class name, and that the passed context is + // an instance of that class name. + if (!empty($this->contextDefinition['class'])) { + if ($value instanceof $this->contextDefinition['class']) { + return $value; + } + throw new ContextException("The context passed was not an instance of {$this->contextDefinition['class']}."); + } + throw new ContextException("An error was encountered while trying to validate the context."); + } + +} diff --git a/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php b/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php new file mode 100644 index 000000000000..5c4373dff024 --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/Context/ContextInterface.php @@ -0,0 +1,68 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Plugin\Context\ContextInterface. + */ + +namespace Drupal\Component\Plugin\Context; + +use Drupal\Component\Plugin\Exception\ContextException; + +/** + * A generic context interface for wrapping data a plugin needs to operate. + */ +interface ContextInterface { + + /** + * Sets the context value. + * + * @param mixed $value + * The value of this context, generally an object based upon the class + * matching the definition passed to setContextDefinition(). + */ + public function setContextValue($value); + + /** + * Gets the context value. + * + * @return mixed + * The currently set context value within this class. + */ + public function getContextValue(); + + /** + * Sets the definition that the context must conform to. + * + * @param mixed $contextDefinition + * A defining characteristic representation of the context against which + * that context can be validated. This is typically a class name, but could + * be extended to support other validation notation. + */ + public function setContextDefinition(array $contextDefinition); + + /** + * Gets the provided definition that the context must conform to. + * + * @return mixed + * The defining characteristic representation of the context. + */ + public function getContextDefinition(); + + /** + * Validate the provided context value against the provided definition. + * + * @param mixed $value + * The context value that should be validated against the context + * definition. + * + * @return mixed + * Returns the context value passed to it. If it fails validation, an + * exception will be thrown. + * + * @throws \Drupal\Component\Plugin\Exception\ContextException + * If validation fails. + */ + public function validate($value); + +} diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php new file mode 100644 index 000000000000..a628f99d2b5d --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php @@ -0,0 +1,109 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Plugin\ContextAwarePluginBase + */ + +namespace Drupal\Component\Plugin; + +use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\Component\Plugin\Context\Context; + +/** + * Base class for plugins that are context aware. + */ +abstract class ContextAwarePluginBase extends PluginBase implements ContextAwarePluginInterface { + + /** + * The data objects representing the context of this plugin. + * + * @var array + */ + protected $context; + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinitions(). + */ + public function getContextDefinitions() { + $definition = $this->getDefinition(); + return !empty($definition['context']) ? $definition['context'] : NULL; + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextDefinition(). + */ + public function getContextDefinition($key) { + $definition = $this->getDefinition(); + if (empty($definition['context'][$key])) { + throw new PluginException("The $key context is not a valid context."); + } + return $definition['context'][$key]; + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContexts(). + */ + public function getContexts() { + $definitions = $this->getContextDefinitions(); + // If there are no contexts defined by the plugin, return an empty array. + if (empty($definitions)) { + return array(); + } + if (empty($this->context)) { + throw new PluginException("There are no set contexts."); + } + $contexts = array(); + foreach (array_keys($definitions) as $key) { + if (empty($this->context[$key])) { + throw new PluginException("The $key context is not yet set."); + } + $contexts[$key] = $this->context[$key]; + } + return $contexts; + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContext(). + */ + public function getContext($key) { + // Check for a valid context definition. + $this->getContextDefinition($key); + // Check for a valid context value. + if (empty($this->context[$key])) { + throw new PluginException("The $key context is not yet set."); + } + + return $this->context[$key]; + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValues(). + */ + public function getContextValues() { + $contexts = array(); + foreach ($this->getContexts() as $key => $context) { + $contexts[$key] = $context->getContextValue(); + } + return $contexts; + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::getContextValue(). + */ + public function getContextValue($key) { + return $this->getContext($key)->getContextValue(); + } + + /** + * Implements \Drupal\Component\Plugin\ContextAwarePluginInterface::setContextValue(). + */ + public function setContextValue($key, $value) { + $context_definition = $this->getContextDefinition($key); + $this->context[$key] = new Context($context_definition); + $this->context[$key]->setContextValue($value); + + return $this; + } + +} diff --git a/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php new file mode 100644 index 000000000000..68d8012e319b --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/ContextAwarePluginInterface.php @@ -0,0 +1,91 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Plugin\ContextAwarePluginInterface. + */ + +namespace Drupal\Component\Plugin; + +use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\Component\Plugin\Context\Context; + +/** + * Interface for defining context aware plugins. + */ +interface ContextAwarePluginInterface extends PluginInspectionInterface { + + /** + * Gets the context definitions of the plugin. + * + * @return array|null + * The context definitions if set, otherwise NULL. + */ + public function getContextDefinitions(); + + /** + * Gets the a specific context definition of the plugin. + * + * @param string $key + * The name of the context in the plugin definition. + * + * @return mixed + * The definition against which the context value must validate. + */ + public function getContextDefinition($key); + + /** + * Gets the defined contexts. + * + * @return array + * The set context objects. + */ + public function getContexts(); + + /** + * Gets a defined context. + * + * @param string $key + * The name of the context in the plugin configuration. This string is + * usually identical to the representative string in the plugin definition. + * + * @return \Drupal\Component\Plugin\Context\ContextInterface + * The context object. + */ + public function getContext($key); + + /** + * Gets the values for all defined contexts. + * + * @return array + * The set context object values. + */ + public function getContextValues(); + + /** + * Gets the value for a defined context. + * + * @param string $key + * The name of the context in the plugin configuration. This string is + * usually identical to the representative string in the plugin definition. + * + * @return mixed + * The currently set context value. + */ + public function getContextValue($key); + + /** + * Sets the value for a defined context. + * + * @param string $key + * The name of the context in the plugin definition. + * @param mixed $value + * The variable to set the context to. This should validate against the + * provided context definition. + * + * @return \Drupal\Component\Plugin\ContextAwarePluginInterface. + * A context aware plugin object for chaining. + */ + public function setContextValue($key, $value); + +} diff --git a/core/lib/Drupal/Component/Plugin/Exception/ContextException.php b/core/lib/Drupal/Component/Plugin/Exception/ContextException.php new file mode 100644 index 000000000000..061825118de7 --- /dev/null +++ b/core/lib/Drupal/Component/Plugin/Exception/ContextException.php @@ -0,0 +1,15 @@ +<?php + +/** + * @file + * Contains \Drupal\Component\Plugin\Exception\ContextException. + */ + +namespace Drupal\Component\Plugin\Exception; + +use Exception; + +/** + * An exception class to be thrown for context plugin exceptions. + */ +class ContextException extends Exception implements ExceptionInterface { } diff --git a/core/lib/Drupal/Core/Plugin/Context/Context.php b/core/lib/Drupal/Core/Plugin/Context/Context.php new file mode 100644 index 000000000000..bcab7e1871ba --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/Context/Context.php @@ -0,0 +1,74 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Plugin\Context\Context. + */ + +namespace Drupal\Core\Plugin\Context; + +use Drupal\Component\Plugin\Context\Context as ComponentContext; +use Drupal\Component\Plugin\Exception\ContextException; +use Drupal\Core\TypedData\TypedDataManager; +use Drupal\Core\TypedData\TypedDataInterface; + +/** + * A Drupal specific context wrapper class. + * + * The validate method is specifically overridden in order to support typed + * data definitions instead of just class names in the contextual definitions + * of plugins that extend ContextualPluginBase. + */ +class Context extends ComponentContext { + + /** + * Overrides \Drupal\Component\Plugin\Context\Context::getContextValue(). + */ + public function getContextValue() { + $typed_value = parent::getContextValue(); + // If the data is of a primitive type, directly return the plain value. + // That way, e.g. a string will be return as plain PHP string. + if ($typed_value instanceof \Drupal\Core\TypedData\TypedDataInterface) { + $type_definition = typed_data()->getDefinition($typed_value->getType()); + if (!empty($type_definition['primitive type'])) { + return $typed_value->getValue(); + } + } + return $typed_value; + } + + /** + * Gets the context value as typed data object. + * + * parent::getContextValue() does not do all the processing required to + * return plain value of a TypedData object. This class overrides that method + * to return the appropriate values from TypedData objects, but the object + * itself can be useful as well, so this method is provided to allow for + * access to the TypedData object. Since parent::getContextValue() already + * does all the processing we need, we simply proxy to it here. + * + * @return \Drupal\Core\TypedData\TypedDataInterface + */ + public function getTypedContext() { + return parent::getContextValue(); + } + + /** + * Override for \Drupal\Component\Plugin\Context\Context::validate(). + */ + public function validate($value) { + if (!empty($this->contextDefinition['type'])) { + $typed_data_manager = new TypedDataManager(); + $typed_data = $typed_data_manager->create($this->contextDefinition, $value); + // If we do have a typed data definition, validate it and return the + // typed data instance instead. + $violations = $typed_data->validate(); + if (count($violations) == 0) { + return $typed_data; + } + throw new ContextException("The context passed could not be validated through typed data."); + } + return parent::validate($value); + } + +} diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php new file mode 100644 index 000000000000..028befde28b6 --- /dev/null +++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php @@ -0,0 +1,33 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Plugin\ContextAwarePluginBase + */ + +namespace Drupal\Core\Plugin; + +use Drupal\Component\Plugin\ContextAwarePluginBase as PluginBase; +use Drupal\Core\Plugin\Context\Context; + +/** + * Drupal specific class for plugins that use context. + * + * This class specifically overrides setContextValue to use the core version of + * the Context class. This code is exactly the same as what is in Component + * ContextAwarePluginBase but it is using a different Context class. + */ +abstract class ContextAwarePluginBase extends PluginBase { + + /** + * Override of \Drupal\Component\Plugin\ContextAwarePluginBase::setContextValue(). + */ + public function setContextValue($key, $value) { + $context_definition = $this->getContextDefinition($key); + $this->context[$key] = new Context($context_definition); + $this->context[$key]->setContextValue($value); + + return $this; + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php new file mode 100644 index 000000000000..888f1e66149a --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/ContextPluginTest.php @@ -0,0 +1,203 @@ +<?php + +/** + * @file + * Contains \Drupal\system\Tests\Plugin\ContextPluginTest. + */ + +namespace Drupal\system\Tests\Plugin; + +use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\plugin_test\Plugin\MockBlockManager; +use Drupal\Component\Plugin\Exception\PluginException; +use Drupal\Component\Plugin\Exception\ContextException; + +/** + * Tests that context aware plugins function correctly. + */ +class ContextPluginTest extends DrupalUnitTestBase { + + public static $modules = array('system', 'user', 'node'); + + public static function getInfo() { + return array( + 'name' => 'Contextual Plugins', + 'description' => 'Tests that contexts are properly set and working within plugins.', + 'group' => 'Plugin API', + ); + } + + protected function setUp() { + parent::setUp(); + $this->installSchema('node', 'node_type'); + } + + /** + * Tests basic context definition and value getters and setters. + */ + function testContext() { + $name = $this->randomName(); + $manager = new MockBlockManager(); + $plugin = $manager->createInstance('user_name'); + // Create a node, add it as context, catch the exception. + $node = entity_create('node', array('title' => $name)); + + // Try to get a valid context that has not been set. + try { + $plugin->getContext('user'); + $this->fail('The user context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The user context is not yet set.'); + } + + // Try to get an invalid context. + try { + $plugin->getContext('node'); + $this->fail('The node context should not be a valid context.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The node context is not a valid context.'); + } + + // Try to get a valid context value that has not been set. + try { + $plugin->getContextValue('user'); + $this->fail('The user context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The user context is not yet set.'); + } + + // Try to call a method of the plugin that requires context before it has + // been set. + try { + $plugin->getTitle(); + $this->fail('The user context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The user context is not yet set.'); + } + + // Try to get a context value that is not valid. + try { + $plugin->getContextValue('node'); + $this->fail('The node context should not be a valid context.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The node context is not a valid context.'); + } + + // Try to pass the wrong class type as a context value. + try { + $plugin->setContextValue('user', $node); + $this->fail('The node context should fail validation for a user context.'); + } + catch (ContextException $e) { + $this->assertEqual($e->getMessage(), 'The context passed was not an instance of Drupal\user\Plugin\Core\Entity\User.'); + } + + // Set an appropriate context value appropriately and check to make sure + // its methods work as expected. + $user = entity_create('user', array('name' => $name)); + $plugin->setContextValue('user', $user); + $this->assertEqual($user->label(), $plugin->getTitle()); + + // Test the getContextDefinitions() method. + $this->assertIdentical($plugin->getContextDefinitions(), array('user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'))); + + // Test the getContextDefinition() method for a valid context. + $this->assertEqual($plugin->getContextDefinition('user'), array('class' => 'Drupal\user\Plugin\Core\Entity\User')); + + // Test the getContextDefinition() method for an invalid context. + try { + $plugin->getContextDefinition('node'); + $this->fail('The node context should not be a valid context.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The node context is not a valid context.'); + } + + // Test typed data context plugins. + $typed_data_plugin = $manager->createInstance('string_context'); + + // Try to get a valid context value that has not been set. + try { + $typed_data_plugin->getContextValue('string'); + $this->fail('The string context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The string context is not yet set.'); + } + + // Try to call a method of the plugin that requires a context value before + // it has been set. + try { + $typed_data_plugin->getTitle(); + $this->fail('The string context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The string context is not yet set.'); + } + + // Set the context value appropriately and check the title. + $typed_data_plugin->setContextValue('string', $name); + $this->assertEqual($name, $typed_data_plugin->getTitle()); + + // Test Complex compound context handling. + $complex_plugin = $manager->createInstance('complex_context'); + + // With no contexts set, try to get the contexts. + try { + $complex_plugin->getContexts(); + $this->fail('There should not be any contexts set yet.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'There are no set contexts.'); + } + + // With no contexts set, try to get the context values. + try { + $complex_plugin->getContextValues(); + $this->fail('There should not be any contexts set yet.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'There are no set contexts.'); + } + + // Set the user context value. + $complex_plugin->setContextValue('user', $user); + + // With only the user context set, try to get the contexts. + try { + $complex_plugin->getContexts(); + $this->fail('The node context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The node context is not yet set.'); + } + + // With only the user context set, try to get the context values. + try { + $complex_plugin->getContextValues(); + $this->fail('The node context should not yet be set.'); + } + catch (PluginException $e) { + $this->assertEqual($e->getMessage(), 'The node context is not yet set.'); + } + + $complex_plugin->setContextValue('node', $node); + $context_wrappers = $complex_plugin->getContexts(); + // Make sure what came out of the wrappers is good. + $this->assertEqual($context_wrappers['user']->getContextValue()->label(), $user->label()); + $this->assertEqual($context_wrappers['node']->getContextValue()->label(), $node->label()); + + // Make sure what comes out of the context values is good. + $contexts = $complex_plugin->getContextValues(); + $this->assertEqual($contexts['user']->label(), $user->label()); + $this->assertEqual($contexts['node']->label(), $node->label()); + + // Test the title method for the complex context plugin. + $this->assertEqual($user->label() . ' -- ' . $node->label(), $complex_plugin->getTitle()); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php index 5db932203ca0..c927f7eb2419 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/PluginTestBase.php @@ -70,6 +70,28 @@ public function setUp() { 'label' => 'Layout Foo', 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock', ), + 'user_name' => array( + 'label' => 'User name', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock', + 'context' => array( + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User') + ), + ), + 'string_context' => array( + 'label' => 'String typed data', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock', + 'context' => array( + 'string' => array('type' => 'string'), + ), + ), + 'complex_context' => array( + 'label' => 'Complex context', + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', + 'context' => array( + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'), + 'node' => array('class' => 'Drupal\node\Plugin\Core\Entity\Node'), + ), + ), ); $this->defaultsTestPluginExpectedDefinitions = array( 'test_block1' => array( diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php index fcf18245125f..7e292597367a 100644 --- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php @@ -66,6 +66,35 @@ public function __construct() { 'derivative' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlockDeriver', )); + // A block plugin that requires context to function. This block requires a + // user object in order to return the user name from the getTitle() method. + $this->discovery->setDefinition('user_name', array( + 'label' => t('User name'), + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock', + 'context' => array( + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User') + ), + )); + + // A block plugin that requires a typed data string context to function. + $this->discovery->setDefinition('string_context', array( + 'label' => t('String typed data'), + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock', + 'context' => array( + 'string' => array('type' => 'string'), + ), + )); + + // A complex context plugin that requires both a user and node for context. + $this->discovery->setDefinition('complex_context', array( + 'label' => t('Complex context'), + 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock', + 'context' => array( + 'user' => array('class' => 'Drupal\user\Plugin\Core\Entity\User'), + 'node' => array('class' => 'Drupal\node\Plugin\Core\Entity\Node'), + ), + )); + // In addition to finding all of the plugins available for a type, a plugin // type must also be able to create instances of that plugin. For example, a // specific instance of a "Main menu" menu block, configured to show just diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php new file mode 100644 index 000000000000..1cb657a4a61d --- /dev/null +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockComplexContextBlock.php @@ -0,0 +1,24 @@ +<?php + +/** + * @file + * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock. + */ + +namespace Drupal\plugin_test\Plugin\plugin_test\mock_block; + +use Drupal\Core\Plugin\ContextAwarePluginBase; + +/** + * Implementation of a complex context plugin used by Plugin API context tests. + * + * @see \Drupal\plugin_test\Plugin\MockBlockManager + */ +class MockComplexContextBlock extends ContextAwarePluginBase { + + public function getTitle() { + $user = $this->getContextValue('user'); + $node = $this->getContextValue('node'); + return $user->label() . ' -- ' . $node->label(); + } +} diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php new file mode 100644 index 000000000000..3fc1f849d1e9 --- /dev/null +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockUserNameBlock.php @@ -0,0 +1,24 @@ +<?php + +/** + * @file + * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock. + */ + +namespace Drupal\plugin_test\Plugin\plugin_test\mock_block; + +use Drupal\Core\Plugin\ContextAwarePluginBase; +use Drupal\Component\Plugin\Discovery\DiscoveryInterface; + +/** + * Implementation of a user name block plugin used by Plugin API context test. + * + * @see \Drupal\plugin_test\Plugin\MockBlockManager + */ +class MockUserNameBlock extends ContextAwarePluginBase { + + public function getTitle() { + $user = $this->getContextValue('user'); + return $user->label(); + } +} diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php new file mode 100644 index 000000000000..14e0ab3bf7ef --- /dev/null +++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/TypedDataStringBlock.php @@ -0,0 +1,23 @@ +<?php + +/** + * @file + * Contains \Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock. + */ + +namespace Drupal\plugin_test\Plugin\plugin_test\mock_block; + +use Drupal\Core\Plugin\ContextAwarePluginBase; + +/** + * Implementation of a String TypedData contextual block plugin used by Plugin + * API context test. + * + * @see \Drupal\plugin_test\Plugin\MockBlockManager + */ +class TypedDataStringBlock extends ContextAwarePluginBase { + + public function getTitle() { + return $this->getContextValue('string'); + } +} -- GitLab