shadoll / lime
lime
Requires
- php: >=7.4
- ext-json: *
- shadoll/anemone: ^4.1
- shadoll/crocus: ^1.0
- shadoll/lantana: ^3.1
- shadoll/riccia: ^1.0
Requires (Dev)
- phpstan/phpstan: ^0.12
- phpstan/phpstan-phpunit: ^0.12
- phpstan/phpstan-strict-rules: ^0.12
- phpunit/phpunit: ^8
- sebastian/phpcpd: ^4.1
README
Library for Lime
Install
composer require shadoll/lime
Логическая часть сервера lime
(для сценариев)
Назначение: Для разделения логики работы приложения от служебных действий.
Расширение построено на модульной (компонентной) структуре с использованием разных паттернов с разных групп Порождающие, Структурные, Поведенческие Порождающие, Структурные для основы работы сервисов и модулей (Singleton, Prototype, Adapter, Decorator) Поведенческие - в работе сценариев (Цепочка, Iterator, Mediator, State, ...)
Слово Condact
- было введено в этот проект для промежуточного простого
понятия сущности, а именно Условие/Действие. Т.е Condact
- это что-то одно
или условие, или действие (в будущем перечень может пополнится)
Модули
Модули представляют динамическое понятие - и смысл и их количество и принцип работы каждого из них нет смысла описывать. Это утверждение касается и условий/действий ...
Достаточно лишь описать интерфейсы которые та или иная сущность обязана реализовать.
Каждый новый модуль должен реализовать интерфейс Lime\Contracts\BeModule
и чаще всего
наследоваться от базового класса модулей Lime\Modules\BaseModule
(где происходит общие действия для всех модулей), разве
если модуль имеет нестандартное поведение можно опустить этот класс
Во всех модулях (которые наследовались от базового абстрактного модуля)
могут регистрировать все свои условия и действия в статическом свойстве $REGISTERED
(без этого класса вам самим придется позаботится о регистации своих событий)
Lime\Contracts\BeModule
Все абстрактные методы интерфейса Lime\Contracts\BeModule
понятны из своего
названия, остановимся на некоторых
getClient
- может возвращать клиент для модуляdynamically
- должен возвращать массив динамических данных для конкретного Condact. (чаще всего возвращает пустой массив) Также у Condact реализован методforDynamically
для дополнительного ключа (решать разработчику какая логика внутри метода будет)fullDynamically
- Все свойства модуля (методdynamically
является частным случаем этого большого метода) (но также все решает разработчик)getValueFor
- этот метод должен уметь отдавать свои данные (данных канешно он не имеет своих, но должен знать как их достать с хранилища с учетом всех уровней вложенности и т.д) Метод достаточно сложен в реализациях для каждого из модулейgetConverting
- получение объекта интерфейсаLime\Contracts\BeConverting
для модуляinit
- инициализация модуля (подготовка данных, первичная инициализация в системе и т.д.)
Lime\Contracts\BeCondact
Обобщенный служебный интерфейс (Его наследуют Lime\Contracts\BeAction
,
Lime\Contracts\BeCondition
)
Все методы также понятны с названия (некоторые):
statically
- Доп. настройки для конкретного Condact (для фронта) (для условий и действий по разному обрабатываются):deep
- дополнительные настройки для Condact (см. примеры)inner
- дополнительные настройки для Condact, поля по которым будет чтото происходить (см. примеры) (важной особенностью - есть наследование от динамики)operator
- для доп. фильтрации операторreplace
- доп данные для работы со свойством объекта.
forDynamically
- дополнительный ключ для метода модуляdynamically
описан выше.
Lime\Contracts\BeAction
, Lime\Contracts\BeCondition
Интерфейсы Действия и Условия.
Каждый Condact должен реализовать 1 из этих интерфейсов
Методы:
handle
- Непосредственная обработка контекста Condact- атрибут
$inner
- данные конфигурации из конкретного элемента правила - массив
$deep
- вложенная глубина элементов всех уровней вплоть к родителю, элементом родителя всегда является0
, то есть итерация с индексом 0
- атрибут
Сервисы
Сервисы должны реализовать интерфейс Lime\Contracts\BeService
Основными (на текущий момент) сервисами являются Lime\Services\ModulesService
и Lime\Services\DataStateService
По необходимости если недостаточно модуля для работы - можно создать свой
сервис (как пример Lime\Modules\Anemone\AnemoneService
) для
более сложной работы с модулями. Сервис интерфейса Lime\Contracts\BeAgent
может быть инициализирован по надобности (как пример при невозможности сериализации
объекта и т.д. пример в том же Lime\Modules\Anemone\AnemoneService
)
Lime\Services\ModulesService
Сервис предназначен для контроля и работы всех модулей системы в рамках одного кастомера (Сервис в основном используется для служебных целей в сервере lime (получение статических и динамических данных о всех известных модулях в рамках кастомера))
Для инициализации необходима модель Lantana\Models\JSSharedCustomers
, если
не смогли ее передать аргументом конструктора - то должны передать в
метод init
прежде нежели будете использовать сервис
Методы:
isReady
- возвращает статус готовности сервиса к работеgetCustomer
- текущий кастомерLantana\Models\JSSharedCustomers
getModules
- список зарегистрированных модулей кастомераgetModule
- получить модуль поuuid
или значения методаgetID
модуляgetEntities
- Получить коллекцию примитивных сущностей модулей (в основном для сериализации для фронт приложения)statically
- список зарегистрированных статических модулейgetAvailableModules
- список зарегистрированных классов модулей
Все новые модули необходимо регистрировать в константе интерфейса
Lime\Contracts\BeModuleService
MODULES_AVAILABLE
Lime\Services\DataStateService
Данный сервис предназначен для работы с данными во время работы сценария. То есть во время работы его состояние постоянно мутирует в зависимости от исхода работы того или другого Condact.
Данные сервиса мутируют в 2 плоскостях: вертикально (по уровням) и горизонтально (по точкам прохождения сценария по Condact)
Причем, вертикальные данные видны сверху (уровня что выше) вниз (к корневому уровню). Вертикальные данные уничтожаются после того как курсор программы покинул уровень вниз (так как вверх покидая курсор будет возвращаться через этот уровень, соответственно есть такая видимость данных) В вики есть рисунки по данным
Так же на каждом уровне можно получить дополнительную изоляцию по названию пулл данных
.
Эти данные так же подчиняются тем же правилам видимости, однак у них особенность
даные могут быть уничтожены до выхода курсора с уровня вниз. Как вывод - на
одном уровне после уничтожения пула можно создать новый пулл и так далее.
В статическом свойстве $MODULES_DATA
регистрируются возможные коллекции и инжекторы
всех статических модулей (в основном это для настройки сценариев)
Все методы этого сервиса - суть в их названиях
Инжекторы
Это дополнительные вспомагательные объекты которые могут внедрять
первичные данные для старта сценария. (возможно надобность в них не оправдана).
Примером инжектора есть Lime\Modules\Anemone\Inject\HookDecorator
котрый
имеет данные амо хука.
Инжекторы должны реализовать интерфейс Lime\Contracts\BeInject
(2 метода, для
инициализации и деструктиризации Инжектора)
Конвертеры
Нужны для более сложной обработки данных (структуры данных) (чего нельзя
добиться или неэффективно в самом модуле) о нем вспоминали при получении в
методе модуля getConverting
2020-06-04 Добавлены исполнители конвертеры (фактически сделан реффакторинг,
логика каждого типа конвертера вынесена в отдельные классы. Фактически объекты
интерфейса Lime\Contracts\BeConverting
становятся проксирующими классами)
Конвертеры должны реализовать интерфейс Lime\Contracts\BeConverting
getValue
- для получения значения "расчета" конвертераgetPreparingData
- подготовка данных (тут необходимо немного вникать так как не все однозначно с этим методом)getConvert
- получить объект интерфейсаLime\Contracts\BeExecuteConvert
(исполнительные конвертеры)
Конвертеры должны неявно принадлежать одному из модулей.
Исполнительные конвертеры
Для простоты конвертеров - один класс конвертера исполнителя должен делать
одно простое действие конвертации. Каждый исполнительный конвертер должен реализовать
интерфейс Lime\Contracts\BeExecuteConvert
(для передачи доп. данных в исполнитель
, если недостаточно метода, используйте конструктор)
Часто встречается параметр extends
внутри статических данных Condact или
модулей (в секциях deep
, inner
, ...).
Особенности паттерна:
- | - разделитель для получения данных из разных ключей:
'extends' => 'deep|pull',
- . - разделитель фильтра, где после точки может быть значение вильтра
или ключ-значение фильтра:
'extends' => 'rules.event:App\\Events\\InnerRuleEvent',
- : - разделитель значения фильтра (выше)
(работает пока не в полном объеме)
===
to be continue...