081d982f054b4dd50a12876a349acca5df6c0fa1
[yaffs-website] / web / core / modules / layout_builder / src / SectionComponent.php
1 <?php
2
3 namespace Drupal\layout_builder;
4
5 use Drupal\Component\Plugin\Exception\PluginException;
6 use Drupal\Core\Plugin\ContextAwarePluginInterface;
7 use Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent;
8
9 /**
10  * Provides a value object for a section component.
11  *
12  * A component represents the smallest part of a layout (for example, a block).
13  * Components wrap a renderable plugin, currently using
14  * \Drupal\Core\Block\BlockPluginInterface, and contain the layout region
15  * within the section layout where the component will be rendered.
16  *
17  * @internal
18  *   Layout Builder is currently experimental and should only be leveraged by
19  *   experimental modules and development releases of contributed modules.
20  *   See https://www.drupal.org/core/experimental for more information.
21  *
22  * @see \Drupal\Core\Layout\LayoutDefinition
23  * @see \Drupal\layout_builder\Section
24  * @see \Drupal\layout_builder\SectionStorageInterface
25  *
26  * @todo Determine whether to retain the name 'component' in
27  *   https://www.drupal.org/project/drupal/issues/2929783.
28  * @todo Determine whether an interface will be provided for this in
29  *   https://www.drupal.org/project/drupal/issues/2930334.
30  */
31 class SectionComponent {
32
33   /**
34    * The UUID of the component.
35    *
36    * @var string
37    */
38   protected $uuid;
39
40   /**
41    * The region the component is placed in.
42    *
43    * @var string
44    */
45   protected $region;
46
47   /**
48    * An array of plugin configuration.
49    *
50    * @var mixed[]
51    */
52   protected $configuration;
53
54   /**
55    * The weight of the component.
56    *
57    * @var int
58    */
59   protected $weight = 0;
60
61   /**
62    * Any additional properties and values.
63    *
64    * @var mixed[]
65    */
66   protected $additional = [];
67
68   /**
69    * Constructs a new SectionComponent.
70    *
71    * @param string $uuid
72    *   The UUID.
73    * @param string $region
74    *   The region.
75    * @param mixed[] $configuration
76    *   The plugin configuration.
77    * @param mixed[] $additional
78    *   An additional values.
79    */
80   public function __construct($uuid, $region, array $configuration = [], array $additional = []) {
81     $this->uuid = $uuid;
82     $this->region = $region;
83     $this->configuration = $configuration;
84     $this->additional = $additional;
85   }
86
87   /**
88    * Returns the renderable array for this component.
89    *
90    * @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
91    *   An array of available contexts.
92    * @param bool $in_preview
93    *   TRUE if the component is being previewed, FALSE otherwise.
94    *
95    * @return array
96    *   A renderable array representing the content of the component.
97    */
98   public function toRenderArray(array $contexts = [], $in_preview = FALSE) {
99     $event = new SectionComponentBuildRenderArrayEvent($this, $contexts, $in_preview);
100     $this->eventDispatcher()->dispatch(LayoutBuilderEvents::SECTION_COMPONENT_BUILD_RENDER_ARRAY, $event);
101     $output = $event->getBuild();
102     $event->getCacheableMetadata()->applyTo($output);
103     return $output;
104   }
105
106   /**
107    * Gets any arbitrary property for the component.
108    *
109    * @param string $property
110    *   The property to retrieve.
111    *
112    * @return mixed
113    *   The value for that property, or NULL if the property does not exist.
114    */
115   public function get($property) {
116     if (property_exists($this, $property)) {
117       $value = isset($this->{$property}) ? $this->{$property} : NULL;
118     }
119     else {
120       $value = isset($this->additional[$property]) ? $this->additional[$property] : NULL;
121     }
122     return $value;
123   }
124
125   /**
126    * Sets a value to an arbitrary property for the component.
127    *
128    * @param string $property
129    *   The property to use for the value.
130    * @param mixed $value
131    *   The value to set.
132    *
133    * @return $this
134    */
135   public function set($property, $value) {
136     if (property_exists($this, $property)) {
137       $this->{$property} = $value;
138     }
139     else {
140       $this->additional[$property] = $value;
141     }
142     return $this;
143   }
144
145   /**
146    * Gets the region for the component.
147    *
148    * @return string
149    *   The region.
150    */
151   public function getRegion() {
152     return $this->region;
153   }
154
155   /**
156    * Sets the region for the component.
157    *
158    * @param string $region
159    *   The region.
160    *
161    * @return $this
162    */
163   public function setRegion($region) {
164     $this->region = $region;
165     return $this;
166   }
167
168   /**
169    * Gets the weight of the component.
170    *
171    * @return int
172    *   The zero-based weight of the component.
173    *
174    * @throws \UnexpectedValueException
175    *   Thrown if the weight was never set.
176    */
177   public function getWeight() {
178     return $this->weight;
179   }
180
181   /**
182    * Sets the weight of the component.
183    *
184    * @param int $weight
185    *   The zero-based weight of the component.
186    *
187    * @return $this
188    */
189   public function setWeight($weight) {
190     $this->weight = $weight;
191     return $this;
192   }
193
194   /**
195    * Gets the component plugin configuration.
196    *
197    * @return mixed[]
198    *   The component plugin configuration.
199    */
200   protected function getConfiguration() {
201     return $this->configuration;
202   }
203
204   /**
205    * Sets the plugin configuration.
206    *
207    * @param mixed[] $configuration
208    *   The plugin configuration.
209    *
210    * @return $this
211    */
212   public function setConfiguration(array $configuration) {
213     $this->configuration = $configuration;
214     return $this;
215   }
216
217   /**
218    * Gets the plugin ID.
219    *
220    * @return string
221    *   The plugin ID.
222    *
223    * @throws \Drupal\Component\Plugin\Exception\PluginException
224    *   Thrown if the plugin ID cannot be found.
225    */
226   public function getPluginId() {
227     if (empty($this->configuration['id'])) {
228       throw new PluginException(sprintf('No plugin ID specified for component with "%s" UUID', $this->uuid));
229     }
230     return $this->configuration['id'];
231   }
232
233   /**
234    * Gets the UUID for this component.
235    *
236    * @return string
237    *   The UUID.
238    */
239   public function getUuid() {
240     return $this->uuid;
241   }
242
243   /**
244    * Gets the plugin for this component.
245    *
246    * @param \Drupal\Core\Plugin\Context\ContextInterface[] $contexts
247    *   An array of contexts to set on the plugin.
248    *
249    * @return \Drupal\Component\Plugin\PluginInspectionInterface
250    *   The plugin.
251    */
252   public function getPlugin(array $contexts = []) {
253     $plugin = $this->pluginManager()->createInstance($this->getPluginId(), $this->getConfiguration());
254     if ($contexts && $plugin instanceof ContextAwarePluginInterface) {
255       $this->contextHandler()->applyContextMapping($plugin, $contexts);
256     }
257     return $plugin;
258   }
259
260   /**
261    * Wraps the component plugin manager.
262    *
263    * @return \Drupal\Core\Block\BlockManagerInterface
264    *   The plugin manager.
265    */
266   protected function pluginManager() {
267     // @todo Figure out the best way to unify fields and blocks and components
268     //   in https://www.drupal.org/node/1875974.
269     return \Drupal::service('plugin.manager.block');
270   }
271
272   /**
273    * Wraps the context handler.
274    *
275    * @return \Drupal\Core\Plugin\Context\ContextHandlerInterface
276    *   The context handler.
277    */
278   protected function contextHandler() {
279     return \Drupal::service('context.handler');
280   }
281
282   /**
283    * Wraps the event dispatcher.
284    *
285    * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface
286    *   The event dispatcher.
287    */
288   protected function eventDispatcher() {
289     return \Drupal::service('event_dispatcher');
290   }
291
292   /**
293    * Returns an array representation of the section component.
294    *
295    * @internal
296    *   This is intended for use by a storage mechanism for section components.
297    *
298    * @return array
299    *   An array representation of the section component.
300    */
301   public function toArray() {
302     return [
303       'uuid' => $this->getUuid(),
304       'region' => $this->getRegion(),
305       'configuration' => $this->getConfiguration(),
306       'additional' => $this->additional,
307       'weight' => $this->getWeight(),
308     ];
309   }
310
311 }