nhance_partner_be/app/Services/Storage/LocalStorageDriver.php

156 lines
4.1 KiB
PHP

<?php
namespace App\Services\Storage;
use CodeIgniter\HTTP\Files\UploadedFile;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Storage;
class LocalStorageDriver implements FileStorageInterface
{
public function __construct(private readonly Storage $config)
{
}
private function fullPath(string $key): string
{
$key = ltrim(str_replace('\\', '/', $key), '/');
return $this->config->localRoot . str_replace('/', DIRECTORY_SEPARATOR, $key);
}
private function ensureDirectory(string $fullPath): void
{
$directory = dirname($fullPath);
if (! is_dir($directory) && ! mkdir($directory, 0777, true) && ! is_dir($directory)) {
throw new FileStorageException("Unable to create directory: {$directory}");
}
}
public function upload(UploadedFile|string $source, string $key, array $options = []): string
{
$fullPath = $this->fullPath($key);
$this->ensureDirectory($fullPath);
if ($source instanceof UploadedFile) {
if (! $source->isValid()) {
throw new FileStorageException($source->getErrorString() ?: 'Invalid uploaded file');
}
if ($source->hasMoved()) {
throw new FileStorageException('Uploaded file has already been moved');
}
$source->move(dirname($fullPath), basename($fullPath));
return $key;
}
if (! is_file($source)) {
throw new FileStorageException("Source file not found: {$source}");
}
if (! copy($source, $fullPath)) {
throw new FileStorageException("Failed to copy file to {$fullPath}");
}
return $key;
}
public function put(string $key, string $contents, array $options = []): string
{
$fullPath = $this->fullPath($key);
$this->ensureDirectory($fullPath);
if (file_put_contents($fullPath, $contents) === false) {
throw new FileStorageException("Failed to write file: {$fullPath}");
}
return $key;
}
public function exists(string $key): bool
{
return is_file($this->fullPath($key));
}
public function delete(string $key): bool
{
$fullPath = $this->fullPath($key);
if (! is_file($fullPath)) {
return false;
}
return unlink($fullPath);
}
public function read(string $key): string
{
$fullPath = $this->fullPath($key);
if (! is_file($fullPath)) {
throw new FileStorageException("File not found: {$key}");
}
$contents = file_get_contents($fullPath);
if ($contents === false) {
throw new FileStorageException("Unable to read file: {$key}");
}
return $contents;
}
public function downloadToTemp(string $key): string
{
$fullPath = $this->fullPath($key);
if (! is_file($fullPath)) {
throw new FileStorageException("File not found: {$key}");
}
return $fullPath;
}
public function streamDownload(string $key, ?string $downloadName = null): ResponseInterface
{
$fullPath = $this->fullPath($key);
if (! is_file($fullPath)) {
throw new FileStorageException("File not found: {$key}");
}
return service('response')->download($fullPath, null)->setFileName($downloadName ?: basename($key));
}
public function temporaryUrl(string $key, int $ttlSeconds = 900): string
{
if (! $this->exists($key)) {
throw new FileStorageException("File not found: {$key}");
}
return base_url(ltrim(str_replace('\\', '/', $key), '/'));
}
public function url(string $key): string
{
return $this->temporaryUrl($key);
}
public function copy(string $fromKey, string $toKey): bool
{
$fromPath = $this->fullPath($fromKey);
$toPath = $this->fullPath($toKey);
if (! is_file($fromPath)) {
throw new FileStorageException("Source file not found: {$fromKey}");
}
$this->ensureDirectory($toPath);
return copy($fromPath, $toPath);
}
}