3 namespace Drupal\plugin_test\Plugin;
5 use Drupal\Component\Plugin\PluginManagerBase;
6 use Drupal\Component\Plugin\Discovery\StaticDiscovery;
7 use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator;
8 use Drupal\Component\Plugin\Factory\ReflectionFactory;
9 use Drupal\Core\Plugin\Context\ContextDefinition;
12 * Defines a plugin manager used by Plugin API derivative unit tests.
14 class MockBlockManager extends PluginManagerBase {
15 public function __construct() {
17 // Create the object that can be used to return definitions for all the
18 // plugins available for this type. Most real plugin managers use a richer
19 // discovery implementation, but StaticDiscovery lets us add some simple
20 // mock plugins for unit testing.
21 $this->discovery = new StaticDiscovery();
23 // Derivative plugins are plugins that are derived from a base plugin
24 // definition and some site configuration (examples below). To allow for
25 // such plugins, we add the DerivativeDiscoveryDecorator to our discovery
27 $this->discovery = new DerivativeDiscoveryDecorator($this->discovery);
29 // The plugin definitions that follow are based on work that is in progress
30 // for the Drupal 8 Blocks and Layouts initiative
31 // (http://groups.drupal.org/node/213563). As stated above, we set
32 // definitions here, because this is for unit testing. Real plugin managers
33 // use a discovery implementation that allows for any module to add new
34 // plugins to the system.
36 // A simple plugin: the user login block.
37 $this->discovery->setDefinition('user_login', [
39 'label' => t('User login'),
40 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserLoginBlock',
43 // A plugin that requires derivatives: the menu block plugin. We do not want
44 // a generic "Menu" block showing up in the Block administration UI.
45 // Instead, we want a block for each menu, but the number of menus in the
46 // system and each one's title is user configurable. The
47 // MockMenuBlockDeriver class ensures that only derivatives, and not the
48 // base plugin, are available to the system.
49 $this->discovery->setDefinition('menu', [
51 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockMenuBlock',
52 'deriver' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockMenuBlockDeriver',
54 // A plugin defining itself as a derivative.
55 $this->discovery->setDefinition('menu:foo', [
57 'label' => t('Base label'),
58 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockMenuBlock',
61 // A block plugin that can optionally be derived: the layout block plugin.
62 // A layout is a special kind of block into which other blocks can be
63 // placed. We want both a generic "Layout" block available in the Block
64 // administration UI as well as additional user-created custom layouts. The
65 // MockLayoutBlockDeriver class ensures that both the base plugin and the
66 // derivatives are available to the system.
67 $this->discovery->setDefinition('layout', [
69 'label' => t('Layout'),
70 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
71 'deriver' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlockDeriver',
74 // A block plugin that requires context to function. This block requires a
75 // user object in order to return the user name from the getTitle() method.
76 $this->discovery->setDefinition('user_name', [
78 'label' => t('User name'),
79 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
81 'user' => $this->createContextDefinition('entity:user', t('User')),
85 // An optional context version of the previous block plugin.
86 $this->discovery->setDefinition('user_name_optional', [
87 'id' => 'user_name_optional',
88 'label' => t('User name optional'),
89 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserNameBlock',
91 'user' => $this->createContextDefinition('entity:user', t('User'), FALSE),
95 // A block plugin that requires a typed data string context to function.
96 $this->discovery->setDefinition('string_context', [
97 'id' => 'string_context',
98 'label' => t('String typed data'),
99 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\TypedDataStringBlock',
102 // A complex context plugin that requires both a user and node for context.
103 $this->discovery->setDefinition('complex_context', [
104 'id' => 'complex_context',
105 'label' => t('Complex context'),
106 'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockComplexContextBlock',
108 'user' => $this->createContextDefinition('entity:user', t('User')),
109 'node' => $this->createContextDefinition('entity:node', t('Node')),
113 // In addition to finding all of the plugins available for a type, a plugin
114 // type must also be able to create instances of that plugin. For example, a
115 // specific instance of a "Main menu" menu block, configured to show just
116 // the top-level of links. To handle plugin instantiation, plugin managers
117 // can use one of the factory classes included with the plugin system, or
118 // create their own. ReflectionFactory is a general purpose, flexible
119 // factory suitable for many kinds of plugin types. Factories need access to
120 // the plugin definitions (e.g., since that's where the plugin's class is
121 // specified), so we provide it the discovery object.
122 $this->factory = new ReflectionFactory($this->discovery);
126 * Creates a new context definition with a label that is cast to string.
128 * @param string $data_type
129 * The required data type.
130 * @param mixed|string|null $label
131 * The label of this context definition for the UI.
132 * @param bool $required
133 * Whether the context definition is required.
135 * @return \Drupal\Core\Plugin\Context\ContextDefinition
137 protected function createContextDefinition($data_type, $label, $required = TRUE) {
138 // We cast the label to string for testing purposes only, as it may be
139 // a TranslatableMarkup and we will do assertEqual() checks on arrays that
140 // include ContextDefinition objects, and var_export() has problems
141 // printing TranslatableMarkup objects.
142 return new ContextDefinition($data_type, (string) $label, $required);