Files
SGF/app/Modules/Purchasing/SupplierDocumentFiles.php
T
2026-11-04 09:37:20 +02:00

33 lines
2.5 KiB
PHP

<?php
namespace App\Modules\Purchasing;
use Illuminate\Support\Facades\Storage;
/** Storage is confined to the already verified composition, never public or client storage. */
final class SupplierDocumentFiles
{
public function root(bool $preview=false,string $resource='supplier'):string {
abort_unless(in_array($resource,['supplier','receipt'],true),403);
$profile=realpath((string)config('receipt_qa.profile'));abort_unless($profile,403);
$base=str_replace('\\','/',dirname($profile));$run=(string)getenv('SGF_ISOLATED_REGRESSION_RUN');
abort_unless(preg_match('/^[a-f0-9]{12}$/D',$run)&&preg_match('~^'.preg_quote('C:/laragon/data/sgf-tempo/run/modular-regression-'.$run.'/private/receipt-composition-','~').'[a-f0-9]{12}$~iD',$base),403);
$container=$base.'/'.$resource.($preview?'-document-previews':'-documents');abort_if(is_link($container),403);
if(!is_dir($container))mkdir($container,0700);
abort_unless(realpath($container)&&str_starts_with(strtolower(realpath($container)),strtolower(realpath($base).DIRECTORY_SEPARATOR)),403);
$root=$preview?$container.'/'.bin2hex(random_bytes(16)):$container;
if(!is_dir($root))mkdir($root,0700);abort_unless(realpath($root)&&!is_link($root),403);return $root;
}
public function using(string $root,\Closure $work,string $disk='supplier_documents'):mixed {
abort_unless(in_array($disk,['supplier_documents','receipt_documents'],true),403);
$before=config('filesystems.disks.'.$disk);config(['filesystems.disks.'.$disk=>['driver'=>'local','root'=>$root,'throw'=>true,'serve'=>false]]);Storage::forgetDisk($disk);
try{return $work(Storage::disk($disk));}finally{Storage::forgetDisk($disk);config(['filesystems.disks.'.$disk=>$before]);}
}
public function path(string $root,string $path,int $tenant,int $supplier):string {
abort_unless(preg_match('~^'.$tenant.'/'.$supplier.'/[A-Za-z0-9]{40}\.(pdf|png|jpe?g)$~D',$path),409,'Referência de anexo inválida.');
$file=realpath($root.'/'.$path);$base=realpath($root);abort_unless($file&&$base&&!is_link($root.'/'.$path)&&str_starts_with(strtolower($file),strtolower($base.DIRECTORY_SEPARATOR)),409,'Anexo indisponível.');return $file;
}
public function discard(string $root,string $path,int $tenant,int $supplier,string $disk='supplier_documents'):void {
$this->path($root,$path,$tenant,$supplier);$this->using($root,fn($storage)=>$storage->delete($path),$disk);
}
}