Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / Block / BlockBase.php
1 <?php
2
3 namespace Drupal\Core\Block;
4
5 use Drupal\Core\Access\AccessResult;
6 use Drupal\Core\Form\FormStateInterface;
7 use Drupal\Core\Messenger\MessengerTrait;
8 use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
9 use Drupal\Core\Plugin\ContextAwarePluginBase;
10 use Drupal\Component\Utility\NestedArray;
11 use Drupal\Core\Language\LanguageInterface;
12 use Drupal\Core\Plugin\PluginWithFormsInterface;
13 use Drupal\Core\Plugin\PluginWithFormsTrait;
14 use Drupal\Core\Render\PreviewFallbackInterface;
15 use Drupal\Core\Session\AccountInterface;
16 use Drupal\Component\Transliteration\TransliterationInterface;
17
18 /**
19  * Defines a base block implementation that most blocks plugins will extend.
20  *
21  * This abstract class provides the generic block configuration form, default
22  * block settings, and handling for general user-defined block visibility
23  * settings.
24  *
25  * @ingroup block_api
26  */
27 abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface {
28
29   use ContextAwarePluginAssignmentTrait;
30   use MessengerTrait;
31   use PluginWithFormsTrait;
32
33   /**
34    * The transliteration service.
35    *
36    * @var \Drupal\Component\Transliteration\TransliterationInterface
37    */
38   protected $transliteration;
39
40   /**
41    * {@inheritdoc}
42    */
43   public function label() {
44     if (!empty($this->configuration['label'])) {
45       return $this->configuration['label'];
46     }
47
48     $definition = $this->getPluginDefinition();
49     // Cast the admin label to a string since it is an object.
50     // @see \Drupal\Core\StringTranslation\TranslatableMarkup
51     return (string) $definition['admin_label'];
52   }
53
54   /**
55    * {@inheritdoc}
56    */
57   public function __construct(array $configuration, $plugin_id, $plugin_definition) {
58     parent::__construct($configuration, $plugin_id, $plugin_definition);
59     $this->setConfiguration($configuration);
60   }
61
62   /**
63    * {@inheritdoc}
64    */
65   public function getConfiguration() {
66     return $this->configuration;
67   }
68
69   /**
70    * {@inheritdoc}
71    */
72   public function setConfiguration(array $configuration) {
73     $this->configuration = NestedArray::mergeDeep(
74       $this->baseConfigurationDefaults(),
75       $this->defaultConfiguration(),
76       $configuration
77     );
78   }
79
80   /**
81    * Returns generic default configuration for block plugins.
82    *
83    * @return array
84    *   An associative array with the default configuration.
85    */
86   protected function baseConfigurationDefaults() {
87     return [
88       'id' => $this->getPluginId(),
89       'label' => '',
90       'provider' => $this->pluginDefinition['provider'],
91       'label_display' => static::BLOCK_LABEL_VISIBLE,
92     ];
93   }
94
95   /**
96    * {@inheritdoc}
97    */
98   public function defaultConfiguration() {
99     return [];
100   }
101
102   /**
103    * {@inheritdoc}
104    */
105   public function setConfigurationValue($key, $value) {
106     $this->configuration[$key] = $value;
107   }
108
109   /**
110    * {@inheritdoc}
111    */
112   public function calculateDependencies() {
113     return [];
114   }
115
116   /**
117    * {@inheritdoc}
118    */
119   public function access(AccountInterface $account, $return_as_object = FALSE) {
120     $access = $this->blockAccess($account);
121     return $return_as_object ? $access : $access->isAllowed();
122   }
123
124   /**
125    * Indicates whether the block should be shown.
126    *
127    * Blocks with specific access checking should override this method rather
128    * than access(), in order to avoid repeating the handling of the
129    * $return_as_object argument.
130    *
131    * @param \Drupal\Core\Session\AccountInterface $account
132    *   The user session for which to check access.
133    *
134    * @return \Drupal\Core\Access\AccessResult
135    *   The access result.
136    *
137    * @see self::access()
138    */
139   protected function blockAccess(AccountInterface $account) {
140     // By default, the block is visible.
141     return AccessResult::allowed();
142   }
143
144   /**
145    * {@inheritdoc}
146    *
147    * Creates a generic configuration form for all block types. Individual
148    * block plugins can add elements to this form by overriding
149    * BlockBase::blockForm(). Most block plugins should not override this
150    * method unless they need to alter the generic form elements.
151    *
152    * @see \Drupal\Core\Block\BlockBase::blockForm()
153    */
154   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
155     $definition = $this->getPluginDefinition();
156     $form['provider'] = [
157       '#type' => 'value',
158       '#value' => $definition['provider'],
159     ];
160
161     $form['admin_label'] = [
162       '#type' => 'item',
163       '#title' => $this->t('Block description'),
164       '#plain_text' => $definition['admin_label'],
165     ];
166     $form['label'] = [
167       '#type' => 'textfield',
168       '#title' => $this->t('Title'),
169       '#maxlength' => 255,
170       '#default_value' => $this->label(),
171       '#required' => TRUE,
172     ];
173     $form['label_display'] = [
174       '#type' => 'checkbox',
175       '#title' => $this->t('Display title'),
176       '#default_value' => ($this->configuration['label_display'] === static::BLOCK_LABEL_VISIBLE),
177       '#return_value' => static::BLOCK_LABEL_VISIBLE,
178     ];
179
180     // Add context mapping UI form elements.
181     $contexts = $form_state->getTemporaryValue('gathered_contexts') ?: [];
182     $form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts);
183     // Add plugin-specific settings for this block type.
184     $form += $this->blockForm($form, $form_state);
185     return $form;
186   }
187
188   /**
189    * {@inheritdoc}
190    */
191   public function blockForm($form, FormStateInterface $form_state) {
192     return [];
193   }
194
195   /**
196    * {@inheritdoc}
197    *
198    * Most block plugins should not override this method. To add validation
199    * for a specific block type, override BlockBase::blockValidate().
200    *
201    * @see \Drupal\Core\Block\BlockBase::blockValidate()
202    */
203   public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
204     // Remove the admin_label form item element value so it will not persist.
205     $form_state->unsetValue('admin_label');
206
207     $this->blockValidate($form, $form_state);
208   }
209
210   /**
211    * {@inheritdoc}
212    */
213   public function blockValidate($form, FormStateInterface $form_state) {}
214
215   /**
216    * {@inheritdoc}
217    *
218    * Most block plugins should not override this method. To add submission
219    * handling for a specific block type, override BlockBase::blockSubmit().
220    *
221    * @see \Drupal\Core\Block\BlockBase::blockSubmit()
222    */
223   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
224     // Process the block's submission handling if no errors occurred only.
225     if (!$form_state->getErrors()) {
226       $this->configuration['label'] = $form_state->getValue('label');
227       $this->configuration['label_display'] = $form_state->getValue('label_display');
228       $this->configuration['provider'] = $form_state->getValue('provider');
229       $this->blockSubmit($form, $form_state);
230     }
231   }
232
233   /**
234    * {@inheritdoc}
235    */
236   public function blockSubmit($form, FormStateInterface $form_state) {}
237
238   /**
239    * {@inheritdoc}
240    */
241   public function getMachineNameSuggestion() {
242     $definition = $this->getPluginDefinition();
243     $admin_label = $definition['admin_label'];
244
245     // @todo This is basically the same as what is done in
246     //   \Drupal\system\MachineNameController::transliterate(), so it might make
247     //   sense to provide a common service for the two.
248     $transliterated = $this->transliteration()->transliterate($admin_label, LanguageInterface::LANGCODE_DEFAULT, '_');
249     $transliterated = mb_strtolower($transliterated);
250
251     $transliterated = preg_replace('@[^a-z0-9_.]+@', '', $transliterated);
252
253     return $transliterated;
254   }
255
256   /**
257    * {@inheritdoc}
258    */
259   public function getPreviewFallbackString() {
260     return $this->t('Placeholder for the "@block" block', ['@block' => $this->label()]);
261   }
262
263   /**
264    * Wraps the transliteration service.
265    *
266    * @return \Drupal\Component\Transliteration\TransliterationInterface
267    */
268   protected function transliteration() {
269     if (!$this->transliteration) {
270       $this->transliteration = \Drupal::transliteration();
271     }
272     return $this->transliteration;
273   }
274
275   /**
276    * Sets the transliteration service.
277    *
278    * @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
279    *   The transliteration service.
280    */
281   public function setTransliteration(TransliterationInterface $transliteration) {
282     $this->transliteration = $transliteration;
283   }
284
285 }