Введение
Все описания форм, таблиц, меню и сообщения панели управления хранятся в XML-файлах в каталоге /usr/local/mgr5/etc/xml. Все используемые панелью XML-файлы написаны в кодировке UTF-8. Результатом выполнения панелью управления любой операции изначально также является документ XML.
Мы не рекомендуем изменять файлы XML, которые идут в комплекте с панелью управления. Но, тем не менее, вы можете добавлять собственные формы и таблицы, добавлять или убирать поля существующих форм с помощью механизма Плагинов и Событий .
Данная статья посвящена описанию файлов XML, используемых панелью управления.
Следующая группа атрибутов может быть использована практически с любыми элементами, описывающими объекты интерфейса
атрибут if Определяет условие (Feature), при котором этот элемент доступен.
атрибут before Определяет, перед каким элементом должен быть размещен этот элемент. В случае, если этот атрибут задан, панель просматривает все элементы находящиеся в том же контексте и помещает этот элемент перед одноименным элементом, у которого значение ключевого атрибута совпадает со значении атрибута before.
- атрибут after аналогичен before, но элемент будет размещен после указанного.
- атрибут first допустимое значение — "yes". Элемент будет размещен первым в списке.
- атрибут last допустимое значение — "yes". Элемент будет размещен последним в списке.
- атрибут level вы можете использовать этот атрибут для любого элемента внутри metadata и mainmenu, чтобы указать, какой уровень доступа должен быть у пользователя, чтобы увидеть те или иные данные. Помимо удаления элементов из metadata будут удалены и данные, которые соответствуют этим элементам. Для элемента col, описывающего столбец в таблице, все соответствующие элементы из строк таблицы. Для input, select, slider, textarea, text, htmldata — соответствующие элементы верхнего уровня. Атрибут может содержать несколько значений разделенных пробелом. Каждое значение имеет следующий формат:
- цифра от 0 до 31 — уровень доступа
- строка — имя уровня доступа или маски
- символ '+' после цифры или строки означает, что доступ должен быть не ниже указанного. При этом строка должна представлять имя уровня, а не маску.
В CORE существует ряд зарегистрированных имен:
- nobody доступ с уровнем 0
- super доступ с уровнем 30
- admin доступ с уровнем 29
- reseller доступ с уровнем 24
- user доступ с уровнем 16
- all маска — любой пользователь
- registered маска — пользователь с доступом выше 0 (прошедший авторизацию)
Например, следующие записи аналогичны: nobody+, all, 0+
Для элементов metadata и mainmenu алгоритм обработки атрибута level отличается.
Ключевые арибуты
При загрузке данных из XML-файлов панель объединяет одинаковые элементы. В этот момент объединяется содержимое элементов и их атрибуты. Одинаковыми считаются элементы находящиеся в одном контексте, имеющие одинаковое имя и, возможно, одинаковое значение ключевого атрибута. Для большинства элементов это атрибут name. Часть элементов, например такие как: toolsep, jscript, if, else — не объединяются никогда.
При загрузке XML-файлов панель никак не меняет содержимое следующих элементов (анализ вложенных элементов не производится): jscript, func, event, query и msg.
Метаданные (metadata)
Метаданные служат для описания элементов интерфейса панели. Каждый элемент metadata описывает один элемент интерфейса.
- атрибут type Тип элемента интерфейса. Может принимать значения form (описывает форму ввода), list (описывает список данных), report (описывает отчет).
- атрибут name Задаёт имя функции, которую описывает данный элемент.
- атрибут helpurl Если присутствует этот элемент, то значение ссылки "помощь" берется из этого атрибута.
- атрибут level Указывает, для каких пользователей доступен этот элемент интерфейса (функция, имя которой указано в атрибуте name). Формат значения атрибута описан во введении .
- атрибут secured Если значение "yes" — данные будут спрятаны в ответах на запросы авторизованные по COOKIE, но содержащие неверный REFERER
элемент include Позволяет добавить в элемент metadata содержимое другого элемента metadata. Имя включаемого элемента должно быть указано в атрибуте name. При загрузке metadata, имя которого было указанного в include, происходит обработка всех условий накладываемых атрибутами: if, after, before, first, last (т.е. изменение порядка узлов). Т.е. порядок узлов в подгружаемой через include XML будет изменен до объединения. Исключение сделано для metadata, имя которых начинается с префикса label_. Для таких metadata обработка атрибутов (if, after, before, first, last) не производится. Условия будут обработаны после объединения документов.
Главное меню (mainmenu)
На данный момент реализована двухуровневая система. Все элементы меню обязательно должны быть сгруппированы по разделам. Разделы не должны содержать подразделов.
Пример описания главного меню для CORE:
<mainmenu level="30" startpage="session">
<node name="srvset">
<node name="product" action="product" type="list"/>
</node>
<node name="stat">
<node name="session" action="session" type="list"/>
<node name="journal" action="journal" type="list"/>
<node name="longtask" action="longtask" type="list"/>
</node>
<node name="set">
<node name="brand" action="brand" type="form"/>
<node name="usermenu" action="usermenu" type="list"/>
<node name="usrparam" action="usrparam" type="form"/>
</node>
<node name="mgrhelp">
<node name="changelog" action="changelog" type="list"/>
<node name="handbook" function="http://ru.5.ispdoc.com/index.php/core-handbook-30"/>
</node>
</mainmenu>
- атрибут level Какой уровень доступа описывает данное меню.
- атрибут startpage Имя страницы, открываемой по умолчанию. Необходимо указать имя функции из главного меню. Если не указано, будет автоматически подставлено имя первой первого попавшегося пункта меню ссылающегося на список.
элемент node Описывает элементы меню и его подразделы.
- Для меню атрибут level является ключевым, но при формировании меню для конкретного уровня доступа происходит объединение всех доступных на этом уровне элементов mainmenu.
Например, если вы хотите добавить элемент меню для всех уровней доступа, вы можете написать следующее:
<mainmenu level="registered">
<node name="stat">
<node name="mystat" first="yes"/>
</node>
</mainmenu>
Данный XML код добавит элемент меню mystat в раздел stat (раздел stat будет создан, если его нет) для пользователей всех уровней (level="registered"). Причем mystat станет первым элементом в разделе stat (first="yes").
Элемент меню (элемент node)
Элемент node описывает элемент меню (нет дочерних узлов), либо его раздел (дочерними node описываются элементы).
- атрибут name Имя функции, которую необходимо вызвать. Кроме того, служит для привязки к языкам.
- атрибут type Задает тип функции. Возможные значения: list или form. Этот атрибут подставляется автоматически.
- атрибут action Задает имя функции, которую необходимо вызвать. Данный параметр подставляется автоматически для тех пунктов, которые ссылаются на функции панели. Его значение копирует значение атрибута name.
- атрибут function Задает URL, по которому необходимо перейти. Этот параметр задается автоматически, если в панели заведена внешняя функция (extaction) с именем заданным в атрибуте name.
Элемент меню с именем handbook обрабатывается особым образом. Если существует такой элемент, вызывается функция help с параметрами topic=handbook и level=<уровень доступа текущей сессии>, которая должна вернуть URL. Этот URL будет подставлен в атрибут function.
Описание языков и переводы (lang)
Пример описания текстовых надписей CORE на английском языке (часть файла core_msg_en.xml):
<lang name="en">
<messages name="label_langs">
<msg name="bg">Български</msg>
<msg name="cn">汉语</msg>
<msg name="cs">Český</msg>
<msg name="de">Deutsch</msg>
<msg name="en">English</msg>
<msg name="es">Español</msg>
<msg name="fi">Suomi</msg>
<msg name="fr">Français</msg>
<msg name="hu">Magyar</msg>
<msg name="jp">日本語</msg>
<msg name="ku">کوردی</msg>
<msg name="nl">Nederlands</msg>
<msg name="pl">Polski</msg>
<msg name="pt">Português</msg>
<msg name="ru">Русский</msg>
<msg name="th">ภาษาไทย</msg>
<msg name="ua">Українська</msg>
<msg name="xx">Developer</msg>
<msg name="zh">中文</msg>
</messages>
<messages name="usrparam">
<include name="label_langs"/>
<msg name="addr">Allowed IP-addresses</msg>
<msg name="atallow">allow for listed IP-addresses</msg>
<msg name="atany">allow for any IP-address</msg>
<msg name="atype">Access to the control panel</msg>
<msg name="button">Icons</msg>
<msg name="buttontext">Icons and captions </msg>
<msg name="buttonview">Toolbar view</msg>
<msg name="confirm">Re-enter password</msg>
<msg name="email">E-mail for notifications </msg>
<msg name="hint_rows">Enter the number of rows per page that will be displayed by default</msg>
<msg name="hint_startpage">Select a page that will be displayed once you log in to the control panel</msg>
<msg name="hint_theme">Select the theme that will be used to display the control panel</msg>
<msg name="hint_timezone">Select the time zone for your region </msg>
<msg name="lang">Language</msg>
<msg name="msg_error_notuniqueemail">The selected e-mail is already used </msg>
<msg name="msg_passwd">Password do not match!</msg>
<msg name="name">Username</msg>
<msg name="password">Password</msg>
<msg name="recordlimit">Number of records </msg>
<msg name="rows">Rows per page</msg>
<msg name="startpage">Start page</msg>
<msg name="text">Text</msg>
<msg name="theme">Theme</msg>
<msg name="timezone">Time zone</msg>
<msg name="title">General settings</msg>
<msg name="title_new">General settings</msg>
</messages>
</lang>
атрибут name Код описываемого языка. Например: en, fr, ru, es.
элемент messages Описывает сообщения для определённой функции.
Описание сообщений для функций (элемент messages)
- атрибут name Имя описываемой функции.
элемент msg Содержит сообщение.
элемент include Импортировать сообщения из указанной секции.
В CORE существует ряд специальных секций messages. Они используются даже несмотря на то, что значению их атрибута @name не соответствует ни одной функции:
- alert — набор сообщений для баннеров
- common — набор общих сообщений
- msgerror — набор сообщений для описания ошибок
- form — набор общих сообщений используемых в формах и отчетах
- list — набор общих сообщений используемых в списках и отчетах
- report — набор общих сообщений используемых в отчетах
Описание сообщения (элемент msg)
- атрибут name Имя сообщения.
Элемент не имеет дочерних узлов. В нём содержится текст сообщения.
Подсказки (hint)
Многие элементы интерфейса имеют текстовые подсказки (hint), которые всплывают при наведении. Они описываются в локализованных сообщениях, и имеют имя с префиксом hint_. Помимо plain текста подсказки могут содержать html теги, которые будут корректно отображаться.
Например, можно вставить в подсказку ссылку:
<msg name="hint_multiselect">Можно выбрать более одного <a href="http://ru.5.ispdoc.com/" target="_blank">элемента</a></msg>
Или выделить особо важный текст:
<msg name="hint_multiselect">Можно выбрать <span style="color:red;">более</span> одного элемента</msg>
Стоит помнить, что html теги должны быть валидны как xml теги.
Чтобы записывать HTML-теги, используйте следующие варианты записи:
-
<![CDATA[SOMETHING]]>
<msg name="hint_color">Я <![CDATA[<font color="yellow">желтого</font>]]> цвета</msg>
- измените
- < на <
- > на >
<msg name="hint_link">Я <a href="https://ya.ru">ссылка</a></msg>
Внешние обработчики (handler/library)
COREmanager предоставляет гибкий механизм для всевозможных изменений в поведении системы. Для написания логики таких модификаций вы можете использовать внешние обработчики написанные на любом языке программирования или библиотеки (shared libraries) написанные на C++.
Для описания внешних обработчиков используется элемент handler:
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
<handler name="lastlogin" type="cgi" ignore_errors="yes">
<event name="auth" after="yes"/>
</handler>
</mgrdata>
- атрибут name –- имя исполняемого файла, который должен находиться в каталоге addon
- атрибут type — тип взаимодействия с обработчиком. Возможные значения: cgi и xml. В первом случае обработчик вызывается с использованием интерфейса CGI, он получает все данные через переменные окружения, а в стандартный поток ввода ему запишут содержимое POST запроса. При использовании типа xml, обработчик также получит все данные через переменные окружения и содержимое POST запроса с стандартный поток ввода. Плюс, после содержимого POST запроса он получит xml документ сформированный на данный момент для ответа на запрос. В обоих случаях результатом выполнения должен быть правильный xml документ записанный в стандартный поток вывода. В первом случае он будет объединен с xml документом сформированным внутри панели, во втором — полученный xml документ полностью заменяет собой тот, что был сформирован ранее.
- атрибут ignore_errors — игнорировать возникающие ошибки. Необязательный параметр. Если указать этот атрибут со значением "yes", то ошибки обработчика не повлияют на работоспособность панели управления. Опция будет применена только к тем обработчикам, для которых будет указана.
элемент event определяет функцию, на вызов которой будет срабатывать обработчик. Функция должна существовать. Если вы хотите определить новую — используйте элемент func.
элемент func создает новую функцию панели (имя функции задается атрибутом @name этого элемента) реализация логики которой полностью ложится на ваш обработчик.
Для загрузки собственной библиотеки используется элемент library. Следующий xml приведет к загрузке библиотеки test из каталога lib:
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
<library name="test"/>
</mgrdata>
Обработчики событий (элемент event)
COREmanager позволяет не только добавлять собственные обработчики для событий, но и определять порядок их вызова. Для этого у элемента event существует ряд атрибутов:
- атрибут priority определяет порядок вызова обработчика. Может принимать значения before и after, для вызова обработчика перед или после базового (см. атрибут @base)
- атрибут base задает имя базового обработчика, относительного которого определен порядок атрибутом @priority. Если базовый обработчик не задан, то при @priority=before обработчик будет добавлен в начало очереди, а при @priority=after — в конец.
Даже если вы указали, что ваш обработчик необходимо вызывать первым/последним или до/после какого-то другого обработчика, это не гарантирует того, что он действительно будет занимать в очереди указанную позицию. Например, если несколько обработчиков хотят быть первыми, они будут выполнены до всех остальных, в порядке обратном порядку их создания (последний созданный будет первым). Если порядок отличается от ожидаемого, вам необходимо явно указать после или перед каким обработчиком необходимо выполнить ваш собственный.
Если не существует обработчика, указанного в атрибуте @base, значение атрибута игнорируется.
Кэширование
В связи с достаточно большой сложностью алгоритма обработки метаданных, панель не работает с исходными XML файлами напрямую. Используется двухуровневая система кэширования.
На первом этапе мы объединяем все XML документы согласно правилам. Затем полученный xml делится на файлы (по одной metadata/messages в файле). Данный кэш перестраивается при запуске панели, если изменилась контрольная сумма исходных документов. Полученные XML документы сохраняются в каталог var/.xmlcache/<manager>.X, где X — число 0 или 1. ' Создается ссылка var/.xmlcache/<manager>, которая указывает каталог, который используется панелью в данный момент времени. Второй каталог используется для предварительного кэширования. Данная операция выполняется следующими командами:
# кэширование метаданных
sbin/xmlinstall --manager <manager> --meta-cache [--apply]
# кэширование сообщений
sbin/xmlinstall --manager <manager> --lang-cache ru --base en [--apply]
В случае использования параметра --apply изменения делаются "на живую" — в каталоге, с которым в данный момент работает панель
На втором этапе происходит обработка различных директив include, изменение порядка узлов согласно правилам, добавляются пропущенные сообщения из других модулей и т.п. Полученный результат сохраняется в каталоге var/.xmlcache/<manager>.X/checked. Он перестраивается в случае изменения набора возможностей (feature) панели или при перестройке всего кэша. Данная операция делается панелью по мере необходимости, когда необходим доступ к тем или иным XML.
Предварительное кэширование
Первый этап может занимать значительное время. Чтобы избежать лишнего простоя при перезапуске панели, можно предварительно перестроить кэш командой:
sbin/xmlinstall --manager <manager> --recache [--apply]
В этом случае рядом с текущим будет создан новый кэш (если используется каталог <manager>.0, будет создан каталог <manager>.1 и наоборот). Панель при запуске проверяет оба каталога, и, если один из них содержит актуальные данные, делает его активным.
Запустив эту же команду с ключом --apply можно немедленно подменить текущий кэш панели новым. Данная функция может быть использована, если вы хотите посмотреть результат изменения xml файла не перезапуская панель. Часть данных (например информацию об уровне доступа) панель читает из XML файлов только на старте