Pull to refresh

MODx Revolution. Итоги. Часть 1

Reading time6 min
Views9.4K
Три с половиной месяца прошло со дня релиза MODx Revolution. Думаю никто не будет спорить, что версия 2.0 была очень сырой и для использования на реальных проектах была не готова. На русскоязычных сайтах о MODx я видел много критики и скептицизма. Что-то вполне заслужено, а что-то из-за отсутствия подробной документации. На данный момент доступна версия 2.0.4-pl2, по которой, на мой взгляд, уже можно подвести итоги: Правильно ли разработчики выбрали направление и инструменты для развития и стоит ли отказаться от MODx Evolution (1.x) и переходить на Revo? В данной статье я постараюсь подробно рассказать об основных особенностях новой системы, которые сам для себя только открываю.



Что такое MODx Revolution



Как говорят разработчики, в первую очередь MODx Revolution — это CMF, т.е. инструмент для создания веб-приложений, а CMS, которая идет в комплекте, это всего лишь «довесок». Рево написан на PHP и использует:
  • базу данных MySQL,
  • технологию преобразования объектов в реляционные модели баз данных xPDO,
  • JavaScript фреймворк Sencha (ExtJS),
  • шаблонизатор Smarty.


Система управления





Несмотря на вышесказанное, разработчики уделили не мало внимания CMS. Чувствуется, что удобство системы управления продумано очень тщательно.
  • Выпадающее меню с кратким описанием каждого пункта (кому не нравится, описания можно отключить);
  • вкладки на панеле слева с быстрым доступом ко всем основным элементам и файлам;
  • почти всё (а может и совсем всё) можно настроить под конкретный проект без необходимости залезать в исходный код;
  • встроенный поиск ресурсов (документов);
  • удобная установка пакетов (дополнений) прямо из CMS.


Если нажать правой кнопкой мыши на каком-то разделе в дереве ресурсов (документов) слева и выбрать «Быстро создать» -> «Документ», то откроется окно для создания документа без перезагрузки страницы, что очень удобно. Есть и быстрое редактирование («Быстро обновить ресурс»). Точно так же можно быстро создать или отредактировать «дополнительные поля» и т.п. Документы можно сортировать и перекладывать по разделам простым перетаскиванием в дереве.

Впрочем, не всё так радужно. Из-за кучи «JavaScript-красивостей» админка работает заметно медленнее чем в Evolution, иногда подвисает на каких-то действиях. Хотя думаю со временем это всё поправится (критичных глюков я не заметил).

Разработка под MODx Revolution



Разделение прав пользователей. В Evo права были фиксированные и только в админке (для «менеджеров»). В Revo появилась возможность создавать свои права и назначать их отдельным группам пользователей. Делается это очень просто:
Идем в «Безопасность» -> «Группы пользователей» -> «Политики доступа». Выбираем имя политики доступа (например «Administrator») и в редактировании добавляем «новое разрешение», например «test_action».
Сохраняем и жмем «Выйти». Чтобы права обновились, нужно заново войти в систему (обновить сессию). Теперь можно в любом месте в коде компонента (сниппета, плагина) проверить имеет ли текущий пользователь права на действие «test_action»:

if (!$modx->hasPermission('test_action')){
  //Если прав на это действие нет, выводим сообщение "Доступ закрыт"
  return $modx->error->failure($modx->lexicon('access_denied'));
}


Это очень коротко, есть возможность настроить права доступа более тонко. В Revo нет разделения на «менеджеров» и «веб-пользователей» как в Evo. Контроль доступа в административной части определяется контекстом «mgr», а во внешней части сайта — контекстом «web».

Создание сниппетов и плагинов без особенных изменений. Сохранены большинство названий функций и аргументы из Evo. Для создания «пакетов» (packages) есть очень удобный и простой в работе модуль PackMan:

Выбираем сниппеты, плагины, чанки, нажимаем кнопку «Export Transport Package» и получаем готовый к установке архив пакета. Теперь можно будет его положить в папку core/packages/ и установить через «Управление пакетами».

Создание страниц в «менеджере». Теперь нет понятия «Модуль». Есть общее название «Компонент». В системе управления можно создать пользовательский интерфейс администрирования компонента. Опишу коротко основные шаги:
1. Создаем пространство имен для нашего компонента («Система» -> «Пространства имен»).

По указанному пути «менеджер» будет искать «контроллер» компонента. Если вы знакомы с паттерном MVC, то понятие «контроллер» вам хорошо известно.
2. Идем в «Система» -> «Действия». Кликнув на нашем пространстве имен «myextra», выбираем «Создать действие здесь». В строке «Контроллер» пишем название PHP-файла контроллера, который лежит в папке указанной ранее. Например «index» (index.php).
3. Теперь создаем пункт в главном меню. Кликаем правой кнопкой мыши на пункте «Компоненты» в блоке «Верхнее меню» и выбираем «Создать пункт меню здесь».

4. В более сложных приложениях стоит все контроллеры складывать в отдельную папку «controllers». Вот содержание моего контроллера index.php:

<?php

$corePath = MODX_CORE_PATH.'components/myextra/';
$assetsUrl = MODX_BASE_URL.'assets/components/myextra/';
$controllersPath = $corePath.'controllers/';
$connectorUrl = $assetsUrl.'connector.php';
$cssUrl = $assetsUrl.'css/';
$jsUrl = $assetsUrl.'js/';

$output .= '<div><h2>Тестовый компонент</h2></div>';
$output .= '<div id="myextra-main-div"></div>';

return $output;


В реальности так делать очень не рекомендуется. Нужно создать модель и т.п. (об этом в следующей части). Можно использовать шаблонизатор Smarty:

$title = 'Тестовый компонент';
//передаем переменную в шаблон
$modx->smarty->assign('title', $title); 
//выводим шаблон
return $modx->smarty->fetch($corePath.'templates/main.tpl');


Можно использовать PHP в роли шаблонизатора (шаблоны нужно вынести в отдельный файл). А можно по-полной использовать ExtJS. Вот пример вывода таблицы значений (Ext.grid.GridPanel):

core/components/myextra/index.php:

<?php

$corePath = MODX_CORE_PATH.'components/myextra/';
$assetsUrl = MODX_BASE_URL.'assets/components/myextra/';
$controllersPath = $corePath.'controllers/';
$connectorUrl = $assetsUrl.'connector.php';
$cssUrl = $assetsUrl.'css/';
$jsUrl = $assetsUrl.'js/';

//подключаем скрипты в HEAD
$modx->regClientStartupHTMLBlock('<script type="text/javascript">
var myextra = {};
myextra.connector_url = "'.$connectorUrl.'";
</script>');
$modx->regClientStartupScript($jsUrl.'datagrid.js'); //скрипт с grid`ом

$output .= '<h2>Тестовый компонент</h2>';
$output .= '<div id="myextra-main-div"></div>';

return $output;


assets/components/myextra/js/datagrid.js:

Ext.onReady(function(){ 
    
    //создаем хранилище данных
    var store = new Ext.data.JsonStore({
        url: myextra.connector_url, //файл источника  данных
        root: 'object.data', //JSON объект с основными данными
        totalProperty: 'object.total', //число элементов в списке
        idProperty: 'orderid',
        remoteSort: false,
        prettyUrls: false,
        fields: [
           {name: 0},
           {name: 1, type: 'int'},
           {name: 2, type: 'float'},
           {name: 3, type: 'int'}
        ]
    });
    store.setDefaultSort(3, 'desc');
    

    //создаем таблицу данных
    var grid = new Ext.grid.GridPanel({
        store: store,
        columns: [
            {header: "Колонка 1", width: 100, sortable: true, dataIndex: 0},
            {header: "Колонка 2", width: 100, sortable: true, dataIndex: 1},
            {header: "Колонка 3", width: 100, sortable: true, dataIndex: 2},
            {header: "Колонка 4", width: 100, sortable: true, dataIndex: 3}
        ],
        renderTo:'myextra-main-div', //DIV в который вставляем таблицу
        width:400,
        autoHeight: true,
        loadMask: true,
        bbar: new Ext.PagingToolbar({
            pageSize: 5, //элементов на странице
            store: store, //источник данных
            displayInfo: true,
            displayMsg: 'Показано {0} - {1} из {2}',
            emptyMsg: "Ничего не найдено"
        })
    });
    
    //загружаем данные
    store.load({params:{
        action: 'mgr/datalist', //действие ("процессор")
        start:0,
        limit:5
      }
    });

});


assets/components/myextra/connector.php:

<?php
/**
 * Myextra Connector
 *
 * @package myextra
 */
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
require_once MODX_CONNECTORS_PATH.'index.php';

/* handle request */
$modx->request->handleRequest(array(
    'processors_path' => $modx->getOption( 'core_path' ) . 'components/myextra/processors/',
    'location' => ''
));


core/components/myextra/processors/mgr/datalist.php:

<?php

$start = $scriptProperties['start']; //получаем данные запроса
$limit = $scriptProperties['limit']; //получаем данные запроса
$total = 50;
$page = $start+1;

//вместо этой "рыбы" будет mysql-запрос

$limit_on_page = $total-($total-($page*$limit));

$outputArray = array();

for($i=$start*$limit;$i<$limit_on_page;$i++){
  $outputArray[] = array('Строка '.($i+1),2,3,4);
}

$outputArray = array(
  'total'=>$total,
  'limit_on_page'=>$limit_on_page,
  'data'=>$outputArray
);

return $modx->error->success('',$outputArray);


В итоге получаем такую табличку:


ExtJS совсем не сложен в изучении, как мне раньше казалось. Главное желание. Он действительно экономит кучу времени.

Документация MODx Revolution пока очень бедная. Немалую часть информации приходится искать в исходниках. Надеюсь скоро эта ситуация изменится, возможно, с вашей помошью.

Конец первой части.

Из этой части думаю всем понятно, что MODx Revolution не на много сложнее Evolution в плане разработки, а возможностей для разработчика на порядок больше.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+35
Comments40

Articles