MODX Evolution is dead long live Evolution CMS on Laravel components

Что такое Evolution CMS 2.0?Этот все тот же MODX Evolution, вот только под капотом будет уже не просто набор каких-то разрозненных функций, объединенных в класс под названием DocumentParser, а целый ряд компонентов, тех самых на которых собран и фреймворк Laravel. Это позволяет нам не писать кучу новой документации и примеров про кешер, события, логирование, файловую систему, кофиги, консоль, миграции, сиды, шаблонизатор Blade, модели Eloquent, Observers, ServiceProvider…

evo1

evo2
evo3

evo4

Немного истории — Разработчики Рэймонд Ирвинг (англ. Raymond Irving) и Райан Траш (англ. Ryan Thrash) представили первый релиз MODX CMS в 2004 году.
— С 2012 Года после выхода MODX Revolution, версия Evolution командой разработки MODX LLC больше не поддерживается, но при этом активно развивается силами сообщества MODX Evolution, не уступая в развитии новой ветке.
— В марте 2013 выходит релиз 1.0.9 ( habr.com/post/173667/ ), который создан исключительно силами сообщества, под руководством Дмитрия Лукьяненко и Евгения Борисова (продолжающих работать над Evo и по сей день). Но релизы все еще выходят под эгидой MODX LCC (с публикацией на modx.com).
— В апреле 2017 MODX LCC приняли решение полностью отказаться от продвижения MODX Evolution ( modx.com/blog/evolution-cms-has-a-new-home ). И с этих пор нашей командой был выбран свой собственный курс развития, не ставящий целью гонку за MODX REVO, как это было ранее.
— В июле 2017 выходит первый релиз Evolution CMS 1.3.0 github.com/evolution-cms/evolution/releases/tag/1.3.0 с полностью переработанным дизайном и целым рядом новых возможностей, воплотивших пожелания сообщества.
— В ноябре на конференции MODXpo 2017 Лукьяненко Дмитрий успешно выступает с докладом о делах в Evolution CMS (https://modcasts.video/videos/evo-cms-life-after-modx).
— Январь 2018. Выход второго крупного релиза Evolution CMS 1.4.0 ( github.com/evolution-cms/evolution/releases/tag/1.4.0 ), кардинально изменившим ряд подходов в разработке.
— Июнь 2018. Принято решение о том чтобы переписать Evolution CMS с использованием компонентов Laravel, но с обязательным условием сохранения полной обратной совместимости.
— Декабрь 2018. Состоялся первый релиз Evolution CMS 2.0.

Очень важным моментом было условие обратной совместимости со старыми версиями системы и у нас это получилось! Можно смело обновить сайт с версии 0.9.6 выпущенной в 2005 году до новой 2.0. Поправить придется только тот код который был написан без учета API системы. Все стандартные дополнения также обновляются и функционируют на новой версии.

Почему именно Laravel?Обширная документация. Активная поддержка. Множество готовых пакетов, которые можно будет использовать и на Evolution 2.0 Изначально мы видели лишь два пути: работать и дальше с устаревшим кодом Evolution, пока это пипл хавает, а сообщество не разбежалось, либо же начать писать новый проект стараясь максимально сохранить старую парадигму разработки с деревом ресурсов, чанками, сниппетами, ТВ параметрами и т.д. Но мы нашли третий вариант в котором понемногу адаптируем устаревший код, сохраняя при этом обратную совместимость.

В ветке 2.0 можно будет работать по старому?Да, можно. Старые конструкции будут и дальше работать, но всю гибкость нововведений вряд ли раскроют. Банальный переход от массива $modx->config к методу $modx->getConfig() уже позволит манипулировать системными настройками движка, которые берутся из базы. А совершить такой переход в сниппетах можно уже сейчас, не обновляясь до версии 2.0, т.к. метод getConfig() есть и в версии 1.4. Плагины на события можно вешать как раньше через админку или через файлы. Все это совершенствует командную разработку, упрощает ведение проекта через git. Разработчики оценят удобство, для остальных внешние изменения не будут столь значительными.

Под EVO мало готовых решений. Не лучше ли было потратить время на их разработку вместо нового релиза?Разработчиков, которые способны написать более или менее вменяемое дополнение в сообществе осталось довольно неммного. Многим просто надоело говнокодить и изобретать велосипеды чтобы поддерживать проблемы старых версий.

Даже если рассматривать на примере файловой системы, то есть целый ряд проблем: нет возможности работать с файлами (копировать, перемещать, удалять) и все это рекурсивно с правильной расстановкой прав которые выставлены в настройках движка. При работе с базой мы вынуждены постоянно заботиться об sql-injection, т.к. зачастую работа происходит с сырыми данными. При работе с шаблонами мы вообще ничего не можем — даже стандартный метод parseChunk по умолчанию не понимает плейсхолдеров. Таким образом, вместо того, чтобы разработчик мог сосредоточиться на бизнес логике приложения, он тратит кучу времени на то, чтобы реализовать одни и те же вещи. А потом этот разработчик выпускает еще одно решение и там опять нужно сделать эти же вещи. Так появляется копипаст, который приводится к использованию однотипных классов/функций/методов в разных компонентах — яркий пример phx.

В общем не для 2018 года такие методы разработки. Таким образом, в Evo очень мало людей, которые бы могли что-то толковое написать и поделиться решением. Поэтому прежде чем писать какие-то компоненты, мы хотим решить все эти проблемы и дать больше свободы разработчикам.

Зачем мне изучать что то новое а не оставаться на 1.4 ?На версии 1.4 мы не можем установить целый сайт 1 кнопкой. Не можем работать в дев-прод версии адекватно, не можем, полноценно использовать шаблоны в файлах. Нет миграций и т. д. В версии 2.0 это все есть. Это как переход от нативных sql запросов на модели.Те, кто работает с моделями в разных фреймворках прекрасно понимают в чем преимущество. Те, кто не умеют работать делают SELECT/INSERT/UPDATE прямо в базу и считают это нормой.

Понять принципы работы в EVO можно за пару вечеров, а все остальные знания которые нужны для работы с EVO нужны также и для работы с Laravel. Теперь не нужно отдельно учить что то, что пригодиться только при использованиии EVO. Это даст универсальную возможность легко работать с EVO зная Laravel и легко переходить к Laravel, работая с EVO.

А так ли все просто и можно ли использовать готовые компоненты от Laravel?Вот есть пакет для генерации схемы таблиц в базе (https://github.com/beyondcode/laravel-er-diagram-generator) Установка это composer require, и создание файла провайдера(core/custom/config/app/providers/Diagram_Generator.php) из 1 строчки:
return BeyondCode\ErdGenerator\ErdGeneratorServiceProvider::class;

Все!

Ближе к делу:
Новые настройки и первые плюсы — Вся папка core/config и core/custom/config уже работает с конфигами в стиле Laravel. Для задействования .env файла необходимо установить пакет vlucas/phpdotenv

— Работа с Composer: добавление зависимостей в core/custom/composer.json и выполнение composer upd из папки core

— Для удобства работы включим инструменты для отладки: Debug и debugbar Tracy
— Debug: cоздаем файл core/custom/config/app/debug.php с содержимым:
<?php 
		return true;

— Функция dump которая показывает информацию в красивом виде:
<?php 
		dump($modx);

— Папка с логами ошибок core/storege/logs
— Tracy: cоздаем файл core/custom/config/tracy/active.php с содержимым:
<?php 
		return 'manager';

tracy

Работа с Шаблонами и Чанками с использованием шаблонизатора BLADE из файлов без использования админки

Привязка шаблонов к документу без необходимости заходить в админку EVOДля работы нам потребуется создать папку views в корне сайта, в которой у нас будут располагаться шаблоны. Собственно и все, никаких дополнительных действий в виде установки чего-либо не требуется.

Evo будет искать шаблоны в следующем порядке:
— tpl-3_doc-5.blade.php — используется для ресурса с id 5 и шаблоном 3;
— doc-5.blade.php — используется для ресурса с id 5;
— tpl-3.blade.php — используется для всех ресурсов с шаблоном 3.

Работа со стандартными элементами посредством шаблонизатора BLADEПрежде чем приступать к работе с BLADE настоятельно рекомендуем ознакомиться с документацией BLADE: laravel.com/docs/5.7/blade
//Вывести плейсхолдер [*pagetitle*]:
{{ $documentObject['pagetitle'] }}
{{ $modx->documentObject['pagetitle'] }}

//Вывести плейсхолдер TV
{{ $documentObject['image'] }}
{{ $modx->documentObject['image']['1'] }}

//Вывести урл [~2~]
{{ urlProcessor::makeUrl('2') }}
{{ $modx->makeUrl('2') }}
@makeUrl('2')

//Вывести системную настройку [(site_name)]
{{ $modx->getConfig('site_name') }}

//Вывести чанк из базы: {{chunkFromDb}}
{{ $modx->getChunk('chunkFromDb') }} 

//Вывести чанк из файла: (/views/partials/chunk.blade.php)
@include('partials.chunk', ['some' => 'data'])

//Вывести сниппет:  
{{ $modx->runSnippet('DocInfo',['docid' => '2']) }}

//Вывести результат работы снипета не экранируя html теги  
{!! $modx->runSnippet('DocInfo',['docid' => '2']) !!}

//Стандартный парсер
@evoParser('[*pagetitle*] [(site_name)]  {{chunkOld}}')

//Использование комментариев 
{{-- Этого комментария не будет в итоговом HTML --}}

//Обработка в цикле и IF (Все из документации по BLADE):
@for ($i = 1; $i <= 10; $i++)
  {{ $i }}
  @if ($i != 10)
  , 
  @endif
@endfor

//Работа с php внутри шаблона (настоятельно не рекомендуюется)
@php
  dump($modx); //красивый var_dump
  $chunk = '{{ $data["param1"] }}';
  $chunk .= '{!! $data["param1"] !!}';
@endphp
//или
<?php
  dump($modx); //красивый var_dump
  $chunk = '{{ $data["param1"] }}';
  $chunk .= '{!! $data["param1"] !!}';
?>

{{ $modx->tpl->parseChunk('@B_CODE:'.$chunk, ['param1' => 'value with "quote"']) }}
{{ time() }}

//Докликстер с использованием инлайновой шаблонизации на BLADE
{!! $modx->runSnippet('DocLister',['parents' => '0', 'tpl' => '@B_CODE:{{ $data["pagetitle"] }}<br />']) !!}

//Докликстер с использованием шаблонизации на BLADE из файла (/views/partials/doc-tpl.blade.php)
{!! $modx->runSnippet('DocLister',[
  'parents' => '2', 
	'tpl' => '@B_FILE:partials/doc-tpl',
	]) 
!!}


Пример готового шаблона с использованием BLADE можно глянуть тут: github.com/dmi3yy/Evo-demosite-on-blade

Работа со сниппетами и плагинами из файлов без использования админки, а также использование событий LaravelВ Evolution 2.0 вводим новую сущность package. Это пакет дополнений который может включать в себя сниппеты, плагины, чанки, модули. Модули пока требуют прописывать себя через админку, но в будущем переделаем, чтобы автоматически подтягивались, также как и все остальные элементы.

1. Создадим наш пакет(example):
Создадим файл: core/custom/packages/example/src/ExampleServiceProvider.php
<?php namespace EvolutionCMS\Custom;

use EvolutionCMS\ServiceProvider;
use Event;

class ExampleServiceProvider extends ServiceProvider
{
    /**
     * Если указать пустую строку, то сниппеты и чанки будут иметь привычное нам именование
     * Допустим, файл test создаст чанк/сниппет с именем test
     * Если же указан namespace то файл test создаст чанк/сниппет с именем example#test
     * При этом поддерживаются файлы в подпапках. Т.е. файл test из папки subdir создаст элемент с именем subdir/test
     */

    protected $namespace = 'example';

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->loadSnippetsFrom(
            dirname(__DIR__). '/snippets/',
            $this->namespace
        );

        $this->loadChunksFrom(
            dirname(__DIR__) . '/chunks/',
            $this->namespace
        );
	//Тут работаем с событиями как EVO так и Laravel:
        Event::listen('evolution.OnWebPageComplete', function($params) {
            echo '<p>Hello Evo events.</p>';
        });
	
	
    }
}


И так мы добавили наш пакет в котором указали пространство имен для сниппета, что дает нам возможность использовать одинаковые сниппеты из разных пакетов, не переживая за то что они будут конфликтовать. Тут же прописываем прослушку событий (плагины) и указываем папку для чанков.

2. Зарегистрируем наш пакет в EVO:Создадим файл: core/custom/config/app/providers/Package_Example.php

<?php
	return EvolutionCMS\Custom\ExampleServiceProvider::class;


3. Добавим чанк:
Создадим файл: core/custom/packages/example/chunks/subdir/test.html
Пример [+time+], [+content+]


Содержимое этого файла обрабатывается парсером MODX, соответственно в нем можно использовать обычные плейсхолдеры MODX (пример с поддержкой чанков с BLADE будет позже).

4. Добавим сниппет:
Создадим файл: core/custom/packages/example/snippet/subdir/test.php
<?php
return $modx->parseChunk('example2#subdir\test', [
    'time' => time(),
    'content' => 'zxc'
], '[+', '+]');


Вызывать сниппет в текущем примере нужно вот так:
Парсер MODX:  
Парсер Blade: {{ $modx->runSnippet('example2#subdir\test') }}


Но если не указывать неймспейс для пакета и не вкладывать сниппет в подпапку, то получим всем привычный вариант


Таким образом мы видим, что теперь можно полноценно работать с дополнениями Evo без необходимости хранить код в Базе данных. При этом оставив полную обратную совместимость с предыдущими версиями.

Работа с DB, MODELSВсе согласно документации Laravel laravel.com/docs/5.7/database, laravel.com/docs/5.7/eloquent Модели в папке core/src/Models с namespace EvolutionCMS\Models. Пример:
$out = EvolutionCMS\Models\SiteContent::where('parent', '=', 0)
    ->orderBy('pagetitle', 'DESC')
    ->limit(10)
    ->get();
foreach ($out as $item) {
    echo "\t [ DOCUMENT #ID " . $item->id . ' ] ' . $item->pagetitle .PHP_EOL;
}


Из ближайших планов:
— Закончить работы по рефакторингу шаблонов админки с полным переносом их на BLADE
— Больше удобства для работы с DEV PROD: миграции, cиды, работа через консоль(artisan), решение проблемы с тем что на DEV и PROD разные id у документов.


— Отделение ядра от дополнений и перенос выбора что установить по умолчанию в момент установки (все что выбрали загрузится и установиться, а остальное не будет загружено).
— Доработка виджета для контроля устаревших дополнений и своевременном уведомлении о том, что рекомендуется обновить, с различным уровнем приоритетов.
— А так же больше документации и примеров.

Как помочь с тестированием?Присылайте ваши пожелания и багрепорты на github: github.com/evolution-cms/evolution/issues
Обязательно указывайте:
— Версию EVO
— Версию PHP
— Версию Mysql
— Скрин с ошибкой
— Как воспроизвести

Это поможет больше времени потратить на код, а не на выяснения что же не работает

Полезные ссылки:
— Скачать Evolution CMS можно тут: github.com/evolution-cms/evolution/releases
github.com/evolution-cms/evolution/releases/tag/2.0.0-alpha
— Официальный репозиторий: github.com/evolution-cms/evolution
— Официальный сайт: evo.im (скоро обновим на нормальный)
— Официальный Slack: evocmf.slack.com
— Официальный Telegram чат: t.me/evolutioncms
— Официальный Telegram канал новостей: t.me/evolutioncmsnews