diff --git a/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php b/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php index 8f74281ee..46ed8b759 100755 --- a/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php +++ b/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php @@ -98,8 +98,67 @@ class Constants_Regenerate_Command extends Command $enums = $reflector->getStaticPropertyValue('enums', []); // We don't need 'rel' for constants generation - // Error check + // Error check - validate enum integrity BEFORE processing + // These checks run outside try-catch to fail immediately foreach ($enums as $column => $enumValues) { + // Validate enum values are integers + foreach ($enumValues as $value => $props) { + if (!is_int($value) && !ctype_digit((string)$value)) { + $this->error("Invalid enum value '{$value}' for column '{$column}' in model '{$fullClassName}'."); + $this->newLine(); + $this->error("ENUM VALUES MUST BE INTEGERS."); + $this->newLine(); + $this->line("The purpose of enum values is to store an INTEGER in the database that corresponds to a"); + $this->line("string in the enum definition. The string label can then be changed in the enum 'label'"); + $this->line("property without affecting the database value, so long as it continues to correspond to"); + $this->line("the same numeric integer."); + $this->newLine(); + $this->line("Example of a properly defined enum:"); + $this->newLine(); + $this->line(" protected static \$enums = ["); + $this->line(" 'status' => ["); + $this->line(" 1 => ['label' => 'Active', 'constant' => 'STATUS_ACTIVE'],"); + $this->line(" 2 => ['label' => 'Inactive', 'constant' => 'STATUS_INACTIVE'],"); + $this->line(" 3 => ['label' => 'Pending', 'constant' => 'STATUS_PENDING'],"); + $this->line(" ],"); + $this->line(" ];"); + $this->newLine(); + $this->line("For more information, run: php artisan rsx:man enums"); + return 1; // Exit with error code + } + } + + // Validate enum column is integer type in database + $columnType = DB::getSchemaBuilder()->getColumnType($table, $column); + $validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint']; + + if (!in_array($columnType, $validIntegerTypes)) { + $this->error("Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}')."); + $this->newLine(); + $this->error("ENUM COLUMNS MUST BE INTEGER TYPES."); + $this->newLine(); + $this->line("Enum values are stored as integers in the database. The column must be defined as an"); + $this->line("integer type (INT, BIGINT, SMALLINT, TINYINT, or MEDIUMINT), not VARCHAR or other string types."); + $this->newLine(); + $this->line("Current column type: {$columnType}"); + $this->line("Required column types: " . implode(', ', $validIntegerTypes)); + $this->newLine(); + $this->line("To fix this issue:"); + $this->line("1. Create a migration to change the column type to an integer"); + $this->line("2. Example migration:"); + $this->newLine(); + $this->line(" public function up()"); + $this->line(" {"); + $this->line(" Schema::table('{$table}', function (Blueprint \$table) {"); + $this->line(" \$table->integer('{$column}')->change();"); + $this->line(" });"); + $this->line(" }"); + $this->newLine(); + $this->line("For more information, run: php artisan rsx:man enums"); + return 1; // Exit with error code + } + + // Check for duplicate constants $constants = []; foreach ($enumValues as $value => $props) { if (isset($props['constant'])) { @@ -141,58 +200,13 @@ class Constants_Regenerate_Command extends Command } // Process enum magic methods and properties + // Note: Validation already performed in early error check section above foreach ($enums as $column => $enumValues) { - // Validate that the database column is an integer type - $columnType = DB::getSchemaBuilder()->getColumnType($table, $column); - $validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint']; - - if (!in_array($columnType, $validIntegerTypes)) { - throw new Exception( - "Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}').\n\n" . - "ENUM COLUMNS MUST BE INTEGER TYPES.\n\n" . - "Enum values are stored as integers in the database. The column must be defined as an " . - "integer type (INT, BIGINT, SMALLINT, TINYINT, or MEDIUMINT), not VARCHAR or other string types.\n\n" . - "Current column type: {$columnType}\n" . - "Required column types: " . implode(', ', $validIntegerTypes) . "\n\n" . - "To fix this issue:\n" . - "1. Create a migration to change the column type to an integer\n" . - "2. Example migration:\n\n" . - " public function up()\n" . - " {\n" . - " Schema::table('{$table}', function (Blueprint \$table) {\n" . - " \$table->integer('{$column}')->change();\n" . - " });\n" . - " }\n\n" . - "For more information, run: php artisan rsx:man enums" - ); - } - $docblock .= " * @method static mixed {$column}_enum()\n"; $docblock .= " * @method static mixed {$column}_enum_select()\n"; $docblock .= " * @method static mixed {$column}_enum_ids()\n"; $seenProps = []; foreach ($enumValues as $value => $props) { - // Validate that enum value is an integer - if (!is_int($value) && !ctype_digit((string)$value)) { - throw new Exception( - "Invalid enum value '{$value}' for column '{$column}' in model '{$fullClassName}'.\n\n" . - "ENUM VALUES MUST BE INTEGERS.\n\n" . - "The purpose of enum values is to store an INTEGER in the database that corresponds to a " . - "string in the enum definition. The string label can then be changed in the enum 'label' " . - "property without affecting the database value, so long as it continues to correspond to " . - "the same numeric integer.\n\n" . - "Example of a properly defined enum:\n\n" . - " protected static \$enums = [\n" . - " 'status' => [\n" . - " 1 => ['label' => 'Active', 'constant' => 'STATUS_ACTIVE'],\n" . - " 2 => ['label' => 'Inactive', 'constant' => 'STATUS_INACTIVE'],\n" . - " 3 => ['label' => 'Pending', 'constant' => 'STATUS_PENDING'],\n" . - " ],\n" . - " ];\n\n" . - "For more information, run: php artisan rsx:man enums" - ); - } - foreach ($props as $p => $v) { if (!in_array($p, $seenProps)) { $docblock .= " * @property-read mixed \${$column}_{$p}\n";