Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Core\Annotation;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Annotation\Plugin;
|
Chris@0
|
6 use Drupal\Core\StringTranslation\TranslatableMarkup;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * @defgroup plugin_context Annotation for context definition
|
Chris@0
|
10 * @{
|
Chris@0
|
11 * Describes how to use ContextDefinition annotation.
|
Chris@0
|
12 *
|
Chris@0
|
13 * When providing plugin annotations, contexts can be defined to support UI
|
Chris@0
|
14 * interactions through providing limits, and mapping contexts to appropriate
|
Chris@0
|
15 * plugins. Context definitions can be provided as such:
|
Chris@0
|
16 * @code
|
Chris@18
|
17 * context_definitions = {
|
Chris@0
|
18 * "node" = @ContextDefinition("entity:node")
|
Chris@0
|
19 * }
|
Chris@0
|
20 * @endcode
|
Chris@0
|
21 *
|
Chris@0
|
22 * To add a label to a context definition use the "label" key:
|
Chris@0
|
23 * @code
|
Chris@18
|
24 * context_definitions = {
|
Chris@0
|
25 * "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
|
Chris@0
|
26 * }
|
Chris@0
|
27 * @endcode
|
Chris@0
|
28 *
|
Chris@0
|
29 * Contexts are required unless otherwise specified. To make an optional
|
Chris@0
|
30 * context use the "required" key:
|
Chris@0
|
31 * @code
|
Chris@18
|
32 * context_definitions = {
|
Chris@0
|
33 * "node" = @ContextDefinition("entity:node", required = FALSE, label = @Translation("Node"))
|
Chris@0
|
34 * }
|
Chris@0
|
35 * @endcode
|
Chris@0
|
36 *
|
Chris@0
|
37 * To define multiple contexts, simply provide different key names in the
|
Chris@0
|
38 * context array:
|
Chris@0
|
39 * @code
|
Chris@18
|
40 * context_definitions = {
|
Chris@0
|
41 * "artist" = @ContextDefinition("entity:node", label = @Translation("Artist")),
|
Chris@0
|
42 * "album" = @ContextDefinition("entity:node", label = @Translation("Album"))
|
Chris@0
|
43 * }
|
Chris@0
|
44 * @endcode
|
Chris@0
|
45 *
|
Chris@0
|
46 * Specifying a default value for the context definition:
|
Chris@0
|
47 * @code
|
Chris@18
|
48 * context_definitions = {
|
Chris@0
|
49 * "message" = @ContextDefinition("string",
|
Chris@0
|
50 * label = @Translation("Message"),
|
Chris@0
|
51 * default_value = @Translation("Checkout complete! Thank you for your purchase.")
|
Chris@0
|
52 * )
|
Chris@0
|
53 * }
|
Chris@0
|
54 * @endcode
|
Chris@0
|
55 *
|
Chris@0
|
56 * @see annotation
|
Chris@0
|
57 *
|
Chris@0
|
58 * @}
|
Chris@0
|
59 */
|
Chris@0
|
60
|
Chris@0
|
61 /**
|
Chris@0
|
62 * Defines a context definition annotation object.
|
Chris@0
|
63 *
|
Chris@0
|
64 * Some plugins require various data contexts in order to function. This class
|
Chris@0
|
65 * supports that need by allowing the contexts to be easily defined within an
|
Chris@0
|
66 * annotation and return a ContextDefinitionInterface implementing class.
|
Chris@0
|
67 *
|
Chris@0
|
68 * @Annotation
|
Chris@0
|
69 *
|
Chris@0
|
70 * @ingroup plugin_context
|
Chris@0
|
71 */
|
Chris@0
|
72 class ContextDefinition extends Plugin {
|
Chris@0
|
73
|
Chris@0
|
74 /**
|
Chris@0
|
75 * The ContextDefinitionInterface object.
|
Chris@0
|
76 *
|
Chris@0
|
77 * @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface
|
Chris@0
|
78 */
|
Chris@0
|
79 protected $definition;
|
Chris@0
|
80
|
Chris@0
|
81 /**
|
Chris@0
|
82 * Constructs a new context definition object.
|
Chris@0
|
83 *
|
Chris@0
|
84 * @param array $values
|
Chris@0
|
85 * An associative array with the following keys:
|
Chris@0
|
86 * - value: The required data type.
|
Chris@0
|
87 * - label: (optional) The UI label of this context definition.
|
Chris@0
|
88 * - required: (optional) Whether the context definition is required.
|
Chris@0
|
89 * - multiple: (optional) Whether the context definition is multivalue.
|
Chris@0
|
90 * - description: (optional) The UI description of this context definition.
|
Chris@0
|
91 * - default_value: (optional) The default value in case the underlying
|
Chris@0
|
92 * value is not set.
|
Chris@0
|
93 * - class: (optional) A custom ContextDefinitionInterface class.
|
Chris@0
|
94 *
|
Chris@0
|
95 * @throws \Exception
|
Chris@0
|
96 * Thrown when the class key is specified with a non
|
Chris@0
|
97 * ContextDefinitionInterface implementing class.
|
Chris@0
|
98 */
|
Chris@0
|
99 public function __construct(array $values) {
|
Chris@0
|
100 $values += [
|
Chris@0
|
101 'required' => TRUE,
|
Chris@0
|
102 'multiple' => FALSE,
|
Chris@0
|
103 'default_value' => NULL,
|
Chris@0
|
104 ];
|
Chris@0
|
105 // Annotation classes extract data from passed annotation classes directly
|
Chris@0
|
106 // used in the classes they pass to.
|
Chris@0
|
107 foreach (['label', 'description'] as $key) {
|
Chris@0
|
108 // @todo Remove this workaround in https://www.drupal.org/node/2362727.
|
Chris@0
|
109 if (isset($values[$key]) && $values[$key] instanceof TranslatableMarkup) {
|
Chris@0
|
110 $values[$key] = (string) $values[$key]->get();
|
Chris@0
|
111 }
|
Chris@0
|
112 else {
|
Chris@0
|
113 $values[$key] = NULL;
|
Chris@0
|
114 }
|
Chris@0
|
115 }
|
Chris@0
|
116 if (isset($values['class']) && !in_array('Drupal\Core\Plugin\Context\ContextDefinitionInterface', class_implements($values['class']))) {
|
Chris@0
|
117 throw new \Exception('ContextDefinition class must implement \Drupal\Core\Plugin\Context\ContextDefinitionInterface.');
|
Chris@0
|
118 }
|
Chris@17
|
119
|
Chris@17
|
120 $class = $this->getDefinitionClass($values);
|
Chris@0
|
121 $this->definition = new $class($values['value'], $values['label'], $values['required'], $values['multiple'], $values['description'], $values['default_value']);
|
Chris@18
|
122
|
Chris@18
|
123 if (isset($values['constraints'])) {
|
Chris@18
|
124 foreach ($values['constraints'] as $constraint_name => $options) {
|
Chris@18
|
125 $this->definition->addConstraint($constraint_name, $options);
|
Chris@18
|
126 }
|
Chris@18
|
127 }
|
Chris@0
|
128 }
|
Chris@0
|
129
|
Chris@0
|
130 /**
|
Chris@17
|
131 * Determines the context definition class to use.
|
Chris@17
|
132 *
|
Chris@17
|
133 * If the annotation specifies a specific context definition class, we use
|
Chris@17
|
134 * that. Otherwise, we use \Drupal\Core\Plugin\Context\EntityContextDefinition
|
Chris@17
|
135 * if the data type starts with 'entity:', since it contains specialized logic
|
Chris@17
|
136 * specific to entities. Otherwise, we fall back to the generic
|
Chris@17
|
137 * \Drupal\Core\Plugin\Context\ContextDefinition class.
|
Chris@17
|
138 *
|
Chris@17
|
139 * @param array $values
|
Chris@17
|
140 * The annotation values.
|
Chris@17
|
141 *
|
Chris@17
|
142 * @return string
|
Chris@17
|
143 * The fully-qualified name of the context definition class.
|
Chris@17
|
144 */
|
Chris@17
|
145 protected function getDefinitionClass(array $values) {
|
Chris@17
|
146 if (isset($values['class'])) {
|
Chris@17
|
147 return $values['class'];
|
Chris@17
|
148 }
|
Chris@17
|
149 if (strpos($values['value'], 'entity:') === 0) {
|
Chris@17
|
150 return 'Drupal\Core\Plugin\Context\EntityContextDefinition';
|
Chris@17
|
151 }
|
Chris@17
|
152 return 'Drupal\Core\Plugin\Context\ContextDefinition';
|
Chris@17
|
153 }
|
Chris@17
|
154
|
Chris@17
|
155 /**
|
Chris@0
|
156 * Returns the value of an annotation.
|
Chris@0
|
157 *
|
Chris@0
|
158 * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface
|
Chris@0
|
159 */
|
Chris@0
|
160 public function get() {
|
Chris@0
|
161 return $this->definition;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 }
|