feat: extend module platform with UI slots, runtime components, CLI tooling and {{userId}} search support
Completes the generic module platform that enables modules to contribute
UI elements, runtime JS components, and search resources without any
core hardcoding.
New generic UI slot types:
- topbar.right_item: module-contributed topbar buttons
- layout.body_end_template: module-contributed dialog/overlay templates
- layout.head_style: module-contributed global CSS
- runtime.component: declarative JS component registration with phase ordering
New infrastructure:
- ModuleAutoloader: PSR-4 autoloading for module-local PHP classes
- ModuleRuntimePageBuilder: symlinks module pages into runtime directory
- ModuleRuntimeAssetPublisher: publishes module CSS/JS to web/modules/
- ModulePermissionSynchronizer: syncs module permissions to DB
- CLI scripts: module-runtime-sync, module-build, module-migrate,
module-permissions-sync, module-assets-sync
- {{userId}} placeholder in SearchDataService for user-scoped search queries
- Component runtime with phased initialization (early/default/late)
- AppContainer.protectExistingBindings() to prevent module→core overwrites
- Architecture tests: ModuleStructureContractTest, CoreTemplateIsolationTest,
FrontendComponentRuntimeContractTest, AppContainerIsolationContractTest
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ use MintyPHP\Http\RequestContext;
|
||||
use MintyPHP\Http\Request;
|
||||
use MintyPHP\I18n;
|
||||
use MintyPHP\Router;
|
||||
use MintyPHP\App\Module\ModuleRegistry;
|
||||
use MintyPHP\App\Module\ModuleRuntimePageBuilder;
|
||||
use MintyPHP\Service\Access\UiAccessService;
|
||||
use MintyPHP\Service\Auth\AuthServicesFactory;
|
||||
use MintyPHP\Session;
|
||||
@@ -24,12 +26,27 @@ chdir(__DIR__ . '/..');
|
||||
require 'vendor/autoload.php';
|
||||
// Load the config parameters
|
||||
require 'config/config.php';
|
||||
// Load the routes
|
||||
require 'config/router.php';
|
||||
// Register shortcut functions
|
||||
require 'lib/Support/helpers.php';
|
||||
$container = require 'lib/App/registerContainer.php';
|
||||
setAppContainer($container);
|
||||
|
||||
// Resolve runtime page root before routes are initialized.
|
||||
$moduleRegistry = app(ModuleRegistry::class);
|
||||
if (count($moduleRegistry->getModules()) > 0) {
|
||||
$runtimePageRoot = __DIR__ . '/../storage/runtime/pages';
|
||||
if (!is_dir($runtimePageRoot) && !is_link($runtimePageRoot)) {
|
||||
$builder = new ModuleRuntimePageBuilder();
|
||||
$builder->build($runtimePageRoot, __DIR__ . '/../pages', $moduleRegistry->getModules());
|
||||
}
|
||||
if (is_dir($runtimePageRoot) || is_link($runtimePageRoot)) {
|
||||
Router::$pageRoot = 'storage/runtime/pages/';
|
||||
}
|
||||
}
|
||||
|
||||
// Load routes after container/module registry are available.
|
||||
require 'config/router.php';
|
||||
|
||||
RequestContext::start();
|
||||
header('X-Request-Id: ' . RequestContext::requestHeaderValue());
|
||||
|
||||
@@ -200,8 +217,8 @@ if ($requestedLocale === '' && !$isAssetRequest && !$isApiRequest) {
|
||||
// Guard: restrict non-public pages to logged-in users
|
||||
// Merge core public paths with module-contributed public paths.
|
||||
$modulePublicPaths = [];
|
||||
if (app(\MintyPHP\App\Module\ModuleRegistry::class) instanceof \MintyPHP\App\Module\ModuleRegistry) {
|
||||
$modulePublicPaths = app(\MintyPHP\App\Module\ModuleRegistry::class)->getPublicPaths();
|
||||
if (app(ModuleRegistry::class) instanceof ModuleRegistry) {
|
||||
$modulePublicPaths = app(ModuleRegistry::class)->getPublicPaths();
|
||||
}
|
||||
$allPublicPaths = array_values(array_unique(array_merge(
|
||||
defined('APP_PUBLIC_PATHS') ? APP_PUBLIC_PATHS : [],
|
||||
|
||||
Reference in New Issue
Block a user