Как создать свою сборку для MODX

Как и обещал, выкладываю инструкцию — как на основе сборки siteExtra сделать свою сборку. Скачать исходники можно на гитхабе https://github.com/ilyautkin/siteExtra. Полученный архив загружаем на сайт и распаковываем.



И так, сначала давайте придумаем название новой сборки — чтобы всегда сразу знать, что это наш продукт. Представим, что мы пользуемся не бутстрапом, а фреймворком Simpliste. Так и назовём нашу сборку, Simpliste.

Открываем файл /siteExtra-master/_build/build.transport.php и указываем наше название, вместо site. После чего открываем наш файл в браузере.

После этих манипуляций в папке /core/packages/ будет создан транспортный пакет с нашей сборкой. Его можно уже скачать и использовать в работе.

Но нам не нужна копия сборки с новым именем. Поэтому, разберёмся со структурой. Если вы знакомы с modExtra, то ничего нового для себя вы не откроете, так как за основу я брал именно этот компонент.

А если вы еще не разбирались с созданием компонентов, сейчас всё подробно объясню.

В файле build.transport.php вы могли заметить целый список резолверов.
$resolvers = array(
    'providers',
    'addons',
    'rename_htaccess',
    'remove_changelog',
    'cache_options',
    'template',
    'tvs',
    'resources',
    'settings',
    'fix_translit',
    'fix_fastuploadtv',
    'manager_customisation'
);

Это список файлов, которые будут запущены во время установки пакета. В основном, вся логика находится в них. Вы можете написать собственные резолверы и включить их в этот список. Можете убрать из списка любой резолвер — и он не будет выполнен. Сами резолверы хранятся в папке /_build/resolvers/.

Что делает каждый из резолверов?
  • providers — подключает репозиторий modstore.pro. Вы можете прописать здесь подключение любых других репозиториев
  • addons — устанавливает дополнения. В файле для каждого провайдера прописан свой список дополнений (почти в самом конце файла — строки со 129 по 151).
  • rename_htaccess — переименовывает файл ht.access. Если вы пользуетесь связкой nginx и php-fpm, для вас этот резолвер бесполезен. Если же на сервере работает Apache, то ht.access надо переименовать, чтобы заработали дружественные URL.
  • remove_changelog — удаляет файл changelog.txt, чтобы ошибка об угрозе исчезла.
  • cache_options — прописывает в конфиге пример настройки для MemCached. Я стараюсь подключать к сайтам MemCached и, чтобы он нормально заработал, нужно внести изменение в файл config.core.php. Со сборкой мне не нужно запоминать, что и куда прописывать — нужно только раскомментировать эти строки:
  • template — указывает установленный шаблон в качестве шаблона по умолчанию
  • tvs — создаёт ТВ-параметры. Если вам какие-то из ТВ-шек мешают, или, наоборот, захочется добавить ТВ, редактируйте этот файл. В нём есть пример создания ТВ типа FastUploadTV и MIGX.
  • resources — создаёт ресурсы. Тут, думаю, всё понятно.
  • settings — устанавливает значение для системных настроек. Код писался на скорую руку, но я планирую в дальнейшем приводить код в порядок и делать редактирование резолверов проще.
  • fix_translit — создаёт таблицу транслитерации. Этот резолвер можно взять в пример, если надо создать какой-нибудь файл, например, файл импорта из CSV или какой-то нужный скрипт.
  • fix_fastuploadtv — указывает правильный адрес папки /connectors/ для FastUploadTV
  • manager_customisation — создаёт правила кастомизации ресурсов. Здесь вы можете вынести определённые ТВ-параметры на первую вкладку ресурса, например.

Резолверы выполняются в порядке их следования. Поэтому, например, установка дополнений указана первым делом, а создание ресурсов происходит после того, как шаблон был указан в качестве дефолтного.

В нашей сборке ничего из этого менять необязательно. Мы переходим к следующей части.


Помимо резолверов в сборке есть 2 папки — /assets/components/simpliste/ и /core/components/simpliste/ (они были переименованы, когда мы в первый раз запустили файл build.transport.php). Всё, что вы загрузите в эти папки, будет распаковано при установке. Поэтому, файлы фреймворка Simpliste мы загрузим в /assets/components/simpliste/framework/ (на иллюстрации слева)

В папке /core/components/simpliste/elements/chunks/ хранятся все чанки, которые будут установлены. Если вы захотите создать новый чанк, не забудьте прописать его еще и в файле /_build/data/transport.chunks.php

Теперь поправим блоки на сайте — чтобы вёрстка соответствовала используемому фреймворку.

Вот, какие изменения я внёс в чанки и в шаблон:

Кроме чанков и шаблонов в сборке присутствуют плагины и сниппет. Так что работа далеко не ограничивается только вёрсткой.

Вот конечный вариант — Сборка Simpliste-1.2.0-beta.transport.zip

Предлагаю в комментариях выкладывать свои варианты сборки, чтобы все могли ими пользоваться.
Илья Уткин
08 августа 2016, 18:42
50
3 117
+20

Комментарии: 24

Андрей Сухомозгий
08 августа 2016, 23:10
0
Очень здорово!
Илья, а подскажи вот такой момент. У тебя один шаблон всего идет в сборке и написано, что ресолвер «указывает установленный шаблон в качестве шаблона по умолчанию». А если я несколько шаблонов создам и захочу какой-то из них сделать по умолчанию? Я смотрю код и не понимаю как ресолвер понимает какой ему шаблон взять и сделать по умолчанию…
Петр
09 августа 2016, 08:13
+1
Слушай, а как запаковать уже скачанный пакет, и потом его установить, т.е чтобы из репозитория не качать?
    Илья Уткин
    09 августа 2016, 09:50
    0
    Нужно написать свой резолвер (наверное, на основе resolve.addons.php). Готового решения у меня нет.
Павел
09 августа 2016, 16:25
0
На тестовом сайте modhost долго компоненты ставятся и это больше минуты примерно занимает… Приходится несколько раз пробовать устанавливать свой пакет, пока все компоненты не будут установлены…
    Илья Уткин
    09 августа 2016, 16:35
    +3
    У меня такая ерунда была, если выбран Белорусский сервер. Попробуйте Hetzner выбрать при создании сайта
    Владимир
    10 августа 2016, 07:29
    0
    Проверил, быстро все встало, точно как установка любого другого пакета. Сервер h5.modhost.pro (Hetzner, Deutschland)
Павел
20 октября 2016, 02:18
0
Кто-нибудь в курсе, как это лечится?\
При установки пакета такая ошибка выскакивает
xPDOVehicle does not support resolvers of type
Алексей
02 декабря 2016, 12:25
0
Доброго времени суток! А есть возможность сделать выбор устанавливаемых tv/шаблонов/чанков/ресурсов/дополнений при установке данного дополнения? В частности изменяю эту сборку под свои нужды, и было бы очень удобно выбирать что установить чекбоксами, как в дополнении modmysettings
    Илья Уткин
    02 декабря 2016, 13:45
    0
    Такой функционал есть в планах, но когда я приступлю к его разработке — я не знаю, пока времени нет
Alexandr
14 декабря 2016, 11:26
0
Подскажите
'CKEditor' => '1.3.0-pl',
		            'Collections' => '3.4.2-pl',
		            'Console' => '2.1.0-beta',
		            'FastUploadTV' => '1.0.0-beta2',
		            'MIGX' => '2.9.6-pl',
		            'translit' => '1.0.0-beta',
		            'VersionX' => '2.1.3-pl'
Версии дополнений указывать обязательно? Что делать если вышла новая версия создавать новый пакет?
    Илья Уткин
    14 декабря 2016, 16:58
    0
    Это минимальные версии. Качаться всегда будет последняя версия.
Aleksandr Huz
04 января 2017, 19:04
0
Добрый день, Илья!

Хочу чтобы чанки помещались в указанные каталоги.
В файле transport.chunks.php
пишу такой код:
$ifCategory = $this->modx->getObject( 'modCategory', array('category' => $v['category']) );
$getCategory = $ifCategory->get('category');
if( $getCategory === '' ){
    $category = $this->modx->newObject('modCategory');
    $category->set('category', $v['category']);
    $category->save();
    $id_category = $category->get('id'); 
} else {
    $id_category = $ifCategory->get('id');
}
на что сборщик выдает ошибку
Fatal error: Call to a member function get() on a non-object
Подскажи, пожалуйста, как решить эту проблему.
    Илья Уткин
    09 января 2017, 10:04
    0
    Если категории не существует, то вторая строчка выдаёт такую ошибку. Проверять на существование категории можно прям в первой строке:
    if(!$ifCategory = $this->modx->getObject('modCategory', array('category' => $v['category']))){
        $category = $this->modx->newObject('modCategory');
        $category->set('category', $v['category']);
        $category->save();
        $id_category = $category->get('id'); 
    } else {
        $id_category = $ifCategory->get('id');
    }
Анатолий
20 марта 2018, 11:31
0
Друзья, а как включить в сборку собственный транспортный пакет который не находится в репозитории?
    Илья Уткин
    20 марта 2018, 16:07
    1
    0
    Создать свой приватный репозиторий и разместить пакет в нём.

      Анатолий
      20 марта 2018, 17:09
      0
      А без репозитория? Локально. Задать как-то путь к транспортнику
        Илья Уткин
        21 марта 2018, 12:23
        0
        Я такого способа не знаю.
          Анатолий
          21 марта 2018, 14:37
          +1
          Анатолий
          22 марта 2018, 21:05
          0
          То есть к $addons добавить еще один массив с локальными пакетами:
          array(
          		'type'			=> 'transport',
          		'path'			=> '/packages/', // путь до локальных пакетов
          		'packages'		=> array(
          			'lightboxgal'	=> array(
          				'version'		=> '1.1.2-pl',
          				'install'		=> true,
          			),
          			'youtubepreview'	=> array(
          				// 'path'			=> '/packages/', // можно указать путь здесь, переопределив тот, который выше
          				'version'		=> '1.0.0-pl',
          				'install'		=> true,
          			),
          		),
          	),
          А дальше в резольвере обработать этот массив типа как тут:

          foreach( $providers as $prov )
          {
          	$transport = (!empty($prov['type']) && $prov['type'] == 'transport') ? true : false;
          
          	if(!$transport && !$provider = $modx->getObject('transport.modTransportProvider', array('service_url' => $prov['service_url'])))
          	{
          		$provider = $modx->newObject('transport.modTransportProvider');
          		$provider->fromArray($prov);
          		$provider->save();
          	}
          
          	if(!$transport) {
          		$provider->getClient();
          	}
          
          	foreach( $prov['packages'] as $packageName => $data )
          	{
          		$install = $transport
          			? $data['install']
          			: $data;
          
          		$params = array();
          
          		if(!$transport)
          		{
          			$response = $provider->request('package', 'GET',
          				array(
          					'query' => $packageName
          			));
          			if(!empty($response))
          			{
          				$foundPackages = simplexml_load_string($response->response);
          				if($foundPackages['total'] > 0)
          				{
          					foreach($foundPackages as $foundPackage)
          					{
          						if(strtolower((string)$foundPackage->name) == strtolower($packageName))
          						{
          							$params = array(
          								'package_name'	=> (string)$foundPackage->name,
          								'signature'		=> (string)$foundPackage->signature,
          								'location'		=> $foundPackage->location,
          							);
          						}
          					}
          				}
          				else {
          					_print('Not found: "'. $packageName .'"');
          				}
          			}
          		}
          		else if($transport)
          		{
          			$path = !empty($data['path'])
          				? $data['path']
          				: $prov['path'];
          
          			$signature = $packageName .'-'. $data['version'];
          			$location = $path . $signature .'.transport.zip';
          
          			if(file_exists($location))
          			{
          				$params = array(
          					'package_name'	=> $packageName,
          					'signature'		=> $signature,
          					'location'		=> $location,
          				);
          			}
          		}
          
          		if(!empty($params))
          		{
          			packageSaveInstall(array_merge(
          				$params,
          				array(
          					'provider'	=> is_object($provider) ? $provider->id : '0',
          					'install'	=> $install ? $install : 0,
          				)
          			));
          		}
          	}
          }
Алексей Бгатов
20 марта 2018, 17:13
1
+3
я пошел по другому пути и вполне норм вроде…
у меня на локалке развернут сайт build...ru, и он заряжен всем базовым из обоих репозиториев, и всеми настройками — системными, визуальными, структурными, htaccess, метатеги, роботс, 404, в общем, все, что так или иначе приходится делать на всех сайтах. Там же, на локалке, я поддерживаю сам модекс и все дополнения в последней версии. И когда новый сайт — тупо заливаю дамп на хостинг, меняю доступы к репозиторию modstore и парольку, и можно работать без предварительной нудятины.
SEQUEL.ONE
23 марта 2018, 21:54
0
Подскажите, а как в ресольвере создать новую системную настройку?