Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
3.85% |
1 / 26 |
|
33.33% |
1 / 3 |
CRAP | |
0.00% |
0 / 1 |
ApiControllerBase | |
3.85% |
1 / 26 |
|
33.33% |
1 / 3 |
38.00 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createEventWithEnabledIsland | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
12 | |||
saveSseData | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Drupal\display_builder\Controller; |
6 | |
7 | use Drupal\Component\Datetime\TimeInterface; |
8 | use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface; |
9 | use Drupal\Core\Controller\ControllerBase; |
10 | use Drupal\Core\Render\RendererInterface; |
11 | use Drupal\Core\TempStore\SharedTempStoreFactory; |
12 | use Drupal\display_builder\Event\DisplayBuilderEvent; |
13 | use Drupal\display_builder\Event\DisplayBuilderEvents; |
14 | use Drupal\display_builder\InstanceInterface; |
15 | use Drupal\display_builder\ProfileInterface; |
16 | use Symfony\Component\DependencyInjection\Attribute\Autowire; |
17 | use Symfony\Component\HttpFoundation\Session\SessionInterface; |
18 | use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; |
19 | |
20 | /** |
21 | * Returns responses for Display builder routes. |
22 | */ |
23 | abstract class ApiControllerBase extends ControllerBase { |
24 | |
25 | public const string SSE_COLLECTION = 'display_builder_sse'; |
26 | |
27 | /** |
28 | * The list of DB events which triggers SSE refresh. |
29 | */ |
30 | public const array SSE_EVENTS = [ |
31 | DisplayBuilderEvents::ON_ATTACH_TO_ROOT, |
32 | DisplayBuilderEvents::ON_ATTACH_TO_SLOT, |
33 | DisplayBuilderEvents::ON_DELETE, |
34 | DisplayBuilderEvents::ON_HISTORY_CHANGE, |
35 | DisplayBuilderEvents::ON_MOVE, |
36 | DisplayBuilderEvents::ON_PRESET_SAVE, |
37 | DisplayBuilderEvents::ON_SAVE, |
38 | DisplayBuilderEvents::ON_UPDATE, |
39 | ]; |
40 | |
41 | /** |
42 | * The Display Builder instance triggering the action. |
43 | */ |
44 | protected InstanceInterface $builder; |
45 | |
46 | /** |
47 | * Plugin ID of the island triggering the HTMX event. |
48 | * |
49 | * If not NULL, the island will be skipped from the event dispatch. Useful to |
50 | * avoid swapping the content of an island which is already in the expected |
51 | * state. For examples, if we move an instance in Builder, Layers or Tree |
52 | * panels, if we change the settings in InstanceForm. |
53 | * |
54 | * @see \Drupal\display_builder\Event\DisplayBuilderEventsSubscriber::dispatchToIslands() |
55 | * @see \Drupal\display_builder\HtmxEvents |
56 | */ |
57 | protected ?string $islandId = NULL; |
58 | |
59 | /** |
60 | * The lazy loaded display builder. |
61 | */ |
62 | protected ?ProfileInterface $displayBuilder = NULL; |
63 | |
64 | public function __construct( |
65 | protected EventDispatcherInterface $eventDispatcher, |
66 | protected MemoryCacheInterface $memoryCache, |
67 | protected RendererInterface $renderer, |
68 | protected TimeInterface $time, |
69 | #[Autowire(service: 'tempstore.shared')] protected SharedTempStoreFactory $sharedTempStoreFactory, |
70 | protected SessionInterface $session, |
71 | ) {} |
72 | |
73 | /** |
74 | * Creates a display builder event with enabled islands only. |
75 | * |
76 | * Use a cache to avoid loading all the builder configuration. |
77 | * |
78 | * @param string $event_id |
79 | * The event ID. |
80 | * @param array|null $data |
81 | * The data. |
82 | * @param string|null $node_id |
83 | * Optional Instance entity ID. |
84 | * @param string|null $parent_id |
85 | * Optional parent ID. |
86 | * |
87 | * @return \Drupal\display_builder\Event\DisplayBuilderEvent |
88 | * The event. |
89 | */ |
90 | protected function createEventWithEnabledIsland($event_id, $data, $node_id, $parent_id): DisplayBuilderEvent { |
91 | $builder_id = (string) $this->builder->id(); |
92 | $key = \sprintf('db_%s_island_enable', $builder_id); |
93 | $island_configuration_key = \sprintf('db_%s_island_configuration', $builder_id); |
94 | $island_enabled = $this->memoryCache->get($key); |
95 | $island_configuration = $this->memoryCache->get($island_configuration_key); |
96 | |
97 | if ($island_configuration === FALSE) { |
98 | $island_configuration = $this->builder->getProfile()->getIslandConfigurations(); |
99 | $this->memoryCache->set($island_configuration_key, $island_configuration); |
100 | } |
101 | else { |
102 | $island_configuration = $island_configuration->data; |
103 | } |
104 | |
105 | if ($island_enabled === FALSE) { |
106 | $island_enabled = $this->builder->getProfile()->getEnabledIslands(); |
107 | $this->memoryCache->set($key, $island_enabled); |
108 | } |
109 | else { |
110 | $island_enabled = $island_enabled->data; |
111 | } |
112 | |
113 | $event = new DisplayBuilderEvent($builder_id, $island_enabled, $island_configuration, $data, $node_id, $parent_id, $this->islandId); |
114 | $this->eventDispatcher->dispatch($event, $event_id); |
115 | |
116 | return $event; |
117 | } |
118 | |
119 | /** |
120 | * Save data for SSE. |
121 | * |
122 | * @param string $event_id |
123 | * The event ID. |
124 | */ |
125 | protected function saveSseData(string $event_id): void { |
126 | if (!\in_array($event_id, $this::SSE_EVENTS, TRUE)) { |
127 | return; |
128 | } |
129 | |
130 | $state = [ |
131 | 'sessionId' => $this->session->getId(), |
132 | 'timestamp' => $this->time->getRequestTime(), |
133 | // instanceId here is the ID of a display_builder_instance entity. |
134 | 'instanceId' => (string) $this->builder->id(), |
135 | ]; |
136 | $collection = $this->sharedTempStoreFactory->get($this::SSE_COLLECTION); |
137 | $collection->set(\sprintf('%s_latest', (string) $this->builder->id()), $state); |
138 | } |
139 | |
140 | } |