Модули позволяют расширять функционал ReadyScript и вмешиваться в стандартный ход выполнения различных операций. Каждый модуль включает в себя классы контроллеров, моделей, шаблоны отображения, изображения, CSS стили, JS файлы, языковые файлы. Такая инкапсуляция позволяет легко переносить модуль между приложениями на платформе ReadyScript. Модуль в ReadyScript - это папка с определенной структурой данных внутри. Модуль обязательно должен располагаться в каталоге для модулей /modules и иметь следующую структуру.
Для того, чтобы модуль был идентифицирован в системе и его можно было установить, необходимо объявить в нем класс ModuleName\Config\File. В данном классе должны быть описаны настройки модуля. Значения по-умолчанию этих настроек должны быть описаны в файле module.xml. В дальнейшем, пользователь сможет менять значения настроек модуля в административной панели в разделе Веб-сайт → Настройка модулей
Конфигурационный класс модуля ModuleName::Config::File - должен быть наследником класса RS::Orm::ConfigObject . RS::Orm::ConfigObject - это ORM объект с особым типом хранища, поэтому добавление свойств(настроек модуля) происходит по общим правилам создания свойств у ORM Объектов, через метод _init. Значения настроек по умолчанию должны возвращаться статическим методом getDefaultValues() в виде массива, в котором ключами являются имена свойств. RS::Orm::ConfigObject имеет следующий набор стандартных свойств, описывающих модуль:
Свойство | Назначение | Ожидаемое значение |
---|---|---|
name | Название модуля | String |
description | Описание | String |
is_system | Флаг, является ли модуль системным. Системные модули невозможно удалить | 1 - модуль системный, 0 - модуль обычный |
dependfrom | Здесь можно указать другие модули, которые должны присутствовать в системе, чтобы установить данный модуль | String. названия модулей должны быть перечислены через запятую |
version | Версия модуля | String. Пример версии: 0.1.0.0 - первая цифра - изменения, влияющие на совместимость, вторая - изменение в стуктуре БД, третья - мелкие правки, четвертая - ревизия из системы контроля версий |
version_date | Дата последнего обновления модуля | String |
core_version | Требуемая для установки версия ядра | String. Например: '0.1.0.0' (одна версия), или '0.1.0.0 - 0.2.0.0' (Диапазон версий), или '>=0.1.0.156' или '<=0.1.0.200' (для всех версий младше или старше требуемой), можно указать смешанно, через запятую так: '<=0.1.0.200, 0.2.0.0 - 0.3.0.0, 1.0.0.0, 1.1.0.0' |
author | Автор модуля | String |
tools | Утилиты по обслуживанию модуля. Отображаются на странице настроек модуля в правой колонке. | Array. Например: array( array( 'url' => '/любая ссылка/', 'title' => t('Название инструмента'), 'description' => t('Описание инструмента') ), ... ) |
В ReadyScript имеется подсистема настройки прав доступа к модулям. Права к модулю - это число от 0 до 255. Каждому из 8-ми битов этого числа может быть присвоено название. Администратор может устанавливать флажок для каждого бита в административной части в разделе настройки прав групп пользователей. Назначение каждого бита при этом будет отображено администратору. Чтобы задать описание битам достаточно перегрузить публичное свойство $access_bit в классе конфигурации модуля. В процессе работы модуля можно проверять состояние любого из 8-ми битов перед выполнением того или иного действия.
Пример конфигурационного файла модуля Каталог
Файл должен содержать основные сведения о модуле и значения параметров конфигурации по-умолчанию.
Обязательные секции:
Если у секции присутствует атрибут multilanguage="true", то это означает, что значение секции подлежит переводу на текущий язык пользователя. Задать различные языковые версии можно с помощью языковых файлов модуля.
Присутствие у секции атрибута type="array", будет означать, что параметр содержит списковое значение. Элементы списка допускается задавать вложенной секцией value. У секции value может быть задан необязательный атрибут key, который будет определять ключ ассоциативного массива параметра.
Пример файла module.xml:
Чтобы реализовать собственный или дополнить стандартный алгоритм установки модуля, необходимо добавить ему класс-установщик Install в пространстве имен ModuleName\Config. Класс должен имплементировать интерфейс RS::Module::InstallInterface .
Рассмотрим данный интерфейс
Для увеличения скорости разработки, в ReadyScript имеется абстрактный класс RS::Module::AbstractInstall, в котором реализовано стандартное поведение установщика модуля. Стандартное поведение заключается в следующем:
Если данное поведение полностью соответствует требованиям модуля, достаточно определить наследника класса RS::Module::AbstractInstall, с пустым телом.
Пример стандартного установщика модуля:
Чтобы реализовать собственный или дополнить стандартный алгоритм удаления модуля, необходимо реализовать класс деинсталяции. Класс должен имплементировать интерфейс RS::Module::UninstallInterface. Рассмотрим данный интерфейс:
Аналогично функционалу установки модуля, для разработчиков есть готовый абстрактный класс RS::Module::AbstractUninstall, реализующий стандартное поведение модуля при удалении. Под стандартным поведением понимается:
После выполнения метода uninstall класса деинсталяции модуля, ReadyScript удаляет папку с модулем. Для создания стандартного класса деинсталяции будет достаточно определить класс UnInstall, как наследника класса RS::Module::AbstractUninstall с пустым телом.
Для случев, когда при обновлении модуля единожды требуется выполнить какой-либо PHP-код разработчика, в ReadyScript предусмотрен класс Patches. Он обязательно должен являться наследником класса RS::Module::AbstractPatches. В классе должен быть реализован метод init(), возвращающий массив идентификаторов патчей. Для каждого идентификатора должен быть реализован метод с одним из следующих префиксов:
Методы с префиксом beforeUpdate будут выполнены до начала процедуры обновления модуля, методы с префиксом afterUpdate соответственно после. Метод из класса Patches выполняется только если они не были запущены раннее, таким образом все методы выполняются единожды.
Пример класса Patches.
Во время выполнения различных операций, система вызывает события. Каждый установленный и включенный модуль в системе может обрабатывать эти события и выполнять какие-либо действия. Некоторые события чувствительны к результату выполнения обработчиков, что позволяет корректировать с помощью сторонних модулей стандартный ход выполнения программы.
Подписка на события системы и непосредственно сами обработчики событий должны располагаться в классе Handlers, в пространстве имен ModuleName. Класс Handlers должен быть наследником класса RS::Event::HandlerAbstract.
В момент инициализации системы событий, скрипт проверяет наличие класса Handlers в каждом модуле и вызывает метод init. Предполагается, что в данном методе произойдет установка обработчиков на события, которые модуль пожелает обрабатывать.
Рассмотрим класс Handlers модуля Shop
Из приведенного выше примера класса видно, что если у метода bind не указаны параметры $callback_class, $callback_method, то ожидается, что в классе будет присутствовать метод, имя которого соответствует имени события без символов точек и минусов. Метод должен быть публичным и статическим. Такой метод и будет обрабатывать соответствующее событие.
Идея расположить все обработчики событий в одном файле приследует цель, создать единое место, в котором будет видна вся "внешняя" деятельность модуля.
Список всех событий см. в разделе События
По умолчанию для определения доступных в модуле прав и их автоматических проверок используется класс RS::AccessControl::DefaultModuleRights . Чтобы реализовать собственную или дополнить стандартную схему прав, необходимо создать класс прав модуля ModuleRights в пространстве имен ModuleName\Config. Класс должен быть наследником класса RS::AccessControl::DefaultModuleRights .
В классе прав модуля можно перегрузить 2 метода:
Классы автоматических проверок прав
В некоторых случаях вместо ручной установки проверки прав в код модуля можно использовать инструкции для автоматических проверок прав
Пример - "файл прав модуля по умолчанию":
Список прав модуля и список интрукций для автоматических проверок можно дополнить из стороннего модуля при помощи событий
В ReadyScript есть некоторые рекомендации по созданию единообразной структуры при использовании внешних PHP-библиотек, устанавливаемых через Composer.
В файле /core/composer.json (и в папке /core/vendor) вы можете увидеть системный список внешних библиотек, которые доступны во всех модулях. Если необходимая для вас библиотека присутствует здесь, то вы можете использовать ее в любом месте вашего кода без каких-либо дополнительных действий.
Пример:
Вносить изменения в системный файл /core/composer.json не нужно, т.к. любые изменения здесь будут отменены при следующем обновлении системы.
В случае, если среди системных внешних библиотек не оказалось нужной для вас, то необходимо установить ее через composer внутри вашего модуля.
Для удобства рекомендуем разместить конфигурационный файл composer.json внутри папки /config вашего модуля, но папка vendor должна быть размещена в корневой папке модуля, так получится вот такая структура:
Чтобы добиться такой структуры, необходимо создать файл /config/composer.json в папке /config вашего модуля со следующим содержимым:
После этого можно открыть консоль вашей операционной системы и не выходя из папки /config выполнить команду на установку модуля через composer.
composer require ...имя пакета...
Автоматически будет создана папка /vendor в корне модуля, в которой будет установлена внешняя библиотека.
Теперь, чтобы воспользоваться внешними библиотеками из вашего класса в Readyscript, необходимо подключить /vendor/autoload.php внутри вашего класса в ReadyScript.
Пример:
На этом примере видно, что мы создали внутренний класс Telegram\Model\TgBot, который наследует и расширяет класс от внешней библиотеки TelegramBot\Telegram, установленной через composer.