Пример добавления терминам базового поля stored_depth:
modulename.module
/** * Implements hook_entity_base_field_info(). */ function modulename_entity_base_field_info(EntityTypeInterface $entity_type) { if ($entity_type->id() == 'taxonomy_term') { $fields = []; $fields['stored_depth'] = BaseFieldDefinition::create('integer') ->setLabel(t('Depth')) ->setSetting('unsigned', TRUE) ->setDefaultValue(0); return $fields; } }modulename.install
/**Похожие записи:
1. В админке добавляем флагу текстовое поле field_ip.
2. Пишем код:
/** * Implements hook_ENTITY_TYPE_presave(): flagging. */ function modulename_flagging_presave(FlaggingInterface $flagging) { if ($flagging->hasField('field_ip')) { $flagging->set('field_ip', \Drupal::request()->getClientIp()); } if ($flagging->getFlagId() == 'my_flag' && \Drupal::currentUser()->isAnonymous()) { $flagging_count = \Drupal::entityQuery('flagging') ->condition('flag_id', $flagging->getFlagId())Похожие записи:
Пример фильтра для оборачивания таблиц в div:
src/Plugin/Filter/TableWrapperFilter.php
/** * @Filter( * id = "table_wrapper_filter", * title = @Translation("Table wrapper"), * description = @Translation("Wrap tables to div."), * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE, * weight = 20 * ) */ class TableWrapperFilter extends FilterBase { /** * {@inheritdoc} */ public function process($text, $langcode) { $result = new FilterProcessResult($text);Похожие записи:
Debounce — функция будет выполнена только тогда, когда после последней попытки вызова прошло определённое время. Задержка начинает заново отсчитываться с каждой новой попыткой вызова. Например если повесить debounce на onscroll с временем 100ms, то функция выполнится через 100ms после прекращения скрола.
Схематично:
Похожие записи:
Часто возникает необходимость, чтобы ajax ссылка с классом use-ajax выполнила запрос ровно один раз, после чего прекратила реакцию на клики (например это ссылка загрузки контента в таб). Реализовать задуманное можно подменой функции Drupal.Ajax.prototype.eventResponse:
(function ($, Drupal) { /** * Override AJAX eventResponse function. */ var originalAjaxEventResponse = Drupal.Ajax.prototype.eventResponse; Drupal.Ajax.prototype.eventResponse = function (element, event) { var $element = $(element);Похожие записи:
Пример добавления для форматтера text_default функционала обрезки текста:
modulename.module
/** * Implements hook_field_formatter_third_party_settings_form(). */ function modulename_field_formatter_third_party_settings_form(FormatterInterface $plugin, FieldDefinitionInterface $field_definition, $view_mode, array $form, FormStateInterface $form_state) { $element = []; if ($plugin->getPluginId() == 'text_default') { $element['max_length'] = [ '#type' => 'number', '#title' => t('Max length'),Похожие записи:
Если роут ваш, то просто добавляем для него опцию _admin_route: TRUE:
modulename.routing.yml
modulename.example_route: ... options: _admin_route: TRUEЕсли роут объявлен в другом модуле, то альтерим его в EventSubscriber-е:
src/EventSubscriber/ModulenameRouteSubscriber.php
<?php namespace Drupal\modulename\EventSubscriber; use Drupal\Core\Routing\RouteSubscriberBase; use Symfony\Component\Routing\RouteCollection; class ModulenameRouteSubscriber extends RouteSubscriberBase {Похожие записи:
Код добавляет необходимые атрибуты ссылке "Login" в "User account menu", чтобы форма входа открывалась в jQuery UI Dialog.
/** * Preprocess function for menu--account.html.twig. */ function THEMENAME_preprocess_menu__account(&$vars) { if (\Drupal::currentUser()->isAnonymous()) { $login_link_url = $vars['items']['user.logout']['url']; /** @var Url $login_link_url */ $login_link_url->mergeOptions([ 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', ], ]);Похожие записи:
Пример формы для сортировки нод по полю field_weight
class ExampleDraggableForm extends FormBase { /** * {@inheritdoc} */ public function getFormId() { return 'example_draggable_form'; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $form['table'] = [ '#type' => 'table', '#header' => ['Title', 'Weight'], '#empty' => 'Empty...', '#tabledrag' => [[ 'action' => 'order', 'relationship' => 'sibling', 'group' => 'node-weight',Похожие записи:
Пример добавления вкладки для материалов типа page:
src/Controller/ModulenameController.php
class ModulenameController extends ControllerBase { public function exampleTabContent(NodeInterface $node) { return ['#markup' => 'Tab content...']; } public function exampleTabAccess(NodeInterface $node) { return AccessResult::allowedIf($node->bundle() === 'page'); } }modulename.routing.yml
entity.node.example_tab: path: '/node/{node}/example-tab' defaults:Похожие записи:
Пример создания элемента формы fullname с тремя полями - Фамилия, имя, отчество.
src/Element/FullnameElement.php
<?php namespace Drupal\modulename\Element; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element\FormElement; /** * @FormElement("fullname") */ class FullnameElement extends FormElement { /** * {@inheritDoc} */ public function getInfo() { $class = get_class($this); return [ '#input' => TRUE, '#process' => [ [$class, 'processElement'], ],Похожие записи:
Пример выполнения ajax запроса на внутренний адрес path/to/controller:
var ajax = new Drupal.Ajax(false, false, { url: Drupal.url('path/to/controller') }); ajax.execute();Контроллер должен вернуть набор команд ajax-фреймворка.
Похожие записи:
После загрузки страницы для каждой ссылки с классом use-ajax создаётся объект Drupal.Ajax, в котором фиксируется адрес, на который по клику отправится ajax запрос. После создания этого объекта менять href ссылки уже бесполезно, надо вручную лезть в Drupal.ajax.instances и менять options.url у нужного объекта.
Ниже пример того, как можно перед отправкой ajax запроса автоматически менять его адрес на значение атрибута ссылки data-ajax-url:
(function ($, Drupal) {Похожие записи:
Похожие записи:
В восьмёрке по умолчанию после удаления сущности не удаляются файлы, залитые в поля типа File. Они не удаляются ни сразу, ни по крону, так как статус файла в таблице file_managed остаётся 1. В версии 8.4 появилась опция make_unused_managed_files_temporary, при включении которой файлы помечаются как временные и удаляются по прошествии 6 часов, однако отредактировать эту опцию из админки нельзя. Включить можно либо с помощью drush:
vendor/bin/drush config-set file.settings make_unused_managed_files_temporary 1 -yПохожие записи:
Способ отключить автозагрузку файлов с помощью js на примере поля field_file:
(function ($, Drupal) { Drupal.behaviors.modulename = { attach: function attach(context, settings) { $('.field--name-field-file .js-form-file', context) .removeOnce('auto-file-upload') .off('.autoFileUpload'); } }; })(jQuery, Drupal);Похожие записи:
Системный автокомплит умеет отправлять на сервер только введённый текст. Послать вместе с текстом какие-то данные, например значение поля или js-переменной, нельзя.
Решение с подменой функции Drupal.ACDB.prototype.search:
autocomplete-fix.js
(function ($) { // Override Drupal.ACDB.prototype.search Drupal.ACDB.prototype.search = function (searchString) { var db = this; this.searchString = searchString; searchString = searchString.replace(/^\s+|\.{2,}\/|\s+$/g, '');Похожие записи:
Block API в восьмёрке подверглось значительным изменениям и усложнениям. Теперь, помимо функционала в ядре, есть три модуля для работы с блоками:
Похожие записи:
Код для роли rid=4 подменяет административное меню management на menu-example:
/** * Implements hook_admin_menu_output_alter(). */ function MODULENAME_admin_menu_output_alter(&$content) { if (user_has_role(4)) { // Remove old links $content['menu'] = array_diff_key($content['menu'], array_flip(element_children($content['menu']))); // Add new links $content['menu'] += admin_menu_links_menu(admin_menu_tree('menu-example')); } }Похожие записи:
В седьмом друпале в настройках Colorbox была опция "Enable Colorbox load", позволяющая ссылкам с классом colorbox-load открываться в колорбоксе. В восьмой версии эту опцию удалили, но её достаточно просто вернуть с помощью кода:
/** * Preprocess variables for page.html.twig. */ function THEMENAME_preprocess_page(&$variables) { \Drupal::service('colorbox.attachment')->attach($variables); }Сбрасываем кэш.
Похожие записи:
Последние комментарии