annotate core/lib/Drupal/Core/Annotation/ContextDefinition.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents 4c8ae668cc8c
children af1871eacc83
rev   line source
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@0 17 * context = {
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@0 24 * context = {
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@0 32 * context = {
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@0 40 * context = {
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@0 48 * context = {
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@0 122 }
Chris@0 123
Chris@0 124 /**
Chris@17 125 * Determines the context definition class to use.
Chris@17 126 *
Chris@17 127 * If the annotation specifies a specific context definition class, we use
Chris@17 128 * that. Otherwise, we use \Drupal\Core\Plugin\Context\EntityContextDefinition
Chris@17 129 * if the data type starts with 'entity:', since it contains specialized logic
Chris@17 130 * specific to entities. Otherwise, we fall back to the generic
Chris@17 131 * \Drupal\Core\Plugin\Context\ContextDefinition class.
Chris@17 132 *
Chris@17 133 * @param array $values
Chris@17 134 * The annotation values.
Chris@17 135 *
Chris@17 136 * @return string
Chris@17 137 * The fully-qualified name of the context definition class.
Chris@17 138 */
Chris@17 139 protected function getDefinitionClass(array $values) {
Chris@17 140 if (isset($values['class'])) {
Chris@17 141 return $values['class'];
Chris@17 142 }
Chris@17 143 if (strpos($values['value'], 'entity:') === 0) {
Chris@17 144 return 'Drupal\Core\Plugin\Context\EntityContextDefinition';
Chris@17 145 }
Chris@17 146 return 'Drupal\Core\Plugin\Context\ContextDefinition';
Chris@17 147 }
Chris@17 148
Chris@17 149 /**
Chris@0 150 * Returns the value of an annotation.
Chris@0 151 *
Chris@0 152 * @return \Drupal\Core\Plugin\Context\ContextDefinitionInterface
Chris@0 153 */
Chris@0 154 public function get() {
Chris@0 155 return $this->definition;
Chris@0 156 }
Chris@0 157
Chris@0 158 }