diff --git a/src/Storage/UploadedFile.php b/src/Storage/UploadedFile.php index c56497af..91251f9d 100644 --- a/src/Storage/UploadedFile.php +++ b/src/Storage/UploadedFile.php @@ -44,7 +44,7 @@ class UploadedFile extends SplFileInfo /** * Local File System */ - protected LocalFilesystemAdapterInterface $localFileSystem; + protected ?LocalFilesystemAdapterInterface $localFileSystem = null; /** * Remove File System @@ -113,28 +113,24 @@ class UploadedFile extends SplFileInfo */ protected int $errorCode; + /** + * Whether mime types were loaded from config + */ + protected bool $mimeTypesLoaded = false; + + /** + * Whether mime types were explicitly set by caller + */ + protected bool $mimeTypesOverridden = false; + /** * @param array $meta - * @throws ConfigException|DiException|BaseException|ReflectionException */ public function __construct(array $meta) { - $adapter = fs()->getAdapter(); - - if (!$adapter instanceof LocalFilesystemAdapterInterface) { - throw FileSystemException::notInstanceOf( - get_class($adapter), - LocalFilesystemAdapterInterface::class - ); - } - - $this->localFileSystem = $adapter; - $this->originalName = $meta['name']; $this->errorCode = $meta['error']; - $this->loadAllowedMimeTypesFromConfig(); - parent::__construct($meta['tmp_name']); } @@ -145,6 +141,8 @@ public function __construct(array $meta) public function setAllowedMimeTypes(array $allowedMimeTypes, bool $merge = true): UploadedFile { $this->setAllowedMimeTypesMap($allowedMimeTypes, $merge); + $this->mimeTypesOverridden = true; + $this->mimeTypesLoaded = true; return $this; } @@ -154,7 +152,7 @@ public function setAllowedMimeTypes(array $allowedMimeTypes, bool $merge = true) public function getName(): string { if (!$this->name) { - $this->name = $this->localFileSystem->fileName($this->originalName ?? ''); + $this->name = $this->getLocalFileSystem()->fileName($this->originalName ?? ''); } return $this->name; @@ -192,7 +190,7 @@ public function getRemoteFileSystem(): ?FilesystemAdapterInterface public function getExtension(): string { if (!$this->extension) { - $this->extension = strtolower($this->localFileSystem->extension($this->originalName ?? '')); + $this->extension = strtolower($this->getLocalFileSystem()->extension($this->originalName ?? '')); } return $this->extension; @@ -268,15 +266,18 @@ public function getDimensions(): array * @param string $dest * @param bool $overwrite * @return bool - * @throws FileUploadException|FileSystemException|ImageResizeException|BaseException + * @throws FileUploadException|FileSystemException|ImageResizeException|BaseException|ReflectionException */ public function save(string $dest, bool $overwrite = false): bool { + $this->ensureAllowedMimeTypesLoaded(); + $localFileSystem = $this->getLocalFileSystem(); + if ($this->errorCode !== UPLOAD_ERR_OK) { throw new FileUploadException($this->getErrorMessage()); } - if (!$this->localFileSystem->isFile($this->getPathname())) { + if (!$localFileSystem->isFile($this->getPathname())) { throw FileUploadException::fileNotFound($this->getPathname()); } @@ -287,15 +288,15 @@ public function save(string $dest, bool $overwrite = false): bool $filePath = $dest . DS . $this->getNameWithExtension(); if (!$this->remoteFileSystem) { - if (!$this->localFileSystem->isDirectory($dest)) { + if (!$localFileSystem->isDirectory($dest)) { throw FileSystemException::directoryNotExists($dest); } - if (!$this->localFileSystem->isWritable($dest)) { + if (!$localFileSystem->isWritable($dest)) { throw FileSystemException::directoryNotWritable($dest); } - if ($overwrite === false && $this->localFileSystem->exists($filePath)) { + if ($overwrite === false && $localFileSystem->exists($filePath)) { throw FileSystemException::fileAlreadyExists($filePath); } } @@ -369,13 +370,51 @@ public function isImage(string $filePath): bool */ protected function moveUploadedFile(string $filePath): bool { + $localFileSystem = $this->getLocalFileSystem(); + if ($this->remoteFileSystem) { - return (bool) $this->remoteFileSystem->put($filePath, $this->localFileSystem->get($this->getPathname())); + return (bool) $this->remoteFileSystem->put($filePath, $localFileSystem->get($this->getPathname())); } elseif ($this->isUploaded()) { return move_uploaded_file($this->getPathname(), $filePath); } else { - return $this->localFileSystem->copy($this->getPathname(), $filePath); + return $localFileSystem->copy($this->getPathname(), $filePath); + } + } + + /** + * @throws ConfigException|DiException|BaseException|ReflectionException + */ + private function getLocalFileSystem(): LocalFilesystemAdapterInterface + { + if ($this->localFileSystem) { + return $this->localFileSystem; + } + + $adapter = fs()->getAdapter(); + + if (!$adapter instanceof LocalFilesystemAdapterInterface) { + throw FileSystemException::notInstanceOf( + get_class($adapter), + LocalFilesystemAdapterInterface::class + ); } + + $this->localFileSystem = $adapter; + + return $this->localFileSystem; + } + + /** + * @throws FileUploadException|LoaderException|ConfigException|DiException|ReflectionException + */ + private function ensureAllowedMimeTypesLoaded(): void + { + if ($this->mimeTypesLoaded || $this->mimeTypesOverridden) { + return; + } + + $this->loadAllowedMimeTypesFromConfig(); + $this->mimeTypesLoaded = true; } /** @@ -387,7 +426,7 @@ protected function allowed(string $extension, string $mimeType): bool $mimeType = strtolower($mimeType); return isset($this->allowedMimeTypes[$mimeType]) && - in_array($extension, (array) $this->allowedMimeTypes[$mimeType], true); + in_array($extension, $this->allowedMimeTypes[$mimeType], true); } /**