Framework updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-02-01 05:16:45 +00:00
parent f48cda006a
commit 0efdcd4cde
27 changed files with 2970 additions and 153 deletions

View File

@@ -250,6 +250,14 @@ class Spa {
const parsed = Spa.parse_url(url);
let path = parsed.path;
// Strip portal prefix if in portal context
if (Rsx_Portal.is_portal() && !Rsx_Portal.has_dedicated_domain()) {
const prefix = Rsx_Portal.get_prefix();
if (path.startsWith(prefix)) {
path = path.substring(prefix.length) || '/';
}
}
// Normalize path - remove leading/trailing slashes for matching
path = path.substring(1); // Remove leading /

View File

@@ -86,3 +86,22 @@ function title(page_title) {
return target;
};
}
/**
* @decorator
* Link a Portal Spa action to its PHP controller method
* Used for portal routes which are handled by Portal_Spa_ManifestSupport
*
* Usage:
* @portal_spa('Portal_Spa_Controller::index')
* class Portal_Dashboard_Action extends Spa_Action { }
*/
function portal_spa(controller_method) {
return function (target) {
// Store controller::method reference on the class
target._spa_controller_method = controller_method;
// Mark as portal SPA action
target._is_portal_spa = true;
return target;
};
}

View File

@@ -51,6 +51,11 @@ class Spa_ManifestSupport extends ManifestSupport_Abstract
// Parse decorators into route configuration
$route_info = static::_parse_decorators($decorators);
// Skip if this is a portal SPA action (handled by Portal_Spa_ManifestSupport)
if (!empty($route_info['is_portal_spa'])) {
continue;
}
// Skip if no route decorator found
if (empty($route_info['routes'])) {
continue;
@@ -155,6 +160,7 @@ class Spa_ManifestSupport extends ManifestSupport_Abstract
'layout' => null,
'spa_controller' => null,
'spa_method' => null,
'is_portal_spa' => false,
];
foreach ($decorators as $decorator) {
@@ -175,6 +181,11 @@ class Spa_ManifestSupport extends ManifestSupport_Abstract
}
break;
case 'portal_spa':
// @portal_spa decorator - handled by Portal_Spa_ManifestSupport, skip here
$config['is_portal_spa'] = true;
break;
case 'spa':
// @spa('Controller::method') - args is array with single string
if (!empty($args[0])) {