ldc-file-storage-service/src/Config/StorageServiceConfig.php
2026-11-03 16:16:19 +01:00

148 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Uwil\Storage\Config;
use Uwil\Storage\Exceptions\UnexpectedStorageException;
use Uwil\Storage\Lib\Utils;
use Uwil\Storage\Lib\ValueObjects\DiskName;
final class StorageServiceConfig
{
public const array UNSUPPORTED_EXTENSIONS = ['svg', 'xml'];
private DiskName $default;
/** @var DiskName[] */
private array $eligibles;
/**
* @param string[] $eligibleDisks
* @param object{'disk':string,'driver':string}[] $laravelExistingDisks
* @param string[] $allowedExtensions
*/
public function __construct(
private string $defaultDisk,
private array $eligibleDisks,
private array $laravelExistingDisks,
private array $allowedExtensions
) {
if (Utils::diskExists($this->defaultDisk) === false) {
throw new UnexpectedStorageException('Default disk does not exist');
}
array_map(
fn ($disk) => Utils::diskExists($disk)
|| throw new UnexpectedStorageException("Eligible disk {$disk} does not exist"),
$this->eligibleDisks
);
array_map(
fn ($disk) => Utils::diskExists($disk->disk)
|| throw new UnexpectedStorageException("Laravel existing disk {$disk->disk} does not exist"),
$this->laravelExistingDisks
);
if (empty($this->laravelExistingDisks)) {
throw new UnexpectedStorageException('Laravel existing disks cannot be empty');
}
if (empty($this->eligibleDisks)) {
throw new UnexpectedStorageException('Eligible disks cannot be empty');
}
$intersect = array_intersect(
$this->eligibleDisks,
array_map(fn ($disk) => $disk->disk, $this->laravelExistingDisks)
);
if (empty($intersect)) {
throw new UnexpectedStorageException('No eligible disks exist in Laravel existing disks');
}
$intersectWithDrivers = array_map(
fn ($disk) => $disk,
array_filter(
$this->laravelExistingDisks,
fn ($disk) => in_array($disk->disk, $intersect, true)
)
);
$defaultDiskWithDriver = array_filter(
$this->laravelExistingDisks,
fn ($disk) => $disk->disk === $this->defaultDisk
);
if (empty($defaultDiskWithDriver)) {
throw new UnexpectedStorageException('Default disk does not exist in Laravel existing disks');
}
$defaultDiskWithDriver = array_values($defaultDiskWithDriver)[0];
$this->default = new DiskName($defaultDiskWithDriver->disk, $defaultDiskWithDriver->driver);
$this->eligibles = array_map(fn ($disk) => new DiskName(
$disk->disk,
$disk->driver
), $intersectWithDrivers);
if (empty($this->allowedExtensions)) {
throw new UnexpectedStorageException('Allowed extensions cannot be empty');
}
foreach ($this->allowedExtensions as $extension) {
if (! is_string($extension) || empty(mb_trim($extension))) {
throw new UnexpectedStorageException("Allowed extension {$extension} is not valid");
}
if (in_array(strtolower(ltrim($extension, '.')), self::UNSUPPORTED_EXTENSIONS, true)) {
throw new UnexpectedStorageException("Extension '{$extension}' is forbidden: XML/SVG sanitization is currently not supported.");
}
}
}
public function getDefaultDisk(): DiskName
{
return $this->default;
}
/** @return DiskName[] */
public function getEligibleDisks(): array
{
return array_map(fn ($disk) => $disk, $this->eligibles);
}
public function isDiskEligible(DiskName | string $disk): bool
{
$diskName = $disk instanceof DiskName ? $disk->value : (string) $disk;
foreach ($this->eligibles as $eligible) {
if ($eligible->value === $diskName) {
return true;
}
}
return false;
}
public function isExtensionAllowed(string $extension): bool
{
$normalized = strtolower(ltrim($extension, '.'));
if (in_array($normalized, self::UNSUPPORTED_EXTENSIONS, true)) {
return false;
}
return in_array(
$normalized,
array_map('strtolower', $this->allowedExtensions),
true
);
}
/** @return string[] */
public function getAllowedExtensions(): array
{
return $this->allowedExtensions;
}
}