Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 76 |
|
0.00% |
0 / 13 |
CRAP | |
0.00% |
0 / 1 |
LogsPanel | |
0.00% |
0 / 70 |
|
0.00% |
0 / 13 |
756 | |
0.00% |
0 / 1 |
create | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
keyboardShortcuts | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
build | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
20 | |||
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 | |||
onSave | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildRows | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
buildRow | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
56 | |||
printSaveAlert | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Drupal\display_builder\Plugin\display_builder\Island; |
6 | |
7 | use Drupal\Core\Datetime\DateFormatterInterface; |
8 | use Drupal\Core\StringTranslation\TranslatableMarkup; |
9 | use Drupal\display_builder\Attribute\Island; |
10 | use Drupal\display_builder\DisplayBuilderHelpers; |
11 | use Drupal\display_builder\HistoryStep; |
12 | use Drupal\display_builder\InstanceInterface; |
13 | use Drupal\display_builder\IslandPluginBase; |
14 | use Drupal\display_builder\IslandType; |
15 | use Symfony\Component\DependencyInjection\ContainerInterface; |
16 | |
17 | /** |
18 | * Logs island plugin implementation. |
19 | */ |
20 | #[Island( |
21 | id: 'logs', |
22 | label: new TranslatableMarkup('Logs'), |
23 | description: new TranslatableMarkup('Logs based on changes history.'), |
24 | type: IslandType::View, |
25 | icon: 'list-columns-reverse', |
26 | )] |
27 | class LogsPanel extends IslandPluginBase { |
28 | |
29 | /** |
30 | * The date formatter. |
31 | */ |
32 | protected DateFormatterInterface $dateFormatter; |
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->dateFormatter = $container->get('date.formatter'); |
40 | |
41 | return $instance; |
42 | } |
43 | |
44 | /** |
45 | * {@inheritdoc} |
46 | */ |
47 | public static function keyboardShortcuts(): array { |
48 | return [ |
49 | 'o' => t('Show the logs'), |
50 | ]; |
51 | } |
52 | |
53 | /** |
54 | * {@inheritdoc} |
55 | */ |
56 | public function build(InstanceInterface $builder, array $data = [], array $options = []): array { |
57 | $load = $builder->toArray(); |
58 | |
59 | if (!$load) { |
60 | return []; |
61 | } |
62 | |
63 | /** @var \Drupal\display_builder\HistoryStep $present */ |
64 | $present = $load['present']; |
65 | |
66 | if (!$present) { |
67 | return []; |
68 | } |
69 | |
70 | $save = $load['save'] ?? NULL; |
71 | $rows = $this->buildRows($load['past'], $present, $load['future'], $save); |
72 | $table = [ |
73 | '#theme' => 'table', |
74 | '#header' => [ |
75 | ['data' => $this->t('Step')], |
76 | ['data' => $this->t('Saved')], |
77 | ['data' => $this->t('Time')], |
78 | ['data' => $this->t('User')], |
79 | ['data' => $this->t('Message')], |
80 | ], |
81 | '#rows' => $rows, |
82 | ]; |
83 | |
84 | return [ |
85 | $table, |
86 | $save ? $this->printSaveAlert(\array_merge($load['past'], [$present], $load['future']), $save) : [], |
87 | ]; |
88 | } |
89 | |
90 | /** |
91 | * {@inheritdoc} |
92 | */ |
93 | public function onAttachToRoot(string $builder_id, string $instance_id): array { |
94 | return $this->reloadWithGlobalData($builder_id); |
95 | } |
96 | |
97 | /** |
98 | * {@inheritdoc} |
99 | */ |
100 | public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array { |
101 | return $this->reloadWithGlobalData($builder_id); |
102 | } |
103 | |
104 | /** |
105 | * {@inheritdoc} |
106 | */ |
107 | public function onMove(string $builder_id, string $instance_id): array { |
108 | return $this->reloadWithGlobalData($builder_id); |
109 | } |
110 | |
111 | /** |
112 | * {@inheritdoc} |
113 | */ |
114 | public function onHistoryChange(string $builder_id): array { |
115 | return $this->reloadWithGlobalData($builder_id); |
116 | } |
117 | |
118 | /** |
119 | * {@inheritdoc} |
120 | */ |
121 | public function onUpdate(string $builder_id, string $instance_id): array { |
122 | return $this->reloadWithGlobalData($builder_id); |
123 | } |
124 | |
125 | /** |
126 | * {@inheritdoc} |
127 | */ |
128 | public function onDelete(string $builder_id, string $parent_id): array { |
129 | return $this->reloadWithGlobalData($builder_id); |
130 | } |
131 | |
132 | /** |
133 | * {@inheritdoc} |
134 | */ |
135 | public function onSave(string $builder_id): array { |
136 | return $this->reloadWithGlobalData($builder_id); |
137 | } |
138 | |
139 | /** |
140 | * Build rows for the logs table. |
141 | * |
142 | * @param \Drupal\display_builder\HistoryStep[] $past |
143 | * Steps with time and log message. |
144 | * @param \Drupal\display_builder\HistoryStep $present |
145 | * A step with time and log message. |
146 | * @param \Drupal\display_builder\HistoryStep[] $future |
147 | * Steps with time and log message. |
148 | * @param \Drupal\display_builder\HistoryStep $save |
149 | * Saved state. |
150 | * |
151 | * @return array |
152 | * A renderable array representing a table row. |
153 | */ |
154 | protected function buildRows(array $past, ?HistoryStep $present, array $future, ?HistoryStep $save): array { |
155 | $rows = []; |
156 | |
157 | foreach (\array_filter($past) as $index => $step) { |
158 | $rows[] = $this->buildRow(-\count($past) + $index, $step, $save); |
159 | } |
160 | |
161 | // Present data. |
162 | $rows[] = $this->buildRow(0, $present, $save); |
163 | |
164 | foreach (\array_filter($future) as $index => $step) { |
165 | $rows[] = $this->buildRow($index + 1, $step, $save); |
166 | } |
167 | |
168 | return $rows; |
169 | } |
170 | |
171 | /** |
172 | * Build a single row for the logs table. |
173 | * |
174 | * @param int $index |
175 | * The row index. |
176 | * @param \Drupal\display_builder\HistoryStep $step |
177 | * The step data containing time and log message. |
178 | * @param \Drupal\display_builder\HistoryStep $save |
179 | * Saved state. |
180 | * |
181 | * @return array |
182 | * A renderable array representing a table row. |
183 | */ |
184 | private function buildRow(int $index, HistoryStep $step, ?HistoryStep $save): array { |
185 | $user = !empty($step->user) ? $this->entityTypeManager->getStorage('user')->load($step->user) : NULL; |
186 | |
187 | return [ |
188 | 'hash' => $step->hash, |
189 | 'data' => [ |
190 | (string) $index, |
191 | ($save && $step->hash === $save->hash) ? '✅' : '', |
192 | $step->time ? DisplayBuilderHelpers::formatTime($this->dateFormatter, $step->time) : NULL, |
193 | $user ? $user->getDisplayName() : NULL, |
194 | $step->log ?? '', |
195 | ], |
196 | 'style' => ($index === 0) ? 'font-weight: bold;' : '', |
197 | ]; |
198 | } |
199 | |
200 | /** |
201 | * Print an alert if the saved step is not in the history. |
202 | * |
203 | * @param \Drupal\display_builder\HistoryStep[] $steps |
204 | * All steps: past, present and future. |
205 | * @param \Drupal\display_builder\HistoryStep $save |
206 | * Saved state. |
207 | * |
208 | * @return array |
209 | * A renderable array. |
210 | */ |
211 | private function printSaveAlert(array $steps, HistoryStep $save): array { |
212 | $save_found = FALSE; |
213 | |
214 | foreach ($steps as $step) { |
215 | if ($step->hash === $save->hash) { |
216 | $save_found = TRUE; |
217 | |
218 | break; |
219 | } |
220 | } |
221 | |
222 | if ($save_found) { |
223 | return []; |
224 | } |
225 | $params = [ |
226 | '%time' => DisplayBuilderHelpers::formatTime($this->dateFormatter, $save->time), |
227 | ]; |
228 | |
229 | return [ |
230 | '#type' => 'html_tag', |
231 | '#tag' => 'p', |
232 | '#value' => $this->t('Saved at %time but not visible in logs', $params), |
233 | ]; |
234 | } |
235 | |
236 | } |