Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at dev 4.0 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Support; 4 5use Illuminate\Http\UploadedFile; 6use Illuminate\Support\Facades\Storage; 7use SocialDept\AtpSchema\Contracts\BlobHandler; 8use SocialDept\AtpSchema\Data\BlobReference; 9 10class DefaultBlobHandler implements BlobHandler 11{ 12 /** 13 * Storage disk to use. 14 */ 15 protected string $disk; 16 17 /** 18 * Storage path prefix. 19 */ 20 protected string $path; 21 22 /** 23 * Create a new DefaultBlobHandler. 24 */ 25 public function __construct( 26 ?string $disk = null, 27 string $path = 'blobs' 28 ) { 29 $this->disk = $disk ?? config('filesystems.default', 'local'); 30 $this->path = $path; 31 } 32 33 /** 34 * Upload blob and create reference. 35 */ 36 public function upload(UploadedFile $file): BlobReference 37 { 38 $hash = hash_file('sha256', $file->getPathname()); 39 $mimeType = $file->getMimeType() ?? 'application/octet-stream'; 40 $size = $file->getSize(); 41 42 // Store with hash as filename to enable deduplication 43 $storagePath = $this->path.'/'.$hash; 44 Storage::disk($this->disk)->put($storagePath, file_get_contents($file->getPathname())); 45 46 return new BlobReference( 47 cid: $hash, // Using hash as CID for simplicity 48 mimeType: $mimeType, 49 size: $size 50 ); 51 } 52 53 /** 54 * Upload blob from path. 55 */ 56 public function uploadFromPath(string $path): BlobReference 57 { 58 $hash = hash_file('sha256', $path); 59 $mimeType = mime_content_type($path) ?: 'application/octet-stream'; 60 $size = filesize($path); 61 62 // Store with hash as filename 63 $storagePath = $this->path.'/'.$hash; 64 Storage::disk($this->disk)->put($storagePath, file_get_contents($path)); 65 66 return new BlobReference( 67 cid: $hash, 68 mimeType: $mimeType, 69 size: $size 70 ); 71 } 72 73 /** 74 * Upload blob from content. 75 */ 76 public function uploadFromContent(string $content, string $mimeType): BlobReference 77 { 78 $hash = hash('sha256', $content); 79 $size = strlen($content); 80 81 // Store with hash as filename 82 $storagePath = $this->path.'/'.$hash; 83 Storage::disk($this->disk)->put($storagePath, $content); 84 85 return new BlobReference( 86 cid: $hash, 87 mimeType: $mimeType, 88 size: $size 89 ); 90 } 91 92 /** 93 * Download blob content. 94 */ 95 public function download(BlobReference $blob): string 96 { 97 $storagePath = $this->path.'/'.$blob->cid; 98 99 if (! Storage::disk($this->disk)->exists($storagePath)) { 100 throw new \RuntimeException("Blob not found: {$blob->cid}"); 101 } 102 103 return Storage::disk($this->disk)->get($storagePath); 104 } 105 106 /** 107 * Generate signed URL for blob. 108 */ 109 public function url(BlobReference $blob): string 110 { 111 $storagePath = $this->path.'/'.$blob->cid; 112 113 // Try to generate a temporary URL if the disk supports it 114 try { 115 return Storage::disk($this->disk)->temporaryUrl( 116 $storagePath, 117 now()->addHour() 118 ); 119 } catch (\RuntimeException $e) { 120 // Fallback to regular URL for disks that don't support temporary URLs 121 return Storage::disk($this->disk)->url($storagePath); 122 } 123 } 124 125 /** 126 * Check if blob exists in storage. 127 */ 128 public function exists(BlobReference $blob): bool 129 { 130 $storagePath = $this->path.'/'.$blob->cid; 131 132 return Storage::disk($this->disk)->exists($storagePath); 133 } 134 135 /** 136 * Delete blob from storage. 137 */ 138 public function delete(BlobReference $blob): bool 139 { 140 $storagePath = $this->path.'/'.$blob->cid; 141 142 if (! Storage::disk($this->disk)->exists($storagePath)) { 143 return false; 144 } 145 146 return Storage::disk($this->disk)->delete($storagePath); 147 } 148}