Files
rspade_system/app/RSpade/Commands/Rsx/Module_Feature_Create_Command.php
root ac082bce2a Add config() Go to Definition support to VS Code extension
Always include params in window.rsxapp to reduce state variations
Add request params to window.rsxapp global
Enhance module creation commands with clear nomenclature guidance
Add module/submodule/feature nomenclature clarification to docs

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 19:13:57 +00:00

163 lines
5.9 KiB
PHP
Executable File

<?php
namespace App\RSpade\Commands\Rsx;
use Illuminate\Console\Command;
use App\RSpade\Core\CodeTemplates\StubProcessor;
class Module_Feature_Create_Command extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rsx:app:module:feature:create
{module : Module name (must exist)}
{feature : Feature name (lowercase with underscores)}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a feature (CRUD page group) within a module. Example: clients, tasks';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$module_name = $this->argument('module');
$feature_name = $this->argument('feature');
// Validate names (lowercase and underscores only)
if (!preg_match('/^[a-z_]+$/', $module_name)) {
$this->error('Module name must contain only lowercase letters and underscores.');
return 1;
}
if (!preg_match('/^[a-z_]+$/', $feature_name)) {
$this->error('Feature name must contain only lowercase letters and underscores.');
return 1;
}
// Check if module exists
$module_path = base_path("rsx/app/{$module_name}");
if (!is_dir($module_path)) {
$this->error("Module '{$module_name}' does not exist.");
$this->line('');
$this->line('NOMENCLATURE:');
$this->line(' Module = Top-level section with shared layout (e.g., frontend, admin)');
$this->line(' Feature = CRUD page group within a module (e.g., clients, tasks)');
$this->line('');
$this->line('Create the module first:');
$this->info(" php artisan rsx:app:module:create {$module_name}");
return 1;
}
// Determine feature path and naming
if ($feature_name === 'index') {
// Index feature goes in module root
$feature_path = $module_path;
$file_prefix = "{$module_name}_index";
} else {
// Other features go in subdirectory
$feature_path = "{$module_path}/{$feature_name}";
$file_prefix = "{$module_name}_{$feature_name}";
// Check if feature directory already exists
if (is_dir($feature_path)) {
$this->error("Feature '{$feature_name}' already exists in module '{$module_name}'");
return 1;
}
// Create feature directory
if (!mkdir($feature_path, 0755, true)) {
$this->error("Failed to create feature directory: {$feature_path}");
return 1;
}
}
// Check if any feature files already exist
$files_to_create = [
"{$feature_path}/{$file_prefix}_controller.php" => 'controller',
"{$feature_path}/{$file_prefix}.blade.php" => 'view',
"{$feature_path}/{$file_prefix}.js" => 'JavaScript',
"{$feature_path}/{$file_prefix}.scss" => 'SCSS',
];
foreach ($files_to_create as $file => $type) {
if (file_exists($file)) {
$this->error("Cannot create feature '{$feature_name}': {$type} file already exists at {$file}");
return 1;
}
}
$this->info("Creating feature '{$feature_name}' in module '{$module_name}'...");
// Generate replacements
$replacements = StubProcessor::generate_replacements($module_name, null, $feature_name);
try {
// Create controller
$controller_content = StubProcessor::process('controller', $replacements);
$controller_file = "{$feature_path}/{$file_prefix}_controller.php";
file_put_contents($controller_file, $controller_content);
$this->info("Created controller: {$file_prefix}_controller.php");
// Create view
$view_content = StubProcessor::process('view', $replacements);
$view_file = "{$feature_path}/{$file_prefix}.blade.php";
file_put_contents($view_file, $view_content);
$this->info("Created view: {$file_prefix}.blade.php");
// Create JavaScript
$js_content = StubProcessor::process('javascript', $replacements);
$js_file = "{$feature_path}/{$file_prefix}.js";
file_put_contents($js_file, $js_content);
$this->info("Created JavaScript: {$file_prefix}.js");
// Create SCSS
$scss_content = StubProcessor::process('scss', $replacements);
$scss_file = "{$feature_path}/{$file_prefix}.scss";
file_put_contents($scss_file, $scss_content);
$this->info("Created SCSS: {$file_prefix}.scss");
} catch (\Exception $e) {
$this->error("Failed to create feature: " . $e->getMessage());
// Clean up on failure
if (is_dir($feature_path) && $feature_name !== 'index') {
$this->cleanup_directory($feature_path);
}
return 1;
}
$this->info("✅ Feature '{$feature_name}' created successfully in module '{$module_name}'!");
$this->info("Route: {$replacements['route_path']}");
$this->info("Controller: {$replacements['controller_class']}");
$this->info("View ID: {$replacements['view_class']}");
return 0;
}
/**
* Clean up directory on failure
*/
protected function cleanup_directory($dir)
{
if (!is_dir($dir)) {
return;
}
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
$path = $dir . '/' . $file;
is_dir($path) ? $this->cleanup_directory($path) : unlink($path);
}
rmdir($dir);
}
}