diff --git a/src/Config.php b/src/Config.php index 4c3679a..4ce9ac8 100644 --- a/src/Config.php +++ b/src/Config.php @@ -29,14 +29,12 @@ class Config extends BaseConfig public ?string $accessToken = null; public ?string $redisUrl = null; public ?string $signingKey = null; - public bool $useAssetBundleCdn = true; public ?string $previewDomain = null; public bool $useQueue = true; public int $staticCacheDuration = DateTimeHelper::SECONDS_YEAR; public int $staticCacheStaleWhileRevalidateDuration = DateTimeHelper::SECONDS_HOUR; public ?string $storageEndpoint = null; public bool $useAssetCdn = true; - public bool $useArtifactCdn = true; public ?string $logLevel = null; private bool $devMode = false; private ?string $region = null; @@ -47,8 +45,6 @@ public function init(): void if (!Helper::isCraftCloud()) { $this->gzipResponse = false; $this->useAssetCdn = false; - $this->useArtifactCdn = false; - $this->useAssetBundleCdn = false; $this->useQueue = false; } } @@ -157,12 +153,6 @@ protected function defineRules(): array 'when' => fn(Config $model) => $model->useAssetCdn, ]; - $rules[] = [ - ['environmentId', 'buildId'], - 'required', - 'when' => fn(Config $model) => $model->useArtifactCdn, - ]; - return $rules; } } diff --git a/src/controllers/AssetsController.php b/src/controllers/AssetsController.php index 147f2ac..c664f5e 100644 --- a/src/controllers/AssetsController.php +++ b/src/controllers/AssetsController.php @@ -80,7 +80,7 @@ public function actionGetUploadUrl(): Response 'targetFilename' => Assets::prepareAssetName($originalFilename), 'filename' => $filename, 'bucket' => $fs->getBucketName(), - 'key' => $fs->prefixPath($filename), + 'key' => $fs->createBucketPath($filename), 'folderId' => $folder->id, ]); } diff --git a/src/fs/AssetsFs.php b/src/fs/AssetsFs.php index e1826ac..04d7596 100644 --- a/src/fs/AssetsFs.php +++ b/src/fs/AssetsFs.php @@ -5,8 +5,9 @@ use craft\cloud\Module; use League\Uri\Components\HierarchicalPath; -class AssetsFs extends CdnFs +class AssetsFs extends Fs { + protected ?string $expires = '1 years'; public ?string $localFsPath = '@webroot/uploads'; public ?string $localFsUrl = '/uploads'; @@ -24,15 +25,8 @@ public static function displayName(): string return 'Craft Cloud'; } - public function getPrefix(): string + public function createBucketPrefix(): HierarchicalPath { - if (!Module::getInstance()->getConfig()->useAssetCdn) { - return ''; - } - - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'assets', - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix()->append('assets'); } } diff --git a/src/fs/BuildArtifactsFs.php b/src/fs/BuildArtifactsFs.php index 493871a..4901e15 100644 --- a/src/fs/BuildArtifactsFs.php +++ b/src/fs/BuildArtifactsFs.php @@ -7,25 +7,16 @@ class BuildArtifactsFs extends BuildsFs { - public ?string $localFsPath = '@webroot'; - public ?string $localFsUrl = '@web'; + public bool $hasUrls = true; public function init(): void { - $this->useLocalFs = !Module::getInstance()->getConfig()->useArtifactCdn; - $this->localFsUrl = Module::getInstance()->getConfig()->artifactBaseUrl ?? $this->localFsUrl; + $this->baseUrl = Module::getInstance()->getConfig()->artifactBaseUrl; parent::init(); } - public function getPrefix(): string + public function createBucketPrefix(): HierarchicalPath { - if (!Module::getInstance()->getConfig()->useArtifactCdn) { - return ''; - } - - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'artifacts', - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix()->append('artifacts'); } } diff --git a/src/fs/BuildsFs.php b/src/fs/BuildsFs.php index 724999a..894c1c6 100644 --- a/src/fs/BuildsFs.php +++ b/src/fs/BuildsFs.php @@ -5,14 +5,15 @@ use craft\cloud\Module; use League\Uri\Components\HierarchicalPath; -abstract class BuildsFs extends CdnFs +abstract class BuildsFs extends Fs { - public function getPrefix(): string + public bool $hasUrls = true; + protected ?string $expires = '1 years'; + + public function createBucketPrefix(): HierarchicalPath { - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'builds', - Module::getInstance()->getConfig()->buildId, - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix() + ->append('builds') + ->append(Module::getInstance()->getConfig()->buildId); } } diff --git a/src/fs/CdnFs.php b/src/fs/CdnFs.php deleted file mode 100644 index 1c909fb..0000000 --- a/src/fs/CdnFs.php +++ /dev/null @@ -1,32 +0,0 @@ -getConfig()->environmentId . ':'; - $tag = StaticCacheTag::create($this->prefixPath($path)) - ->minify(false) - ->withPrefix($prefix); - - Module::getInstance()->getStaticCache()->purgeTags($tag); - - return true; - } catch (\Throwable $e) { - return false; - } - } -} diff --git a/src/fs/CpResourcesFs.php b/src/fs/CpResourcesFs.php index 037d942..0467f34 100644 --- a/src/fs/CpResourcesFs.php +++ b/src/fs/CpResourcesFs.php @@ -6,11 +6,8 @@ class CpResourcesFs extends BuildsFs { - public function getPrefix(): string + public function createBucketPrefix(): HierarchicalPath { - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'cpresources', - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix()->append('cpresources'); } } diff --git a/src/fs/Fs.php b/src/fs/Fs.php index d33865d..b23a5c9 100644 --- a/src/fs/Fs.php +++ b/src/fs/Fs.php @@ -8,6 +8,8 @@ use Craft; use craft\behaviors\EnvAttributeParserBehavior; use craft\cloud\Module; +use craft\cloud\StaticCache; +use craft\cloud\StaticCacheTag; use craft\errors\FsException; use craft\flysystem\base\FlysystemFs; use craft\fs\Local; @@ -30,9 +32,6 @@ use yii\base\InvalidConfigException; /** - * - * @property-read string $bucketName - * @property-read string $prefix * @property-read ?string $settingsHtml */ abstract class Fs extends FlysystemFs @@ -44,8 +43,8 @@ abstract class Fs extends FlysystemFs public ?string $subpath = null; public ?string $localFsPath = null; public ?string $localFsUrl = null; - public ?string $url = '__URL__'; public bool $useLocalFs = false; + public ?string $baseUrl = null; /** * @inheritDoc @@ -66,13 +65,13 @@ protected function defineRules(): array protected function getLocalFs(): Local { $path = $this->localFsPath - ? HierarchicalPath::new($this->localFsPath)->append($this->prefixPath())->toString() + ? $this->createPath('')->prepend($this->localFsPath) : null; $this->localFs = $this->localFs ?? Craft::createObject([ 'class' => Local::class, 'hasUrls' => $this->hasUrls, - 'path' => $path, + 'path' => $path->toString(), 'url' => $this->localFsUrl, ]); @@ -93,19 +92,16 @@ public function getRootUrl(): ?string public function createUrl(string $path = ''): UriInterface { - $baseUrl = $this->useLocalFs - ? $this->getLocalFs()->getRootUrl() ?? '/' - : Module::getInstance()->getConfig()->cdnBaseUrl; + $baseUrl = $this->useLocalFs ? $this->getLocalFs()->getRootUrl() : $this->baseUrl; - // If an alias is unparsed by now, we have to fall back to a root relative URL. - // This likely means this is a console request and @web isn't set. - if (str_starts_with($baseUrl, '@')) { - $baseUrl = '/'; + if ($baseUrl) { + return Modifier::from($baseUrl) + ->appendSegment($this->createPath($path)) + ->getUri(); } - return Modifier::from($baseUrl) - ->appendSegment($this->prefixPath($path)) - ->removeEmptySegments() + return Modifier::from(Module::getInstance()->getConfig()->cdnBaseUrl) + ->appendSegment($this->createBucketPath($path)) ->getUri(); } @@ -145,6 +141,7 @@ public function settingsAttributes(): array return array_merge(parent::settingsAttributes(), [ 'expires', 'subpath', + 'baseUrl', 'localFsPath', 'localFsUrl', ]); @@ -180,7 +177,7 @@ protected function createAdapter(): AwsS3V3Adapter return new AwsS3V3Adapter( client: $this->getClient(), bucket: $this->getBucketName(), - prefix: $this->prefixPath(), + prefix: $this->createBucketPath('')->toString(), ); } @@ -189,7 +186,22 @@ protected function createAdapter(): AwsS3V3Adapter */ protected function invalidateCdnPath(string $path): bool { - return true; + if (!$this->hasUrls) { + return true; + } + + try { + $prefix = StaticCache::CDN_PREFIX . Module::getInstance()->getConfig()->environmentId . ':'; + $tag = StaticCacheTag::create($this->createBucketPath($path)) + ->minify(false) + ->withPrefix($prefix); + + Module::getInstance()->getStaticCache()->purgeTags($tag); + + return true; + } catch (\Throwable $e) { + return false; + } } /** @@ -227,26 +239,24 @@ public function getSettingsHtml(): ?string ]); } - protected function getPrefix(): string + protected function createBucketPrefix(): HierarchicalPath { - if ($this->useLocalFs) { - return ''; - } - - return HierarchicalPath::fromRelative(Module::getInstance()->getConfig()->environmentId) - ->withoutEmptySegments() - ->withoutTrailingSlash(); + return HierarchicalPath::fromRelative(Module::getInstance()->getConfig()->environmentId); } - public function prefixPath(string $path = ''): string + protected function createPath(string $path): HierarchicalPath { return HierarchicalPath::fromRelative( - $this->getPrefix(), $this->subpath ?? '', $path, )->withoutEmptySegments(); } + public function createBucketPath(string $path): HierarchicalPath + { + return $this->createBucketPrefix()->append($this->createPath($path)); + } + public function getBucketName(): ?string { return Module::getInstance()->getConfig()->projectId; @@ -308,7 +318,7 @@ public function presignedUrl(string $command, string $path, DateTimeInterface $e $command = $this->getClient()->getCommand($command, [ 'Bucket' => $this->getBucketName(), - 'Key' => $this->prefixPath($path), + 'Key' => $this->createBucketPath($path)->toString(), ] + $commandConfig); $request = $this->getClient()->createPresignedRequest( diff --git a/src/fs/StorageFs.php b/src/fs/StorageFs.php index 6cfa3f9..955eb09 100644 --- a/src/fs/StorageFs.php +++ b/src/fs/StorageFs.php @@ -6,13 +6,8 @@ class StorageFs extends Fs { - public bool $hasUrls = false; - - public function getPrefix(): string + public function createBucketPrefix(): HierarchicalPath { - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'storage', - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix()->append('storage'); } } diff --git a/src/fs/TmpFs.php b/src/fs/TmpFs.php index 17fbc5b..a6cc196 100644 --- a/src/fs/TmpFs.php +++ b/src/fs/TmpFs.php @@ -6,11 +6,8 @@ class TmpFs extends StorageFs { - public function getPrefix(): string + public function createBucketPrefix(): HierarchicalPath { - return HierarchicalPath::fromRelative( - parent::getPrefix(), - 'tmp', - )->withoutEmptySegments()->withoutTrailingSlash(); + return parent::createBucketPrefix()->append('tmp'); } } diff --git a/src/templates/fsSettings.html b/src/templates/fsSettings.html index 6de44bf..2c0ad73 100644 --- a/src/templates/fsSettings.html +++ b/src/templates/fsSettings.html @@ -9,8 +9,25 @@ value: fs.subpath, errors: fs.getErrors('subpath'), placeholder: "path/to/subpath"|t('cloud'), + tip: "This value will be appended to all paths and URLs for the filesystem."|t('cloud'), }) }} +