Перейти к содержанию

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

Как 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. Определяет порядок загрузки:
  5. pruneUnsatisfiableModules() удаляет модули, требуемые зависимости которых недоступны (каскадно, с зарегистрированным предупреждением), чтобы загрузка никогда не прерывалась
  6. Топологическая сортировка (DFS) по графу зависимостей
  7. В пределах одной и той же группы зависимостей выполните сортировку по убыванию priority, затем по алфавиту
  8. Выдает ModuleCycleException для циклов (подкласс \RuntimeException; циклические зависимости остаются фатальными)
  9. Отсутствующие необязательные зависимости автоматически пропускаются
  10. Resolves class name: my-module → FQN XcVm\Module\MyModule\MyModuleModule (kebab-case → PascalCase; может быть переопределен с помощью клавиши class в конфигурации)
  11. Регистрирует автозагрузчик модуля PSR-4 (сопоставляет XcVm\Module\<Name> с каталогом модуля)
  12. Создает экземпляр класса 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/ загружается только один раз.