fbd4e92e9f
Full rewrite: swap out the v1 framework (src/, controllers/, views/, twig/, sass/, skeleton/) for the working v2 codebase from phpproject (App/, novaconium/, public/).
97 lines
4.1 KiB
PHP
97 lines
4.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Manual PSR-4 autoloader (no Composer).
|
|
*
|
|
* There's no vendor/autoload.php here — this file *is* the autoloader.
|
|
* `spl_autoload_register()` below registers a callback that PHP invokes
|
|
* automatically the first time an unknown class/namespace is referenced
|
|
* (e.g. `new Router(...)` or `use Lib\Mailer;`), so nothing else in this
|
|
* project ever has to manually `require` a class file.
|
|
*
|
|
* Two different resolution strategies live in that one callback:
|
|
* - `Twig\` and `App\` are plain one-directory-per-namespace PSR-4 (see
|
|
* $__psr4_prefixes below) — no override behavior, just a straight
|
|
* namespace-to-path mapping.
|
|
* - `Lib\` is resolved against an *ordered list* of directories (see
|
|
* $__lib_dirs below) — the first one where the file exists wins. This
|
|
* is what lets a project drop a same-named class into `App/lib/` to
|
|
* override a `novaconium/lib/` default, without editing novaconium/ at
|
|
* all — the same App-over-novaconium pattern used for pages/layouts
|
|
* (see Overlay.php) and Sass colors, just implemented here instead.
|
|
*/
|
|
|
|
// Straight namespace -> directory mapping, one entry per prefix. No
|
|
// override list here because neither of these is meant to be replaced by
|
|
// a project: Twig is vendored framework code, and App\ is the framework's
|
|
// own core classes (Router, Renderer, Cache, etc.) — see
|
|
// novaconium/src/. (A project's own code goes under Lib\, below.)
|
|
$__psr4_prefixes = [
|
|
'Twig\\' => __DIR__ . '/vendor/twig/src/',
|
|
'App\\' => __DIR__ . '/src/',
|
|
];
|
|
|
|
// Lib\ is resolved against App/lib first so a project can add/override
|
|
// classes, falling back to novaconium's default lib/ when not found there.
|
|
// Order matters: this array is walked top-to-bottom and the first file
|
|
// that actually exists on disk wins, so App/lib/ always gets first look.
|
|
$__lib_dirs = [
|
|
__DIR__ . '/../App/lib/',
|
|
__DIR__ . '/lib/',
|
|
];
|
|
|
|
// The callback PHP calls whenever a referenced class hasn't been loaded
|
|
// yet. It only ever needs to `require` the right file (or silently return
|
|
// if nothing matches, which just leaves the class undefined and PHP throws
|
|
// its own "Class not found" error) — there's no class map to build or
|
|
// cache, since every lookup is a cheap `is_file()` check against a handful
|
|
// of candidate paths.
|
|
spl_autoload_register(function (string $class) use (&$__psr4_prefixes, &$__lib_dirs): void {
|
|
// Lib\Foo\Bar -> try App/lib/Foo/Bar.php, then novaconium/lib/Foo/Bar.php.
|
|
if (str_starts_with($class, 'Lib\\')) {
|
|
$relative = substr($class, strlen('Lib\\'));
|
|
foreach ($__lib_dirs as $baseDir) {
|
|
$file = $baseDir . str_replace('\\', '/', $relative) . '.php';
|
|
if (is_file($file)) {
|
|
require $file;
|
|
return;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Twig\Foo\Bar -> novaconium/vendor/twig/src/Foo/Bar.php,
|
|
// App\Foo\Bar -> novaconium/src/Foo/Bar.php.
|
|
// Only one prefix can ever match (they don't overlap), so the loop
|
|
// just finds which one applies and returns right after handling it.
|
|
foreach ($__psr4_prefixes as $prefix => $baseDir) {
|
|
if (!str_starts_with($class, $prefix)) {
|
|
continue;
|
|
}
|
|
|
|
$relative = substr($class, strlen($prefix));
|
|
$file = $baseDir . str_replace('\\', '/', $relative) . '.php';
|
|
|
|
if (is_file($file)) {
|
|
require $file;
|
|
}
|
|
|
|
return;
|
|
}
|
|
});
|
|
|
|
// Twig 3.x calls trigger_deprecation() (normally provided by symfony/deprecation-contracts,
|
|
// which we don't vendor). Provide the same signature so deprecated code paths don't fatal.
|
|
// This has nothing to do with class autoloading above — it's defined here
|
|
// simply because this file already runs on every request before Twig does,
|
|
// making it a convenient, guaranteed-to-run-first place for the shim to live.
|
|
if (!function_exists('trigger_deprecation')) {
|
|
function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void
|
|
{
|
|
@trigger_error(
|
|
($package || $version ? "Since $package $version: " : '') . ($args ? vsprintf($message, $args) : $message),
|
|
E_USER_DEPRECATED
|
|
);
|
|
}
|
|
}
|