63 lines
2.0 KiB
PHP
63 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
class CoverUrl
|
|
{
|
|
private const DEFAULT_FILES_CDN = 'https://files.skinbase.org';
|
|
|
|
public static function forUser(?string $hash, ?string $ext, ?int $version = null): ?string
|
|
{
|
|
$coverHash = trim((string) $hash);
|
|
$coverExt = strtolower(trim((string) $ext));
|
|
|
|
if ($coverHash === '' || $coverExt === '') {
|
|
return null;
|
|
}
|
|
|
|
$base = self::resolveBaseUrl();
|
|
$p1 = substr($coverHash, 0, 2);
|
|
$p2 = substr($coverHash, 2, 2);
|
|
$v = $version ?? time();
|
|
|
|
return sprintf('%s/covers/%s/%s/%s.%s?v=%s', $base, $p1, $p2, $coverHash, $coverExt, $v);
|
|
}
|
|
|
|
private static function resolveBaseUrl(): string
|
|
{
|
|
$configured = trim((string) config('cdn.files_url', self::DEFAULT_FILES_CDN));
|
|
|
|
// If a non-default CDN/files host is configured, always respect it.
|
|
if ($configured !== '' && $configured !== self::DEFAULT_FILES_CDN) {
|
|
return rtrim($configured, '/');
|
|
}
|
|
|
|
// Local/dev fallback: derive a web path from uploads.storage_root when it lives under public/.
|
|
$local = self::deriveLocalBaseFromStorageRoot();
|
|
if ($local !== null) {
|
|
return $local;
|
|
}
|
|
|
|
return rtrim($configured !== '' ? $configured : self::DEFAULT_FILES_CDN, '/');
|
|
}
|
|
|
|
private static function deriveLocalBaseFromStorageRoot(): ?string
|
|
{
|
|
$storageRoot = str_replace('\\', '/', rtrim((string) config('uploads.storage_root'), DIRECTORY_SEPARATOR));
|
|
$publicRoot = str_replace('\\', '/', rtrim((string) public_path(), DIRECTORY_SEPARATOR));
|
|
$appUrl = rtrim((string) config('app.url'), '/');
|
|
|
|
if ($storageRoot === '' || $publicRoot === '' || $appUrl === '') {
|
|
return null;
|
|
}
|
|
|
|
if (! str_starts_with(strtolower($storageRoot), strtolower($publicRoot))) {
|
|
return null;
|
|
}
|
|
|
|
$suffix = trim((string) substr($storageRoot, strlen($publicRoot)), '/');
|
|
|
|
return $suffix === '' ? $appUrl : ($appUrl . '/' . $suffix);
|
|
}
|
|
}
|