Reorganize RSpade directory structure for clarity
Improve Jqhtml_Integration.js documentation with hydration system explanation Add jqhtml-laravel integration packages for traditional Laravel projects 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
170
app/RSpade/Core/Manifest/Modules/Model_ManifestSupport.php
Executable file
170
app/RSpade/Core/Manifest/Modules/Model_ManifestSupport.php
Executable file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace App\RSpade\Core\Manifest\Modules;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use ReflectionClass;
|
||||
use App\RSpade\Core\Cache\RsxCache;
|
||||
use App\RSpade\Core\Manifest\Manifest;
|
||||
use App\RSpade\Core\Manifest\ManifestSupport_Abstract;
|
||||
|
||||
/**
|
||||
* Support module for extracting database metadata for Rsx_Model_Abstract classes
|
||||
* This runs after the primary manifest is built to add model metadata
|
||||
*/
|
||||
class Model_ManifestSupport extends ManifestSupport_Abstract
|
||||
{
|
||||
/**
|
||||
* Process the manifest and add model database metadata
|
||||
*
|
||||
* @param array &$manifest_data Reference to the manifest data array
|
||||
* @return void
|
||||
*/
|
||||
public static function process(array &$manifest_data): void
|
||||
{
|
||||
// Initialize models key if it doesn't exist
|
||||
if (!isset($manifest_data['data']['models'])) {
|
||||
$manifest_data['data']['models'] = [];
|
||||
}
|
||||
|
||||
// All PHP files should already be loaded in Phase 3 of manifest processing
|
||||
// Get all classes extending Rsx_Model_Abstract
|
||||
$model_entries = Manifest::php_get_extending('Rsx_Model_Abstract');
|
||||
|
||||
foreach ($model_entries as $model_entry) {
|
||||
if (!isset($model_entry['fqcn'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fqcn = $model_entry['fqcn'];
|
||||
$class_name = $model_entry['class'] ?? '';
|
||||
|
||||
$cachekey = 'Model_ManifestSupport_' . $model_entry['file'] . '__' . $model_entry['hash'];
|
||||
$cache = RsxCache::get_persistent($cachekey);
|
||||
|
||||
if (!empty($cache)) {
|
||||
$manifest_data['data']['models'][$class_name] = $cache;
|
||||
}
|
||||
|
||||
include_once($model_entry['file']);
|
||||
|
||||
// Check if class is abstract
|
||||
if (\App\RSpade\Core\Manifest\Manifest::php_is_abstract($fqcn)) {
|
||||
// Skip abstract classes
|
||||
continue;
|
||||
}
|
||||
|
||||
// Instantiate the model to get table name
|
||||
$model_instance = new $fqcn();
|
||||
$table_name = $model_instance->getTable();
|
||||
|
||||
// Check if table exists
|
||||
if (!Schema::hasTable($table_name)) {
|
||||
// This is acceptable, maybe migrations didnt run or migrations are broken. Just skip adding
|
||||
// the database metadata to the manifest.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get column information
|
||||
$columns = [];
|
||||
|
||||
// Use SHOW COLUMNS to get column information
|
||||
$column_results = DB::select("SHOW COLUMNS FROM `{$table_name}`");
|
||||
|
||||
foreach ($column_results as $column) {
|
||||
$columns[$column->Field] = [
|
||||
'type' => static::__parse_column_type($column->Type),
|
||||
'nullable' => ($column->Null === 'YES'),
|
||||
'key' => $column->Key,
|
||||
'default' => $column->Default,
|
||||
'extra' => $column->Extra,
|
||||
];
|
||||
}
|
||||
|
||||
// Look up the file's metadata to get public_static_methods extracted during reflection
|
||||
$file_path = $model_entry['file'] ?? '';
|
||||
$public_static_methods = [];
|
||||
|
||||
// Find the public_static_methods data from the files array
|
||||
if ($file_path && isset($manifest_data['data']['files'][$file_path])) {
|
||||
$file_metadata = $manifest_data['data']['files'][$file_path];
|
||||
$public_static_methods = $file_metadata['public_static_methods'] ?? [];
|
||||
}
|
||||
|
||||
// Store model metadata with database info AND preserved public_static_methods
|
||||
$full_data = [
|
||||
'fqcn' => $fqcn,
|
||||
'file' => $file_path,
|
||||
'table' => $table_name,
|
||||
'columns' => $columns,
|
||||
'public_static_methods' => $public_static_methods, // Include the public static methods
|
||||
'class' => $class_name, // Ajax_Endpoint_Controller expects this
|
||||
];
|
||||
|
||||
$manifest_data['data']['models'][$class_name] = $full_data;
|
||||
|
||||
RsxCache::set_persistent($cachekey, $full_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse MySQL column type to a simpler format
|
||||
*
|
||||
* CRITICAL: TINYINT(1) is treated as boolean (common MySQL boolean convention)
|
||||
* All other TINYINT sizes are treated as integers
|
||||
*
|
||||
* @param string $type MySQL column type (e.g., "varchar(255)", "tinyint(1)")
|
||||
* @return string Simplified type
|
||||
*/
|
||||
protected static function __parse_column_type(string $type): string
|
||||
{
|
||||
// Special case: tinyint(1) is boolean
|
||||
if (preg_match('/^tinyint\(1\)/i', $type)) {
|
||||
return 'boolean';
|
||||
}
|
||||
|
||||
// Extract base type without parameters
|
||||
if (preg_match('/^([a-z]+)/', $type, $matches)) {
|
||||
$base_type = $matches[1];
|
||||
|
||||
// Map MySQL types to simplified types
|
||||
$type_map = [
|
||||
'int' => 'integer',
|
||||
'bigint' => 'integer',
|
||||
'tinyint' => 'integer', // tinyint(1) handled above, others are integers
|
||||
'smallint' => 'integer',
|
||||
'mediumint' => 'integer',
|
||||
'varchar' => 'string',
|
||||
'char' => 'string',
|
||||
'text' => 'text',
|
||||
'mediumtext' => 'text',
|
||||
'longtext' => 'text',
|
||||
'datetime' => 'datetime',
|
||||
'timestamp' => 'datetime',
|
||||
'date' => 'date',
|
||||
'time' => 'time',
|
||||
'decimal' => 'decimal',
|
||||
'float' => 'float',
|
||||
'double' => 'double',
|
||||
'boolean' => 'boolean',
|
||||
'json' => 'json',
|
||||
'enum' => 'enum',
|
||||
];
|
||||
|
||||
return $type_map[$base_type] ?? $base_type;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this support module
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string
|
||||
{
|
||||
return 'Model Database Metadata';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user