Организуем библиотеки и патчи в drupal-проекте
Работа с патчами.
Если у вас более-менее стабильный набор патчей под проекты, имеет смысл выделить их в отдельный файл. Делается это довольно элементарно: с помощью https://github.com/cweagans/composer-patches .
Достаточно сделать: composer require cweagans/composer-patches, а потом добавить в свой composer.json:
"extra": {
"patches-file": "composer.patches.json",
"enable-patching": true
...
И создать файл composer.patches.json, в котором указать требуемые патчи, например:
{
"patches": {
"drupal/core": {
"Fix images link problem": "https://www.drupal.org/files/issues/2018-09-11/edit_drupalimage-86x-2855521-27.patch"
},
"drupal/features": {
"Fix features-import-all bug": "https://www.drupal.org/files/issues/2018-04-16/fix-features-import-all-2961007.patch",
"Fix unicode error": "https://www.drupal.org/files/issues/2018-08-15/2992790-drupal-component-namespace-case.patch"
},
"drupal/colorbutton": {
"issue:#2919123#comment-12393742": "https://www.drupal.org/files/issues/2919123.patch"
},
"drupal/ckeditor_font": {
"issue#2900789#comment-12501946": "https://www.drupal.org/files/issues/ckeditor_font_8_1_0_libraries_integration_01.patch"
}
}
}
Вуаля, при следующем composer update/install патчи будут применяться, а мы в git истории будем легко отслеживать именно правку файла с патчами.
Работа с библиотеками
Мы хотим складывать все js-зависимости (слайдеры, colorbox, и т.п.) в отдельную папку libraries и хранить это в composer-файле. Сделать это очень просто: сначала убедимся что стоит composer/installers. Для этого сделаем composer require composer/installers .
После чего в разделе "installer-paths" вашего composer.json укажите путь куда складывать библиотеки:
"installer-paths": {
"core": ["type:drupal-core"],
"modules/contrib/{$name}": ["type:drupal-module"],
"modules/custom/{$name}": ["type:drupal-custom-module"],
"modules/features/{$name}": ["type:drupal-custom-feature"],
"profiles/contrib/{$name}": ["type:drupal-profile"],
"themes/contrib/{$name}": ["type:drupal-theme"],
"drush/contrib/{$name}": ["type:drupal-drush"],
"themes/repository/{$name}": ["type:drupal-custom-theme"],
"libraries/{$name}": ["type:drupal-library"]
}
А именно: добавить строчку "libraries/{$name}": ["type:drupal-library"] .
Далее, т.к. библиотек много, нам бы хотелось хранить пути к ним в отдельном файле, для этого нам нужно убедиться что он стоит (вообще должен, для composer-based drupal-инсталляции он уже включен. Честно говоря не помню как было с ранними версиями 8.x ядра, но в новых уже есть): composer require wikimedia/composer-merge-plugin . Т.е. установить плагин https://github.com/wikimedia/composer-merge-plugin, он позволяет разделить composer.json файл на несколько составляющих (в т.ч. сделать файл с отдельным списком репозиториев). После чего, в composer.json нужно добавить:
"merge-plugin": {
"include": [
"core/composer.json",
"composer.libraries.json"
],
"recurse": false,
"replace": false,
"merge-extra": false
},
А именно, мы добавили "composer.libraries.json", в котором нужно указать все наши библиотеки. Пример нашего типового (да, он довольно большой, но может кому пригодится, т.к. там чаще всего используемый UI-контриб).
{
"repositories": [{
"type": "package",
"package": {
"name": "ckeditor/colorbutton",
"type": "drupal-library",
"version": "4.10.0",
"dist": {
"url": "https://download.ckeditor.com/colorbutton/releases/colorbutton_4.10.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/panelbutton",
"type": "drupal-library",
"version": "4.10.0",
"dist": {
"url": "https://download.ckeditor.com/panelbutton/releases/panelbutton_4.10.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/font",
"type": "drupal-library",
"version": "4.10.0",
"dist": {
"url": "https://download.ckeditor.com/font/releases/font_4.10.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "kenwheeler/slick",
"type": "drupal-library",
"version": "1.8.0",
"dist": {
"url": "https://github.com/kenwheeler/slick/archive/1.8.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "bgrins/spectrum",
"type": "drupal-library",
"version": "1.8.0",
"dist": {
"url": "https://github.com/bgrins/spectrum/archive/1.8.0.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "recurser/jquery-simple-color",
"type": "drupal-library",
"version": "1.2.2",
"dist": {
"url": "https://github.com/recurser/jquery-simple-color/archive/v1.2.2.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "algolia/places",
"version": "1.9.0",
"type": "drupal-library",
"extra": {
"installer-name": "algolia.places"
},
"dist": {
"url": "https://registry.npmjs.org/places.js/-/places.js-1.9.0.tgz",
"type": "tar"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/autogrow",
"version": "4.10.0",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.autogrow"
},
"dist": {
"url": "https://download.ckeditor.com/autogrow/releases/autogrow_4.10.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/codemirror",
"version": "v1.17.5",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.codemirror"
},
"dist": {
"url": "https://github.com/w8tcha/CKEditor-CodeMirror-Plugin/releases/download/v1.17.5/CKEditor-CodeMirror-Plugin.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/fakeobjects",
"version": "4.10.0",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.fakeobjects"
},
"dist": {
"url": "https://download.ckeditor.com/fakeobjects/releases/fakeobjects_4.10.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/image",
"version": "4.10.0",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.image"
},
"dist": {
"url": "https://download.ckeditor.com/image/releases/image_4.10.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/link",
"version": "4.10.0",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.link"
},
"dist": {
"url": "https://download.ckeditor.com/link/releases/link_4.10.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "codemirror/codemirror",
"version": "5.39.2",
"type": "drupal-library",
"extra": {
"installer-name": "codemirror"
},
"dist": {
"url": "https://github.com/components/codemirror/archive/5.39.2.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/geocomplete",
"version": "1.7.0",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.geocomplete"
},
"dist": {
"url": "https://github.com/ubilabs/geocomplete/archive/1.7.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/icheck",
"version": "1.0.2 ",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.icheck"
},
"dist": {
"url": "https://github.com/fronteed/icheck/archive/1.0.2.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/inputmask",
"version": "4.0.0",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.inputmask"
},
"dist": {
"url": "https://github.com/RobinHerbots/jquery.inputmask/archive/4.0.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/intl-tel-input",
"version": "13.0.0",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.intl-tel-input"
},
"dist": {
"url": "https://github.com/jackocnr/intl-tel-input/archive/v13.0.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/rateit",
"version": "1.1.1",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.rateit"
},
"dist": {
"url": "https://github.com/gjunge/rateit.js/archive/1.1.1.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/select2",
"version": "4.0.5",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.select2"
},
"dist": {
"url": "https://github.com/select2/select2/archive/4.0.5.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/textcounter",
"version": "0.8.0",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.textcounter"
},
"dist": {
"url": "https://github.com/ractoon/jQuery-Text-Counter/archive/0.8.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jquery/timepicker",
"version": "1.11.13",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.timepicker"
},
"dist": {
"url": "https://github.com/jonthornton/jquery-timepicker/archive/1.11.13.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "progress-tracker/progress-tracker",
"version": "1.4.0",
"type": "drupal-library",
"extra": {
"installer-name": "progress-tracker"
},
"dist": {
"url": "https://github.com/NigelOToole/progress-tracker/archive/v1.4.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "signature_pad/signature_pad",
"version": "2.3.0",
"type": "drupal-library",
"extra": {
"installer-name": "signature_pad"
},
"dist": {
"url": "https://github.com/szimek/signature_pad/archive/v2.3.0.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
},
{
"type": "package",
"package": {
"name": "jackmoore/colorbox",
"version": "2.3.0",
"type": "drupal-library",
"extra": {
"installer-name": "colorbox"
},
"dist": {
"url": "https://github.com/jackmoore/colorbox/archive/master.zip",
"type": "zip"
},
"require": {
"composer/installers": "~1.0"
}
}
}
]
}
Обратите внимание, в некоторых указан параметр "extra": { "installer-name": "algolia.places" }, он сообщает, что нужно директорию в libraries назвать определенным образом. Т.е. у нас будет /libraries/algolia.places/ каталог, т.к. именно такой путь указан в drupal-модуле который требует эту библиотеку и именно в данный путь мы ее будем разворачивать.
После чего нам достаточно указать все эти библиотеки как зависимости (установить т.е), набрав composer require ckeditor/colorbutton ckeditor/panelbutton (и все остальные).
Можно разбить это на небольшие файлы и хранить в конкретных кастомных модулях. Например если вам для фичи нужна конкретная js-библиотека, логично хранить эту зависимость в composer.json фичи. Для этого, добавляем в глобальный composer.json:
"merge-plugin": {
"include": [
"core/composer.json",
"composer.libraries.json",
"modules/custom/*/composer.json",
"modules/features/*/composer.json",
"modules/repository/*/composer.json"
],
"recurse": true,
"replace": false,
"merge-extra": true
},
Теперь вы можете хранить зависимости внутри фичи, пример нашей фичи с настройками ckeditor:
{
"name": "radon_features/ckeditor_editor_settings",
"type": "drupal-custom-feature",
"description": "Ckeditor default settings for editor role",
"license": "GPL-2.0+",
"homepage": "https://git.ra-don.com/radon_features/ckeditor_editor_settings",
"minimum-stability": "dev",
"require": {
"composer/installers": "^1.3",
"radon_modules/ckawesome": "dev-master",
"drupal/ckeditor_font": "^1.0",
"drupal/ckeditor_tabletoolstoolbar": "^1.0",
"drupal/ckeditor_tableselection": "^1.0",
"drupal/ckeditor_tableresize": "^1.0",
"drupal/ckeditor_uploadimage": "^1.3",
"drupal/ckeditor_youtube": "^1.0",
"drupal/colorbutton": "^1.0",
"drupal/panelbutton": "^1.0",
"ckeditor/autogrow": "^4.10",
"ckeditor/codemirror": "^1.17",
"ckeditor/colorbutton": "^4.10",
"ckeditor/fakeobjects": "^4.10",
"ckeditor/font": "^4.10",
"ckeditor/image": "^4.10",
"ckeditor/link": "^4.10",
"ckeditor/panelbutton": "^4.10",
"ckeditor/tableresize": "^4.7",
"ckeditor/tableselection": "^4.7",
"ckeditor/tabletoolstoolbar": "^0.0.1"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
},
{
"type": "composer",
"url": "https://repo.ra-don.ru"
},
{
"type": "package",
"package": {
"name": "ckeditor/tabletoolstoolbar",
"version": "0.0.1",
"type": "drupal-library",
"dist": {
"url": "https://download.ckeditor.com/tabletoolstoolbar/releases/tabletoolstoolbar_0.0.1.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/tableselection",
"version": "4.7.2",
"type": "drupal-library",
"dist": {
"url": "https://download.ckeditor.com/tableselection/releases/tableselection_4.7.2.zip",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name": "ckeditor/tableresize",
"version": "4.7.2",
"type": "drupal-library",
"dist": {
"url": "https://download.ckeditor.com/tableresize/releases/tableresize_4.7.2.zip",
"type": "zip"
}
}
}
]
}
Вариант с asset-packagist
Можно делать проще и не хранить все пути в composer.libraries.yml, а воспользоваться готовым репозиторием https://asset-packagist.org/ . Что для этого нужно:
- Убедиться что стоит installers extender:
composer require oomphinc/composer-installers-extender
- Добавить репозиторий в раздел repositories вашего composer.json
"repositories": { { "type": "composer", "url": "https://asset-packagist.org" } }
- Добавить нужные типы/пути в composer.json
"extra": { "installer-types": [ "npm-asset", "bower-asset" ], "installer-paths": { "web/libraries/{$name}": [ "type:drupal-library", "type:npm-asset", "type:bower-asset" ] } }
Примечание: вы тут же можете указать нужный каталог для распаковки (мало ли, разработчик модуля для drupal.org решил писать в нестандартный путь. Но вообще разработчику модуля хорошо бы при обнаружении написать об этом. Тем не менее возможность есть:
"extra": { "installer-paths": { "web/libraries/chosen": ["npm-asset/chosen-js"], "web/libraries/{$name}": [ "type:drupal-library", "type:npm-asset", "type:bower-asset" ] } }
Для пакета npm-asset/shosen.js он будет поставлен в web/libraries/chosen
-
Все, ставите нужную библиотеку как обычный пакет, указывая либо точную версию, либо минимальную:
composer require npm-asset/chosen-js:1.8.0 или composer require npm-asset/chosen-js:^1.8