Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 63
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
HistoryButtons
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 11
420
0.00% covered (danger)
0.00%
0 / 1
 defaultConfiguration
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 buildConfigurationForm
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 configurationSummary
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 build
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
72
 onAttachToRoot
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
2
 onMove
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
2
 onUpdate
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
2
 rebuild
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Plugin\display_builder\Island;
6
7use Drupal\Core\Form\FormStateInterface;
8use Drupal\Core\StringTranslation\TranslatableMarkup;
9use Drupal\display_builder\Attribute\Island;
10use Drupal\display_builder\InstanceInterface;
11use Drupal\display_builder\IslandConfigurationFormInterface;
12use Drupal\display_builder\IslandConfigurationFormTrait;
13use Drupal\display_builder\IslandPluginBase;
14use Drupal\display_builder\IslandType;
15
16/**
17 * History buttons island plugin implementation.
18 */
19#[Island(
20  id: 'history',
21  enabled_by_default: TRUE,
22  label: new TranslatableMarkup('History'),
23  description: new TranslatableMarkup('Undo and Redo buttons.'),
24  type: IslandType::Button,
25)]
26class HistoryButtons extends IslandPluginBase implements IslandConfigurationFormInterface {
27
28  use IslandConfigurationFormTrait;
29
30  /**
31   * {@inheritdoc}
32   */
33  public function defaultConfiguration(): array {
34    return ['display_clear_button' => FALSE];
35  }
36
37  /**
38   * {@inheritdoc}
39   */
40  public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
41    $configuration = $this->getConfiguration();
42    $form['display_clear_button'] = [
43      '#title' => $this->t('Enable the "Clear" button'),
44      '#description' => $this->t('A button to clear the logs history (past and future).'),
45      '#type' => 'checkbox',
46      '#default_value' => $configuration['display_clear_button'],
47    ];
48
49    return $form;
50  }
51
52  /**
53   * {@inheritdoc}
54   */
55  public function configurationSummary(): array {
56    $configuration = $this->getConfiguration();
57
58    if ($configuration['display_clear_button']) {
59      return [
60        $this->t('With clear button.'),
61      ];
62    }
63
64    return [
65      $this->t('Without clear button.'),
66    ];
67  }
68
69  /**
70   * {@inheritdoc}
71   */
72  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
73    $builder_id = (string) $builder->id();
74    $future = $builder->getCountFuture();
75    $past = $builder->getCountPast();
76
77    $undo = $this->buildButton($past ? (string) $past : '', 'undo', 'arrow-counterclockwise', $this->t('Undo (shortcut: u)'), ['u' => $this->t('Undo last change')]);
78
79    if (empty($past)) {
80      $undo['#attributes']['disabled'] = 'disabled';
81    }
82    $redo = $this->buildButton($future ? (string) $future : '', 'redo', 'arrow-clockwise', $this->t('Redo (shortcut: r)'), ['r' => $this->t('Redo last undone change')]);
83
84    if (empty($future)) {
85      $redo['#attributes']['disabled'] = 'disabled';
86    }
87
88    $clear = $this->buildButton('', 'clear', 'clock-history', $this->t('Clear history (shortcut: C)'), ['C' => $this->t('Clear all changes history')]);
89    $clear['#props']['variant'] = 'warning';
90    $clear['#attributes']['outline'] = TRUE;
91
92    // Just hide the button to keep it in the dom, if not keyboard shortcut will
93    // fail.
94    $configuration = $this->getConfiguration();
95
96    if (!$configuration['display_clear_button'] || (empty($past) && empty($future))) {
97      $clear['#attributes']['class'] = ['hidden'];
98    }
99
100    return [
101      '#type' => 'component',
102      '#component' => 'display_builder:button_group',
103      '#slots' => [
104        'buttons' => [
105          $this->htmxEvents->onUndo($undo, $builder_id),
106          $this->htmxEvents->onRedo($redo, $builder_id),
107          $this->htmxEvents->onClear($clear, $builder_id),
108        ],
109      ],
110    ];
111  }
112
113  /**
114   * {@inheritdoc}
115   */
116  public function onAttachToRoot(string $builder_id, string $instance_id): array {
117    return $this->rebuild($builder_id);
118  }
119
120  /**
121   * {@inheritdoc}
122   */
123  public function onAttachToSlot(string $builder_id, string $instance_id, string $parent_id): array {
124    return $this->rebuild($builder_id);
125  }
126
127  /**
128   * {@inheritdoc}
129   */
130  public function onMove(string $builder_id, string $instance_id): array {
131    return $this->rebuild($builder_id);
132  }
133
134  /**
135   * {@inheritdoc}
136   */
137  public function onHistoryChange(string $builder_id): array {
138    return $this->rebuild($builder_id);
139  }
140
141  /**
142   * {@inheritdoc}
143   */
144  public function onUpdate(string $builder_id, string $instance_id): array {
145    return $this->rebuild($builder_id);
146  }
147
148  /**
149   * {@inheritdoc}
150   */
151  public function onDelete(string $builder_id, string $parent_id): array {
152    return $this->rebuild($builder_id);
153  }
154
155  /**
156   * Rebuilds the island with the given builder ID.
157   *
158   * @param string $builder_id
159   *   The ID of the builder.
160   *
161   * @return array
162   *   The rebuilt island.
163   */
164  private function rebuild(string $builder_id): array {
165    if (!$this->builder) {
166      // @todo pass \Drupal\display_builder\InstanceInterface object in
167      // parameters instead of loading again.
168      /** @var \Drupal\display_builder\InstanceInterface $builder */
169      $builder = $this->entityTypeManager->getStorage('display_builder_instance')->load($builder_id);
170      $this->builder = $builder;
171    }
172
173    return $this->addOutOfBand(
174      $this->build($this->builder),
175      '#' . $this->getHtmlId($builder_id),
176      'innerHTML'
177    );
178  }
179
180}