Files
rspade_system/app/RSpade/Commands/Rsx/RsxFileAttachCommand.php
root 29c657f7a7 Exclude tests directory from framework publish
Add 100+ automated unit tests from .expect file specifications
Add session system test
Add rsx:constants:regenerate command test
Add rsx:logrotate command test
Add rsx:clean command test
Add rsx:manifest:stats command test
Add model enum system test
Add model mass assignment prevention test
Add rsx:check command test
Add migrate:status command test

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-25 03:59:58 +00:00

157 lines
5.1 KiB
PHP

<?php
/**
* CODING CONVENTION:
* This file follows the coding convention where variable_names and function_names
* use snake_case (underscore_wherever_possible).
*/
namespace App\RSpade\Commands\Rsx;
use Illuminate\Console\Command;
use Rsx\Models\File_Attachment_Model;
use App\RSpade\Core\Locks\RsxLocks;
/**
* File Attach Command
* ====================
*
* PURPOSE:
* Attach an existing file to a different model or update attachment metadata.
*
* FEATURES:
* - Change polymorphic relationship (fileable_type/fileable_id)
* - Update metadata fields (category, type_meta, meta JSON)
* - Set fileable_order for ordering
* - Uses file locking to prevent race conditions
*/
class RsxFileAttachCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rsx:file:attach
{key : 64-char hex attachment key}
{--model= : Model to attach to (Model:ID)}
{--category= : Update fileable_category}
{--type-meta= : Update fileable_type_meta}
{--meta= : Update fileable_meta JSON}
{--order= : Set fileable_order}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Attach file to model or update attachment metadata';
/**
* Execute the console command.
*/
public function handle()
{
$key = $this->argument('key');
// Validate at least one option provided
if (!$this->option('model') &&
!$this->option('category') &&
!$this->option('type-meta') &&
!$this->option('meta') &&
!$this->option('order')) {
$this->error('Error: Must specify at least one update option');
$this->info('');
$this->info('Update options:');
$this->info(' --model=Model:ID Attach to model');
$this->info(' --category="cat" Set category');
$this->info(' --type-meta="meta" Set type meta');
$this->info(' --meta=\'{"key":"val"}\' Set meta JSON');
$this->info(' --order=1 Set order');
return 1;
}
// Find attachment
$attachment = File_Attachment_Model::where('key', $key)->first();
if (!$attachment) {
$this->error("Error: File attachment not found with key: {$key}");
return 1;
}
// Acquire file write lock
$lock = RsxLocks::get_lock(
RsxLocks::SERVER_LOCK,
RsxLocks::LOCK_FILE_WRITE,
RsxLocks::WRITE_LOCK,
30
);
try {
$updated_fields = [];
// Update model attachment
if ($model_spec = $this->option('model')) {
if (!str_contains($model_spec, ':')) {
$this->error('Error: --model format must be Model:ID (e.g., User_Model:42)');
return 1;
}
list($model_class, $model_id) = explode(':', $model_spec, 2);
$attachment->fileable_type = $model_class;
$attachment->fileable_id = (int)$model_id;
$updated_fields[] = "Attached to {$model_class}:{$model_id}";
}
// Update category
if ($category = $this->option('category')) {
$attachment->fileable_category = $category;
$updated_fields[] = "Category: {$category}";
}
// Update type meta
if ($type_meta = $this->option('type-meta')) {
$attachment->fileable_type_meta = $type_meta;
$updated_fields[] = "Type Meta: {$type_meta}";
}
// Update meta JSON
if ($meta_json = $this->option('meta')) {
$meta = json_decode($meta_json, true);
if ($meta === null && json_last_error() !== JSON_ERROR_NONE) {
$this->error('Error: Invalid JSON in --meta option');
return 1;
}
$attachment->set_meta($meta);
$updated_fields[] = "Meta JSON updated";
}
// Update order
if ($this->option('order') !== null) {
$order = (int)$this->option('order');
$attachment->fileable_order = $order;
$updated_fields[] = "Order: {$order}";
}
$attachment->save();
// Output success
$this->info('');
$this->info('[OK] File attachment updated');
$this->info('');
$this->info(" File: {$attachment->file_name}");
$this->info(" Key: {$attachment->key}");
$this->info('');
$this->info('Updated fields:');
foreach ($updated_fields as $field) {
$this->info(" - {$field}");
}
$this->info('');
return 0;
} finally {
RsxLocks::release_lock($lock);
}
}
}