API миграции в Drupal позволяет «тащить» данные из разных источников, но работает это на базе контрибных модулей, т.е. не из коробки.
Например, модуль migrate_source_csv добавляет возможность добавить CSV файл как источник данных.
Создание каких то простых миграций обычно не вызывает сложностей. Но обычно требуется тянуть весьма сложный контент, например, с попутным созданием параграфов, или добавлением reference entity типа media поля и т.п.
Также неплохо бы иметь возможность выбирать файл CSV, используя форму в админке, а не прописанное значение в конфиг файле. (Из коробки предлагается запускать миграцию через drush.)
Ну и раз процесс этот не быстрый, то при запуске миграции хотелось бы видеть линейку прогресса и прочие прелести цивилизованной миграции.
Понадобится такой набор плагинов (они активируют за одно нужные плагины из ядра):
- migrate_plus
- migrate_source_csv
- migrate_tools
Начнем с описания тестового кейса.
Описание входных данных
У нас есть CSV файл со следующими полями:
- id — айди статьи
- title — заголовок
- date — дата в формате Y-m-d
- category — термин, содержит название одной категории
- tags — термины, перечислены через запятую, это теги статьи
- thumbnail — url на картинку
- summary — тизер, краткое описание статьи
- body — html текст статьи, может содержать изображения в виде тега <img>
Поле body подразумевает необходимость обработки текста, для того чтобы локализовать (скопировать и зарегистрировать в Drupal) картинки, которые есть в теле статьи. HTML код этих картинок нужно будет заменить.
Описание приёмника данных
Я мигрирую данные в node:blog. Т.е. мне нужно создать новую публикацию для каждой статьи из источника. При этом картинка должна встать в field_blog_image типа media reference (bundle: image).
Текст статьи должен превратится в параграф. В моем случает это параграф с машинным именем bp_simple, который помимо разных простых полей, имеет поле форматированного текста, куда и должен попасть исходный HTML. В node создано поле field_blog_components, оно как раз и является reference field для параграфов.
Кастомные обработчики (process plugins)
При некоторой сноровке и танцах с бубном, можно попробовать обойтись существующими обработчиками, но мне удобнее (в плане контроля и функционала) было написать несколько небольших обработчиков, которые будут помогать при миграции.
Всего их три:
term_generate
Размещается в /src/Plugin/migrate/process/TermGenerate.php
Основная задача — по входному текстовому значению создать/найти термин в указанном словаре и вернуть его в виде [‘target_id’ => TERMID] массива.
media_generate
Размещается в /src/Plugin/migrate/process/MediaGenerate.php
Создаёт по переданной URL — последовательно File entity, далее Media entity, и возвращает последний в виде MEDIAID.
Для файла можно задать папку в public://, где будет создаваться файл. При этом если такой файл уже есть, то будет использован существующий. Для Media требуется указать bundle, а также field, куда будет сохранять ссылка на файл. Опять же, если Midia entity с указателем на файл уже существует — то плагин вернет эту сущность, вместо создания новой.
file_allocation
Размещается в /src/Plugin/migrate/process/FileAllocation.php
Наиболее сложный обработчик из рассмотренных.
Он принимает HTML текст и просматривает его на наличие изображений. Если изображение размещено на указанном домене (либо если используется относительная корневая ссылка), то выполняется «локализация» картинки.
В процессе «локализации» картинка копируется (если еще не была скопирована ранее) и старое изображение в тексте заменяется рендером скопированной картинки.
Этапы миграции
По идее, нам требуется выполнить две миграции — сначала создать параграфы, а потом прикрепить их к создаваемым статьям блога. Поэтому у нас будет две конфигурации для миграции данных.
Основной файл будет указывать на то, что у нас есть зависимость от миграции параграфов и Migration API пройдется сначала по дочерним миграциям.
Основной файл миграции
Миграция параграфов.
Источник данных — файл, указанный пользователем, нужно будет подставить в обе конфигурации.
Отладка и работа с конфигурациями миграции
На начальном этапе я выполняю drush cex, чтобы получить конфигурацию сайта в виде набора файлов (где она у вас настроена). Там я создаю файлы, начинающиеся с migrate_plus.migration.
И каждый раз для актуализации правок выполняется drush cim.
Отлаженные файлы конфигурации миграций можно впоследствии добавить в /config/install вашего модуля (удалив uuid).
Обычно этот процесс описывается в документации иначе, предлагается создать конфигурацию через импорт, что тоже рабочая схема, но редактировать в таком случае довольно не удобно.
/admin/config/development/configuration/single/import