logo

Дополнительные типы блоков (EBT) — новый опыт конструктора страниц❗

Дополнительные типы блоков (EBT) — стилизованные, настраиваемые типы блоков: слайдшоу, вкладки, карточки, аккордеоны и многие другие. Встроенные настройки для фона, DOM Box, плагины Javascript.

Демо EBT модули Скачать EBT модули

❗Дополнительные типы параграфов (EPT) — новый опыт работы с параграфами

Дополнительные типы параграфов (EPT) — набор модулей, основанный на аналогичных параграфах.

Демо EPT модули Скачать EPT модули

Scroll
13/06/2025, by Ivan

Создание нового класса формы настроек EPT

Я слышал от многих программистов опасения по поводу большого количества настроек для модулей EPT: DOM Box, фон, границы, классы и т.д. Эти разработчики подразумевали, что редакторы контента будут запутываться или иначе подталкиваться к созданию радикально разных абзацев, отступов, фонов. Некоторые проекты требуют гибкости и большего числа настроек для редакторов контента, а в других проектах используются достаточно строгие гайдлайны с компонентами. В таких случаях нужно изменить виджет поля настроек EPT.

Также, если вы создаёте новый модуль EPT и подключаете javascript-плагин с опциями, вам потребуется использовать собственный виджет настроек EPT с полями для этих опций.

В ядре модуля EPT есть класс EptSettingsDefaultWidget для виджета поля настроек EPT. Он включает DOM Box, фон и все остальные настройки. Давайте создадим новый класс EptSettingsSimpleWidget (я размещу его в ядре модуля EPT). В нём будут только три настройки: ширина и отступ (spacing, для отступа под абзацем).

Создайте новый файл:
/src/Plugin/Field/FieldWidget/EptSettingsSimpleWidget.php

<?php

namespace Drupal\ept_core\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Utility\Color;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ept_core\Plugin\Field\FieldWidget\EptSettingsDefaultWidget;

/**
 * Реализация плагина виджета 'ept_settings_simple'.
 *
 * @FieldWidget(
 *   id = "ept_settings_simple",
 *   label = @Translation("EPT простые настройки абзаца"),
 *   field_types = {
 *     "ept_settings"
 *   }
 * )
 */
class EptSettingsSimpleWidget extends EptSettingsDefaultWidget  {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    foreach ($values as &$value) {
      $value += ['ept_settings' => []];
    }
    return $values;
  }

}

Мы расширяем базовый класс настроек EptSettingsDefaultWidget. В аннотации @FieldWidget указываем id = "ept_settings_simple" и label = @Translation("EPT Simple settings").

/**
 * Реализация плагина виджета 'ept_settings_simple'.
 *
 * @FieldWidget(
 *   id = "ept_settings_simple",
 *   label = @Translation("EPT простые настройки абзаца"),
 *   field_types = {
 *     "ept_settings"
 *   }
 * )
 */

Также реализованы два метода formElement() и massageFormValues(). Метод massageFormValues() можно оставить как есть. Drupal автоматически сериализует все настройки в одно поле field_ept_settings, поэтому неважно, сколько настроек у вас есть — они будут храниться как сериализованный массив, и вам нужно лишь указать поля настроек через Form API:

https://www.drupal.org/docs/drupal-apis/form-api

В методе formElement() мы определим поля настроек. Спрячем настройки DOM Box и границ:

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    unset($element['ept_settings']['design_options']['box1']);
    unset($element['ept_settings']['design_options']['other_settings']['border_color']);
    unset($element['ept_settings']['design_options']['other_settings']['border_style']);
    unset($element['ept_settings']['design_options']['other_settings']['border_radius']);

    return $element;
  }

Если вы примените новый виджет для одного из ваших типов параграфов EPT:

Простой виджет EPT
Simple EPT widget

Вы увидите более компактную форму настроек:

Форма настроек EPT
EPT settings form

Теперь уберём и настройки фона. Если вам нужны только настройки фона, а остальные не нужны — расширьте EptSettingsDefaultWidget и создайте свой виджет. Вот пример, как сделать настройки EPT максимально простыми.

...
    unset($element['ept_settings']['design_options']['other_settings']['background_color']);
    unset($element['ept_settings']['design_options']['other_settings']['background_media']);
    unset($element['ept_settings']['design_options']['other_settings']['background_image_style']);
...

В нашей форме теперь осталось только два поля:

Только два поля
Only two fields

Осталось добавить поле Spacing для задания отступа снизу. Для этого мы используем дополнительные CSS-классы для управления отступами:

spacing-none,
spacing-sm,
spacing-md,
spacing-lg,
spacing-xl,
spacing-xxl

Если потребуется больший список значений отступа — расширяйте EptSettingsSimpleWidget и создавайте собственный класс виджета, как мы делали с EptSettingsDefaultWidget.

$element['ept_settings']['design_options']['other_settings']['spacing'] = [
      '#type' => 'select',
      '#title' => $this->t('Background Image Style'),
      '#options' => [
        'spacing-none' => $this->t('Нет'),
        'spacing-sm' => $this->t('Маленький'),
        'spacing-md' => $this->t('Средний'),
        'spacing-lg' => $this->t('Большой'),
        'spacing-xl' => $this->t('Очень большой'),
        'spacing-xxl' => $this->t('Двойной очень большой'),
      ],
      '#default_value' => $items[$delta]->ept_settings['design_options']['other_settings']['spacing'] ?? 'spacing-none',
    ];

Теперь вижу три способа добавить стили для нашего блока:

1. Переопределить шаблон блока и добавить класс отступа прямо в классы блока.

2. Генерировать стили на лету и добавлять их как inline-стили для каждого параграфа.

3. Добавлять класс через javascript, генерируя отдельный скрипт для каждого параграфа EPT.

4. Переопределить список классов в функции template_preprocess_block().

Все эти подходы рабочие, но проще всего использовать функцию template_process_paragraph(). К тому же в файле ebt_core.module уже есть функция ept_core_preprocess_block(). Используем её:

...
  if (!empty($ept_settings[0]['ept_settings']['design_options']['other_settings']['spacing'])) {
    $variables['attributes']['class'][] = $ept_settings[0]['ept_settings']['design_options']['other_settings']['spacing'];
  }
...
Средний отступ
Medium spacing
Spacing class
Spacing class

Теперь мы передаём ключи поля Spacing как имена классов, и с помощью CSS задаём нужные значения отступов для этих классов:

/ebt_core/scss/ept_core.scss

.spacing-sm {
  margin-bottom: 10px;
}

.spacing-md {
  margin-bottom: 20px;
}

.spacing-lg {
  margin-bottom: 30px;
}

.spacing-xl {
  margin-bottom: 40px;
}

.spacing-xxl {
  margin-bottom: 50px;
}

Вы можете переопределять эти значения в своём CSS, например так, используя любой класс из контента или body:

body .spacing-sm {
  margin-bottom: 15px;
}

Также можно переопределить список вариантов отступа в своём классе виджета настроек EBT.

Вот и всё, теперь вы можете выбирать между DOM Box и простым select для задания отступов для ваших EBT-блоков.

Если есть вопросы по модулям EBT — задавайте их на Drupal.org или через контактную форму:

Связаться

Создать issue на Drupal.org

Связаться в LinkedIn