@@ -21,6 +21,18 @@ final class FinancialAttachmentService
|
||||
];
|
||||
|
||||
public function saveUploadedFile($file, string $subdir): ?string
|
||||
{
|
||||
$staged = $this->stageUploadedFile($file, $subdir);
|
||||
if ($staged === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->finalizeStagedFile($staged);
|
||||
|
||||
return $staged['final_name'];
|
||||
}
|
||||
|
||||
public function stageUploadedFile($file, string $subdir): ?array
|
||||
{
|
||||
if (!$file instanceof UploadedFile) {
|
||||
return null;
|
||||
@@ -46,11 +58,50 @@ final class FinancialAttachmentService
|
||||
throw new \RuntimeException('File too large. Maximum size is 5 MB.');
|
||||
}
|
||||
|
||||
$dir = $this->ensureSubdir($subdir);
|
||||
$name = $file->getRandomName();
|
||||
$file->move($dir, $name);
|
||||
$tmpSubdir = '_tmp' . DIRECTORY_SEPARATOR . trim($subdir, '/');
|
||||
$tmpDir = $this->ensureSubdir($tmpSubdir);
|
||||
$tmpName = 'pending-' . bin2hex(random_bytes(8)) . '-' . $name;
|
||||
$file->move($tmpDir, $tmpName);
|
||||
|
||||
return $name;
|
||||
return [
|
||||
'subdir' => trim($subdir, '/'),
|
||||
'final_name' => $name,
|
||||
'temporary_subdir' => $tmpSubdir,
|
||||
'temporary_name' => $tmpName,
|
||||
'temporary_path' => $tmpDir . DIRECTORY_SEPARATOR . $tmpName,
|
||||
];
|
||||
}
|
||||
|
||||
public function finalizeStagedFile(array $staged): string
|
||||
{
|
||||
$tmpPath = (string)($staged['temporary_path'] ?? '');
|
||||
$finalName = basename((string)($staged['final_name'] ?? ''));
|
||||
$subdir = (string)($staged['subdir'] ?? '');
|
||||
|
||||
if ($tmpPath === '' || $finalName === '' || $subdir === '' || !is_file($tmpPath)) {
|
||||
throw new \RuntimeException('Temporary upload is missing.');
|
||||
}
|
||||
|
||||
$finalDir = $this->ensureSubdir($subdir);
|
||||
$finalPath = $finalDir . DIRECTORY_SEPARATOR . $finalName;
|
||||
if (!@rename($tmpPath, $finalPath)) {
|
||||
throw new \RuntimeException('Unable to finalize uploaded evidence.');
|
||||
}
|
||||
|
||||
return $finalName;
|
||||
}
|
||||
|
||||
public function discardStagedFile(?array $staged): void
|
||||
{
|
||||
if ($staged === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tmpPath = (string)($staged['temporary_path'] ?? '');
|
||||
if ($tmpPath !== '' && is_file($tmpPath)) {
|
||||
@unlink($tmpPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function resolvePath(string $subdir, string $filename): ?string
|
||||
|
||||
Reference in New Issue
Block a user