Add MODEL-CARBON-01 rule to prevent Carbon casts in models
Remove auto-generated tests and .expect files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace App\RSpade\CodeQuality\Rules\Models;
|
||||
|
||||
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
|
||||
use App\RSpade\Core\Manifest\Manifest;
|
||||
|
||||
class ModelCarbonCasts_CodeQualityRule extends CodeQualityRule_Abstract
|
||||
{
|
||||
/**
|
||||
* Laravel cast values that use Carbon
|
||||
*/
|
||||
private const CARBON_CASTS = [
|
||||
'date',
|
||||
'datetime',
|
||||
'timestamp',
|
||||
'immutable_date',
|
||||
'immutable_datetime',
|
||||
'immutable_datetime:', // With format
|
||||
'datetime:', // With format
|
||||
];
|
||||
|
||||
public function get_id(): string
|
||||
{
|
||||
return 'MODEL-CARBON-01';
|
||||
}
|
||||
|
||||
public function get_name(): string
|
||||
{
|
||||
return 'No Carbon Casts in Models';
|
||||
}
|
||||
|
||||
public function get_description(): string
|
||||
{
|
||||
return 'Models must not use Carbon-based casts. Use Rsx_Date_Cast or Rsx_DateTime_Cast instead.';
|
||||
}
|
||||
|
||||
public function get_file_patterns(): array
|
||||
{
|
||||
return ['*.php'];
|
||||
}
|
||||
|
||||
public function get_default_severity(): string
|
||||
{
|
||||
return 'critical';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this rule is called during manifest scan
|
||||
*
|
||||
* EXCEPTION: This rule has been explicitly approved to run at manifest-time because
|
||||
* Carbon casts break the framework's date handling philosophy (strings, not objects).
|
||||
*/
|
||||
public function is_called_during_manifest_scan(): bool
|
||||
{
|
||||
return true; // Explicitly approved for manifest-time checking
|
||||
}
|
||||
|
||||
public function check(string $file_path, string $contents, array $metadata = []): void
|
||||
{
|
||||
// Only check PHP files in /rsx/ directory
|
||||
if (!str_contains($file_path, '/rsx/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get class name from metadata if available
|
||||
$class_name = $metadata['class'] ?? null;
|
||||
if (!$class_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if not a model
|
||||
if (!Manifest::php_is_subclass_of($class_name, 'Rsx_Model_Abstract')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for $casts property
|
||||
if (!preg_match('/\$casts\s*=\s*\[(.*?)\];/s', $contents, $matches)) {
|
||||
return; // No $casts property
|
||||
}
|
||||
|
||||
$casts_content = $matches[1];
|
||||
$casts_start_line = $this->find_casts_line($contents);
|
||||
|
||||
// Check for Carbon-based cast values
|
||||
$violations = [];
|
||||
foreach (self::CARBON_CASTS as $carbon_cast) {
|
||||
// Match 'column' => 'date', 'column' => 'datetime', etc.
|
||||
// Also match with format like 'datetime:Y-m-d'
|
||||
$pattern = "/['\"](\w+)['\"]\s*=>\s*['\"](" . preg_quote($carbon_cast, '/') . "[^'\"]*)['\"]|^\s*['\"](" . preg_quote($carbon_cast, '/') . ")['\"]$/m";
|
||||
if (preg_match_all($pattern, $casts_content, $cast_matches, PREG_SET_ORDER)) {
|
||||
foreach ($cast_matches as $match) {
|
||||
$column = $match[1] ?? 'unknown';
|
||||
$cast_value = $match[2] ?? $match[3] ?? $carbon_cast;
|
||||
$violations[] = "'{$column}' => '{$cast_value}'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for simple patterns like 'date' as value
|
||||
foreach (self::CARBON_CASTS as $carbon_cast) {
|
||||
$simple_pattern = "/=>\s*['\"]" . preg_quote(rtrim($carbon_cast, ':'), '/') . "(?::[^'\"]*)?['\"]/";
|
||||
if (preg_match_all($simple_pattern, $casts_content, $simple_matches)) {
|
||||
// Already captured above, but this ensures we catch all
|
||||
}
|
||||
}
|
||||
|
||||
// Better detection: find all cast values that are Carbon-based
|
||||
$violations = [];
|
||||
preg_match_all("/['\"](\w+)['\"]\s*=>\s*['\"]([^'\"]+)['\"]/", $casts_content, $all_casts, PREG_SET_ORDER);
|
||||
|
||||
foreach ($all_casts as $cast_match) {
|
||||
$column = $cast_match[1];
|
||||
$cast_value = $cast_match[2];
|
||||
|
||||
// Check if this cast value is Carbon-based
|
||||
foreach (self::CARBON_CASTS as $carbon_cast) {
|
||||
$base_cast = rtrim($carbon_cast, ':');
|
||||
if ($cast_value === $base_cast || str_starts_with($cast_value, $base_cast . ':')) {
|
||||
$violations[] = "'{$column}' => '{$cast_value}'";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($violations)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$error_message = "Code Quality Violation (MODEL-CARBON-01) - Carbon Casts Forbidden\n\n";
|
||||
$error_message .= "Model class '{$class_name}' uses Carbon-based casts in \$casts property:\n";
|
||||
$error_message .= implode("\n", array_map(fn($v) => " - {$v}", array_unique($violations))) . "\n\n";
|
||||
$error_message .= "File: {$file_path}\n";
|
||||
$error_message .= "Line: {$casts_start_line}\n\n";
|
||||
$error_message .= "CRITICAL: RSpade uses string-based dates, not Carbon objects.\n\n";
|
||||
$error_message .= "Resolution:\n";
|
||||
$error_message .= "Remove these entries from \$casts. The framework automatically applies:\n";
|
||||
$error_message .= " - Rsx_Date_Cast for DATE columns (returns 'YYYY-MM-DD' strings)\n";
|
||||
$error_message .= " - Rsx_DateTime_Cast for DATETIME columns (returns ISO 8601 strings)\n\n";
|
||||
$error_message .= "If you need the column cast, use the explicit RSpade casts:\n";
|
||||
$error_message .= " 'column' => Rsx_Date_Cast::class\n";
|
||||
$error_message .= " 'column' => Rsx_DateTime_Cast::class";
|
||||
|
||||
throw new \App\RSpade\CodeQuality\RuntimeChecks\YoureDoingItWrongException(
|
||||
$error_message,
|
||||
0,
|
||||
null,
|
||||
$file_path,
|
||||
$casts_start_line
|
||||
);
|
||||
}
|
||||
|
||||
private function find_casts_line(string $contents): int
|
||||
{
|
||||
$lines = explode("\n", $contents);
|
||||
foreach ($lines as $i => $line) {
|
||||
if (preg_match('/\$casts\s*=/', $line)) {
|
||||
return $i + 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:31
|
||||
* Generated on: 2025-12-25 20:57:53
|
||||
* Table: _api_keys
|
||||
*
|
||||
* @property int $id
|
||||
@@ -53,7 +53,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Api_Key_Model extends Rsx_System_Model_Abstract
|
||||
{
|
||||
{
|
||||
protected $table = '_api_keys';
|
||||
|
||||
public static $enums = [];
|
||||
|
||||
@@ -30,42 +30,51 @@ use App\RSpade\Core\Files\File_Storage_Model;
|
||||
* provides the basic structure for categorizing uploaded files.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_
|
||||
* @property integer $id
|
||||
* @property string $key
|
||||
* @property integer $file_storage_id
|
||||
* @property string $file_name
|
||||
* @property string $file_extension
|
||||
* @property integer $file_type_id
|
||||
* @property integer $width
|
||||
* @property integer $height
|
||||
* @property integer $duration
|
||||
* @property boolean $is_animated
|
||||
* @property integer $frame_count
|
||||
* @property string $fileable_type
|
||||
* @property integer $fileable_id
|
||||
* @property string $fileable_category
|
||||
* @property string $fileable_type_meta
|
||||
* @property integer $fileable_order
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: _file_attachments
|
||||
*
|
||||
* @property int $id
|
||||
* @property mixed $key
|
||||
* @property int $file_storage_id
|
||||
* @property mixed $file_name
|
||||
* @property mixed $file_extension
|
||||
* @property int $file_type_id
|
||||
* @property int $width
|
||||
* @property int $height
|
||||
* @property int $duration
|
||||
* @property bool $is_animated
|
||||
* @property int $frame_count
|
||||
* @property mixed $fileable_type
|
||||
* @property int $fileable_id
|
||||
* @property mixed $fileable_category
|
||||
* @property mixed $fileable_type_meta
|
||||
* @property int $fileable_order
|
||||
* @property string $fileable_meta
|
||||
* @property integer $site_id
|
||||
* @property string $session_id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property integer $created_by
|
||||
* @property integer $updated_by
|
||||
* @method static mixed file_type_id_enum()
|
||||
* @method static mixed file_type_id_enum_select()
|
||||
* @method static mixed file_type_id_enum_ids()
|
||||
* @property-read mixed $file_type_id_constant
|
||||
* @property-read mixed $file_type_id_label
|
||||
* @property int $site_id
|
||||
* @property mixed $session_id
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property int $created_by
|
||||
* @property int $updated_by
|
||||
*
|
||||
* @property-read string $file_type_id_label
|
||||
* @property-read string $file_type_id_constant
|
||||
* @property-read array $file_type_id_enum_val
|
||||
*
|
||||
* @method static array file_type_id_enum_val() Get all enum definitions with full metadata
|
||||
* @method static array file_type_id_enum_select() Get selectable items for dropdowns
|
||||
* @method static array file_type_id_enum_labels() Get simple id => label map
|
||||
* @method static array file_type_id_enum_ids() Get array of all valid enum IDs
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class File_Attachment_Model extends Rsx_Site_Model_Abstract
|
||||
{
|
||||
/** __AUTO_GENERATED: */
|
||||
{
|
||||
/**
|
||||
* _AUTO_GENERATED_ Enum constants
|
||||
*/
|
||||
const FILE_TYPE_IMAGE = 1;
|
||||
const FILE_TYPE_ANIMATED_IMAGE = 2;
|
||||
const FILE_TYPE_VIDEO = 3;
|
||||
@@ -73,6 +82,9 @@ class File_Attachment_Model extends Rsx_Site_Model_Abstract
|
||||
const FILE_TYPE_TEXT = 5;
|
||||
const FILE_TYPE_DOCUMENT = 6;
|
||||
const FILE_TYPE_OTHER = 7;
|
||||
|
||||
/** __AUTO_GENERATED: */
|
||||
|
||||
/** __/AUTO_GENERATED */
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@ use App\RSpade\Core\Database\Models\Rsx_Model_Abstract;
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:31
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: _file_storage
|
||||
*
|
||||
* @property int $id
|
||||
@@ -30,7 +30,7 @@ use App\RSpade\Core\Database\Models\Rsx_Model_Abstract;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class File_Storage_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
// Required static properties from parent abstract class
|
||||
public static $enums = [];
|
||||
public static $rel = [];
|
||||
|
||||
@@ -14,7 +14,7 @@ use App\RSpade\Core\Models\Region_Model;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:31
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: countries
|
||||
*
|
||||
* @property int $id
|
||||
@@ -32,7 +32,7 @@ use App\RSpade\Core\Models\Region_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Country_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
public static $enums = [];
|
||||
|
||||
protected $table = 'countries';
|
||||
|
||||
@@ -12,7 +12,7 @@ use App\RSpade\Core\Database\Models\Rsx_System_Model_Abstract;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:31
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: ip_addresses
|
||||
*
|
||||
* @property int $id
|
||||
@@ -30,7 +30,7 @@ use App\RSpade\Core\Database\Models\Rsx_System_Model_Abstract;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Ip_Address_Model extends Rsx_System_Model_Abstract
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Enum field definitions
|
||||
* @var array
|
||||
|
||||
@@ -24,7 +24,7 @@ use App\RSpade\Core\Session\Session;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:31
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: login_users
|
||||
*
|
||||
* @property int $id
|
||||
@@ -62,7 +62,7 @@ class Login_User_Model extends Rsx_Model_Abstract implements
|
||||
\Illuminate\Contracts\Auth\Authenticatable,
|
||||
\Illuminate\Contracts\Auth\Access\Authorizable,
|
||||
\Illuminate\Contracts\Auth\CanResetPassword
|
||||
{
|
||||
{
|
||||
/**
|
||||
* _AUTO_GENERATED_ Enum constants
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ use App\RSpade\Core\Models\Country_Model;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:54
|
||||
* Table: regions
|
||||
*
|
||||
* @property int $id
|
||||
@@ -31,7 +31,7 @@ use App\RSpade\Core\Models\Country_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Region_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
public static $enums = [];
|
||||
|
||||
protected $table = 'regions';
|
||||
|
||||
@@ -14,7 +14,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: sites
|
||||
*
|
||||
* @property int $id
|
||||
@@ -31,7 +31,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Site_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ use App\RSpade\Core\Database\Models\Rsx_Site_Model_Abstract;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: user_invites
|
||||
*
|
||||
* @property int $id
|
||||
@@ -28,7 +28,7 @@ use App\RSpade\Core\Database\Models\Rsx_Site_Model_Abstract;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User_Invite_Model extends Rsx_Site_Model_Abstract
|
||||
{
|
||||
{
|
||||
/**
|
||||
* Enum field definitions
|
||||
* @var array
|
||||
|
||||
@@ -23,41 +23,47 @@ use App\RSpade\Core\Models\User_Profile_Model;
|
||||
* See: php artisan rsx:man acls
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_
|
||||
* @property integer $id
|
||||
* @property integer $login_user_id
|
||||
* @property integer $site_id
|
||||
* @property string $first_name
|
||||
* @property string $last_name
|
||||
* @property string $phone
|
||||
* @property integer $role_id
|
||||
* @property boolean $is_enabled
|
||||
* @property integer $user_role_id
|
||||
* @property string $email
|
||||
* @property \Carbon\Carbon $deleted_at
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property integer $created_by
|
||||
* @property integer $updated_by
|
||||
* @property integer $deleted_by
|
||||
* @property string $invite_code
|
||||
* @property \Carbon\Carbon $invite_accepted_at
|
||||
* @property \Carbon\Carbon $invite_expires_at
|
||||
* @method static mixed role_id_enum()
|
||||
* @method static mixed role_id_enum_select()
|
||||
* @method static mixed role_id_enum_ids()
|
||||
* @property-read mixed $role_id_constant
|
||||
* @property-read mixed $role_id_label
|
||||
* @property-read mixed $role_id_permissions
|
||||
* @property-read mixed $role_id_can_admin_roles
|
||||
* @property-read mixed $role_id_selectable
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: users
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $login_user_id
|
||||
* @property int $site_id
|
||||
* @property mixed $first_name
|
||||
* @property mixed $last_name
|
||||
* @property mixed $phone
|
||||
* @property int $role_id
|
||||
* @property bool $is_enabled
|
||||
* @property int $user_role_id
|
||||
* @property mixed $email
|
||||
* @property string $deleted_at
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property int $created_by
|
||||
* @property int $updated_by
|
||||
* @property int $deleted_by
|
||||
* @property mixed $invite_code
|
||||
* @property string $invite_accepted_at
|
||||
* @property string $invite_expires_at
|
||||
*
|
||||
* @property-read string $role_id_label
|
||||
* @property-read string $role_id_constant
|
||||
* @property-read array $role_id_enum_val
|
||||
*
|
||||
* @method static array role_id_enum_val() Get all enum definitions with full metadata
|
||||
* @method static array role_id_enum_select() Get selectable items for dropdowns
|
||||
* @method static array role_id_enum_labels() Get simple id => label map
|
||||
* @method static array role_id_enum_ids() Get array of all valid enum IDs
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User_Model extends Rsx_Site_Model_Abstract
|
||||
{
|
||||
/** __AUTO_GENERATED: */
|
||||
{
|
||||
/**
|
||||
* _AUTO_GENERATED_ Enum constants
|
||||
*/
|
||||
const ROLE_DEVELOPER = 100;
|
||||
const ROLE_ROOT_ADMIN = 200;
|
||||
const ROLE_SITE_OWNER = 300;
|
||||
@@ -66,6 +72,9 @@ class User_Model extends Rsx_Site_Model_Abstract
|
||||
const ROLE_USER = 600;
|
||||
const ROLE_VIEWER = 700;
|
||||
const ROLE_DISABLED = 800;
|
||||
|
||||
/** __AUTO_GENERATED: */
|
||||
|
||||
/** __/AUTO_GENERATED */
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@@ -7,7 +7,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: user_permissions
|
||||
*
|
||||
* @property int $id
|
||||
@@ -22,7 +22,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User_Permission_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
protected $table = 'user_permissions';
|
||||
protected $fillable = []; // No mass assignment - always explicit
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: user_profiles
|
||||
*
|
||||
* @property int $id
|
||||
@@ -51,7 +51,7 @@ use App\RSpade\Core\Models\User_Model;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User_Profile_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
{
|
||||
/**
|
||||
* The table associated with the model
|
||||
*
|
||||
|
||||
@@ -11,33 +11,45 @@ use App\RSpade\Core\Database\Models\Rsx_Model_Abstract;
|
||||
* and two-factor authentication via email or SMS.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_
|
||||
* @property integer $id
|
||||
* @property string $email
|
||||
* @property string $verification_code
|
||||
* @property integer $verification_type_id
|
||||
* @property \Carbon\Carbon $verified_at
|
||||
* @property \Carbon\Carbon $expires_at
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property integer $created_by
|
||||
* @property integer $updated_by
|
||||
* @method static mixed verification_type_id_enum()
|
||||
* @method static mixed verification_type_id_enum_select()
|
||||
* @method static mixed verification_type_id_enum_ids()
|
||||
* @property-read mixed $verification_type_id_constant
|
||||
* @property-read mixed $verification_type_id_label
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: user_verifications
|
||||
*
|
||||
* @property int $id
|
||||
* @property mixed $email
|
||||
* @property mixed $verification_code
|
||||
* @property int $verification_type_id
|
||||
* @property string $verified_at
|
||||
* @property string $expires_at
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property int $created_by
|
||||
* @property int $updated_by
|
||||
*
|
||||
* @property-read string $verification_type_id_label
|
||||
* @property-read string $verification_type_id_constant
|
||||
* @property-read array $verification_type_id_enum_val
|
||||
*
|
||||
* @method static array verification_type_id_enum_val() Get all enum definitions with full metadata
|
||||
* @method static array verification_type_id_enum_select() Get selectable items for dropdowns
|
||||
* @method static array verification_type_id_enum_labels() Get simple id => label map
|
||||
* @method static array verification_type_id_enum_ids() Get array of all valid enum IDs
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class User_Verification_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
/** __AUTO_GENERATED: */
|
||||
{
|
||||
/**
|
||||
* _AUTO_GENERATED_ Enum constants
|
||||
*/
|
||||
const VERIFICATION_TYPE_EMAIL = 1;
|
||||
const VERIFICATION_TYPE_SMS = 2;
|
||||
const VERIFICATION_TYPE_EMAIL_RECOVERY = 3;
|
||||
const VERIFICATION_TYPE_SMS_RECOVERY = 4;
|
||||
|
||||
/** __AUTO_GENERATED: */
|
||||
|
||||
/** __/AUTO_GENERATED */
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ use App\RSpade\Core\Database\Models\Rsx_Site_Model_Abstract;
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:32
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: _search_indexes
|
||||
*
|
||||
* @property int $id
|
||||
@@ -37,7 +37,7 @@ use App\RSpade\Core\Database\Models\Rsx_Site_Model_Abstract;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Search_Index_Model extends Rsx_Site_Model_Abstract
|
||||
{
|
||||
{
|
||||
// Required static properties from parent abstract class
|
||||
public static $enums = [];
|
||||
public static $rel = [];
|
||||
|
||||
@@ -41,7 +41,7 @@ use App\RSpade\Core\Session\User_Agent;
|
||||
*/
|
||||
/**
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-10 02:59:33
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: _sessions
|
||||
*
|
||||
* @property int $id
|
||||
@@ -63,7 +63,7 @@ use App\RSpade\Core\Session\User_Agent;
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Session extends Rsx_System_Model_Abstract
|
||||
{
|
||||
{
|
||||
// Enum definitions (required by abstract parent)
|
||||
public static $enums = [];
|
||||
|
||||
|
||||
@@ -5,29 +5,42 @@ namespace App\RSpade\Lib\Flash;
|
||||
use App\RSpade\Core\Database\Models\Rsx_Model_Abstract;
|
||||
|
||||
/**
|
||||
* _AUTO_GENERATED_
|
||||
* @property integer $id
|
||||
* @property integer $session_id
|
||||
* @property integer $type_id
|
||||
* _AUTO_GENERATED_ Database type hints - do not edit manually
|
||||
* Generated on: 2025-12-25 20:57:55
|
||||
* Table: _flash_alerts
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $session_id
|
||||
* @property int $type_id
|
||||
* @property string $message
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property integer $created_by
|
||||
* @property integer $updated_by
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @method static mixed type_id_enum()
|
||||
* @method static mixed type_id_enum_select()
|
||||
* @method static mixed type_id_enum_ids()
|
||||
* @property-read mixed $type_id_constant
|
||||
* @property-read mixed $type_id_label
|
||||
* @property string $created_at
|
||||
* @property int $created_by
|
||||
* @property int $updated_by
|
||||
* @property string $updated_at
|
||||
*
|
||||
* @property-read string $type_id_label
|
||||
* @property-read string $type_id_constant
|
||||
* @property-read array $type_id_enum_val
|
||||
*
|
||||
* @method static array type_id_enum_val() Get all enum definitions with full metadata
|
||||
* @method static array type_id_enum_select() Get selectable items for dropdowns
|
||||
* @method static array type_id_enum_labels() Get simple id => label map
|
||||
* @method static array type_id_enum_ids() Get array of all valid enum IDs
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Flash_Alert_Model extends Rsx_Model_Abstract
|
||||
{
|
||||
/** __AUTO_GENERATED: */
|
||||
{
|
||||
/**
|
||||
* _AUTO_GENERATED_ Enum constants
|
||||
*/
|
||||
const TYPE_SUCCESS = 1;
|
||||
const TYPE_ERROR = 2;
|
||||
const TYPE_INFO = 3;
|
||||
const TYPE_WARNING = 4;
|
||||
|
||||
/** __AUTO_GENERATED: */
|
||||
|
||||
/** __/AUTO_GENERATED */
|
||||
|
||||
// Enum constants (auto-generated by rsx:migrate:document_models)
|
||||
|
||||
@@ -1135,6 +1135,10 @@ Sessions persist 365 days. Never implement "Remember Me".
|
||||
|
||||
**Two Classes - Strict Separation**: `Rsx_Time` (datetimes with timezone) | `Rsx_Date` (calendar dates, no timezone)
|
||||
|
||||
**String-Based Philosophy**: RSpade uses ISO strings, not Carbon objects. Dates are `"2025-12-24"`, datetimes are `"2025-12-24T15:30:00-06:00"`. Same format in PHP, JavaScript, JSON, database queries. No object serialization issues.
|
||||
|
||||
**Model Casts**: `Rsx_Model_Abstract` auto-applies `Rsx_Date_Cast` (DATE columns) and `Rsx_DateTime_Cast` (DATETIME columns). Never define `$casts` with `'date'`, `'datetime'`, or `'timestamp'` - these use Carbon and are blocked by `rsx:check`.
|
||||
|
||||
### Rsx_Time - Moments in Time
|
||||
```php
|
||||
use App\RSpade\Core\Time\Rsx_Time;
|
||||
@@ -1226,6 +1230,8 @@ Options: `--user=ID`, `--console`, `--screenshot-path`, `--screenshot-width=mobi
|
||||
|
||||
**SPA routes ARE server routes.** If you get 404, the route doesn't exist - check route definitions. Never dismiss as "SPA can't be tested server-side".
|
||||
|
||||
**rsx:debug captures the fully-rendered final DOM state** after all async operations, component lifecycles, and data loading complete. If the DOM doesn't match expectations, it's not a timing issue - what you see is what the user sees. Investigate the actual code, not the capture timing.
|
||||
|
||||
### Debugging
|
||||
|
||||
- **rsx_dump_die()** - Debug output
|
||||
|
||||
Reference in New Issue
Block a user