's3']); $hash = $status === 'pending' ? null : str_repeat($source === 'local' ? 'a' : ($source === 'object' ? 'b' : 'c'), 40); $ext = $status === 'pending' ? null : 'jpg'; if ($source === 'local') { $root = (string) config('uploads.local_originals_root'); $path = $root . DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR . $hash . '.jpg'; File::ensureDirectoryExists(dirname($path)); File::put($path, 'local'); } elseif ($source === 'object') { Storage::disk('s3')->put("artworks/original/bb/bb/{$hash}.jpg", 'object'); } $artwork = Artwork::factory()->create([ 'file_name' => $status === 'pending' ? 'pending' : 'audit-' . $status, 'hash' => $hash, 'file_ext' => $ext, 'file_path' => '', ]); $exit = Artisan::call('artworks:audit-download-files', [ '--id' => $artwork->id, '--chunk' => 1, ]); $output = Artisan::output(); expect($exit)->toBe(Command::SUCCESS) ->and($output)->toContain("classification={$expected} count=1") ->and($output)->toContain('processed=1'); })->with([ ['available', 'local', 'LOCAL_OK'], ['available', 'object', 'OBJECT_OK'], ['pending', null, 'PENDING'], ['missing', null, 'MISSING_EVERYWHERE'], ]); it('marks an explicit id once when requested', function (): void { Storage::fake('s3'); config(['uploads.object_storage.disk' => 's3']); $hash = str_repeat('cd', 20); Storage::disk('s3')->put("artworks/original/cd/cd/{$hash}.jpg", 'object'); $artwork = Artwork::factory()->create([ 'hash' => $hash, 'file_ext' => 'jpg', 'file_path' => '', ]); expect(Artisan::call('artworks:audit-download-files', [ '--id' => $artwork->id, '--chunk' => 1, '--mark-status' => true, ]))->toBe(Command::SUCCESS); $artwork->refresh(); expect($artwork->download_status)->toBe('available') ->and($artwork->download_source)->toBe('object') ->and(Artisan::output())->toContain('processed=1'); });