Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
DisplayBuilderEventsSubscriber
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 12
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSubscribedEvents
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onActive
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onAttachToRoot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onAttachToSlot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onDelete
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onHistoryChange
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onMove
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onUpdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onSave
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onPresetSave
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 dispatchToIslands
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Event;
6
7use Drupal\Core\Entity\EntityTypeManagerInterface;
8use Drupal\display_builder\IslandPluginManagerInterface;
9use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
11/**
12 * The event subscriber for Display Builder islands.
13 */
14class DisplayBuilderEventsSubscriber implements EventSubscriberInterface {
15
16  /**
17   * Constructs a new DisplayBuilderEventsSubscriber object.
18   */
19  public function __construct(
20    protected IslandPluginManagerInterface $islandManager,
21    protected EntityTypeManagerInterface $entityTypeManager,
22  ) {}
23
24  /**
25   * {@inheritdoc}
26   */
27  public static function getSubscribedEvents(): array {
28    return [
29      DisplayBuilderEvents::ON_ACTIVE => 'onActive',
30      DisplayBuilderEvents::ON_ATTACH_TO_ROOT => 'onAttachToRoot',
31      DisplayBuilderEvents::ON_ATTACH_TO_SLOT => 'onAttachToSlot',
32      DisplayBuilderEvents::ON_DELETE => 'onDelete',
33      DisplayBuilderEvents::ON_HISTORY_CHANGE => 'onHistoryChange',
34      DisplayBuilderEvents::ON_MOVE => 'onMove',
35      DisplayBuilderEvents::ON_UPDATE => 'onUpdate',
36      DisplayBuilderEvents::ON_SAVE => 'onSave',
37      DisplayBuilderEvents::ON_PRESET_SAVE => 'onPresetSave',
38    ];
39  }
40
41  /**
42   * Event handler for when a block becomes active.
43   *
44   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
45   *   The event object.
46   */
47  public function onActive(DisplayBuilderEvent $event): void {
48    $this->dispatchToIslands($event, __FUNCTION__, [$event->getData()]);
49  }
50
51  /**
52   * Event handler for when a block is attached to the root.
53   *
54   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
55   *   The event object.
56   */
57  public function onAttachToRoot(DisplayBuilderEvent $event): void {
58    $this->dispatchToIslands($event, __FUNCTION__, [$event->getNodeId()]);
59  }
60
61  /**
62   * Event handler for when a block is attached to a slot.
63   *
64   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
65   *   The event object.
66   */
67  public function onAttachToSlot(DisplayBuilderEvent $event): void {
68    $this->dispatchToIslands($event, __FUNCTION__, [$event->getNodeId(), $event->getParentId()]);
69  }
70
71  /**
72   * Event handler for when a block is deleted.
73   *
74   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
75   *   The event object.
76   */
77  public function onDelete(DisplayBuilderEvent $event): void {
78    $this->dispatchToIslands($event, __FUNCTION__, [$event->getParentId()]);
79  }
80
81  /**
82   * Event handler for when the history changes.
83   *
84   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
85   *   The event object.
86   */
87  public function onHistoryChange(DisplayBuilderEvent $event): void {
88    $this->dispatchToIslands($event, __FUNCTION__);
89  }
90
91  /**
92   * Event handler for when a block is moved.
93   *
94   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
95   *   The event object.
96   */
97  public function onMove(DisplayBuilderEvent $event): void {
98    $this->dispatchToIslands($event, __FUNCTION__, [$event->getNodeId()]);
99  }
100
101  /**
102   * Event handler for when a block is updated.
103   *
104   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
105   *   The event object.
106   */
107  public function onUpdate(DisplayBuilderEvent $event): void {
108    $this->dispatchToIslands($event, __FUNCTION__, [$event->getNodeId(), $event->getCurrentIslandId()]);
109  }
110
111  /**
112   * Event handler for when a display is saved.
113   *
114   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
115   *   The event object.
116   */
117  public function onSave(DisplayBuilderEvent $event): void {
118    $this->dispatchToIslands($event, __FUNCTION__, [$event->getData()]);
119  }
120
121  /**
122   * Event handler for when a preset is saved.
123   *
124   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
125   *   The event object.
126   */
127  public function onPresetSave(DisplayBuilderEvent $event): void {
128    $this->dispatchToIslands($event, __FUNCTION__);
129  }
130
131  /**
132   * Dispatch the event with a generic code.
133   *
134   * @param \Drupal\display_builder\Event\DisplayBuilderEvent $event
135   *   The event object.
136   * @param string $method
137   *   The method to dispatch.
138   * @param array $parameters
139   *   (Optional) The parameters to the method.
140   */
141  private function dispatchToIslands(DisplayBuilderEvent $event, string $method, array $parameters = []): void {
142    \array_unshift($parameters, $event->getBuilderId());
143
144    $configuration = $event->getIslandConfiguration();
145    /** @var \Drupal\display_builder\InstanceInterface $builder */
146    $builder = $this->entityTypeManager->getStorage('display_builder_instance')->load($event->getBuilderId());
147    $contexts = $builder->getContexts();
148    $islands = $this->islandManager->createInstances($this->islandManager->getDefinitions(), $contexts, $configuration);
149
150    $island_enabled = $event->getEnabledIslands();
151
152    foreach ($islands as $island_id => $island) {
153      if (!isset($island_enabled[$island_id])) {
154        continue;
155      }
156
157      // Skip the island triggering the HTMX event. Useful to avoid swapping
158      // the content of an island which is already in the expected state.
159      // For examples, if we move an instance in Builder, Layers or Tree
160      // panels, if we change the settings in InstanceForm.
161      // @see Drupal\display_builder\Controller\ApiControllerBase::islandId
162      if ($island_id === $event->getCurrentIslandId()) {
163        continue;
164      }
165
166      if (!\method_exists($island, $method)) {
167        continue;
168      }
169      $result = $island->{$method}(...$parameters);
170
171      if ($result !== NULL) {
172        $event->appendResult($island_id, $result);
173      }
174    }
175  }
176
177}