Использование:
$response = new AjaxResponse();Похожие записи:
К сожалению, мигратор метатегов из модуля metatag не всегда корректно срабатывает. В моём случае он отказался работать и метатеги не перенеслись вместе с контентом. Быстро был найден простой вариант:
1. Используем для экспорта метатегов модуль metatag_import_export_csv. Он позволяет делать экспорт как одного типи материала, так и сразу всех. Есть GUI и drush-команда. В каталоге files будет создан каталог metatag_import_export_csv и в нём будут файлы экспорта.
2. Затем нужно отредактировать файл как вам нужно. В моём случае понадобилось только 3 поля, nid, description и keywords.
3. Для импорта используем модуль feeds. На момент написания этой заметки нужно было использовать dev-версию, потому что вот этот коммит еще не попал в релиз, а он нужен нам, чтобы указывать в какие nid загружать метатеги.
4. Для модуля metatag понадобится патч из этого issue для интеграции с feeds.
5. Создаём в feeds потоки данных для импорта и импортируем данные из нашего файлы экспорта. Этот процесс я не буду расписывать, он тянет на отдельную статью.
Задача: миграция метатегов из модуля metatags_quick в модуль metatag
У модуля metatag для Drupal 7 есть субмодуль metatag import, однако я не увидел в нем кнопку для миграции метатегов из модуля metatags_quick. Есть только кнопки для миграции из модулей nodewords и page_title. Поиск в гугле привёл меня в этот коммит, где и обнаружилась уже добавленная в модуль metatag drush-команда для миграции метатегов из модуля metatags_quick в модуль metatag.
Запускаем команду drush mtcmq и она перенесёт метатеги. После этого можно удалить поля модуля metatags_quick из типа материала и запустить крон для их полного удаления.
Кто работал с муниципальными/государственными заказчиками знает, что опросы проводимые на сайтах в большинстве своём "липовые". Если окажется, что население недовольно оказываемыми услугами учреждения, то тут же в дело вмешается прокуратура. Поэтому отчеты типа "Удовлетворены ли вы работой учреждения" имеют результаты сопоставимые с рейтингами тоталитарных лидеров (> 80%)
Выяснилось, что модуль опросов poll для Drupal 8/9 такой важной функциональности не имеет. Предложенный на drupal.org патч сначала работал, потом при добавлении фейковых голосов стала вываливаться ошибка БД и опрос перестал сохраняться.
Так как у меня было всего 2 часа на эту задачу, пришлось быстро набросать патч для добавления этой функциональности. Что делает патч:
Патч применяется к последней стабильной версии модуля poll 1.4
Ссылка на issue https://www.drupal.org/project/poll/issues/3035898
Прямая ссылка на патч https://www.drupal.org/files/issues/2020-12-18/poll-3035898-8.patch
Примерно полгода назад, столкнувшись с невозможностью выполнить несложные требования по форматированию изображений с помощью имеющихся преобразований (image effects), я написал модуль Ratio Crop, который реализует следующее преобразование: картинка обрезается по "выступающей" стороне таким образом, чтобы соотношение сторон соответствовало заданному. Другая сторона остаётся неизменной.
Откуда возникла потребность: допустим, мы хотим показывать на странице с жёсткой разбивкой картинки (для наглядности, одну картинку), которую можем разглядывать как бы в увеличительное стекло. Для такого "увеличительного стекла" существует полно скриптов, вот, например: JQuery Zoom. Такой скрипт загружает на страницу исходную картинку, при отображении страницы масштабирует её под размер контейнера, а при наведении курсора (или другом действии пользователя) отображает картинку в исходном разрешении в рамках того же контейнера, передвигая её в ответ на движения курсора.
Скриншоты зума в действии:
Картинка на странице масштабирована под размер контейнера
При наведении курсора картинка отображается в полный размер, но не выходит за пределы контейнера
Исходные картинки, которые у нас есть, немного разные, как по размерам, так и по отношению сторон. Обрезать все под один размер не хочется - пусть те, что больше, отображаются при наведении курсора в свою исходную величину, с большей детализацией. Тем не менее под один формат их обрезать надо, чтобы не перекосило при вставке в контейнер фиксированных размеров.
Для наглядности возьмём две картинки немного разного размера и отношения сторон:
Первая - 769x424px, отношение сторон 1.8
750x500, отношение сторон 1.5
Приведём их к формату 4:3
Получились размеры 565х424 и 667х500
Размеры разные, но отношение сторон одинаково.
Как ни странно, добиться такого результата имеющимися преобразованиями (Crop, Resize, Scale, Scale & Crop) не получилось. Crop обрезает, а Resize сжимает под фиксированный размер, нам это сразу не подходит. Scale сохраняет исходное отношение сторон, это как раз, что нам не надо. Ближе всего к желаемому эффекту Scale and Crop, но оно тоже подгоняет под фиксированный размер.
К счастью, в 8м Друпале выход всегда есть - написать свой плагин (как легко догадаться, преобразования изображений - это именно плагины). Примеры в ядре достаточно наглядны и показательны, поэтому в реализации особых проблем не возникло, заняло это дело несколько часов. Следует отметить, что плагинов на самом деле не один, а два: один (ImageEffect) предоставляет весь интерфейс, производит первичную обработку входных данных и вызывает непосредственно обработчик изображения, то есть второй плагин (ImageToolkitOperation). Второй плагин должен быть реализован для каждой графической библиотеки отдельно, у меня, как и большинства, я думаю, GD, поэтому я сделал только для GD. Писать тесты тоже поленился, хотя они бы пригодились - редкий случай, когда предельно ясно, что и как тестировать.
Интерфейс преобразования простой и интуитивно понятный:
В верхней строчке - отношение сторон x:y, виджет внизу определяет, как обрезать выступающую сторону при обрезке: если, например, выбран квадратик внизу слева, то, если картинку нужно обрезать по высоте, будет обрезано сверху, если по ширине - справа, и т.д.
На данный момент drupal.org считает, что модуль установлен на 55 сайтах.
Пользуйтесь на здоровье, предлагайте усовершенствования, делитесь сценариями использования. Всегда рад обратной связи.
Этот материал будет Вам полезен, если совпали следующие условия:
Всё что нужно сделать, это положить файлы в корень проекта вот так
После чего при миграции указать путь /var/www
Теперь мигратор будет брать локальные файлы и копировать их в web/sites/default/files с большой скоростью
После окончания миграции файлы из корня проекта можно удалить
К сожалению, я не осилил модуль webform_migrate. Вернее "из коробки" он ничего не делал, документация очень скудная и даже нет примеров использования.
В поисках информации я наткнулся на репозиторий https://github.com/JAyenGreen/webform_d7_to_d8
Это модуль для Drupal 8. Я кинул его в /modules/custom и включил на сайте. Далее по шагам:
1) Прописываем в settings.php или в settings.local.php ваши данные для базы старого сайта, например
$databases['upgrade']['default'] = array (
'database' => 'drupal7database',
'username' => 'drupal7user',
'password' => 'drupal7password',
'prefix' => '',
'host' => 'drupal7host',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
);
2) Смотрим NID вашей вебформы на старом сайте, у меня это 3114
3) Запускаем миграцию в режиме симуляции
drush ev 'webform_d7_to_d8(["nid" => 3114, "simulate" => TRUE])'
У меня вывалилась куча ошибок связанная с миграцией отправлений "submissions". Они мне не нужны на новом сайте, поэтому исключаем их из миграций
drush ev 'webform_d7_to_d8(["nid" => 3114, "max_submissions" => 0])'
4) Готово! На новом сайте появилась новая вебформа
Поделитесь своим опытом миграций в комментариях
данная инструкция создана по горячим следам работы с реальным проектом. Отдельная благодарность Ивану Абраменко и его уроку Галерея Isotope для Drupal 8. Инструкция делалась для себя, чтобы потом не тратить лишнее время на воспроизводство, т. к. довольно редкий кейс. Инструкция предполагает определенный уровень знаний особенностей работы с Drupal.
ЗадачиПример того, что должно получиться на выходе
Процесс 1. Необходимые модули и js-скриптыНе будем рассматривать процесс установки модулей и их библиотек. Все стандартно. Исключение — photoswipe (на его страничке все подробно описано) и сам isotope (о нем подробнее ниже).
- media — входит в ядро
- paragraphs:
- photoswipe (модуль и его библиотека):
Библиотека после установки (через composer), должна появиться в папке libraries:
Проверяем статус библиотеки photoswipe в системе — /admin/reports/status
- isotope:
1.1. файл isotope.pkgd.min.js размещаем в папке js вашей темы. Там же создаем файл инициализации — isotope_init.js
1.2. прописываем isotope в библиотеках темы — у меня это файл mytheme.libraries.yml
isotope_lib:подключать саму библиотеку в дальнейшем будем в twig того блока, где она должна работать.
2. Настройки и создание необходимых справочников и материалов2.1. Создаем справочник Категорий (/admin/structure/taxonomy/add) — у меня его машинное имя categories. Заполняем его терминами.
2.2. Создаем новый тип Медиа - /admin/structure/media/add, где прописываем необходимое поле:
Все настройки — на ваше усмотрение.
2.3. Создаем новый тип параграфа Photo (/admin/structure/paragraphs_type/add), где прописываем необходимые поля:
поле категорий (field_category_img) предполагает выбор опции:
«Допустимое количество значений» - неограниченно
2.4. Добавляем новый тип материалов Photos (/admin/structure/types/add), где создаем поле:
опция «Допустимое количество значений» - неограниченно.
2.5. Переходим в content (содержимое) и создаем новый материал, тип Photos (/node/add/photos). Заполняем картинками с указанием на их категории:
3.1. Создаем представление по выводу картинок в виде галлереи (/admin/structure/views/add). У меня это «Лучшие Проекты» с машинным именем best_projects.
3.2. Сохраняем и переходим на страницу работы с полями и фильтрами.
3.3. Сначала прописываем необходимые связи. Цель — получить прямой доступ к картинке (она у нас загружена через медиа)
3.4. Добавляем поля категорий и картинки в блоке «Поля»:
3.5. Во время настройки поля Категории есть 3 момента:
3.6. Настройка поля картинки заключается в выборе форматера и прописывании его опций.
3.7. Для подключения режима галереи к блоку фотографий, необходимо в настройках общего класса указать photoswipe-gallery
3.8. На данном этапе оканчиваем настройку этого представления прописыванием в настройках раздела "Формат" в классе строки шаблон нашего поля категорий:
Это обеспечивает вывод в html в классах картинки перечня из её категорий, что важно для работы скрипта isotope.
Предварительная настройка окончена, на следующем этапе мы к нему еще вернемся.
4. Создание представления по выводу фильтров и его настройка4.1. Создаем представление для вывода фильтров (выбираем блок)
4.2. Сохраняем и переходим на страницу настроек полей и фильтров.
К полю наименование термина добавляем второе поле — его id. Сразу же исключаем его из вывода.
4.3. Для ограничения списка терминов только теми, по которым есть привязка к фотографиям, в связях выбираем:
и ставим признак «Эта связь обязательна». В результате в выдачу попадут только категории, имеющие привязку к картинкам.
Для устранения дублирования некоторых категорий включаем агрегацию (Расширенное-Другое):
4.4. В завершение в настройках Формата классу сроки присваиваем класс «views-button»
4.5. Сохраняем представление и переходим к файлу mytheme.theme для написания препроцесс-функции:
<?php4.6. Создаем в папке темплейтов twig блока фильтров views-view-field—projects-filters—block-1—name.html, где:
«Лучшие Проекты» с машинным именем best_projects) и подключаем в шапке «Область представления» и выбираем наше представление фильтров.
Итоговая форма представления картинок
Прописываем следующий код:
(function ($) {$('.view-projects-filters > .view-content').once('add-all').prepend('Все');
// init Isotope
var $grid = $('.view-best-projects > .view-content').isotope({
itemSelector: '.best-projects-photo',
layoutMode: 'fitRows'
});
// bind filter button click
$('.view-projects-filters').once().on( 'click', 'button', function() {
var filterValue = $( this ).attr('data-filter');
$grid.isotope({ filter: filterValue });
});
$('.view-projects-filters .button').on('click', function () {
var activeGallery = ($(this).data('filter')); //get the current filter
$(".photoswipe-gallery .best-projects-photo a").each(function () {
$(this).removeClass('photoswipe'); //remove all photoswipe classes
});
$(".photoswipe-gallery .best-projects-photo" + activeGallery +" a").each(function () {
$(this).addClass('photoswipe'); //add photoswipe class only for active images
});
});
}
};
})(jQuery);
Который состоит из условных 2 частей:
Всё.
Скоро будет 12 лет, как на drupal.org весит незакрытое ишью с просьбой добавить возможность использовать токены в контактных формах, но воз и ныне там. По традиции фиксим самостоятельно:
// MODULENAME.module /** * Implements hook_form_BASE_FORM_ID_alter(): contact_form_form. */ function MODULENAME_form_contact_form_form_alter(array &$form, FormStateInterface $form_state) { $form['recipients_new'] = [ '#type' => 'textfield', '#title' => $form['recipients']['#title'],Похожие записи:
Узнать список доступных полей у конкретной контент-сущности можно заглянув в её метод baseFieldDefinitions().
Нода:
$node = \Drupal\node\Entity\Node::create([
// Required fields
'type' => 'page', // Node type id
'title' => 'Example node',
// Optional fields
'status' => \Drupal\node\NodeInterface::PUBLISHED,
'uid' => 0,
'created' => time(),
'changed' => time(),
'promote' => \Drupal\node\NodeInterface::NOT_PROMOTED,
'sticky' => \Drupal\node\NodeInterface::NOT_STICKY,
// Custom fields
Похожие записи:
Экспортируем:
mysqldump --user=USERNAME --password=PASSWORD DATABASE_NAME > dump.sqlИмпортируем:
mysql --user=USERNAME --password=PASSWORD DATABASE_NAME < dump.sqlПохожие записи:
Рассказывает автор модуля Александр Левицкий, backend-разработчик студии ADCI Solutions.
Большинство модулей для шеринга веб-страниц в социальные медиа, которые лежат на drupal.org - это друпальные блоки, в которых эти соцмедиа предопределённы заранее. И никакие другие добавить в эти модули нельзя, разве что хакнув их.
На одном из проектов я разработал принципиально другой модуль для этих целей. Название у него - понятнее некуда: Social Sharing.
ПредысторияВ работе широко известного сервиса для шеринга веб-страниц в соцсети AddToAny есть момент, ставший принципиальным для нашего клиента.
Так выглядит обычный URL шеринга страницы в Twitter:
https://twitter.com/intent/tweet?text=Hello%20world
А вот тот же шеринг той же страницы, но выполненный через AddToAny:
https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fwww.addtoa...
Мы видим, что сначала запрос проходит через AddToAny, там обрабатывается и уже потом расшаривается в Twitter. Хотя контент, который шерится, подразумевается как публичный, клиент не хотел, чтобы трафик шёл где-то ещё. Ну, потому что.
Нужно было что-то гибкое и кастомное. MVP такого модуля я сделал для клиента, а доработанную версию, которой и является Social Sharing, выкатил на drupal.org. От модуля, который использовался на проекте осталось примерно 20%, буквально одна лишь основная идея.
Что изменилось:
Теперь подробно и по порядку.
Почему стоит выбирать Social SharingТеперь поговорим подробнее о конфигурации различных фич.
Extrafield configuration
Если для разных сущностей на сайте нужны одинаковые ссылки шеринга с одинаковым контентом, который будет шериться, то можно воспользоваться Extrafield. Для него есть отдельная страница конфигурации, где пользователь может настроить:
Минусом данного способа является то, что эти настройки - глобальные для всех сущностей, и при необходимости поменять их для одного типа сущности (например, список соцсетей) они поменяются везде, где используются. Это поле удобно использовать, если не требуется гибкости, и список ссылок останется неизменным на всём сайте.
Entity field configuration
Ниже приведены примеры конфигурации нового типа поля. В отличии от extrafield это поле может быть настроено для каждой сущности отдельно. Можно задать общие настройки по умолчанию и при необходимости переопределить эти настройки для каждой единицы этой сущности.
Рассмотрим на примере. У нас есть тип сущности Node. У этой сущности могут быть различные бандлы (Article, Basic page, Blogpost и т. д.). Для каждого бандла мы можем добавить поле типа Social sharing и задать индивидуальные настройки по умолчанию для каждого из бандлов. Далее мы будет создавать контент на нашем сайте - добавлять ноды для этих бандлов. В каждой отдельной ноде пользователь может выбрать, оставить настройки для шеринга, заданные по умолчанию, или переопределить их для текущей ноды (см. скриншот ниже).
Ещё одной ключевой особенностью этого способа является то, что есть возможность использовать токены. С поддержкой токенов появилась возможность шерить любой контент, который может присутствовать в ноде.
Block Configuration
С блоком все так же довольно просто. Пользователь может добавить блок в любой регион на сайте, выбрать сервисы для шеринга и задать URL для шеринга, либо оставить предложенный по умолчанию.
Displaying the links (Block and entity field)
Ниже приведён пример отображения ссылок на шеринг в блоке и в качестве поля для текущей ноды. Может возникнуть резонный вопрос: “А почему же нет иконок?”. За весь мой опыт работы мне не встретился ни один проект где были бы использованы стандартные иконки с какого-то сервиса (например, Fontawesome). Всегда есть дизайн и всегда в дизайне есть эти иконки, которые добавляются фронтенд-разработчиком во время темизации. Но в планах дальнейшего развития модуля есть пункт о добавлении различных пресетов иконок.
Добавление соцсети, которой нет в модуле
Если в модуле отсутствует необходимая для вас соцсеть, то добавить ее не составит большого труда, если с навыками программирования у вас всё хорошо. Для этого нужно создать свой кастомный модуль и добавить в этом модуле новый плагин. Плагин будет автоматически интегрирован в функциональность, предоставляемую модулем, и вы сможете использовать свою соцсеть наравне с остальными. Как работают плагины, в Drupal, можно почитать тут.
Пример файла path-to-custom-modules/mymodule/src/Plugin/ShareService.php
У каких-то известных до сих пор модулей есть только блок, у каких-то только филд, где-то есть и филд, и блок, но поменять или добавить сервисы нельзя, и почти нигде с модулем не интегрирован views и нет поддержки токенов, что ограничивает выбор контента при шеринге. Модуль Social Sharing собирает разрозненную функциональность большинства модулей и в ключевых местах значительно её улучшает, что делает его лидером среди всех остальных.
Буду рад, если вы встроите модуль в свои проекты и оставите замечания и пожелания по его работе.
Институт истории науки входит в состав некоммерческой организации «Общество Макса Планка». Он был основан в 1994 году и является одним из более чем 80 научно-исследовательских институтов Общества.
Деятельность Института охватывает культуры всех времён, народов и географических направлений и ставит целью исследовать, как изменяются базовые научные концепции и определения и как культура влияет на науку.
ЦелиИнституту требовался сайт для исследовательской группы Epistemes of Modern Acoustics, изучающей акустику одновременно как объект и инструмент познания. Сайт должен:
Что мы сделали:
У информации на сайте есть своя специфика. Это и наличие библиографических данных, и обилие специфических полей различного типа, и кастомные поля, и связи между контентом. Это создало у администраторов потребность в особых рабочих инструментах. Drupal оказался наиболее подходящей для этого CMS.
У исследовательской группы уже был сайт, но в продакшн он не попал. В его основе лежала CMS Drupal 7, а для работы с библиографическими данными использовался модуль Bibliography. Со временем выяснилось, что такая комбинация технологий утыкается в ограничения и не может покрыть всех нужд группы. Его представители обратили внимание на молодой (для своего времени) и перспективный Drupal 8. Однако на тот момент модуль Bibliography не имел версии, совместимой с этой версией CMS, и планов по её реализации тоже не было. Тут-то и пригодился наш проект Bibliography & Citation, который стал альтернативной Bibliography.
Что такое Bibliography & CitationПроект Bibliography & Citation (или BibCite), созданный в ADCI Solutions, помогает организовывать, систематизировать и хранить библиографические данные о контенте в спектре от интернет-страниц до научных работ и оформлять цитирование этих источников согласно множеству стандартов, принятых в разное время и в разных организациях.
По данным drupal.org, на момент публикации кейса проект используется на более чем 282 сайтах. Его задачи уникальны, поэтому каждое использование — с высокой долей вероятности осмысленное. Будучи компанией-создателем проекта, мы это очень ценим.
О том, кто и как использует проект, читайте в статье Five use cases that highlight the benefits of the Bibliography & Citation project.
КонтентDrupal — это прежде всего одна из самых удобных и безопасных систем управления контентом. И в процессе работы мы задействовали весь свой опыт, чтобы поддержать доброе имя Drupal: создали типы контента, перенесли содержимое старого сайта на новый, внедрили специальные инструменты для работы с библиографическими данными и переработали UI админ-панели с помощью виджетов Inline Entity Form, Field Group и других. И клиент, и администраторы сайта остались довольны.
ТИПЫ КОНТЕНТАСтруктура контента, которого на сайте очень много, играла важнейшую роль. Многие из типов контента прямо связаны с научной работой, поэтому необходимы. Кроме таких привычных типов, как «текст», «изображения», «аудио» и «видео» включили типы «личность», «эксперимент», «инструмент», «локация», «эссе».
МИГРАЦИЯ КОНТЕНТАПеренести огромное количество контента с одного сайта на другой помог встроенный в Drupal 8 модуль Migrate и вспомогательные модули Migrate Tools и Migrate Plus.
ОТОБРАЖЕНИЕ КОНТЕНТАМодуль Display Suite помог фронтенд-разработчику создать страницы с учётом дизайнерских макетов. Другой модуль, Field Group, даёт возможность объединять поля в группы по какому-либо признаку. Блок «Оглавление», помогающий быстро перемещаться между разным частями контента на странице, построен на модулях TOC API и TOC Filter. Всё вместе упрощает фронтенд-разработчику работу со стилями.
ПОИСКСамая часто используемая функция. Работает на модуле Search API, поисковой платформе Solr на серверной стороне и модуле Facets.
Результаты поиска строятся на основных типах, их свойствах и тегах. Перемещаться по страницам можно с помощью тегов, группирующих разные виды контента.
Модерация контентаРазмещать контент могут и администраторы, и обычные пользователи, что облегчает жизнь контент-менеджеров сайта. Им, в свою очередь, остаётся только проверить контент, оставить по нему замечания и опубликовать.
Если вам нужна такая же функциональность, в ядре Drupal есть модуль Content Moderation.
Научные данные и цитированиеБиблиографические данные хранятся в сущностях Reference, Contributor и Keyword. За хранение данных отвечает модуль Bibliography & Citation — Entity. Обращаем внимание, что библиографические данные отделены от контента, но в определённых случаях они могут легко ссылаться друг на друга с помощью поля Entity Reference.
Модуль Inline Entity Form уменьшает количество действий, которые администратор должен тратить на работу с контентом и библиографическими данными. Благодаря модулю он может создавать и редактировать библиографические данные в форме с тем самым контентом, к которому эти библиографические данные относятся.
Сборка сайта из готовых программных решенийПланировалось, что некоторые функциональные части сайта, типы контента и т. д. будут заново использоваться на других сайтах института. Для этого необходимо держать соответствующие настройки не только в базе данных, но и в коде. Вообще же экспорт в кодовую базу разных настроек вроде типов контента с полями, пользовательских ролей с правами доступа, представлений, макетов страниц и т. д. — очень распространённая практика в Drupal, дающая кучу преимуществ.
Эти возможности были реализованы как с помощью функциональности Configuration Management из ядра Drupal, так и с помощью дополнительного модуля Features. Этот модуль позволяет запаковывать связанные конфигурации (например, контент-тип и привязанные к нему поля, отображения контента типа Teaser или Full View и т. д.) в обычные Drupal-модули. Эти модули содержит в себе необходимые конфигурации и при установке на Drupal-сайте разворачивают содержащийся в нём кусок функциональности.
Для каждой страницы с научным материалом создан QR-код со ссылкой, ведущей на соответствующую страницу. QR-код можно скачать в виде изображения и вставлять в документы.
Администраторам нужна была функциональность для связывания разных типов контента. В результате связанный контент отображается в секции Related Objects на страницах контента.
Некоторые сущности могут относиться друг к другу.Для решения подобной задачи вполне подходит модуль Relation. Но, во-первых, у него не было и нет рабочей версии для Drupal 8, а во-вторых, использовать его для связи всего двух сущностей было бы избыточно — он создан для куда более сложных задач. Поэтому мы реализовали простую связь между двумя сущностями.
Для удобства навигации по странице мы расширили функциональность модуля TOC Filter. Этот модуль нужен для создания оглавления, и по умолчанию он использует для этого встречающиеся в тексте заголовки H2 и H3. Мы же сделали так, чтобы TOC Filter выводил якоря и на другие поля и группы полей типа категорий, связанного контента и т. д.
Вклад в DrupalЭтот проект показал, как проектом Bibliography & Citation пользуются на самом деле, что позволило улучшить его работу и написать дополнения. В частности, несколько дополнений было сделано к модулю Bibliography & Citation — Migrate. Модули Field Group, Search API sorts и TOC API тоже лишились ряда недостатков после того, как мы предложили их разработчикам исправления.
ЗаключениеDrupal 8 идеально подходит для сайтов с обилием контента: даёт для авторов большие возможности из коробки и расширяется для любых нужд. Проект Bibliography & Citation получил толчок в развитии, мы собрали обратную связь по его работе, а сообщество отреагировало всплеском интереса к нему.
Небольшой костыль, который позволит указывать тип прогрессбара ajax-ссылки в атрибуте data-progress-type.
// MODULENAME.js (function ($, Drupal) { /** * Override AJAX "beforeSend" callback. */ var originalAjaxBeforeSend = Drupal.Ajax.prototype.beforeSend; Drupal.Ajax.prototype.beforeSend = function (xmlhttprequest, options) { var $element = $(this.element); // Set progress type from "data-progress-type" attribute // @TODO Remove after close issue https://www.drupal.org/project/drupal/issues/2818463Похожие записи:
По умолчанию блоки с формами кэшируются только для анонимных пользователей. Для залогинённых же друпал добавляет во все формы элемент form_token со свойством '#cache' => ['max-age' => 0] (тырк), который запрещает кэшировать все вышестоящие элементы (блок, страница и т.д.). Чтобы этого избежать и включить кэширование блока для всех, нужно отключить генерацию form_token:
Похожие записи:
Drupal 9 вышел 3 июня 2020 года. Значит ли это, что более ранние версии, а вместе с ними и наши советы, вмиг потеряли актуальность? Нет. Во-первых, стабильной работы от Drupal 9 стоит ждать только начиная с версии 9.1, чей выход назначен на декабрь 2020 года. Во-вторых, из всех проектов для Drupal 8 пока только 3 244 (примерно треть, но их число растёт) совместимы с Drupal 9. В третьих, поддержка Drupal 8 закончится в декабре 2021 года. И, наконец, в-четвёртых, в мире насчитывается чуть больше 300 тысяч сайтов, использующий тот или иной релиз Drupal 8, и вероятнее всего, их число пополнится, когда владельцы сайтов на Drupal 7 решатся на миграцию.
Дайте Drupal-сообществу довести новый релиз до ума, а пока улучшайте сайты на Drupal 8 — надеемся, описанный в статье опыт разработчиков ADCI Solutions вам в этом поможет.
Какие проблемы чаще всего испытывают сайтыЛюбой опытный веб-разработчик обязательно сталкивался с сайтами, страдавшими от одной или нескольких проблем:
Это происходит тогда, когда в процессе разработки сайта игнорируются передовые методы. Данная статья расскажет о самых распространенных проблемах и способах их решения. Мы специально не стали создавать отдельные списки для каждой проблемы, так как иногда один модуль способен решить сразу несколько.
Список нерекомендуемых модулей DrupalВот список модулей, которые на работающем сайте должны быть отключены. Дело не в том, плохие они или нет, а в том, что их использование оправдано только на этапе разработки.
В большинстве случаев эти модули вам тоже не понадобятся:
Избыток модулей может замедлить работу сайта, а если они страдают от слабой поддержки и багов, то безопасность и стабильность работы сайта находятся под угрозой.
Список рекомендуемых модулей DrupalМы настоятельно рекомендуем использовать следующие модули, которые помогут вам в решении множества проблем:
Drupal 8 дает возможность быстрого редактирования и предпросмотра страниц. Все продвинутые опции вынесены в правый сайдбар. Администрирование стало намного проще, однако возможности для редактуры пока что далеки от идеала. Сложность работы с сайтом зависит от вас.
Всё вышесказанное основано на многолетнем опыте разработки. Придерживаясь этого опыта, вы сумеете сэкономить время и избежать самых распространенных ошибок. Удачи!
Подписывайтесь на наш блог на Medium и следите за нами на Яндекс Дзене, ВКонтакте и в инстаграме.
Отчёт о работе с одним из зарубежных клиентов нашей студии, компанией WeighMyRack, помогающей любителям скалолазания подобрать экипировку по выгодной цене.
К нашему обоюдному удовольствию, работа всё ещё продолжается, но этот кейс отражает её важную часть.
Проект непростой, а потому в тексте присутствует кое-какие специфические понятия, дать которым определение мы считаем своим долгом.
Ритейлер — сайт или магазин, который продает товары и предоставляет нам потоки данных, или фиды.
Фид — поток данных. В нашем случае это .csv или .txt-файл, содержащий всю необходимую информацию о товаре и обновляющийся раз в день.
Импорт — процесс обновления информации, полученной из фида.
Main-сервер — главный сервер для работы с данными, которые видит пользователь на сайте.
Sync-сервер — вспомогательный сервер для вычислений.
Контрибный модуль — Drupal-модуль, развиваемый сообществом.
О клиентеКомпания ADCI Solutions познакомилась с соосновательницей WeighMyRack в конце 2018 года, а в начале 2019 начали работу. Ей требовалась команда с глубокой экспертизой в Drupal для сложного проекта, и как можно скорее — разработчики из команды поддержки сайта решили закрыть своё агентство. После технического интервью и нескольких переписок клиент выбрал нас. Мы до сих пор продолжаем сотрудничество.
О сайтеКомпания WeighMyRack позиционирует себя как прайс-площадку с возможностью для сравнения цен между товарами от производителей из Америки, Европы, Великобритании, Австралии и Канады. В качестве российских аналогов можно было бы привести Яндекс.Маркет и price.ru. Но WeighMyRack специализируется только на товарах для скалолазов, что делает его ближе к нишевым сервисам Podarki.ru, Mobiguru.ru и Kolestorg.ru, подсказывающим цены в магазинах подарков, мобильных устройств и автозапчастей соответственно. WeighMyRack не является магазином сам по себе и зарабатывает на процентах с продаж, совершаемых пользователями, перешедшими с прайс-площадки на сайт производителя скалолазного снаряжения.
Перед нами стояла задача масштабировать импорт за счёт подключения более 10 дополнительных фидов, сделать рефакторинг кода, обновить CMS, устранить баги из имеющейся функциональности, улучшить производительность сайта и интерфейс.
Что получил клиент:
Теперь о том, как нам дался этот успех.
Добавляем новую функциональностьКлючевая функциональность сайта собрана на страницах с категориями товаров. Здесь пользователь может:
Мы улучшили UX этих страниц. В частности, с помощью Drupal-модуля Facet API мы сделали несколько новых фильтров, использующи информацию из фидов (страна магазина, который продает товар, скидки и т. п.).
Чистим сайт от неработающего кодаКопаясь у сайта во внутренностях, мы нашли контрибные модули и темы, код которых не соответствовал коду тех же модулей и тем, хранящихся в репозитории Drupal. Так делают, чтобы заставить модуль решать изначально не предполагавшиеся для него задачи. Но формально такие изменения считаются багами, а усугубляло ситуацию то, что модули не получали обновлений безопасности 2-3 года. В метафорическом смысле это делало из проекта в минное поле.
Что это значит на практике? Во-первых, стоило попытаться обновить доработанный модуль до какой-нибудь версии, и всё могло сломаться; во-вторых, баг может воспроизводиться на одной единственной странице раз в месяц; и в-третьих, никогда не известно, насколько большую роль играли эти доработки в жизни сайта — может, выводили текст на странице покрасивее, а может, изменяли работу с базой данных.
Порой бывает сложно сказать, насколько сильно влияют изменения в коде на общую работу сайта. Хорошо, если код написан чисто, с комментариями и без багов. А что, если комментариев нет? А если связи с разработчиком не имеется? Поэтому прежде чем начинать работать, нужно было понять глубину изменений в модулях.
В итоге мы почистили модули от неправильного кода ровно настолько, чтобы можно было обновить сайт и не разрабатывать его с нуля.
Сохраняем данные максимально свежимиРаботу сайта с данными обеспечивали два сервера: main и sync. Первый занимался обработкой пользовательских запросов, второй — импортом данных. Они связаны между собой с помощью Jenkins — системы, которая позволяет автоматизировать процессы разработки и деплоя.
Почему двумя задачами не мог заниматься один сервер? Залог успеха любого сайта — быстрая загрузка. Это любят все. Если бы в нашем случае импорты происходили на main-сервере, пользователь во время загрузки страницы успевал бы выпить чашку кофе. Поэтому пока один сервер занят длительной монотонной вычислительной работой, другой работает с пользователями.
Контент-менеджер WeighMyRack создаёт на main-сервере страницы с товарами, следит, чтобы информация была актуальной, и прописывает уникальные идентификаторы товара, благодаря которым можно соотнести строчки из фидов со страницами товаров на сайте.
А пока контент-менеджер что-то меняет на main-сервере, на sync-сервере может происходить импорт. И то, и другое меняет базу данных, и нам надо было сохранить все. А если какой-то из серверов упадёт, важно было иметь максимально свежие данные.
У нас уже был настроен модуль backup_migrate, делающий бэкапы на сервере раз в день по таймеру, а также имелись еженедельные бэкапы на хостинге Digital Ocean. Но этого было мало, и, чтобы заставить два сервера работать в унисон с базой данных, мы написали скрипт, который делает ежедневные бэкапы данных перед началом очередного импорта и записывает их в бэкап-хранилище на удалённом сервере с отладочным сайтом.
Это дало нам уверенность, что обновленная информация появится на рабочем сайте. И если основной сайт упадет, у нас все равно будет бэкап менее, чем 12-часовой давности.
Ускоряем обновление данных в два разаКогда ритейлеров было два, система импорта работала примерно так. Скрипт для каждого фида вытаскивал из них информацию, на основе которой обновлялась страница товара на сайте. Скрипты запускались последовательно, и как только оба импорта заканчивались, мы объединяли обновлённую информацию о товарах на sync-сервере и возможные изменения на main-сервере.
В среднем эти два канала обновлялись 3-5 часов. Но клиенту нужно было развивать бизнес и добавлять ритейлеров. Когда мы это сделали, закономерно увеличилось время полного импортирования. В какой-то момент оно выросло до 24 часов, с чем нельзя было мириться.
Как снизить время? Обрабатывать фиды не последовательно, а параллельно. В этом случае мы имеем дело с многопоточностью, когда несколько запросов пытаются одновременно получить доступ к одной и той же информации.
Для описания многопоточности напрашивается аналогия с библиотекой. Посетитель просит книжку, но оказывается, что она есть в одном экземпляре, который кто-то забрал. Придётся ждать, пока книгу вернут. В этой аналогии книга — это страница товара, в которую пишутся данные, а посетители библиотеки — потоки, которые хотят писать данные.
Но Drupal не ждёт, когда вернут книгу, а идёт домой к человеку, который ее читает, и не просто садится читать рядом, но и дописывает что-то в нее. В этом и был конфликт: невозможно предугадать, чьи изменения сохранятся. А нам нужно было сохранить каждое.
Когда мы тестировали обновление для 1000 продуктов, обновлялись только 500-600. В поисках решения мы встроили lock mechanism — «замок», позволяющий контролировать данные и не дающий вмешаться другим процессам, пока данные зависят от текущего.
Рассмотрим абстрактный пример работы lock mechanism. P1 и P2 — это процессы, вносящие изменения в файл.
Работа без lock mechanism. На этапе 3.2 P2 не знает об изменениях со стороны P1, поэтому во время сохранения переписывает изменения, внесённые P1. Проще говоря. без lock mechanism невозможно предугадать, чьи изменения сохранятся.
Работа с lock mechanism. Пока один процесс пишет изменения, второй ждёт свой очереди.В результате мы cнизили время обновления с 26-28 часов до 12-15 часов. В этом нам помогли принципы программирования многопоточных приложений Concurrency и Multithreading.
Защищаем сайт от DDoS-атакСуть DDoS-атак — в огромном количестве запросов, под натиском которых база данных MySQL не справляется со своей работой, и не рассчитанный на такую нагрузку сайт падает. За время работы на проекте атаки случились 3-4 раза. Приятного в этом мало, поэтому мы установили систему для мониторинга и возобновления процессов Monit. Благодаря ей тот или иной процесс или сервис перезапускался спустя 3 минуты после того, как MySQL, Apache или httpd переставали отвечать, и сайт продолжал работать нормально — удобно, если DDoS-атака производится ночью.
Ускоряем загрузку сайтаДо нашего участия PageSpeed Insights показывал 1-2 из 100 на подавляющем большинстве страниц. Сейчас сайт откликается и грузится в разы быстрее прежнего — помогли оптимизация сервера, подключение агрегации css/js и использование технологии Lazy Load для особо тяжелых страниц.
ПерспективыМы сохраняем отношения и разрабатываем новую функциональность. Готова к релизу страница, где перечислена только продукция последнего года. Также в процессе — система глобального поиска по сайту, который понимает, что искал пользователь, и редиректит их на страницы брендов, типов снаряжения и т. п.
Остались вопросы? Задайте их в комментариях.
Коронавирус коснулся всего. На фоне эпидемии и возникших у бизнеса внеплановых проблем в Drupal приняли решение продлить поддержку Drupal 7 до 28 ноября 2022 года, а не до ноября 2021 года, как планировалось ранее. Это большая услуга владельцам 700 тысяч сайтов, у которых нет времени и средств для переноса сайта на старшую версию CMS. На Drupal 8 продление не распространяется: поддержка этой версии закончится в ноябре 2021 года, как и планировалось, так как её срок окончания зависит от срока окончания поддержки Symfony 3.
Что эта фора в 1 год значит для вас как владельца сайта?
ВыгодыЕсли вкратце, то:
Мы как студия веб-разработки оценили ситуацию и увидели в этом возможность успеть сделать то, что откладывалось в прошлом, но поможет укрепить бизнес в будущем.
Не суетитесьВ зависимости от размеров сайта миграция сайта может занять от полугода. При прежнем дедлайне начать её пришлось бы буквально сейчас, но лишний год снижает напряжение, и можно спокойно распланировать бюджет и вдумчивее поискать подрядчиков.
Дождитесь контрибных модулей для Drupal 8Иногда задержаться на Drupal 7 вынуждает то, что некоторые важные модули, поддерживаемые сообществом, пока что не работают на Drupal 8. Поэтому можно либо понадеяться, что разработчики обновят модули, либо писать модуль самому.
На проекте До 16-ти мы используем в нескольких ключевых разделах модуль для платежного шлюза Сбербанка Sberbank rbs payment. Мы зависим от него: без возможности оплаты нет смысла запускать новый сайт.
Другой сценарий — написать свой модуль. Когда выпустили версию Drupal 8, мы обратили внимание, что создатели модуля Biblio, решающего задачи по хранению библиографических данных на сайтах библиотек и институтов, перестали его развивать и не портировали на новую версию CMS. В ответ на это мы выпустили проект Bibliography & Citation, ставший на сегодня единственным инструментом для решения таких специфических задач, если у вас Drupal-сайт.
Проверьте сторонние библиотекиУ вас появилось время изучить сторонние библиотеки, на которых работает ваш сайт, и посмотреть, подойдут ли они к требованиям Drupal 8 и 9. В случае проблем ищите альтернативу, дождитесь обновления или разработайте нужную библиотеку сами.
Снова приведем в пример клинику «До 16-ти». Мы работаем с двумя базами данных: базой клиники на Microsoft SQL и базой сайта на MySQL. Чтобы подключить базы одна к другой, мы использовали PHP-расширение. Оно работает на PHP 5.6, но для нормально работы с Drupal 8 рекомендуется версия PHP не ниже 7.3 . Поэтому нам нужно либо писать новое расширение, либо искать альтернативу.
Мигрируйте сайт частямиЕсли проект большой, а полного бюджета нет, то двух с лишним лет точно хватит, чтобы переносить сайт на новую CMS постепенно, оставляя какие-то части сайта на Drupal 8 или 9, а другие на Drupal 7. Но мы хотим предупредить, что такое решение сулит костыли и может оказаться сложным в реализации.
Уберите лишнееПосмотрите на проект со стороны — возможно, какие-то разделы и функциональность работают на устаревшем коде, который либо можно не тащить на новый сайт, либо отрефакторить. И то, и другое зависит от проекта и нужд.
Перенос сайта с Drupal 7 на старшие версии — это, по сути, полная переделка сайта. Может быть, в этот момент можно задуматься о полном или частичном редизайне? Это шанс переосмыслить проект и довести его до ума.
Посмотрите на сайт с точки зрения accessibilityБудьте реалистом: мы живем в 2020 году, в котором пренебрежение этикой может ударить по кошельку и репутации. Если вы государственная или сотрудничающая с государством компания, то на вас могут подать в суд за сайт, которым не могут пользоваться люди с ограничениями по зрению, слуху, физическим и умственным возможностям.
Пока есть время, оцените свой сайт с точки зрения доступности. Если вы не встречались с этим понятием прежде, то прочитайте серию наших статей, где мы говорим об основных определениях из области accessibility, объясняем их на примерах и касаемся юридической стороны.
Не стоит расслаблятьсяУ продления поддержки Drupal 7 есть свои позитивные моменты, но лучше относиться к этому как ко временной мере. Надо понимать, что Drupal-сообщество расставляет приоритеты в пользу Drupal 8 и Drupal 9, пока что нестабильной и потому требующей скорейших баг-фиксов и новых патч-версий.
Пересев с морально устаревшего Drupal 7 на Drupal 8 или 9, вы сделаете сайт удобнее для пользователей и облегчите себе жизнь при работе с контентом. На уровне функциональности свежая версия CMS ничем не будет отличаться от своего предшественника — нововведения ожидаются с версии 9.1, которая выйдет в декабре 2020 года. А пока что усилия разработчиков направлены на обновления зависимостей от сторонних библиотек и удаление старого кода.
Если вы ищете веб-студию, которая поможет вам с переносом Drupal-сайта, то поиск подошел к концу. Расскажите нам о вашем проекте в письме: hello@adcillc.com.
Подписывайтесь на наш Medium-блог, а также следите за нами на vc.ru, в инстаграме и ВКонтакте.
Пример добавления чекбокса в форму настройки всех блоков меню:
/** * Implements hook_form_FORM_ID_alter(): block_form. */ function MODULENAME_form_block_form_alter(array &$form, FormStateInterface $form_state) { $block_config = $form_state->getFormObject()->getEntity(); /** @var BlockInterface $block_config */ $block_plugin = $block_config->getPlugin(); /** @var BlockPluginInterface $block_plugin */ if ($block_plugin instanceof SystemMenuBlock) { $form['third_party_settings']['MODULENAME']['nofollow'] = [ '#type' => 'checkbox',Похожие записи:
Модуль fasttoggle позволяет быстро, с помощью ajax, менять состояние нод и комментариев.
Модуль fasttoggle активно используется для модерации на друпал.ру и, в рамках перехода друпал.ру на Drupal 8/9, я написал версию для этих версий ядра
Версия для Д8/9 умеет:
Последние комментарии