Files
XC_VM/docs/ru/development/autoloader.md
T
Divarion-D f8a37947b1 feat(tmdb)!: fold the tmdb module into core, replace stale standard-set copies
The panel is deeply coupled to TMDb (VOD import, player metadata, admin
search, two crons), so shipping it as an uninstallable module only added
failure modes: after the move to hash-suffixed dirs (tmdb_f4e6e) every
hardcoded `Modules/tmdb/lib/...` require broke, and 2.3.3 crons died with
"Failed opening required TmdbClient.php".

tmdb -> core:
- Vendored \TMDB client -> src/Infrastructure/Tmdb/lib/; the only loader
  is TmdbApiService::requireLibrary() (now public, also loads Release.php).
- TmdbApiService -> XcVm\Infrastructure\Tmdb — composer-autoloaded in every
  bootstrap context, no module boot required (player scope never booted
  modules, so module-namespace classes were unreachable there).
- TmdbCron / TmdbPopularCron -> XcVm\Domain\Vod; cron jobs -> Cli/CronJobs
  (picked up by the console.php scan; command names cron:tmdb and
  cron:tmdb_popular are unchanged).
- TmdbController -> Public/Controllers/Admin; tmdb_search / tmdb api
  actions registered in routes/admin.php (same dispatchApi fallback).
- Domain/Vod services and player_functions.php load the lib through
  TMDbService::requireLibrary() instead of hardcoded module paths.
- tmdb removed from config/bundled_modules.php. ModuleLoader gains
  CORE_PROVIDED_MODULES: released watch/plex archives still declare
  "dependencies": ["tmdb"] — such deps are stripped during manifest
  normalization and in ModuleManager::listModules().
- syncBundledModules() purges stale on-disk tmdb module dirs and their
  config/modules.php state on upgraded panels, so the old copy cannot boot
  alongside the core implementation and collide on command names.

Standard-set provisioning fix (root cause of the "Undefined variable $db"
errors from watch/plex settings views on 2.3.3):
- Production still ran watch_e6c86/plex_20cd9-less legacy copies migrated
  from 2.3.2 with generated hash_ids; provisionStandardSet() treated any
  same-name directory as "already on disk" and never fetched the pinned
  1.0.2/1.0.1 releases that contain the fix. A same-name directory whose
  identity does not match the pinned hash_id is now considered stale: it
  is deleted and the pinned release is installed in its place.
- installModuleFromSource(): when the module is already recorded as
  installed (files re-provisioned over a stale copy), run updateModule()
  (incremental from->to migrations) instead of re-running the initial
  install.
2026-07-05 20:17:31 +03:00

112 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Автозагрузка (PSR-4)
XC_VM загружает классы стандартным автозагрузчиком **Composer PSR-4**; namespace кодирует путь к файлу, поэтому разрешение — это прямой `file_exists` без сканирования и без кэша.
---
## Обзор
Каждый класс первого уровня живёт под корневым namespace `XcVm\`, отображённым на `src/`:
```text
XcVm\Core\Auth\Authenticator -> src/Core/Auth/Authenticator.php
XcVm\Domain\Stream\StreamService -> src/Domain/Stream/StreamService.php
XcVm\Public\Controllers\Admin\UserController -> src/Public/Controllers/Admin/UserController.php
```
Маппинг объявлен в `src/composer.json`:
```json
"autoload": {
"psr-4": {
"XcVm\\": "./",
"M3uParser\\": "Core/Parsing/M3uParser/src/",
"Chrisyue\\PhpM3u8\\": "Core/Parsing/PhpM3u8/src/"
}
}
```
`src/vendor/` (автозагрузчик Composer + продакшен-зависимости) закоммичен и
поставляется как есть — на пути деплоя нет Composer и `composer install` не
запускается. **Кэша карты классов нет** (без `optimize-autoloader`): промах по
классу — это обычный поиск по пути, а не пересканирование каталогов.
## Добавление нового класса
Создайте файл по пути, на который отображается его namespace — и всё; Composer разрешит его по требованию:
```php
// src/Domain/Billing/InvoiceService.php
namespace XcVm\Domain\Billing;
class InvoiceService {
public static function generate(int $userId): string { /* ... */ }
}
```
Ссылайтесь на него из другого namespaced-кода через `use` или по FQCN:
```php
use XcVm\Domain\Billing\InvoiceService;
```
Кэш чистить не нужно, реестр править не нужно. Новый под-namespace (например,
`XcVm\Domain\Billing`) работает сразу, потому что отображается прямо на каталог.
## Правила именования
| Правило | Пример |
| --- | --- |
| Имя файла **должно** совпадать с именем класса | `InvoiceService.php` → `class InvoiceService` |
| Один класс на файл | PSR-4 разрешает один класс на путь; multi-class файлы разделять |
| Namespace **должен** совпадать с путём каталога (регистрозависимо) | `src/Domain/Billing/` → `namespace XcVm\Domain\Billing;` |
| PascalCase для классов и каталогов | `StreamService`, `DatabaseHandler`, `Core/Auth/` |
| Соглашение проекта: без `declare(strict_types=1)` | — |
Поскольку namespace несёт расположение, одинаковые короткие имена в разных
namespace больше не конфликтуют — `XcVm\Public\Controllers\Admin\PlexController` и
`XcVm\Module\Plex\PlexController` различны.
## Процедурные и сторонние файлы
Некоторые файлы намеренно **не** в namespace и подключаются явным `require`, а не
автозагрузчиком:
- процедурные точки входа, view и bootstrap-склейка (`Public/index.php`,
`Public/Views/**`, `Infrastructure/Bootstrap/*.php`);
- глобальные константы и функции (`Core/Config/*`, обработчик ошибок);
- ioncube-класс `XC_VM` и встроенный `Infrastructure/Tmdb/lib/*`.
Вендорные пакеты `M3uParser` и `Chrisyue\PhpM3u8` имеют собственные PSR-4-префиксы
(выше) и автозагружаются штатно.
## Модули
Классы модулей используют namespace `XcVm\Module\<Name>\…`, но **не**
регистрируются в `composer.json` (slug-каталоги модулей/маркетплейса — `plex`,
`watch-d2bho` — не укладываются в одно PSR-4-правило). Их разрешает собственный
PSR-4-резолвер `ModuleLoader`: снимает базовый namespace модуля и отображает
остаток на под-путь внутри каталога модуля. См. [Систему модулей](modules.md).
## Инструменты разработки
Закоммиченный `vendor/` — только продакшен. PHPStan и PHP-CS-Fixer — это
`require-dev`-пакеты; ставьте их локально командой:
```bash
make dev-tools # = cd src && composer install
```
Они никогда не коммитятся (CI-гейт требует прод-only закоммиченный vendor). См.
[Рабочий процесс разработки](../guides/dev-workflow.md).
## Связанные файлы
| Файл | Роль |
| --- | --- |
| `src/composer.json` | Карта PSR-4-префиксов + зависимости |
| `src/composer.lock` | закоммиченный lock для воспроизводимого `composer install` |
| `src/vendor/` | закоммиченный автозагрузчик Composer + прод-зависимости |
| `src/bootstrap.php` | определяет `MAIN_HOME`, подключает `vendor/autoload.php` |
| `src/Core/Module/ModuleLoader.php` | PSR-4-резолвер классов модулей |