diskName === 'local_secure_images'; } /** * Change the originally provided path to fit any disk-specific requirements. * This also ensures the path is kept to the expected root folders. */ protected function adjustPathForDisk(string $path): string { $path = (new WhitespacePathNormalizer())->normalizePath(str_replace('uploads/images/', '', $path)); if ($this->usingSecureImages()) { return $path; } return 'uploads/images/' . $path; } /** * Check if a file at the given path exists. */ public function exists(string $path): bool { return $this->filesystem->exists($this->adjustPathForDisk($path)); } /** * Get the file at the given path. */ public function get(string $path): ?string { return $this->filesystem->get($this->adjustPathForDisk($path)); } /** * Get a stream to the file at the given path. * @returns ?resource */ public function stream(string $path): mixed { return $this->filesystem->readStream($this->adjustPathForDisk($path)); } /** * Save the given image data at the given path. Can choose to set * the image as public which will update its visibility after saving. */ public function put(string $path, string $data, bool $makePublic = false): void { $path = $this->adjustPathForDisk($path); $this->filesystem->put($path, $data); // Set visibility when a non-AWS-s3, s3-like storage option is in use. // Done since this call can break s3-like services but desired for other image stores. // Attempting to set ACL during above put request requires different permissions // hence would technically be a breaking change for actual s3 usage. if ($makePublic && !$this->isS3Like()) { $this->filesystem->setVisibility($path, 'public'); } } /** * Destroys an image at the given path. * Searches for image thumbnails in addition to main provided path. */ public function destroyAllMatchingNameFromPath(string $path): void { $path = $this->adjustPathForDisk($path); $imageFolder = dirname($path); $imageFileName = basename($path); $allImages = collect($this->filesystem->allFiles($imageFolder)); // Delete image files $imagesToDelete = $allImages->filter(function ($imagePath) use ($imageFileName) { return basename($imagePath) === $imageFileName; }); $this->filesystem->delete($imagesToDelete->all()); // Cleanup of empty folders $foldersInvolved = array_merge([$imageFolder], $this->filesystem->directories($imageFolder)); foreach ($foldersInvolved as $directory) { if ($this->isFolderEmpty($directory)) { $this->filesystem->deleteDirectory($directory); } } } /** * Get the mime type of the file at the given path. * Only works for local filesystem adapters. */ public function mimeType(string $path): string { $path = $this->adjustPathForDisk($path); return $this->filesystem instanceof FilesystemAdapter ? $this->filesystem->mimeType($path) : ''; } /** * Get a stream response for the image at the given path. */ public function response(string $path): StreamedResponse { return $this->filesystem->response($this->adjustPathForDisk($path)); } /** * Check if the image storage in use is an S3-like (but not likely S3) external system. */ protected function isS3Like(): bool { $usingS3 = $this->diskName === 's3'; return $usingS3 && !is_null(config('filesystems.disks.s3.endpoint')); } /** * Check whether a folder is empty. */ protected function isFolderEmpty(string $path): bool { $files = $this->filesystem->files($path); $folders = $this->filesystem->directories($path); return count($files) === 0 && count($folders) === 0; } }