Помните, что из-за процесса разработки Drupal 8 на момент написания этой статьи некоторые части кода могли быть устаревшими. Взгляните на этот репозиторий, в котором я пытаюсь обновить пример кода и заставить его работать с последней версией Drupal 8.
С появлением аннотированных плагинов в Drupal 8 многое изменилось. У нас есть более упорядоченный подход к описанию и обнаружению частей функциональности, расширяющих ядро. Наряду со многими другими компонентами прежний Field API (часть более крупного и консолидированного Entity API) теперь основан на плагинах.
В этом уроке мы рассмотрим определение пользовательского поля форматера для существующего поля (изображения). Мы хотим добиться того, чтобы под ним отображалось изображение с небольшим заголовком. Этот заголовок будет значением title
назначенным изображению, если оно существует.
Код, который мы здесь пишем, можно найти в этом хранилище как модуль image_title_caption
. Но давайте посмотрим, как мы можем достичь этого конечного результата.
Модуль Drupal
Давайте начнем с создания нового пользовательского модуля ( image_title_caption
) только с одним файлом:
image_title_caption.info.yml :
name: Image title caption type: module description: Uses the image title field as a caption core: 8.x dependencies: - image
Здесь нет ничего необычного. Мы даже можем включить модуль, если захотим.
Плагин
В Drupal 8 форматеры полей (например, типы полей и сами виджеты) являются плагинами. Базовые определяются либо базовыми модулями, либо могут быть найдены в пространстве имен Drupal\Core\Field\Plugin\Field\FieldFormatter
. И, как мы видели в предыдущей статье, в которой мы рассматривали пользовательские блоки , плагины src/Plugin/
папку src/Plugin/
нашего модуля. В случае форматеров полей это будет каталог src/Plugin/Field/FieldFormatter
.
Ниже вы можете увидеть наш собственный класс форматера:
src / Plugin / Field / FieldFormatter / ImageTitleCaption.php :
<?php /** * @file * Contains \Drupal\image_title_caption\Plugin\Field\FieldFormatter\ImageTitleCaption. */ namespace Drupal\image_title_caption\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldItemListInterface; use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter; /** * Plugin implementation of the 'image_title_caption' formatter. * * @FieldFormatter( * id = "image_title_caption", * label = @Translation("Image with caption from title"), * field_types = { * "image" * } * ) */ class ImageTitleCaption extends ImageFormatter { /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items) { $elements = parent::viewElements($items); foreach ($elements as &$element) { $element['#theme'] = 'image_title_caption_formatter'; } return $elements; } }
Это наш плагин. Ничего другого. Над объявлением класса у нас есть аннотация @FieldFormatter, через которую обнаруживается плагин. Мы указываем идентификатор плагина ( image_title_caption
), метку и массив типов полей, с image_title_caption
этот форматтер может использоваться. В нашем случае последний содержит только тип поля image
по умолчанию, но мы могли бы поддерживать больше, если бы захотели, даже пользовательские типы полей. Значения, входящие в этот массив, являются идентификаторами подключаемых модулей, поэтому если вы посмотрите на подключаемый модуль типа поля изображения , то увидите, что его идентификатором является image
.
Класс выглядит просто, потому что мы расширяемся от плагина ImageFormatter
по умолчанию, определенного базовым модулем Image. Для нашей цели все, что нам нужно переопределить, — это viewElements()
который отвечает за возврат массива рендеринга наших полевых данных. Последний может быть найден в списке $items
и может быть использован и подготовлен для рендеринга.
Первое, что мы делаем в этом методе, — это вызываем метод родительского класса для элементов и сохраняем его в переменной. Это уже подготовит изображение для рендеринга, как если бы оно было нормально.
По умолчанию плагин ImageFormatter
(родитель) использует тему image_formatter
внутри массива рендеринга для вывода значений поля изображения. Здесь мы делаем то, что для каждого элемента мы заменяем эту тему своей собственной: image_title_caption_formatter
. Затем мы возвращаем элементы (массив визуализации) так же, как это делает родитель.
Вы заметите это в Drupal 8: мы получаем очень хорошее представление о том, что нам нужно делать, из родительских классов, которые мы расширяем. И если вы спросите меня, это гораздо лучше, чем выяснить, что делает какой-то магический крючок или функция.
Тема
Поскольку тема image_title_caption_formatter
мы указали выше, до сих пор мнимая, нам нужно ее создать. Внутри .module
файла нашего модуля нам нужно реализовать hook_theme
:
image_title_caption.module :
/** * Implements hook_theme(). */ function image_title_caption_theme() { return array( 'image_title_caption_formatter' => array( 'variables' => array('item' => NULL, 'item_attributes' => NULL, 'url' => NULL, 'image_style' => NULL), ), ); }
Это должно выглядеть знакомо, поскольку оно очень похоже на Drupal 7. Пожалуйста, обратите внимание на переменные, которые мы передаем этой теме. Мы намереваемся переопределить стандартную тему image_formatter
поэтому здесь должны быть переданы те же переменные. Кроме того, поскольку тема image_formatter
предварительно обработана, нам также потребуется создать препроцессор для нашей темы:
/** * Implements template_preprocess_image_title_caption_formatter(). */ function template_preprocess_image_title_caption_formatter(&$vars) { template_preprocess_image_formatter($vars); $vars['caption'] = String::checkPlain($vars['item']->get('title')->getValue()); }
В этом препроцессоре мы выполняем два действия:
- Мы уверены, что переменные, переданные в файл шаблона, будут предварительно
image_formatter
препроцессором темыimage_formatter
по умолчанию. Это делается для того, чтобы все переменные были в точности одинаковыми, и изображение отображалось так, как обычно. - Мы создаем новую переменную с названием
caption
которая будет содержать очищенное значение заголовка изображения.
Для санации мы используем класс помощника String
статически. Мы все еще находимся внутри файла .module
поэтому мы не можем внедрить его, но нам нужно использовать его вверху файла:
use Drupal\Component\Utility\String;
шаблон
Наконец, нам нужно создать файл шаблона для нашей новой темы:
templates / image-title-caption-formatter.html.twig :
{% if url %} <a href="{{ url }}">{{ image }}</a> {% else %} {{ image }} {% endif %} {% if caption %} <div class="image-caption">{{ caption }}</div> {% endif %}
Как и в Drupal 7, имя этого файла важно, поскольку оно отражает название темы. Что касается содержимого, они почти такие же, как шаблон, используемый темой image_formatter
за исключением подписи, напечатанной внизу.
Это работает?
Теперь, когда мы написали код, нам нужно включить модуль и очистить все кэши, если мы внесли изменения в код после включения. Пришло время проверить это.
Например, перейдите к настройкам отображения поля типа содержимого статьи в admin/structure/types/manage/article/display
. В поле «Изображение» под заголовком « Format
можно выбрать Image with caption from title
формате Image with caption from title
. Сохраните форму и перейдите в admin/structure/types/manage/article/fields/node.article.field_image
и убедитесь, что заголовок поля изображения включен.
Наконец, вы можете отредактировать статью, загрузить изображение и указать заголовок. Этот заголовок будет продолжать вести себя как таковой, но, кроме того, он будет отображаться под изображением в качестве заголовка. Конечно, вы все еще можете придать ему стиль и т. Д.
Вывод
В этой статье мы увидели, как легко создать средство форматирования поля и расширить поведение по умолчанию в Drupal 8. Мы только коснулись переопределения viewElements()
этого плагина, но мы можем сделать гораздо больше для дальнейшей настройки. Вы также не обязаны расширять ImageFormatter
. Существует множество существующих плагинов, которые вы можете расширить или использовать в качестве примера.
Кроме того, вы можете легко создавать новые типы полей и виджеты. Это аналогичный процесс, но вам нужно принять во внимание некоторую информацию о схеме, использовать разные классы аннотаций и написать еще немного кода. Но дело в том, что вы очень гибки в этом.