Files
XC_VM/docs/ru/development/module-lifecycle.md
T
Divarion_D d4da90f37b fix(docs): translate bold spans atomically and auto-prune orphaned ru pages
The line-by-line web translator reordered words inside `**bold**` spans and
misplaced/dropped the markers, producing `**LB` or `****` (empty bold). Mask
each `**...**` as ONE atomic sentinel: translate the inner text on its own,
then store the whole balanced `**inner**` — the engine never sees the markers
and cannot reorder or collapse them. Also harden the anthropic prompt to keep
emphasis balanced.

Auto-prune: after translating, delete generated docs/ru files whose docs/en
source no longer exists (renamed/removed) and drop now-empty dirs, so the tree
mirrors docs/en 1:1 (removes the stale development/modules.md and
guides/geoip-and-device-detection.md).

Bump PROMPT_VERSION to 6 to invalidate the contaminated cache and regenerate
docs/ru (0 broken bold spans remaining, aside from pre-existing multi-line
bold that spans a soft line break).
2026-08-27 18:07:43 +03:00

7.7 KiB
Raw Blame History

Жизненный цикл модуля

Как XC_VM обнаруживает, загружает, включает/отключает, устанавливает и распространяет модули во время выполнения. Чтобы создать модуль, смотрите Разработка модуля; для его расширений смотрите Точки расширения модуля.

Включение / выключение модулей

Все обнаруженные модули загружаются по умолчанию. Используйте src/config/modules.php для переопределения состояния:

return [
    'my-module' => ['state' => 'disabled'],  // preferred
    // or legacy boolean (still accepted):
    'my-module' => ['enabled' => false],
];

Доступные значения state (подкрепленные перечислением ModuleState):

Ценность Значение
enabled Загрузка модуля (по умолчанию)
disabled Модуль обнаружен, но пропущен
installing Переходное состояние, заданное значением ModuleManager во время установки
failed Ошибка установки; модуль пропущен (не загружен)

Панельная диагностика. На странице Модули отображается желтый значок ⚠ Проблема зависимости рядом со статусом модуля, если требуемая зависимость отсутствует или не включена (например, в plex указано Enabled, а в watch - failed). Во всплывающей подсказке к значку перечислены конкретные проблемы. Это поле dependency_warnings вычисляется с помощью ModuleManager::listModules().

Чтобы переопределить класс, разрешенный для модуля:

return [
    'my-module' => ['class' => 'XcVm\\Module\\MyModuleV2\\MyModuleV2Module'],
];

config/modules.php содержит только переопределения. Пустой или отсутствующий файл означает, что все обнаруженные загружаются модули.


Как работает загрузка

ModuleLoader выполняет эти действия при каждом запросе:

  1. Сканирование src/Modules/*/module.json
  2. Применяет переопределения из config/modules.php
  3. Фильтры по окружающей среде (main / lb / any)
  4. Определяет порядок загрузки:
    • pruneUnsatisfiableModules() удаляет модули, требуемые зависимости которых недоступны (каскадно, с зарегистрированным предупреждением), чтобы загрузка никогда не прерывалась
    • Топологическая сортировка (DFS) по графу зависимостей
    • В пределах одной и той же группы зависимостей выполните сортировку по убыванию priority, затем по алфавиту
    • Выдает ModuleCycleException для циклов (подкласс \RuntimeException; циклические зависимости остаются фатальными)
    • Отсутствующие необязательные зависимости автоматически пропускаются
  5. Resolves class name: my-module → FQN XcVm\Module\MyModule\MyModuleModule (kebab-case → PascalCase; может быть переопределен с помощью клавиши class в конфигурации)
  6. Регистрирует автозагрузчик модуля PSR-4 (сопоставляет XcVm\Module\<Name> с каталогом модуля)
  7. Создает экземпляр класса module

В веб-контексте:

  • bootAll($container, $router) → вызовы boot(), registerRoutes(), registerNavbar(), и подписывается на события для каждого загруженного модуля

В контексте командной строки:

  • registerAllCommands($registry) → вызывает registerCommands() для каждого загруженного модуля

Marketplace: установка через расширение C

Модули с платформы устанавливаются через ModuleManager::downloadFromPlatform():

$manager->downloadFromPlatform(slug: 'my-module', version: '1.2.0', apiKey: $key);

Под капотом:

  1. XC_VM::module_install($slug, $version, $apiKey) — Расширение C загружает, расшифровывает и распаковывает файлы
  2. installModule($slug) — запускает install() в модуле
  3. EventDispatcher::dispatch(new PackageInstalledEvent(...)) — отправляет событие
  4. hotReload($slug, $path) — загружает модуль в текущем запросе без перезапуска PHP-FPM

Изолированные подсистемы

Модуль может быть полностью изолированной подсистемой со своей собственной точкой входа и начальной загрузкой (например, Ministra). Это соглашение, а не маркерный интерфейс — он остается обычный модуль ModuleInterface/BaseModule:

class MyModule extends BaseModule {

    public function getName(): string {
        return 'my-module';
    }

    public function getVersion(): string {
        return '1.0.0';
    }
}

Изоляция означает, что подсистема работает через свою собственную общедоступную точку входа (например, my-module/portal.php, путь относительно src/, который обрабатывает свой собственный bootstrap) с отдельным путем начальной загрузки. Он использует общую инфраструктуру (базу данных, кэш, конфигурацию), но участвует ли нет в основных Router, ModuleLoader::bootAll() или NavbarRegistry. Реализации boot() и registerRoutes() обычно являются оставлено как унаследованное бездействие.


Composer обнаружение пакета

Модули могут распространяться в виде Composer пакетов с "type": "xcvm-module":

{
    "name": "vendor/my-xcvm-module",
    "type": "xcvm-module",
    "extra": {
        "xcvm": {
            "module-path": "src"
        }
    }
}

ModuleLoader автоматически сканирует vendor/composer/installed.json (Composer 1 и 2 форматирует) и обнаруживает все установленные пакеты xcvm-module вместе со встроенным каталог src/Modules/. Пакеты дедуплицируются — модуль как в modules/, так и в vendor/ загружается только один раз.