236 lines
7.7 KiB
PHP
236 lines
7.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace FlysystemOffload\Filesystem;
|
|
|
|
use FlysystemOffload\Filesystem\Adapters\AdapterInterface;
|
|
use FlysystemOffload\Filesystem\Adapters\S3Adapter;
|
|
use FlysystemOffload\Filesystem\Adapters\WebdavAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\SftpAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\GoogleCloudAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\AzureBlobAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\DropboxAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\GoogleDriveAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\OneDriveAdapter;
|
|
use FlysystemOffload\Filesystem\Adapters\PrefixedAdapter;
|
|
use League\Flysystem\Filesystem;
|
|
use League\Flysystem\FilesystemAdapter;
|
|
use InvalidArgumentException;
|
|
|
|
/**
|
|
* Factory para crear instancias de Filesystem con diferentes adaptadores
|
|
*/
|
|
class FilesystemFactory
|
|
{
|
|
/**
|
|
* Mapa de proveedores a clases de adaptadores
|
|
*/
|
|
private const ADAPTER_MAP = [
|
|
's3' => S3Adapter::class,
|
|
'webdav' => WebdavAdapter::class,
|
|
'sftp' => SftpAdapter::class,
|
|
'gcs' => GoogleCloudAdapter::class,
|
|
'azure' => AzureBlobAdapter::class,
|
|
'dropbox' => DropboxAdapter::class,
|
|
'google-drive' => GoogleDriveAdapter::class,
|
|
'onedrive' => OneDriveAdapter::class,
|
|
];
|
|
|
|
/**
|
|
* Crea un Filesystem basado en la configuración proporcionada
|
|
*
|
|
* @param array $config Configuración del filesystem
|
|
* @return Filesystem
|
|
* @throws InvalidArgumentException Si el proveedor no es válido
|
|
*/
|
|
public static function create(array $config): Filesystem
|
|
{
|
|
$provider = $config['provider'] ?? '';
|
|
|
|
if (empty($provider)) {
|
|
throw new InvalidArgumentException('Provider is required in configuration');
|
|
}
|
|
|
|
$adapter = self::createAdapter($provider, $config);
|
|
|
|
// Aplicar prefijo global si está configurado
|
|
if (!empty($config['prefix'])) {
|
|
$adapter = new PrefixedAdapter($adapter, $config['prefix']);
|
|
}
|
|
|
|
return new Filesystem($adapter);
|
|
}
|
|
|
|
/**
|
|
* Crea un adaptador específico basado en el proveedor
|
|
*
|
|
* @param string $provider Nombre del proveedor
|
|
* @param array $config Configuración del adaptador
|
|
* @return FilesystemAdapter
|
|
* @throws InvalidArgumentException Si el proveedor no es soportado
|
|
*/
|
|
private static function createAdapter(string $provider, array $config): FilesystemAdapter
|
|
{
|
|
$provider = strtolower(trim($provider));
|
|
|
|
if (!isset(self::ADAPTER_MAP[$provider])) {
|
|
throw new InvalidArgumentException(
|
|
sprintf(
|
|
'Unsupported provider: %s. Supported providers: %s',
|
|
$provider,
|
|
implode(', ', array_keys(self::ADAPTER_MAP))
|
|
)
|
|
);
|
|
}
|
|
|
|
$adapterClass = self::ADAPTER_MAP[$provider];
|
|
|
|
if (!class_exists($adapterClass)) {
|
|
throw new InvalidArgumentException(
|
|
sprintf('Adapter class not found: %s', $adapterClass)
|
|
);
|
|
}
|
|
|
|
/** @var AdapterInterface $adapterInstance */
|
|
$adapterInstance = new $adapterClass();
|
|
|
|
if (!$adapterInstance instanceof AdapterInterface) {
|
|
throw new InvalidArgumentException(
|
|
sprintf('Adapter must implement AdapterInterface: %s', $adapterClass)
|
|
);
|
|
}
|
|
|
|
// Normalizar configuración específica del proveedor
|
|
$normalizedConfig = self::normalizeConfig($provider, $config);
|
|
|
|
return $adapterInstance->createAdapter($normalizedConfig);
|
|
}
|
|
|
|
/**
|
|
* Normaliza la configuración según el proveedor
|
|
*
|
|
* @param string $provider Nombre del proveedor
|
|
* @param array $config Configuración original
|
|
* @return array Configuración normalizada
|
|
*/
|
|
private static function normalizeConfig(string $provider, array $config): array
|
|
{
|
|
$normalized = $config;
|
|
|
|
// Normalizar permisos para WebDAV y SFTP
|
|
if (in_array($provider, ['webdav', 'sftp'], true)) {
|
|
$normalized = self::normalizePermissions($normalized);
|
|
}
|
|
|
|
// Normalizar configuración específica de S3
|
|
if ($provider === 's3') {
|
|
$normalized = self::normalizeS3Config($normalized);
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
|
|
/**
|
|
* Normaliza permisos de archivos y directorios
|
|
*
|
|
* @param array $config Configuración original
|
|
* @return array Configuración con permisos normalizados
|
|
*/
|
|
private static function normalizePermissions(array $config): array
|
|
{
|
|
$permissionKeys = ['file_public', 'file_private', 'dir_public', 'dir_private'];
|
|
|
|
foreach ($permissionKeys as $key) {
|
|
if (isset($config[$key])) {
|
|
// Si es string, mantenerlo como string (el adaptador lo convertirá)
|
|
// Si es int, mantenerlo como int
|
|
// Esto permite flexibilidad en la configuración
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Establecer valores por defecto si no existen
|
|
$config['file_public'] = $config['file_public'] ?? 0644;
|
|
$config['file_private'] = $config['file_private'] ?? 0600;
|
|
$config['dir_public'] = $config['dir_public'] ?? 0755;
|
|
$config['dir_private'] = $config['dir_private'] ?? 0700;
|
|
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* Normaliza configuración específica de S3
|
|
*
|
|
* @param array $config Configuración original
|
|
* @return array Configuración normalizada
|
|
*/
|
|
private static function normalizeS3Config(array $config): array
|
|
{
|
|
// Asegurar que use_path_style_endpoint sea booleano
|
|
if (isset($config['use_path_style_endpoint'])) {
|
|
$config['use_path_style_endpoint'] = filter_var(
|
|
$config['use_path_style_endpoint'],
|
|
FILTER_VALIDATE_BOOLEAN
|
|
);
|
|
}
|
|
|
|
// Normalizar región
|
|
if (isset($config['region'])) {
|
|
$config['region'] = strtolower(trim($config['region']));
|
|
}
|
|
|
|
return $config;
|
|
}
|
|
|
|
/**
|
|
* Obtiene la lista de proveedores soportados
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getSupportedProviders(): array
|
|
{
|
|
return array_keys(self::ADAPTER_MAP);
|
|
}
|
|
|
|
/**
|
|
* Verifica si un proveedor es soportado
|
|
*
|
|
* @param string $provider Nombre del proveedor
|
|
* @return bool
|
|
*/
|
|
public static function isProviderSupported(string $provider): bool
|
|
{
|
|
return isset(self::ADAPTER_MAP[strtolower(trim($provider))]);
|
|
}
|
|
|
|
/**
|
|
* Obtiene información sobre un proveedor específico
|
|
*
|
|
* @param string $provider Nombre del proveedor
|
|
* @return array Información del proveedor
|
|
* @throws InvalidArgumentException Si el proveedor no es soportado
|
|
*/
|
|
public static function getProviderInfo(string $provider): array
|
|
{
|
|
$provider = strtolower(trim($provider));
|
|
|
|
if (!self::isProviderSupported($provider)) {
|
|
throw new InvalidArgumentException("Unsupported provider: {$provider}");
|
|
}
|
|
|
|
$adapterClass = self::ADAPTER_MAP[$provider];
|
|
$adapter = new $adapterClass();
|
|
|
|
return [
|
|
'name' => $provider,
|
|
'class' => $adapterClass,
|
|
'required_keys' => $adapter->getRequiredConfigKeys(),
|
|
'optional_keys' => $adapter->getOptionalConfigKeys(),
|
|
'description' => method_exists($adapter, 'getDescription')
|
|
? $adapter->getDescription()
|
|
: '',
|
|
];
|
|
}
|
|
}
|