mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-03 12:02:29 +02:00
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).
142 lines
7.7 KiB
Markdown
142 lines
7.7 KiB
Markdown
# Жизненный цикл модуля
|
||
|
||
Как XC_VM обнаруживает, загружает, включает/отключает, устанавливает и распространяет модули во время выполнения. Чтобы создать модуль, смотрите [Разработка модуля](module-authoring.md); для его расширений смотрите [Точки расширения модуля](module-extension-points.md).
|
||
|
||
## Включение / выключение модулей
|
||
|
||
|
||
Все обнаруженные модули загружаются по умолчанию. Используйте `src/config/modules.php` для переопределения состояния:
|
||
|
||
```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()`.
|
||
|
||
Чтобы переопределить класс, разрешенный для модуля:
|
||
|
||
```php
|
||
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()`:
|
||
|
||
```php
|
||
$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`:
|
||
|
||
```php
|
||
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"`:
|
||
|
||
```json
|
||
{
|
||
"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/` загружается только один раз.
|
||
|
||
---
|