3 namespace Drupal\Core\Block;
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\Session\AccountInterface;
15 use Drupal\Component\Transliteration\TransliterationInterface;
18 * Defines a base block implementation that most blocks plugins will extend.
20 * This abstract class provides the generic block configuration form, default
21 * block settings, and handling for general user-defined block visibility
26 abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface {
28 use ContextAwarePluginAssignmentTrait;
30 use PluginWithFormsTrait;
33 * The transliteration service.
35 * @var \Drupal\Component\Transliteration\TransliterationInterface
37 protected $transliteration;
42 public function label() {
43 if (!empty($this->configuration['label'])) {
44 return $this->configuration['label'];
47 $definition = $this->getPluginDefinition();
48 // Cast the admin label to a string since it is an object.
49 // @see \Drupal\Core\StringTranslation\TranslatableMarkup
50 return (string) $definition['admin_label'];
56 public function __construct(array $configuration, $plugin_id, $plugin_definition) {
57 parent::__construct($configuration, $plugin_id, $plugin_definition);
58 $this->setConfiguration($configuration);
64 public function getConfiguration() {
65 return $this->configuration;
71 public function setConfiguration(array $configuration) {
72 $this->configuration = NestedArray::mergeDeep(
73 $this->baseConfigurationDefaults(),
74 $this->defaultConfiguration(),
80 * Returns generic default configuration for block plugins.
83 * An associative array with the default configuration.
85 protected function baseConfigurationDefaults() {
87 'id' => $this->getPluginId(),
89 'provider' => $this->pluginDefinition['provider'],
90 'label_display' => static::BLOCK_LABEL_VISIBLE,
97 public function defaultConfiguration() {
104 public function setConfigurationValue($key, $value) {
105 $this->configuration[$key] = $value;
111 public function calculateDependencies() {
118 public function access(AccountInterface $account, $return_as_object = FALSE) {
119 $access = $this->blockAccess($account);
120 return $return_as_object ? $access : $access->isAllowed();
124 * Indicates whether the block should be shown.
126 * Blocks with specific access checking should override this method rather
127 * than access(), in order to avoid repeating the handling of the
128 * $return_as_object argument.
130 * @param \Drupal\Core\Session\AccountInterface $account
131 * The user session for which to check access.
133 * @return \Drupal\Core\Access\AccessResult
136 * @see self::access()
138 protected function blockAccess(AccountInterface $account) {
139 // By default, the block is visible.
140 return AccessResult::allowed();
146 * Creates a generic configuration form for all block types. Individual
147 * block plugins can add elements to this form by overriding
148 * BlockBase::blockForm(). Most block plugins should not override this
149 * method unless they need to alter the generic form elements.
151 * @see \Drupal\Core\Block\BlockBase::blockForm()
153 public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
154 $definition = $this->getPluginDefinition();
155 $form['provider'] = [
157 '#value' => $definition['provider'],
160 $form['admin_label'] = [
162 '#title' => $this->t('Block description'),
163 '#plain_text' => $definition['admin_label'],
166 '#type' => 'textfield',
167 '#title' => $this->t('Title'),
169 '#default_value' => $this->label(),
172 $form['label_display'] = [
173 '#type' => 'checkbox',
174 '#title' => $this->t('Display title'),
175 '#default_value' => ($this->configuration['label_display'] === static::BLOCK_LABEL_VISIBLE),
176 '#return_value' => static::BLOCK_LABEL_VISIBLE,
179 // Add context mapping UI form elements.
180 $contexts = $form_state->getTemporaryValue('gathered_contexts') ?: [];
181 $form['context_mapping'] = $this->addContextAssignmentElement($this, $contexts);
182 // Add plugin-specific settings for this block type.
183 $form += $this->blockForm($form, $form_state);
190 public function blockForm($form, FormStateInterface $form_state) {
197 * Most block plugins should not override this method. To add validation
198 * for a specific block type, override BlockBase::blockValidate().
200 * @see \Drupal\Core\Block\BlockBase::blockValidate()
202 public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
203 // Remove the admin_label form item element value so it will not persist.
204 $form_state->unsetValue('admin_label');
206 $this->blockValidate($form, $form_state);
212 public function blockValidate($form, FormStateInterface $form_state) {}
217 * Most block plugins should not override this method. To add submission
218 * handling for a specific block type, override BlockBase::blockSubmit().
220 * @see \Drupal\Core\Block\BlockBase::blockSubmit()
222 public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
223 // Process the block's submission handling if no errors occurred only.
224 if (!$form_state->getErrors()) {
225 $this->configuration['label'] = $form_state->getValue('label');
226 $this->configuration['label_display'] = $form_state->getValue('label_display');
227 $this->configuration['provider'] = $form_state->getValue('provider');
228 $this->blockSubmit($form, $form_state);
235 public function blockSubmit($form, FormStateInterface $form_state) {}
240 public function getMachineNameSuggestion() {
241 $definition = $this->getPluginDefinition();
242 $admin_label = $definition['admin_label'];
244 // @todo This is basically the same as what is done in
245 // \Drupal\system\MachineNameController::transliterate(), so it might make
246 // sense to provide a common service for the two.
247 $transliterated = $this->transliteration()->transliterate($admin_label, LanguageInterface::LANGCODE_DEFAULT, '_');
248 $transliterated = mb_strtolower($transliterated);
250 $transliterated = preg_replace('@[^a-z0-9_.]+@', '', $transliterated);
252 return $transliterated;
256 * Wraps the transliteration service.
258 * @return \Drupal\Component\Transliteration\TransliterationInterface
260 protected function transliteration() {
261 if (!$this->transliteration) {
262 $this->transliteration = \Drupal::transliteration();
264 return $this->transliteration;
268 * Sets the transliteration service.
270 * @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
271 * The transliteration service.
273 public function setTransliteration(TransliterationInterface $transliteration) {
274 $this->transliteration = $transliteration;