Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 65 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
StateButtons | |
0.00% |
0 / 59 |
|
0.00% |
0 / 11 |
420 | |
0.00% |
0 / 1 |
create | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
build | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
30 | |||
onSave | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAttachToRoot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAttachToSlot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onMove | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onHistoryChange | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onUpdate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onDelete | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isOverridden | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
rebuild | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Drupal\display_builder\Plugin\display_builder\Island; |
6 | |
7 | use Drupal\Core\Entity\FieldableEntityInterface; |
8 | use Drupal\Core\Extension\ModuleHandlerInterface; |
9 | use Drupal\Core\StringTranslation\TranslatableMarkup; |
10 | use Drupal\display_builder\Attribute\Island; |
11 | use Drupal\display_builder\InstanceInterface; |
12 | use Drupal\display_builder\IslandPluginBase; |
13 | use Drupal\display_builder\IslandType; |
14 | use Drupal\display_builder_entity_view\Field\DisplayBuilderItemList; |
15 | use Symfony\Component\DependencyInjection\ContainerInterface; |
16 | |
17 | /** |
18 | * State buttons island plugin implementation. |
19 | */ |
20 | #[Island( |
21 | id: 'state', |
22 | enabled_by_default: TRUE, |
23 | label: new TranslatableMarkup('State'), |
24 | description: new TranslatableMarkup('Buttons to publish and reset the display.'), |
25 | type: IslandType::Button, |
26 | )] |
27 | class StateButtons extends IslandPluginBase { |
28 | |
29 | /** |
30 | * The module handler. |
31 | */ |
32 | protected ModuleHandlerInterface $moduleHandler; |
33 | |
34 | /** |
35 | * {@inheritdoc} |
36 | */ |
37 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): static { |
38 | $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); |
39 | $instance->moduleHandler = $container->get('module_handler'); |
40 | |
41 | return $instance; |
42 | } |
43 | |
44 | /** |
45 | * {@inheritdoc} |
46 | */ |
47 | public function build(InstanceInterface $builder, array $data = [], array $options = []): array { |
48 | $builder_id = (string) $builder->id(); |
49 | |
50 | if (!$builder->canSaveContextsRequirement()) { |
51 | return []; |
52 | } |
53 | |
54 | $buttonGroup = [ |
55 | '#type' => 'component', |
56 | '#component' => 'display_builder:button_group', |
57 | '#slots' => [ |
58 | 'buttons' => [], |
59 | ], |
60 | ]; |
61 | |
62 | $hasSave = $builder->hasSave(); |
63 | $saveIsCurrent = $hasSave ? $builder->saveIsCurrent() : FALSE; |
64 | |
65 | if (!$saveIsCurrent) { |
66 | $save = $this->buildButton('', 'save', 'floppy', $this->t('Save this display in current state, this will publish your display. (shortcut: S)'), ['S' => $this->t('Save this display (shift+S)')]); |
67 | $save['#props']['variant'] = 'primary'; |
68 | $save['#attributes']['outline'] = TRUE; |
69 | $buttonGroup['#slots']['buttons'][] = $this->htmxEvents->onSave($save, $builder_id); |
70 | |
71 | $restore = $this->buildButton('', 'restore', 'arrow-repeat', $this->t('Restore to last saved version')); |
72 | $restore['#props']['variant'] = 'warning'; |
73 | $restore['#attributes']['outline'] = TRUE; |
74 | $buttonGroup['#slots']['buttons'][] = $this->htmxEvents->onReset($restore, $builder_id); |
75 | } |
76 | |
77 | if ($this->isOverridden($builder_id)) { |
78 | $save = $this->buildButton('', 'revert', 'box-arrow-in-down', $this->t('Revert to default display (not overridden)')); |
79 | $revert['#props']['variant'] = 'danger'; |
80 | $revert['#attributes']['outline'] = TRUE; |
81 | $buttonGroup['#slots']['buttons'][] = $this->htmxEvents->onRevert($revert, $builder_id); |
82 | } |
83 | |
84 | return $buttonGroup; |
85 | } |
86 | |
87 | /** |
88 | * {@inheritdoc} |
89 | */ |
90 | public function onSave(string $builder_id): array { |
91 | return $this->reloadWithGlobalData($builder_id); |
92 | } |
93 | |
94 | /** |
95 | * {@inheritdoc} |
96 | */ |
97 | public function onAttachToRoot(string $builder_id, string $instance_id): array { |
98 | return $this->rebuild($builder_id); |
99 | } |
100 | |
101 | /** |
102 | * {@inheritdoc} |
103 | */ |
104 | public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array { |
105 | return $this->rebuild($builder_id); |
106 | } |
107 | |
108 | /** |
109 | * {@inheritdoc} |
110 | */ |
111 | public function onMove(string $builder_id, string $instance_id): array { |
112 | return $this->rebuild($builder_id); |
113 | } |
114 | |
115 | /** |
116 | * {@inheritdoc} |
117 | */ |
118 | public function onHistoryChange(string $builder_id): array { |
119 | return $this->rebuild($builder_id); |
120 | } |
121 | |
122 | /** |
123 | * {@inheritdoc} |
124 | */ |
125 | public function onUpdate(string $builder_id, string $instance_id): array { |
126 | return $this->rebuild($builder_id); |
127 | } |
128 | |
129 | /** |
130 | * {@inheritdoc} |
131 | */ |
132 | public function onDelete(string $builder_id, string $parent_id): array { |
133 | return $this->rebuild($builder_id); |
134 | } |
135 | |
136 | /** |
137 | * Check if the display builder is on an entity override. |
138 | * |
139 | * @param string $builder_id |
140 | * The ID of the builder. |
141 | * |
142 | * @return bool |
143 | * Returns TRUE if the display builder is on an entity override. |
144 | */ |
145 | protected function isOverridden(string $builder_id): bool { |
146 | if (!$this->moduleHandler->moduleExists('display_builder_entity_view')) { |
147 | return FALSE; |
148 | } |
149 | |
150 | $instanceInfos = DisplayBuilderItemList::checkInstanceId($builder_id); |
151 | |
152 | if (!isset($instanceInfos['entity_type_id'], $instanceInfos['entity_id'], $instanceInfos['field_name'])) { |
153 | return FALSE; |
154 | } |
155 | |
156 | // Do not get the profile entity ID from Instance context because the |
157 | // data stored there is not reliable yet. |
158 | // See: https://www.drupal.org/project/display_builder/issues/3544545 |
159 | $entity = $this->entityTypeManager->getStorage($instanceInfos['entity_type_id']) |
160 | ->load($instanceInfos['entity_id']); |
161 | |
162 | if (!($entity instanceof FieldableEntityInterface)) { |
163 | return FALSE; |
164 | } |
165 | |
166 | $overriddenField = $entity->get($instanceInfos['field_name']); |
167 | |
168 | if ($overriddenField->isEmpty()) { |
169 | return FALSE; |
170 | } |
171 | |
172 | return TRUE; |
173 | } |
174 | |
175 | /** |
176 | * Rebuilds the island with the given builder ID. |
177 | * |
178 | * @param string $builder_id |
179 | * The ID of the builder. |
180 | * |
181 | * @return array |
182 | * The rebuilt island. |
183 | */ |
184 | private function rebuild(string $builder_id): array { |
185 | if (!$this->builder) { |
186 | // @todo pass \Drupal\display_builder\InstanceInterface object in |
187 | // parameters instead of loading again. |
188 | /** @var \Drupal\display_builder\InstanceStorage $storage */ |
189 | $storage = $this->entityTypeManager->getStorage('display_builder_instance'); |
190 | /** @var \Drupal\display_builder\InstanceInterface $builder */ |
191 | $builder = $storage->load($builder_id); |
192 | $this->builder = $builder; |
193 | } |
194 | |
195 | return $this->addOutOfBand( |
196 | $this->build($this->builder), |
197 | '#' . $this->getHtmlId($builder_id), |
198 | 'innerHTML' |
199 | ); |
200 | } |
201 | |
202 | } |