Commit Graph
77 Commits
Author SHA1 Message Date
Divarion_D 98aea670c3 build(rector): add Rector scaffolding (stage 1 — config + make targets + docs)
Adopt Rector as a require-dev tool alongside PHPStan/phpcs for safe, mechanical
refactoring:

- src/composer.json: add rector/rector ^2.0 (require-dev) + refactor/refactor:dry
  composer scripts.
- build/rector.php: narrowly-scoped config over the PSR-4 class trees
  (Core/Domain/Cli/Infrastructure). Skips the \TMDB lib, the streaming hot-path,
  vendor, tmp/backups. Import-adding stays OFF (the check-procedural-use gate
  relies on positional use imports). Behaviour-changing rules are disabled
  (SafeDeclareStrictTypes, UseIdenticalOverEqualWithSameType); only the safe
  deadCode + codeQuality prepared sets run (incl. the empty-if/else collapse).
- Makefile: `make rector` (dry-run, non-zero on pending changes) and
  `make rector-fix` (apply). Both require dev-tools.
- docs/en/guides/refactoring.md + dev-workflow.md + mkdocs.yml nav: the
  detect -> diff -> verify -> apply workflow.

No source code is changed by this commit — scaffolding only. `make rector-fix`
output will be reviewed separately.
2026-09-13 16:48:17 +03:00
Divarion_D 53efe7071c refactor(admin-ui): rename vuexy identifiers to newui + fix mangled names
Rename the last lowercase "vuexy" identifiers left after the de-brand:
- views {header,footer,menu,vendors,topbar}.vuexy.php -> .newui.php
- functions xc_admin_use_vuexy / xc_vuexy_vendor_* / _xc_vuexy_icon -> *_newui*
- constant XC_VUEXY_PAGES -> XC_NEWUI_PAGES
- E2E spec vuexy-tables.spec.ts -> newui-tables.spec.ts + drop the brand
  name from test/Makefile prose

Also fix two identifiers the earlier brand scrub corrupted (a bare "Vuexy"
in a name became "Bootstrap 5", inserting a space): class
XcVuexyMenuBuilder -> XcNewuiMenuBuilder (was a parse error in the menu view)
and global key xmVuexyVendors -> xmNewuiVendors.

Refs: #148 #178
2026-09-03 19:50:15 +03:00
Divarion_D f348cf08cc test(e2e): Playwright smoke harness for the Bootstrap 5 admin
Add a browser E2E project under tests/e2e/ that runs against a live panel
(there is no built-in server). Verified green (7/7) against a canary instance.

- playwright.config.ts: loads tests/e2e/.env (dotenv); a `setup` project logs in
  once (auth.setup.ts — form #username/#password/#login_button -> ./login) and
  stores the session, the chromium project reuses it via storageState. baseURL is
  normalized to a trailing slash so relative gotos keep the access-code segment.
- Smoke specs: shell renders (sidebar/navbar, server-stamped data-bs-theme);
  Dashboard group + Home link; six stat tiles + a live ./api?action=stats 200;
  charts + server selector; customizer theme change persists across reload and
  reset (opening the customizer panel) clears it.
- Config via env: XC_E2E_BASE_URL (admin base incl. access code), XC_E2E_USER,
  XC_E2E_PASS (see .env.example / README). Makefile: `make e2e` / `e2e-ui` /
  `e2e-install`. node_modules/.auth/results/.env gitignored; @playwright/test
  pinned ~1.49 (Node 18+).
2026-09-01 20:14:21 +03:00
Divarion_D 1aede3bf4c refactor(i18n): co-locate language files with the Translator
Move the .ini language files from src/resources/langs/ to
src/Core/Localization/lang/, next to the Translator subsystem that owns
them — which already defaulted its $langsDir to __DIR__ . '/lang/'. This
dissolves the now-vestigial src/resources/ bucket (its data/ tree went
with admin_constants, libs/ was empty).

- bootstrap.php calls Translator::init() with no argument, relying on the
  class's own __DIR__-relative default instead of MAIN_HOME . 'resources/langs/'.
- Makefile LB removal list points at Core/Localization/lang (and drops the
  gone resources/langs, resources/libs); LB still ships no UI translations.
- Drop the stale src/resources entries from phpstan scanDirectories and the
  phpunit coverage excludes.
- Update the English docs (translations guide, build-system table); the ru
  tree is regenerated before release.
2026-08-31 21:28:16 +03:00
Divarion_D c27950093f refactor(admin): replace admin_constants globals with reference classes and enums
Move the 17 global lookup arrays from resources/data/admin_constants.php
into PSR-4 classes and enums, eliminating the last big pile of `global`
reference data.

New XcVm\Core\Reference\* (const + static accessors, FfmpegBinaries-style):
GeoReference, LocaleReference, DeviceReference, UiReference,
PermissionReference, StatusBadge. New XcVm\Core\Enum\* (backed enums with
label()/options(), ModuleState-style): Theme (int), ResellerAction and
ClientFilter (string).

All consumers migrated off `global $rX` / `$GLOBALS['rX']` and the
BaseAdminController extract bridge: TableController, DashboardController,
SearchAjaxController, SettingsController, ResellerAPI and
ResellerLoginController call the classes directly, and 21 view templates
import them via `use`. The extract whitelist entries, the bootstrap
require and admin_constants.php itself are removed.

Fixes a latent bug: TableController read $rClientFilters without a
`global`, so the client-request log showed raw status codes instead of
labels; ClientFilter::labelFor() now resolves them.

The reference classes and the three new enums are excluded from the
load-balancer build (all consumers are already MAIN-only).

Adds unit tests for the enums, StatusBadge and the reference data.
2026-08-31 20:58:23 +03:00
Divarion_D 8aff75f91b fix(fanout): keep run.sh executable so xc_fanout always starts
The keepalive supervisor bin/xc_fanout/run.sh was deployed without its exec bit (a mode-dropping sync left it 0644), so 'service' could not launch it -> xc_fanout never started -> every stream served the not-on-air clip. Three defences: (1) Makefile set_permissions ships run.sh (and console.php) as 0755 in the archive; (2) service launches it via 'bash run.sh' so a lost exec bit no longer breaks startup; (3) StartupCommand chmods it +x on boot as a backstop.
2026-08-23 22:12:45 +03:00
Divarion_D 48a69def2b build(docs): unbuffered translate output, cache/venv under build/
Run tools/docs/translate.py with python -u and print per-file progress so 'make docs-translate' shows live output instead of going silent. Relocate the translation cache and venv under build/ (build/docs-cache, build/docs-venv).
2026-08-23 13:49:58 +03:00
Divarion_D 9dd2ac2a48 chore(cs): replace PHP-CS-Fixer with phpcs + Slevomat Coding Standard
PHP-CS-Fixer's `no_unused_imports` is conservative — it treats a class name that
merely appears in a PHPDoc *description* as "used", so genuinely-dead imports
(e.g. `use ...Request;` next to a "Request IP" doc description) were never
flagged. Slevomat's UnusedUses is precise: it parses annotation *types*
(@param/@return/@var), so it keeps docblock-typed imports but removes truly
unused ones — matching what Intelephense (P1003) reports.

- Swap require-dev: friendsofphp/php-cs-fixer -> squizlabs/php_codesniffer +
  slevomat/coding-standard (+ phpcodesniffer-composer-installer, allow-listed).
- New narrow ruleset build/phpcs.xml.dist (import/namespace hygiene only, NOT
  full PSR-12): UnusedUses (searchAnnotations=true), UseFromSameNamespace,
  UseDoesNotStartWithBackslash, AlphabeticallySortedUses, UseSpacing,
  NamespaceSpacing. View templates stay excluded.
- Makefile: `make cs` -> phpcs, `make cs-fix` -> phpcbf (same target names).
- CI code-style job, CLAUDE.md, CONTRIBUTING.md, docs, .gitignore updated;
  build/.php-cs-fixer.dist.php removed. Committed vendor stays production-only.
2026-08-21 17:55:24 +03:00
Divarion_D 5b06aa4c46 docs: output MkDocs build to build/site (keep repo root clean)
Move the generated site out of the repo root: site_dir -> build/site, with the
Pages upload path and .gitignore updated to match. build/ already holds tooling
config, so the build output no longer clutters the top-level listing.
2026-08-21 17:17:18 +03:00
Divarion_D bdbcde97c7 docs: commit generated ru, translate locally before release (not in CI)
CI translation was slow, so move it out of GitHub Actions: docs/ru is now a
committed, generated tree refreshed LOCALLY before a release; CI only builds it.

- pages.yml: drop the setup-python/cache/translate steps — the workflow now just
  installs the build toolchain and runs `mkdocs build --strict` on the committed
  en+ru trees.
- .gitignore: stop ignoring docs/ru (now committed); keep site/ + .docs-cache/.
- Split deps: docs/requirements.txt = build only (mkdocs-material, static-i18n,
  used by CI); tools/docs/requirements.txt = translators (local-only).
- Makefile: docs-venv installs both; docs-build/docs-serve no longer translate
  (translation is the deliberate `make docs-translate` release step).
- updates_checklist.md: new "Regenerate translated documentation" step
  (make docs-translate + docs-build, commit docs/ru with the release commit).
- Commit the generated docs/ru (37 files, translators/yandex).

Rule: edit ONLY docs/en; docs/ru is generated — never hand-edit it.
2026-08-20 22:37:44 +03:00
Divarion_D dcd1d8c860 docs: migrate to MkDocs Material with auto-translated ru from English
Replace the hand-maintained Docsify site (parallel docs/en + docs/ru trees
that had already drifted) with a MkDocs Material build where English is the
single source of truth and Russian is generated at build time.

Engine & structure
- mkdocs.yml: Material theme, site_url for the /XC_VM/ Pages subpath, and a
  two-tab information architecture — User Guide (administration, API/Swagger,
  UI translations, diagnostics, info/FAQ) vs Developer Guide (architecture,
  workflow, security, integrations, build). Files are NOT moved — the split is
  nav-only, so URLs and cross-links stay stable.
- mkdocs-static-i18n (folder mode): English at root, Russian under /ru/, with a
  language switcher. `mkdocs build --strict` validates every link/anchor.

Translation pipeline (tools/docs/translate.py)
- Engine-agnostic via DOCS_TRANSLATE_PROVIDER: translators (free, no API key —
  default), anthropic, deepl, or noop. Per-file sha256 cache so only changed
  English files are re-translated. Markdown-safe: code, URLs, HTML tags and
  glossary terms (XC_VM, FFmpeg, HLS, ...) are masked and never translated.
  A file whose translation fails falls back to English so the build never breaks.
- docs/ru is generated and gitignored — never committed. It is produced locally
  (`make docs-serve` / `docs-build`) and in CI.

CI & tooling
- pages.yml: build-then-upload (setup-python -> install -> restore .docs-cache
  with restore-keys -> translate -> mkdocs build --strict -> deploy), replacing
  the verbatim docs/ upload.
- Makefile: docs-venv / docs-translate / docs-build / docs-serve.
- docs/requirements.txt; .gitignore for docs/ru, site/, .docs-cache.

Migration details
- Removed Docsify control files (index.html, _navbar.md, _sidebar.md, .nojekyll)
  and de-Docsify-ed body links in 6 English files (en-us/ aliases -> relative,
  swagger _media paths, stripped ':ignore' link syntax).
- Preserved the two Russian-only planning docs (no English source) by moving
  them into docs/adr/ as *.ru.md (repo-internal, excluded from the site).
2026-08-20 22:09:34 +03:00
Divarion_D 9ffbe1a34b build: add on-demand phpstan-deadcode audit (unused-public)
Adds a `make phpstan-deadcode` target and build/phpstan-deadcode.neon that
layer tomasvotruba/unused-public on top of the main PHPStan setup to report
unused PUBLIC methods/properties/constants. It is an on-demand audit, NOT a
CI gate (expect false positives for dynamically-invoked code — routes,
#[ListensTo] subscribers, CLI handlers, view templates).

unused-public is a require-dev package (installed by `make dev-tools`); the
committed vendor/ stays production-only.
2026-08-11 21:45:32 +03:00
Divarion_D fda7f41258 refactor(ministra): move Stalker portal from module into core (src/Ministra)
Ministra stops being a module — the whole Stalker portal (portal.php,
MinistraBootstrap, PortalHandler/PortalHelpers and the STB front-end) now
lives in src/Ministra/ under the XcVm\Ministra namespace, served at
/home/xc_vm/Ministra via the nginx alias.

- src/ministra/* and Modules/ministra_85a7d/{PortalHandler,PortalHelpers}
  → src/Ministra/; MinistraModule.php + module.json removed. Ministra was
  the only committed module, so src/Modules/ keeps a .gitkeep.
- portal.php resolves PortalHandler as a sibling and derives MAIN_HOME from
  its new location (glob crutch gone).
- nginx alias + AuthRepository $rAlias switched to /home/xc_vm/Ministra
  (PascalCase); ministra entry dropped from bundled_modules.php.
- Makefile: Modules/ removed from LB_DIRS — all modules are MAIN-only, so
  the ~50 MB of portal assets no longer ship to LB nodes.
- ArchitectureTest: zero committed modules is now a valid state.
- PHPStan: analyse src/Ministra, exclude the procedural portal.php entry,
  repath the ministra baseline entries.
- Docs (architecture, ministra-browser-emulation, extraction plan) updated
  to the new layout; the "extract to a separate repo" plan is cancelled.

Verified: php -l, make gates, make phpstan (No errors), full unit suite
(432 tests). On-server smoke: handshake + get_profile work end-to-end with
a registered MAC after deploy.
2026-08-11 21:41:11 +03:00
Divarion_D 7f3812e165 chore(build): move phpstan / php-cs-fixer config out of the repo root
Relocate the dev-tooling config into build/ so the project root only holds
source and first-class project files:
- phpstan.dist.neon        -> build/phpstan.dist.neon
- phpstan-baseline.neon    -> build/phpstan-baseline.neon
- .php-cs-fixer.dist.php    -> build/.php-cs-fixer.dist.php
- .php-cs-fixer.cache       -> build/ (regenerated there; gitignored)

Because neon/CS-Fixer resolve relative paths against the config file's own
directory, the internal references are re-anchored one level up (src/ ->
../src/, tools/ -> ../tools/, Finder in(__DIR__.'/../src'); the baseline's
path: entries likewise). The Makefile now points PHPStan at the config with
-c build/phpstan.dist.neon (it previously relied on root auto-discovery),
generates the baseline into build/, and passes --config=build/... to CS-Fixer;
the CS-Fixer cache is pinned to build/ via setCacheFile and re-gitignored.

No behaviour change. Verified: make phpstan (No errors), make cs (0 fixable),
make gates. CI runs through these make targets, so it is covered.
2026-08-09 19:37:11 +03:00
Divarion_D cb056cdcf5 fix(phpstan): wire constants-stub regen into make, refresh drifted stub
gen-constants-stub.php had no Makefile/CI target, so tools/phpstan/
constants.stub.php (a bootstrapFile in phpstan.dist.neon) silently drifted:
regenerating it added DB_ACCESS_PWD and GIT_REPO_PROXY (real runtime define()s
in src/Core/Config/AppConfig.php that PHPStan could not see). Added `make
phpstan-stub` so the stub is regenerable/discoverable, and refreshed it
(129 -> 131 constants).
2026-08-07 21:03:42 +03:00
Divarion-D 0532b82c96 refactor(tests): remove deprecated global $db exemptions from ArchitectureTest 2026-07-07 21:51:51 +03:00
Divarion-D 270f5d2006 build(make): don't re-run the deleted_files step in main
main_copy_files already copies the git-tracked migrations/deleted_files.txt into
the archive, so the separate delete_files_list step just re-copied and reprinted
it (looking like regeneration). Drop it from the `main` chain; keep it as an
optional manual preview. LB still needs lb_delete_files_list (migrations/ is not
in LB_DIRS).
2026-07-02 21:28:51 +03:00
Divarion-D e6166f56b5 Refactor code structure for improved readability and maintainability 2026-06-28 20:30:14 +03:00
Divarion-D 64ed6bac65 fix(make): add dev-clean target to remove development tools and restore production vendor 2026-06-26 21:10:11 +03:00
Divarion-D 8d39f90902 chore(tools): remove php_syntax_check.sh — covered by PHPStan/CS/PHPUnit
`php -l` syntax checking is redundant with the real linters/validators (PHPStan
  parses the code, PHP-CS-Fixer and the PHPUnit bootstrap also fail on parse
  errors). Remove the script and every reference to it:

  - Makefile: drop the `syntax_check` target and its .PHONY entry.
  - CI (ci.yml): drop the dedicated `lint` (PHP Syntax Check) job.
  - Release workflows (build-release, build_pre-release): drop the "Check syntax"
    step from the Quality Gate (PHPUnit remains).
  - CONTRIBUTING.md: replace the syntax-check pre-commit guidance with the real
    checks (make dev-tools / phpstan / cs / gates / phpunit).
  - updates_checklist (en/ru): replace `make syntax_check` with the quality-check
    suite and drop the stale "Security scan" snippet that referenced the removed
    script and a non-existent tools/run_scan.sh (Semgrep runs automatically in CI).
2026-06-26 19:00:10 +03:00
Divarion-D 7634c0fc75 chore: migrate workflows to support pre-release assets 2026-06-26 11:50:10 +03:00
Divarion-D f0f12c8de0 build(makefile): align dev-tool targets with the prod-only vendor model
The committed src/vendor/ is production-only now, so PHPStan / PHP-CS-Fixer are no
longer present until installed. Update the Makefile accordingly:

- Drop the stale 'ships as a committed dev dependency' comments.
- Add a 'dev-tools' target (cd src && composer install) to install the require-dev
  tooling locally; CI runs the equivalent step itself.
- phpstan / phpstan-baseline / cs / cs-fix now guard on the binary and print a
  clear 'run make dev-tools' hint instead of a cryptic 'No such file' when the
  dev tools have not been installed.
2026-06-25 22:06:08 +03:00
Divarion-D baf6c8e231 build: ship a production-only vendor; install dev tools via Composer
Switch from "commit vendor with dev deps + strip at release" to the standard
application model: the committed src/vendor/ is PRODUCTION-ONLY, and dev tooling
(PHPStan, PHP-CS-Fixer + ~37 transitive deps) is installed on demand with
"composer install".

- Regenerate the committed src/vendor/ via "composer install --no-dev"
  (34 MB -> ~0.5 MB; only the Composer autoloader + gemorroj/m3u-parser +
  chrisyue/php-m3u8 remain). This also stops PHPStan\PharAutoloader registering
  in production.
- Commit src/composer.lock (un-ignored) — this is an application, so the lock is
  committed to make "composer install" reproducible across dev/CI.
- Revert the release-time strip step (Makefile hooks + tools/build/
  strip-dev-vendor.sh) — no longer needed; the archive ships the prod vendor as-is.
- CI: the phpstan and code-style jobs now run "composer install --working-dir=src"
  (with tools: composer) to obtain the dev tools before running.
- New gate tools/ci/check-vendor-prod-only.sh (+ make check-vendor-prod-only,
  wired into "make gates"): asserts no require-dev package from composer.lock is
  committed under src/vendor/ — guards against accidentally committing a
  dev-bloated vendor. Inspects git-tracked files, so it is correct even in a CI
  job that already ran "composer install".
- Fix verify-lb-archive.sh: LB legitimately ships most of Cli/Commands and
  Cli/CronJobs (edge commands + certbot/cache/cleanup crons), so flag only the
  genuinely privileged dirs + the specific install/root files, not the whole dirs.
- .gitignore / composer.json notes updated.

Verified before pruning: PHPStan no errors, PHPUnit 303, cs + gates green. After
pruning: PHPUnit 303 (prod-only vendor), all three gates green. Local dev tools
restored afterwards with "composer install" (not committed).
2026-06-25 21:51:13 +03:00
Divarion-D 0165b595d5 build: strip Composer dev dependencies from release archives
The committed src/vendor/ carries require-dev packages (PHPStan, PHP-CS-Fixer +
their transitive symfony/react/psr deps, ~33 MB) so they are available for local
dev and CI. They must not ship to production — besides the weight, PHPStan's
files-autoload registers PHPStan\PharAutoloader at runtime on every request.

Add tools/build/strip-dev-vendor.sh and hook it into both `make main` and
`make lb` right after the file-copy step (before archiving). It runs against the
staged TEMP_DIR, not the repo:
- removes every dev package dir listed in vendor/composer/installed.json
  (dev-package-names) and their bin shims;
- regenerates the autoloader with `composer dump-autoload --no-dev` (drops the
  dev files-autoload, incl. the PharAutoloader);
- prunes the emptied vendor namespace dirs.
LB does not stage composer.json (not in LB_ROOT_FILES); the script copies it in
so dump-autoload can run (harmless metadata in the LB archive).

Result: shipped vendor/ goes 34 MB -> ~0.8 MB, contains only the Composer
autoloader + the two prod packages (gemorroj/m3u-parser, chrisyue/php-m3u8);
M3uParser/Chrisyue still autoload and no PharAutoloader is registered. The
committed src/vendor/ is left untouched (dev tooling stays for local use).
2026-06-25 21:34:32 +03:00
Divarion-D 2bed01e660 chore(psr4): final phase step 2 — remove the legacy autoload.php entirely
The XC_Autoloader fallback was already retired (no-op stub); this deletes it for
good. Resolution is now 100% Composer PSR-4 (+ ModuleLoader for modules), no
legacy scanner, no class-map cache.

- Move `define('MAIN_HOME', ...)` into bootstrap.php (autoload.php used to define
  it); bootstrap.php now requires only vendor/autoload.php.
- Drop `\XC_Autoloader::clearCache()/warmCache()` from StartupCommand.
- tests/bootstrap.php: locate-guard + require switched to vendor/autoload.php.
- Entry points that required autoload.php directly — Public/index.php,
  Public/admin/index.php, Public/stream/index.php, Public/progress/index.php,
  ministra/portal.php and Admin/Reseller TableController — switched to
  vendor/autoload.php (defining MAIN_HOME where they did not already). These were
  not in the plan's checklist; found via grep during execution.
- phpstan.dist.neon: drop src/autoload.php from scanFiles.
- Makefile: drop autoload.php from LB_ROOT_FILES.
- deleted_files.txt: add autoload.php (client cleanup on update).
- AutoloadOrderTest: now asserts the XC_Autoloader class and file are gone.
- git rm src/autoload.php.
- PSR4_MIGRATION_PLAN.md: mark final-phase step 2 done.

Verified: grep XC_Autoloader:: = 0; php -l clean; PHPStan no errors; PHPUnit
303/303; make gates pass; bootstrap smoke — MAIN_HOME + XC_Bootstrap present,
XC_Autoloader gone, only the Composer autoloader registered.
2026-06-25 21:11:00 +03:00
Divarion-D e9bc5de0e4 test/ci(psr4): add the missing migration regression gates
Adds the automated gates the PSR-4 plan specified but that were verified only
manually per phase:

PHPUnit (run by the existing test job):
- AutoloadOrderTest      — Composer autoloader registered; the retired
                           XC_Autoloader scanner is NOT in the SPL stack; init()
                           is a no-op; no igbinary class-map cache is written.
- BootstrapPathsTest     — no live require/include points at a lowercase renamed
                           dir (the Фаза-1 grep-gate, as a runtime guard).
- ConsoleDiscoveryTest   — console.php FQCN discovery resolves every Cli command
                           file and the concrete command surface stays stable.

Shell gates (new 'PSR-4 Regression Gates' CI job + 'make gates'):
- tools/ci/check_procedural_use.php — procedural/view files must import every
  migrated class they use, with the `use` ABOVE the usage (PHP imports are
  positional). Runs with short_open_tag=1 so short-tag templates are analysed.
- tools/ci/verify-lb-archive.sh — reproduces the Makefile LB file selection from
  the real LB_* vars and asserts no privileged tree (Admin/Reseller/Player
  controllers, Domain/User|Device, Cli/CronJobs|Commands) ships to an LB node
  (security blocker 1).

Makefile: cs/cs-fix now force short_open_tag=1; new print-%, check-procedural-use,
verify-lb-archive and aggregate `gates` targets.
2026-06-25 20:57:53 +03:00
Divarion-D 1a0ad5667a chore(cs): add PHP-CS-Fixer (import/namespace hygiene only)
Add friendsofphp/php-cs-fixer as a committed Composer dev dependency (src/vendor/,
same model as PHPStan — no composer install on deploy).

- .php-cs-fixer.dist.php: deliberately NARROW ruleset — no_unused_imports,
  ordered_imports, no_leading_import_slash, single_line_after_imports,
  blank_line_after_namespace, no_extra_blank_lines[use]. NO @PSR12 / indentation
  rules: the codebase is tab-indented legacy and a full reformat would be
  unreviewable. Indent forced to tabs, LF endings. Excludes vendor, the bundled
  Modules/tmdb/lib, tmp/, backups/.
- Makefile: 'make cs' (dry-run, fails on diff — CI) and 'make cs-fix' (apply).
- CI: new 'Code Style (PHP-CS-Fixer)' job running 'make cs' on PHP 8.3.
- .gitignore: ignore .php-cs-fixer.cache.
2026-06-25 20:24:34 +03:00
Divarion-D 045b8f6bd0 chore(deps): install PHPStan via Composer, drop downloaded PHAR
The downloaded phpstan.phar could not resolve namespaced third-party
packages now living in src/vendor/ (M3uParser, PhpM3u8), failing CI with
class.notFound on StreamService::parseM3U.

- add phpstan/phpstan 2.1.17 as a Composer dev dependency (committed to
  src/vendor/); the vendor/bin/phpstan binary auto-loads
  src/vendor/autoload.php, so vendor symbols resolve
- Makefile: drop the phpstan-install PHAR download; run src/vendor/bin/phpstan
- remove the stale Core/Parsing/M3uParser excludePath from phpstan.dist.neon
- drop the obsolete tools/phpstan/phpstan.phar gitignore entry

make phpstan: No errors (278 files).
2026-06-25 19:58:38 +03:00
Divarion-D 1a296d0985 chore(psr4): phase 1 — rename 7 top-level dirs to PascalCase
Atomic case-rename of the seven class-holding source directories to match the
PSR-4 namespace casing, plus every consequent path reference. No code logic
changes — pure structural rename. (config/content/resources/signals/migrations/
ministra/storage/tmp/vendor/www/bin stay lowercase.)

- git mv: core→Core, domain→Domain, infrastructure→Infrastructure,
  streaming→Streaming, modules→Modules, cli→Cli, public→Public (module subdirs
  like Modules/plex stay lowercase; loaded by ModuleLoader, not Composer).
- PHP filesystem paths updated across src/ + tests/: require/include, glob/scandir
  bases, view includes, asset/nginx-alias paths, autoload.php registerDirectories(),
  ModuleLoader/ModuleManager module roots, console.php discovery dirs.
- src/composer.json PSR-4 vendored-lib paths → Core/Parsing/...; vendor/ regenerated.
- nginx.conf: docroot + SCRIPT_FILENAME → Public/. SCRIPT_NAME and the public-facing
  /streaming/*.php compat routes are URLs, left unchanged.
- Build/CI: Makefile LB_DIRS / LB_DIRS_TO_REMOVE / LB_FILES_TO_REMOVE PascalCased
  (closes the LB-archive privileged-leak blocker); phpstan.dist.neon paths/
  scanDirectories/excludePaths; phpunit.xml.dist coverage; phpstan-baseline.neon
  regenerated (294→294 errors, no new resolution failures).
- migrations/deleted_files.txt: old lowercase trees listed for client cleanup
  (assumes case-sensitive FS — the supported Linux target).

Verified: grep-gate 0 live lowercase-dir require/include in src+tests; php -l clean;
PHPUnit 292/292; PHPStan no errors; Composer first / XC_Autoloader last in SPL stack;
global classes resolve from the renamed dirs.
2026-06-24 20:10:34 +03:00
Divarion-D 7e5732cdcb chore(psr4): phase 0 — Composer PSR-4 autoloader foundation
Introduce a committed Composer PSR-4 autoloader without changing class
resolution behavior, as the foundation for the incremental PSR-4 migration.

- src/composer.json: PSR-4 (XcVm\ -> ./, M3uParser\, Chrisyue\PhpM3u8\),
  platform php 8.1.33 (deploy runtime), optimize-autoloader/classmap-authoritative
  false (live path resolution, no class-map cache). autoload.files left empty:
  global functions are still loaded by existing require glue; moving them is
  deferred until that glue is removed.
- src/vendor/ + src/composer.lock: committed (deploy path has no Composer);
  generated with 'composer update' from src/. Regenerate with dump-autoload.
- src/bootstrap.php, tests/bootstrap.php: require vendor/autoload.php first,
  then the legacy autoload.php.
- src/autoload.php: drop the igbinary disk cache (enableFileCache/saveCache/
  shutdown handler/root-chown + bottom call); register at the END of the SPL
  queue (prepend=false) so Composer wins for XcVm\* and only still-global
  classes fall through to the in-memory scanner.
- Makefile: add vendor to LB_DIRS so load-balancer archives ship the loader.
- phpstan.dist.neon: exclude src/vendor/* from analysis.
- .gitignore: document that src/vendor/ is intentionally tracked.
- ci.yml: add composer-audit job (no-op until real require deps exist).

Verified: php -l clean; Composer first / XC_Autoloader last in the SPL stack;
tmp/cache/autoload_map no longer written; PHPUnit 292/292; PHPStan no errors.
2026-06-24 19:07:37 +03:00
Divarion-D 69669d8e1c feat(phpstan): add PHPStan static analysis setup and constants stub generation 2026-06-23 19:28:45 +03:00
Divarion-D 484a758ca0 chore: add Git LFS tracking, CODEOWNERS, SECURITY.md, and CI workflows 2026-06-21 22:11:49 +03:00
Divarion-D 1896387e46 refactoring(modules): remove the magscan module and update the documentation 2026-05-29 18:44:30 +03:00
Divarion-D 9d8641a61c refactoring(modules): remove fingerprint module and update related documentation 2026-05-29 18:31:55 +03:00
Divarion-D 9fc09dd495 fix(watch module) Forced mode 2026-05-29 18:11:47 +03:00
Divarion-DandCopilot 64dc25097c Add server installation command and proxy installation flow
- Implemented `ServerInstallCommand` for installing and configuring servers via SSH.
- Created `ProxyInstallFlow` class to handle proxy-specific installation tasks.
- Updated `ServerService` to use the new command structure for server installations.
- Modified API endpoint to initiate server installations using the new command format.
- Enhanced error handling and logging during installation processes.

Co-authored-by: Copilot <copilot@github.com>
2026-05-12 14:23:48 +03:00
Divarion-D fbe0cf63cf chore: update utils, cron jobs, table controller, and build config
- QueryHelper: add utility methods for safe SQL operations
- AdminHelpers/SystemInfo: extract reusable admin utility functions
- ServerRepository: update query methods
- CacheCronJob/ServersCronJob: align with service layer conventions
- TableController: refactor DataTable logic for admin views
- Update Makefile build configuration
2026-04-20 20:35:36 +03:00
Divarion-D 531be6e9e0 docs(build): sync LB/update docs with current Makefile and updater 2026-04-17 15:58:36 +03:00
Divarion-D 1bd4180b4b feat: add syntax check target to Makefile and update changelog for version 2.1.1 2026-04-13 22:06:39 +03:00
Divarion-D aa6cd5803d feat: LB build includes public/ directory
- Makefile: add public/ to LB_DIRS with admin-only exclusions
2026-04-13 21:52:56 +03:00
Divarion-D ac3064436e feat: add target to generate deleted_files.txt for update process 2026-04-13 01:04:54 +03:00
Divarion-D d9bbd6c35b build: unify install and update into a single archive
Replace separate install/update build targets with a single archive that
serves both purposes. The update script (src/update) now extracts to a
temp directory, removes excluded dirs (binaries, config, user data), and
copies remaining files over the live installation.

Changes:
- Remove main_update, lb_update, lb_update_copy_files,
  main_update_copy_files Makefile targets and UPDATE_EXCLUDE_DIRS var
- Move exclude dirs list into src/update (Python) where filtering
  actually happens at runtime
- Rewrite doUpdate() to use tempdir extraction with try/finally cleanup
- Make delete_files_list/lb_delete_files_list gracefully skip when
  LAST_TAG is empty (warn instead of error)
- Simplify CI workflows: one make command per variant instead of
  conditional install + update steps
- Add ARCHITECTURE.md §5.5 documenting update flow
- Update en/ru docs: update-system.md, updates_checklist.md
- Update makefile-build.instructions.md with new targets
2026-04-12 17:38:35 +03:00
Divarion-D 6cc892f9a7 refactor: eliminate proxy functions, migrate to direct class method calls
312 files changed, 2866 insertions(+), 24110 deletions(-)

Proxy function replacements (130+ functions):
- goHome() -> AdminHelpers::goHome()
- checkPermissions() -> PageAuthorization::checkPermissions()
- getBouquet/getCategory/etc -> Service::getById()
- deleteStream/deleteLine/etc -> Repository/Service::delete()
- APIRequest/systemapirequest -> ApiClient::request/systemRequest()
- prepareArray/preparecolumn -> QueryHelper methods
- confirmIDs/parserelease/etc -> AdminHelpers methods
- getSettings/clearSettingsCache -> SettingsManager methods
- destroySession -> SessionManager::clearContext()
- getMag/getEnigma/deleteMAG/etc -> MagService/EnigmaService
- getSeriesTrailer/getMovieTMDB/etc -> TMDbService methods

Removed legacy files:
- src/includes/admin.php (main proxy hub)
- src/includes/libs/ (35+ files moved to core/modules)
- src/includes/python/ (moved to bin/python)
- src/includes/api/ (moved to Controllers)
- src/includes/ts.php, reseller_api.php
- src/infrastructure/legacy/admin_proxies.php
- tools/run_scan.sh, update_redis_conf.sh

Additional fixes:
- SQL query placeholder migration (BouquetService, CategoryService)
- PHP 8.x null-safe access (live.php, server_view.php, stream.php)
- TmdbCron: extracted variable for repeated similar_text calls
2026-04-09 21:24:48 +03:00
Divarion-D 07789f7a33 Rename test_installer to install 2026-04-07 19:55:28 +03:00
Divarion-D c47690dd42 build: Makefile cleanup — UPDATE_EXCLUDE_DIRS, rewrite update targets, simplify permissions 2026-04-07 19:49:29 +03:00
Divarion-D c75777ed87 chore: remove FFmpeg 4.3, 4.4, 5.1 binaries and references
Drop three legacy FFmpeg versions (4.3, 4.4, 5.1), freeing ~288 MB.
Remaining supported versions: 8.0, 7.1, 4.0 (legacy fallback).

- Remove FFMPEG/FFPROBE_BIN_43/44/51 constants from Binaries.php
- Remove switch cases from FfmpegPaths.php (fallback → 4.0)
- Remove version options from admin settings UI dropdown
- Remove chmod lines from Makefile
- Update README.md version list
- Delete src/bin/ffmpeg_bin/{4.3,4.4,5.1}/ directories
2026-03-18 21:47:16 +03:00
Divarion-D 2dd8d3bd1e refactor: absorb includes/bootstrap/ into XC_Bootstrap
Merge the three legacy bootstrap files into XC_Bootstrap::boot(CONTEXT_ADMIN):

- admin_session.php → already covered by XC_Bootstrap::initSession()
- admin_runtime.php (status constants) → already covered by defineStatusConstants()
- admin_runtime.php (globals) → new initAdminGlobals() method
- admin_bootstrap.php (orchestrator) → eliminated, admin.php calls XC_Bootstrap directly

New private methods in XC_Bootstrap:
- initAdminGlobals(): MobileDetect, timeouts, servers, protocol, translator, admin_constants
- detectProtocol(): inlined issecure()+getProtocol() logic

Updated:
- includes/admin.php: require bootstrap.php + XC_Bootstrap::boot() instead of bridge
- Makefile: remove includes/bootstrap from LB_DIRS_TO_REMOVE
- ARCHITECTURE.md: remove bootstrap/ from tree and LB example
- docs/{en,ru}/builds/build_system.md: remove row from LB tables
- Comments in admin_functions_fc.php, functions.php

Deleted:
- includes/bootstrap/admin_bootstrap.php
- includes/bootstrap/admin_runtime.php
- includes/bootstrap/admin_session.php
2026-03-18 21:34:00 +03:00
Divarion-D d75080ddc5 refactor: move langs/ from includes/ to resources/
Migrate 7 locale .ini files (bg, de, en, es, fr, pt, ru) from
src/includes/langs/ to src/resources/langs/ per ARCHITECTURE.md
migration map.

Updated references:
- bootstrap.php: Translator::init() path
- includes/bootstrap/admin_runtime.php: Translator::init() path
- Makefile: removed includes/langs from LB_DIRS_TO_REMOVE
- ARCHITECTURE.md: marked migration as done, updated LB example
- docs/en/builds/build_system.md: updated excluded dirs table
- docs/ru/builds/build_system.md: updated excluded dirs table

Removed empty src/includes/langs/ directory.
2026-03-18 21:10:08 +03:00
Divarion-D a113fb3ec9 refactor: remove legacy proxy files, migrate all callers to console.php
- Delete src/status, src/tools, src/crons/epg.php (logic already in CLI commands)
- Update BalancerCommand: fix remote file_exists to SSH test -f, fix stripos check
- Update StartupCommand, UpdateCommand: use PHP_BIN + console.php
- Update dashboard.php: replace hardcoded sudo php with PHP_BIN
- Update install/test_installer: sentinel console.php, exec paths
- Update Makefile: remove status/tools from LB_ROOT_FILES and set_permissions
- Update docs: migration_guide, update-system (EN/RU)
- Update test-install: README.md, auto_install.sh
2026-03-18 20:32:51 +03:00
Divarion-D 2478ba612a fix(build): update git diff commands to exclude renames 2026-03-17 21:21:20 +03:00