Enhance refactor commands with controller-aware Route() updates and fix code quality violations

Add semantic token highlighting for 'that' variable and comment file references in VS Code extension
Add Phone_Text_Input and Currency_Input components with formatting utilities
Implement client widgets, form standardization, and soft delete functionality
Add modal scroll lock and update documentation
Implement comprehensive modal system with form integration and validation
Fix modal component instantiation using jQuery plugin API
Implement modal system with responsive sizing, queuing, and validation support
Implement form submission with validation, error handling, and loading states
Implement country/state selectors with dynamic data loading and Bootstrap styling
Revert Rsx::Route() highlighting in Blade/PHP files
Target specific PHP scopes for Rsx::Route() highlighting in Blade
Expand injection selector for Rsx::Route() highlighting
Add custom syntax highlighting for Rsx::Route() and Rsx.Route() calls
Update jqhtml packages to v2.2.165
Add bundle path validation for common mistakes (development mode only)
Create Ajax_Select_Input widget and Rsx_Reference_Data controller
Create Country_Select_Input widget with default country support
Initialize Tom Select on Select_Input widgets
Add Tom Select bundle for enhanced select dropdowns
Implement ISO 3166 geographic data system for country/region selection
Implement widget-based form system with disabled state support

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-30 06:21:56 +00:00
parent e678b987c2
commit f6ac36c632
5683 changed files with 5854736 additions and 22329 deletions

View File

@@ -1171,7 +1171,7 @@ class Manifest
console_debug('MANIFEST', 'Cache file written successfully', [
'path' => $cache_file,
'size' => $file_size,
'permissions' => $file_perms
'permissions' => $file_perms,
]);
} else {
console_debug_force('MANIFEST', 'WARNING: Cache file does not exist after rebuild!', $cache_file);
@@ -1262,6 +1262,7 @@ class Manifest
// Extract just the class name (last part after final backslash)
$parts = explode('\\', $class_name);
return end($parts);
}
@@ -1612,146 +1613,9 @@ class Manifest
// ------------------------------------------------------------------------
// ---- Private / Protected Methods:
// ------------------------------------------------------------------------
/**
* Generate JavaScript stub files for PHP controllers with Internal API methods
* These stubs enable IDE autocomplete for Ajax.call() invocations from JavaScript
*/
protected static function _generate_js_api_stubs(): void
{
$stub_dir = storage_path('rsx-build/js-stubs');
// Create directory if it doesn't exist
if (!is_dir($stub_dir)) {
mkdir($stub_dir, 0755, true);
}
// Track generated stub files for cleanup
$generated_stubs = [];
// Process each file
foreach (static::$data['data']['files'] as $file_path => &$metadata) {
// Skip non-PHP files
if (!isset($metadata['extension']) || $metadata['extension'] !== 'php') {
continue;
}
// Skip files without classes or public static methods
if (!isset($metadata['class']) || !isset($metadata['public_static_methods'])) {
continue;
}
// Check if this is a controller (extends Rsx_Controller_Abstract)
$class_name = $metadata['class'] ?? '';
if (!static::php_is_subclass_of($class_name, 'Rsx_Controller_Abstract')) {
continue;
}
// Check if this controller has any Ajax_Endpoint methods
$api_methods = [];
foreach ($metadata['public_static_methods'] as $method_name => $method_info) {
if (!isset($method_info['attributes'])) {
continue;
}
// Check for Ajax_Endpoint attribute
$has_api_internal = false;
foreach ($method_info['attributes'] as $attr_name => $attr_data) {
if ($attr_name === 'Ajax_Endpoint' ||
basename(str_replace('\\', '/', $attr_name)) === 'Ajax_Endpoint') {
$has_api_internal = true;
break;
}
}
if ($has_api_internal && isset($method_info['static']) && $method_info['static']) {
$api_methods[$method_name] = [
'name' => $method_name,
];
}
}
// If no API methods, remove js_stub property if it exists and skip
if (empty($api_methods)) {
if (isset($metadata['js_stub'])) {
unset($metadata['js_stub']);
}
continue;
}
// Generate stub filename and paths
$controller_name = $metadata['class'];
$stub_filename = static::_sanitize_stub_filename($controller_name) . '.js';
$stub_relative_path = 'storage/rsx-build/js-stubs/' . $stub_filename;
$stub_full_path = base_path($stub_relative_path);
// Check if stub needs regeneration
$needs_regeneration = true;
if (file_exists($stub_full_path)) {
// Get mtime of source PHP file
$source_mtime = $metadata['mtime'] ?? 0;
$stub_mtime = filemtime($stub_full_path);
// Only regenerate if source is newer than stub
if ($stub_mtime >= $source_mtime) {
// Also check if the API methods signature has changed
// by comparing a hash of the methods
$api_methods_hash = md5(json_encode($api_methods));
$old_api_hash = $metadata['api_methods_hash'] ?? '';
if ($api_methods_hash === $old_api_hash) {
$needs_regeneration = false;
}
}
}
// Store the API methods hash for future comparisons
$metadata['api_methods_hash'] = md5(json_encode($api_methods));
if ($needs_regeneration) {
// Generate stub content
$stub_content = static::_generate_stub_content($controller_name, $api_methods);
// Write stub file
file_put_contents($stub_full_path, $stub_content);
}
$generated_stubs[] = $stub_filename;
// Add js_stub property to manifest data (relative path)
$metadata['js_stub'] = $stub_relative_path;
// Add the stub file itself to the manifest
// This is critical because storage/rsx-build/js-stubs is not in scan directories
$stat = stat($stub_full_path);
static::$data['data']['files'][$stub_relative_path] = [
'file' => $stub_relative_path,
'hash' => sha1_file($stub_full_path),
'mtime' => $stat['mtime'],
'size' => $stat['size'],
'extension' => 'js',
'class' => $controller_name,
'is_stub' => true, // Mark this as a generated stub
'source_controller' => $file_path, // Reference to the source controller
];
}
// Clean up orphaned stub files (both from disk and manifest)
$existing_stubs = glob($stub_dir . '/*.js');
foreach ($existing_stubs as $existing_stub) {
$filename = basename($existing_stub);
if (!in_array($filename, $generated_stubs)) {
// Remove from disk
unlink($existing_stub);
// Remove from manifest
$stub_relative_path = 'storage/rsx-build/js-stubs/' . $filename;
if (isset(static::$data['data']['files'][$stub_relative_path])) {
unset(static::$data['data']['files'][$stub_relative_path]);
}
}
}
}
// DEAD CODE REMOVED: _generate_js_api_stubs()
// Stub generation now handled by Controller_BundleIntegration
// ------------------------------------------------------------------------
/**
* Generate JavaScript stub files for ORM models
@@ -2093,34 +1957,10 @@ class Manifest
return strtolower(str_replace('_', '-', $controller_name));
}
/**
* Generate JavaScript stub content for a controller
*/
private static function _generate_stub_content(string $controller_name, array $api_methods): string
{
$content = "/**\n";
$content .= " * Auto-generated JavaScript stub for {$controller_name}\n";
$content .= ' * Generated by RSX Manifest at ' . date('Y-m-d H:i:s') . "\n";
$content .= " * DO NOT EDIT - This file is automatically regenerated\n";
$content .= " */\n\n";
$content .= "class {$controller_name} {\n";
foreach ($api_methods as $method_name => $method_info) {
$content .= " /**\n";
$content .= " * Call {$controller_name}::{$method_name} via Ajax.call()\n";
$content .= " * @param {...*} args - Arguments to pass to the method\n";
$content .= " * @returns {Promise<*>}\n";
$content .= " */\n";
$content .= " static async {$method_name}(...args) {\n";
$content .= " return Ajax.call('{$controller_name}', '{$method_name}', args);\n";
$content .= " }\n\n";
}
$content .= "}\n";
return $content;
}
// ------------------------------------------------------------------------
// DEAD CODE REMOVED: _generate_stub_content()
// Stub generation now handled by Controller_BundleIntegration
// ------------------------------------------------------------------------
/**
* Get or create the kernel instance
@@ -2936,6 +2776,7 @@ class Manifest
// Check if method calls parent::methodname()
// Use the correct file for trait methods
$source_file_to_read = $is_from_trait ? $method_file : $file_path;
try {
$method_source = file($source_file_to_read);
$start_line = $method->getStartLine() - 1;
@@ -3488,6 +3329,7 @@ class Manifest
$has_route = false;
$has_ajax_endpoint = false;
$has_task = false;
foreach ($method_info['attributes'] as $attr_name => $attr_instances) {
if ($attr_name === 'Route' || str_ends_with($attr_name, '\\Route')) {
@@ -3496,17 +3338,26 @@ class Manifest
if ($attr_name === 'Ajax_Endpoint' || str_ends_with($attr_name, '\\Ajax_Endpoint')) {
$has_ajax_endpoint = true;
}
if ($attr_name === 'Task' || str_ends_with($attr_name, '\\Task')) {
$has_task = true;
}
}
if ($has_route && $has_ajax_endpoint) {
// Check for conflicting attributes
$conflicts = [];
if ($has_route) $conflicts[] = 'Route';
if ($has_ajax_endpoint) $conflicts[] = 'Ajax_Endpoint';
if ($has_task) $conflicts[] = 'Task';
if (count($conflicts) > 1) {
$class_name = $metadata['class'] ?? 'Unknown';
throw new \RuntimeException(
"Controller action cannot have both Route and Ajax_Endpoint attributes.\n" .
"Method cannot have multiple execution type attributes: " . implode(', ', $conflicts) . "\n" .
"Class: {$class_name}\n" .
"Method: {$method_name}\n" .
"File: {$file_path}\n" .
'A controller action must be either a web route OR an AJAX endpoint, not both.'
'A method must be either a Route, Ajax_Endpoint, OR Task, not multiple types.'
);
}
}