Кастомизация администраторской панели

Doit CMS имеет возможности для некоторой кастомизации и переопределения стандартного поведения системы администрирования: столбцы в списке объектов, свои собственные элементы управления, настройка сортировки и так далее.

В большинстве случаев данные возможности не нужны, однако в некоторых случаях они могут пригодиться.

Список и сортировка

Для настроек в большинстве случаев используется файл ini в папке fields, привязанный к таблице. Например, для таблицы pages это файл /app/fields/pages.ini. Также этот файл можно редактировать на странице добавления объекта при помощи меню Скаффолдинг → Текущий шаблон.

Указание столбцов

Для указания столбцов, отображаемых в списке элементов, выделен раздел опций [admin.columns].

В этом разделе указываются столбцы в виде столбец=Название столбца для администратора. Несколько столбцов настраиваются на нескольких строках. Например:

[admin.columns]
url=Адрес страницы
title=Заголовок страницы

или

[admin.columns]
title=Название
color=Цвет
price=Стоимость

Направление сортировки

По умолчанию система сортирует по полю sort, от меньшего значения к большему. Если необходимо инвертировать направление сортировки, следует указать файле следующее:

[admin.list]
sort_direction=asc

sort_direction может принимать два значения: asc и desc. Эта опция автоматически прикрепляется также к странице сортировки порядка элементов. Следует обратить внимание, что установка опции никак не повлияет на поведение объектов модели и контроллера на самом сайте, для этого есть метод order_by объекта ActiveRecord.

Поле сортировки

Для переопределения поля, по которому производится сортировка (например, по алфавиту), используется параметр sort_field. При указании это поля сортировка порядка элементов потеряет смысл, так как она основана на манипуляции значениями поля sort.

К слову, именно эти поля использует система для сортировки путём щелчков по заголовкам таблицы.

Например:

[admin.list]
sort_field=title

Также доступно использование обеих параметров:

[admin.list]
sort_field=title
sort_direction=asc

Эта опция бесполезна в некоторых случаях, например, когда поле стоимости является текстовым (в данном случае сортировка произойдёт по алфавиту) или по текстовому полю даты формата userdate, в данном случае сортировка также произойдёт по алфавиту. Эту опцию можно использовать например для того, чтобы вывести непромодерированные записи в верху списка (sort_field=is_active) или отсортировать по дате последнего изменения (sort_field=updated_at).

Для сортировки по более сложным полям (даты, цены в текстовых строках, сортировка по нескольким столбцам) необходимо использовать опцию source с заданными параметрами сортировки.

Сортировка через GET запросы

Также поля в системе администрирования могут сортироваться при помощи GET запросов. Например, параметр /admin/list/pages?sort_field=title заставит сортироваться по полю title. Также можно указать направление сортировки при помощи параметра sort_direction, принимающего значения asc или desc.

Переопределение значений в таблице (list=yes)

Администратор может указать, какие столбцы выводить в таблице. Однако иногда нам необходимо переопределить их вывод (допустим, вывести картинку). Для этого используется параметр list=yes:

[admin.use_model]
list=yes

Данная опция сообщает системе, что для страницы со списком объекто необходимо использовать модель, не отображать данные в чистом виде, а использовать класс ActiveRecord, описывающий эту таблицу. То есть мы можем вывести в таблице несуществующее столбце link, а его значение задать в модели:

<?php
class Page extends ActiveRecord
{
    function link()
    {
        if($this->get('link')!=''){
            return $this->get('link');
        }
        if($this->get('url')=='index'){
            return '/';
        }
        return '/' . $this->get('url');
    }   
}

Другой пример - вывод превью картинки прямо в таблице. Допустим, мы храним изображение в поле image.

Прописываем в списке столбцов поле image_mini (не существующее):

[admin.columns]
title=Название
image_mini=Картинка
created_at=Дата создания
[admin.use_model]
list=yes

Далее создаём метод image_mini в классе модели этой таблицы:

<?php
class Page extends ActiveRecord
{
    function image_mini()
    {
        if($this->get('image')){
            return '<img src="' . d()->preview(array($this->get('image'), '200', '100')) . '">';
        }
        return 'Нет изображения';
    }
}

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

Опция source: привязка источника данных

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

Он используется следующим образом:

[admin.use_model]
source=d()->News->where('`is_activated` = 1 and `user_id` IS NULL')->order_by_userdate

Также это позволяет делать альтернативные списки, например, создав файл banned_users.ini в папке fields, и прописав там:

[admin.use_model]
source=d()->User->only('banned')

К подобному файлу можно обращаться по адресу /admin/list/banned_users, а сами данные будут браться из таблицы users.

Постраничная навигация

Постраничная навигация появляется в списке объектов автоматически, начиная с 100-го элемента. Однако можно переопределить это число, используя опцию paginator:

[admin.use_model]
paginator=10

Если система автоматически перебивает пагинатор, заданный в параметре source, то можно указать paginator=yes, или другое нечисловое значение. Это нужно для того, чтобы автоматический метод paginate(), который применит система к этой модели, не был вызван.

[admin.use_model]
source=d()->User->paginate(3)
paginator=yes

TODO: Переопределение столбца для списка сортировки

TODO: Пользовательские элементы управления

На странице редактирования объектов вставлены элементы управления. ini-файл позволяет вставить поля типа small, rich, checkbox и так далее. Иногда бывает нужно вставить свой собственный элемент, например, раскрывающийся список с собственными элементами или поле выбора цвета.

Система при запросе поля small вызывает функцию admin_small. Сама функция не существует в явном виде, зато есть соответствующий шаблон в папке /cms/mod_admin: _small.html.

Нам остаётся взять заготовку (small, select или что нам ближе), и скопировать её в папку app или папку нашего модуля в папке app. Разумеется, его надо переименовать (начинаться он должен на admin_. Если мы создадим таким образом файл admin_mysuperselect.html, то получим возможность использовать его в ini - файле:

[admin.fields]
small title "Название"
rich text "Текст"
mysuperselect color "Выберите цвет"

Полученный файл admin_mysuperselect можно кастомизировать для собственных элементов управления. Сам шаблон использует для этого несколько переменных, таких как d()->title, d()->name, d()->value. Это позволяет сделать такие элементы, как:

  • Выбор точки на карте
  • Выбор цвета
  • Разделение столбцов для мультиколоночного модуля
  • Раскрывающийся список с двухуровневым деревом
  • HTML-вставка на страницу редактирования (например, для справки или инструкций)
  • Комплексный элемент из нескольких элементов управления
  • Профиль пользователя с фотографией, для которого мы модерируем комментарий.
  • Другие элементы управления

Примеры использования можно посмотреть в /cms/mod_admin, это такие поля, как small, rich, checkbox, checkboxes, select_table, которые могут послужить основой или образцом для своих элементов.

Действия при сохранении

Роутер системы Doit CMS предполагает, что при переопределении функции мы можем указать не одно, а несколько параметров.

Например (файл router.init.ini):

[urls]
...
/news/      content     news#show  pages#show   fosv_show

Это означает, что вместо функции content будут выполнены несколько других функций подряд.

Применительно к системе администрирования это означает, что мы можем переопределить "родную" функцию admin_save_data.

Например, так:

[urls]
...
/admin/edit/pages/   admin_save_data  do_my_action admin_save_data

Для таблицы pages перед сохранением будет вызываться функция do_my_action(), которая, например, сделает запись в логе или отправит письмо по электронной почте, и уже после этого выполнит своё обычное предназначение. В этой функции доступны данные $_POST (так как массив суперглобальный).

Кроме того, можно просто переопределить полностью admin_save_data, и тогда она вовсе не вызовется.

Аналогично можно прописать действие для конкретного объекта:

[urls]
...
/admin/edit/pages/73    admin_save_data  do_my_action admin_save_data

Также можно переопределить данные из массива $_POST до сохранения. Для этого необходимо прописать в роутере:

[urls]
...
/admin/edit/pages/  content  do_my_action admin_edit

Обратите внимание, что переопределяется функция content.

<?php
function do_my_action()
{
    $_POST['data']['title'] = 'Новое значение';
}

Это может быть использовано для того, чтобы удалять изображение при создании превью на этапе сохранения изображения. Вот пример функции, которая удалит файл, сохранив превью:

<?php
function delete_original_image()
{   
    if(isset($_POST['data']['image'])){
        if(substr($_POST['data']['image'],0,9)=='/storage/' && file_exists($_SERVER['DOCUMENT_ROOT'].$_POST['data']['image']) && is_file(($_SERVER['DOCUMENT_ROOT'].$_POST['data']['image']))){
            unlink( ($_SERVER['DOCUMENT_ROOT'].$_POST['data']['image']));
        }
    }
}

Соответственно и вызывать её надо до сохранения.

Более сложный способ - переопределить в роутере свою собственную функцию сохранения и редактирования, со своими шаблонами, и написать свой обработчик форм. Это даст возможность свободно писать тот код, который нужен, и не вписываться в рамки системы.

/admin/edit/pages/  content  my_own_code

TODO: Примеры использования

Модерация

Картинки в списке и при сортировке

Поля "Да" и "Нет"


comments powered by Disqus