Контракт и совместимость
Провайдер — сторонний код: он наследует AbstractEndpoint, реализует EndpointInterface, зовёт Request, Response, Config. Значит, у него есть право знать, на что можно опираться, а что завтра перепишут.
Эта страница отвечает на три вопроса: что обещано, как это проверяется и что будет с обеими линиями пакета дальше.
Что обещано
Каждый класс ядра (MxApi\Core\*) объявляет свою природу тегом в docblock.
| Тег | Значение |
|---|---|
@api | Обещание стороннему коду. Публичные и protected-сигнатуры не меняются внутри старшей версии |
@internal | Внутренняя механика. Может измениться в любом релизе без предупреждения |
Публичная часть (@api)
| Класс / интерфейс | Зачем нужен провайдеру |
|---|---|
Endpoint\AbstractEndpoint | база эндпоинта: readParams(), readPaging(), readCursor(), nextCursor() |
Endpoint\ProcessorEndpoint | эндпоинт поверх процессора MODX и его хуки |
Endpoint\EndpointInterface | контракт эндпоинта: getMetadata(), handle() |
Endpoint\EndpointMetadata, Endpoint\ParameterMetadata | паспорт эндпоинта и его параметров, включая константы |
Endpoint\EtagAwareInterface | необязательный интерфейс: версия ответа до его сборки |
Endpoint\EndpointContext | платформа, конфигурация, авторизация внутри handle() |
Http\Request, Http\Response, Http\ApiException | вход, ответ и ошибки |
Config | чтение настроек пакета |
Provider\ProviderInterface | контракт провайдера |
Middleware\MiddlewareInterface | контракт промежуточного обработчика |
Auth\AuthContext, Platform\PlatformUser, Platform\ProcessorResult | что приходит в эндпоинт при авторизации и от процессора |
Platform\PlatformInterface | читать можно, реализовывать не нужно: адаптеры платформы поставляет сам пакет |
protected-методы AbstractEndpoint и ProcessorEndpoint — тоже часть контракта: ради них класс и наследуют.
Внутренняя часть (@internal)
Kernel, Routing\Router, Routing\RouteMatch, Registry\EndpointRegistry, Registry\CatalogFilter, OpenApi\OpenApiGenerator, Http\ETag, Paging\Cursor, Auth\TokenService и репозитории, Maintenance\MaintenanceService, встроенные обработчики Middleware\RateLimitMiddleware и Middleware\IdempotencyMiddleware.
Пользоваться ими из провайдера не надо: то, что вам от них нужно, доступно через публичные классы. Например, курсор создаётся не Cursor::encode(), а nextCursor() — иначе вы завяжетесь на формат подписи, который вправе измениться.
Публичный HTTP-контракт — отдельная вещь
Маршруты, конверт success / data / meta, коды ошибок, имена параметров и таблицы БД — это контракт с вызывающей системой, а не с кодом провайдера. Он тоже соблюдается по semver, и его правила описаны там, где описан он сам: Токены и аутентификация, Каталог и OpenAPI.
Как это проверяется
Граница не живёт «в головах» — она проверяется тестами пакета, и их два.
Слепок контракта. Сигнатуры и константы всех @api-классов записаны в фикстуру. Любая правка публичной сигнатуры роняет тест, и diff фикстуры прямо показывает, что именно меняется у интеграторов. Класс ядра, забывший объявить @api или @internal, тест тоже роняет — «внутренний по умолчанию» здесь не работает.
Паритет ядра. Каталог src/Core в линиях для MODX 2 и MODX 3 побайтово одинаков: различаются только адаптеры платформы. Манифест хэшей лежит в обеих линиях одним и тем же файлом, поэтому забытый перенос правки роняет тесты той линии, куда её не донесли — а не всплывает у интегратора, который написал провайдера один раз на обе версии MODX.
Версии и линии
У пакета две линии, они развиваются параллельно и отличаются только платформой:
| Линия | MODX | PHP |
|---|---|---|
1.x | Revolution 2.6+ | 7.4+ |
2.x | Revolution 3.0+ | 8.1+ |
Старшая цифра здесь не значит «новее»: 2.x — это не следующая версия после 1.x, а та же функциональность на другой платформе. Возможности появляются в обеих линиях одновременно и с одинаковой средней цифрой: 1.1.0 и 2.1.0 — один и тот же релиз.
Правила смены цифр внутри линии обычные:
| Цифра | Когда меняется |
|---|---|
| старшая | ломающая правка @api-класса или публичного HTTP-контракта |
| средняя | новые возможности, совместимые со старым кодом провайдеров |
| младшая | исправления |
Что считается ломающим: удаление или переименование публичного метода, новый обязательный параметр, новый метод в интерфейсе, который реализуют сторонние классы, смена смысла возвращаемого значения. Что ломающим не считается: новый необязательный ключ паспорта эндпоинта, новый необязательный интерфейс (как EtagAwareInterface), новый метод AbstractEndpoint, изменение чего угодно с тегом @internal.
Что будет с линией для MODX 2
Линия 1.x живёт, пока её можно развивать без ломающей правки ядра. Когда очередная возможность потребует сломать публичный контракт в двойке, поддержка линии на этом остановится: версии 2.0.0 для MODX 2 не будет.
Причина простая. Ломающая правка означает, что установленные провайдеры чинить придётся всем, а на MODX 2 «починить» обычно значит «перейти на MODX 3». Растить в двойке параллельную несовместимую ветку — это два разных ядра под одним именем и конец паритету, ради которого провайдер и пишется один раз.
Что это значит на практике: код провайдера, написанный по @api-контракту сегодня, работает в обеих линиях и продолжит работать в двойке до конца её поддержки. Готовиться к переезду нужно не к дате, а к событию — объявлению о заморозке линии; оно будет в changelog пакета.
Что это значит для вашего пакета
- Опирайтесь только на
@api. Всё нужное там есть; если кажется, что нет — вероятно, задача решается иначе, чем через внутренний класс. - Читайте changelog при обновлении mxApi. Ломающие правки описываются там поимённо: какая сигнатура изменилась и что делать.
- Пишите провайдера один раз на обе линии. Платформенно-зависимый код — это
getModx()и то, что вокруг него; всё остальное переносится без правок.ProcessorEndpointпереносится целиком, кроме адресации самого процессора (Свой эндпоинт). - Свои эндпоинты версионируйте сами. Ваш
pathиscope— это ваш публичный контракт с интегратором, и mxApi за него не отвечает. Для смены несовместимого маршрута естьroute_aliases: старый путь остаётся рабочим и указывает на тот же эндпоинт.
Дальше
- Свой эндпоинт: пошагово — как написать провайдера.
- Справочник эндпоинта — все ключи паспорта, хуки, события, кэширование ответов и курсоры.
- Системные настройки — что настраивается на стороне сайта.
