From 813b33d628929f49728b4693dcf457ec9980835a Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 15:50:01 +0100 Subject: [PATCH 01/15] fix: use updated google cloud --- common/oatbox/filesystem/FileSystem.php | 14 +- .../oatbox/filesystem/FileSystemService.php | 16 +- .../filesystem/utils/FlyWrapperTrait.php | 95 +++++++----- .../wrapper/GoogleStorageWrapper.php | 137 +++++++++++++++++- 4 files changed, 204 insertions(+), 58 deletions(-) diff --git a/common/oatbox/filesystem/FileSystem.php b/common/oatbox/filesystem/FileSystem.php index 78c9a8b2f..85dde8a3e 100644 --- a/common/oatbox/filesystem/FileSystem.php +++ b/common/oatbox/filesystem/FileSystem.php @@ -21,14 +21,14 @@ namespace oat\oatbox\filesystem; -use League\Flysystem\FilesystemInterface; +use League\Flysystem\FilesystemOperator; use oat\oatbox\filesystem\utils\FileSystemWrapperTrait; -use League\Flysystem\AdapterInterface; +use League\Flysystem\FilesystemAdapter; /** * Class Filesystem */ -class FileSystem implements FilesystemInterface +class FileSystem implements FilesystemOperator { use FileSystemWrapperTrait; @@ -38,7 +38,7 @@ class FileSystem implements FilesystemInterface protected $id; /** - * @var FilesystemInterface + * @var FilesystemOperator */ protected $filesystem; @@ -53,7 +53,7 @@ class FileSystem implements FilesystemInterface * @param $id * @param $adapter */ - public function __construct($id, FilesystemInterface $flySystem, $prefix) + public function __construct($id, FilesystemOperator $flySystem, $prefix) { $this->id = $id; $this->filesystem = $flySystem; @@ -69,7 +69,7 @@ public function getId() } /** - * @return FilesystemInterface + * @return FilesystemOperator * @throws \common_Exception */ protected function getFileSystem() @@ -80,7 +80,7 @@ protected function getFileSystem() /** * Get the Adapter. * - * @return AdapterInterface adapter + * @return FilesystemAdapter adapter */ private function getAdapter() { diff --git a/common/oatbox/filesystem/FileSystemService.php b/common/oatbox/filesystem/FileSystemService.php index eb5542d1d..fd81374dd 100755 --- a/common/oatbox/filesystem/FileSystemService.php +++ b/common/oatbox/filesystem/FileSystemService.php @@ -22,11 +22,11 @@ namespace oat\oatbox\filesystem; use oat\oatbox\service\ConfigurableService; -use League\Flysystem\AdapterInterface; +use League\Flysystem\FilesystemAdapter; use common_exception_Error; use Zend\ServiceManager\ServiceLocatorAwareInterface; use League\Flysystem\Filesystem as FlyFileSystem; -use League\Flysystem\FilesystemInterface; +use League\Flysystem\FilesystemOperator; /** * A service to reference and retrieve filesystems @@ -98,7 +98,7 @@ public function hasDirectory($id) * Retrieve an existing FileSystem by ID. * * @param string $id - * @return FilesystemInterface + * @return FilesystemOperator * @throws \common_exception_Error * @throws \common_exception_NotFound */ @@ -118,7 +118,7 @@ public function getFileSystem($id) * * @param string $id * @param string $subPath - * @return FilesystemInterface + * @return FilesystemOperator */ public function createFileSystem($id, $subPath = null) { @@ -131,7 +131,7 @@ public function createFileSystem($id, $subPath = null) * * @deprecated never rely on a directory being local, use addDir instead * @param string $id - * @return FilesystemInterface + * @return FilesystemOperator */ public function createLocalFileSystem($id) { @@ -189,7 +189,7 @@ public function unregisterFileSystem($id) * Get file adapter by file * * @param File $file - * @return AdapterInterface + * @return FilesystemAdapter * @throws \common_exception_NotFound * @throws common_exception_Error */ @@ -229,7 +229,7 @@ protected function getAdapterConfig($id) * @param string $id * @throws \common_exception_NotFound if adapter doesn't exist * @throws \common_exception_Error if adapter is not valid - * @return AdapterInterface + * @return FilesystemAdapter */ protected function getFlysystemAdapter($id) { @@ -255,7 +255,7 @@ protected function getFlysystemAdapter($id) } } - if (!is_subclass_of($class, 'League\Flysystem\AdapterInterface')) { + if (!is_subclass_of($class, 'League\Flysystem\FilesystemAdapter')) { throw new common_exception_Error('"' . $class . '" is not a flysystem adapter'); } $adapter = (new \ReflectionClass($class))->newInstanceArgs($options); diff --git a/common/oatbox/filesystem/utils/FlyWrapperTrait.php b/common/oatbox/filesystem/utils/FlyWrapperTrait.php index 5a727b3ac..5f54eb8e9 100644 --- a/common/oatbox/filesystem/utils/FlyWrapperTrait.php +++ b/common/oatbox/filesystem/utils/FlyWrapperTrait.php @@ -2,7 +2,7 @@ namespace oat\oatbox\filesystem\utils; -use League\Flysystem\AdapterInterface; +use League\Flysystem\FilesystemAdapter; use League\Flysystem\Config; /** @@ -14,92 +14,109 @@ trait FlyWrapperTrait { /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::write() + * @see \League\Flysystem\FilesystemAdapter::write() */ public function write($path, $contents, Config $config) { - return $this->getAdapter()->write($path, $contents, $config); + $this->getAdapter()->write($path, $contents, $config); + + return $this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::writeStream() + * @see \League\Flysystem\FilesystemAdapter::writeStream() */ public function writeStream($path, $resource, Config $config) { - return $this->getAdapter()->writeStream($path, $resource, $config); + $this->getAdapter()->writeStream($path, $resource, $config); + + return $this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::update() + * @see \League\Flysystem\FilesystemAdapter::update() */ public function update($path, $contents, Config $config) { - return $this->getAdapter()->update($path, $contents, $config); + $this->getAdapter()->write($path, $contents, $config); + + return $this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::updateStream() + * @see \League\Flysystem\FilesystemAdapter::updateStream() */ public function updateStream($path, $resource, Config $config) { - return $this->getAdapter()->updateStream($path, $resource, $config); + $this->getAdapter()->writeStream($path, $resource, $config); + + return $this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::rename() + * @see \League\Flysystem\FilesystemAdapter::rename() */ - public function rename($path, $newpath) + public function rename($path, $newpath, $config = []) { - return $this->getAdapter()->rename($path, $newpath); + $this->getAdapter()->move($path, $newpath, $config); + + return $this->getAdapter()->fileExists($newpath); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::copy() + * @see \League\Flysystem\FilesystemAdapter::copy() */ - public function copy($path, $newpath) + public function copy($path, $newpath, $config = []) { - $this->getAdapter()->copy($path, $newpath); + $this->getAdapter()->copy($path, $newpath, $config); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::delete() + * @see \League\Flysystem\FilesystemAdapter::delete() */ public function delete($path) { - return $this->getAdapter()->delete($path); + $this->getAdapter()->delete($path); + + return !$this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::deleteDir() + * @see \League\Flysystem\FilesystemAdapter::deleteDir() */ public function deleteDir($dirname) { - return $this->getAdapter()->deleteDir($dirname); + $this->getAdapter()->deleteDirectory($dirname); + + return !$this->getAdapter()->directoryExists($dirname); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::createDir() + * @see \League\Flysystem\FilesystemAdapter::createDir() */ public function createDir($dirname, Config $config) { - return $this->getAdapter()->createDir($dirname, $config); + $this->getAdapter()->createDirectory($dirname, $config); + + return $this->getAdapter()->directoryExists($dirname); } /** * (non-PHPdoc) - * @see \League\Flysystem\AdapterInterface::setVisibility() + * @see \League\Flysystem\FilesystemAdapter::setVisibility() */ public function setVisibility($path, $visibility) { - return $this->getAdapter()->setVisibility($path, $visibility); + $this->getAdapter()->setVisibility($path, $visibility); + return $this->getAdapter()->visibility($path); } /** @@ -108,12 +125,12 @@ public function setVisibility($path, $visibility) */ public function has($path) { - return $this->getAdapter()->has($path); + return $this->getAdapter()->fileExists($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::read() + * @see \League\Flysystem\FilesystemAdapter::read() */ public function read($path) { @@ -122,7 +139,7 @@ public function read($path) /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::readStream() + * @see \League\Flysystem\FilesystemAdapter::readStream() */ public function readStream($path) { @@ -131,7 +148,7 @@ public function readStream($path) /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::listContents() + * @see \League\Flysystem\FilesystemAdapter::listContents() */ public function listContents($directory = '', $recursive = false) { @@ -140,53 +157,55 @@ public function listContents($directory = '', $recursive = false) /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::getMetadata() + * @see \League\Flysystem\FilesystemAdapter::getMetadata() */ public function getMetadata($path) { - return $this->getAdapter()->getMetadata($path); + $list = iterator_to_array($this->getAdapter()->listContents($path)); + return (array)$list[0]; } /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::getSize() + * @see \League\Flysystem\FilesystemAdapter::getSize() */ public function getSize($path) { - return $this->getAdapter()->getSize($path); + return $this->getAdapter()->fileSize($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::getMimetype() + * @see \League\Flysystem\FilesystemAdapter::getMimetype() */ public function getMimetype($path) { - return $this->getAdapter()->getMimetype($path); + return $this->getAdapter()->mimeType($path); } /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::getTimestamp() + * @see \League\Flysystem\FilesystemAdapter::getTimestamp() */ public function getTimestamp($path) { - return $this->getAdapter()->getTimestamp($path); + $list = iterator_to_array($this->getAdapter()->listContents($path)); + return (array)$list[0]['createdAt'] ?? (array)$list[0]['timestamp']; } /** * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::getVisibility() + * @see \League\Flysystem\FilesystemAdapter::getVisibility() */ public function getVisibility($path) { - return $this->getAdapter()->getVisibility($path); + return $this->getAdapter()->visibility($path); } /** * Return the adapter implementation * - * @return AdapterInterface + * @return FilesystemAdapter */ abstract public function getAdapter(); } diff --git a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php b/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php index c29847a9f..08b545e0b 100644 --- a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php +++ b/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php @@ -20,18 +20,26 @@ namespace oat\oatbox\filesystem\wrapper; +use League\Flysystem\Config; +use League\Flysystem\DirectoryListing; +use League\Flysystem\FilesystemException; +use League\Flysystem\FilesystemOperator; +use League\Flysystem\UnableToCopyFile; +use League\Flysystem\UnableToDeleteFile; +use League\Flysystem\UnableToSetVisibility; +use League\Flysystem\UnableToWriteFile; use oat\oatbox\service\ConfigurableService; -use League\Flysystem\AdapterInterface; +use League\Flysystem\FilesystemAdapter; use oat\oatbox\filesystem\utils\FlyWrapperTrait; use oat\oatbox\log\LoggerAwareTrait; use Google\Cloud\Storage\StorageClient; -use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter; +use League\Flysystem\GoogleCloudStorage\GoogleCloudStorageAdapter; /** * @deprecated Please install `oat-sa/lib-generis-gcp` and use \oat\Gcp\Gcs\GcsFlyWrapper * @author Joel Bout */ -class GoogleStorageWrapper extends ConfigurableService implements AdapterInterface +class GoogleStorageWrapper extends ConfigurableService implements FilesystemOperator { use FlyWrapperTrait; use LoggerAwareTrait; @@ -51,16 +59,135 @@ private function getClient() } /** - * @return AdapterInterface + * @return FilesystemAdapter */ public function getAdapter() { if (is_null($this->adapter)) { $client = $this->getClient(); $bucket = $client->bucket($this->getOption('bucket')); - $adapter = new GoogleStorageAdapter($client, $bucket); + $adapter = new GoogleCloudStorageAdapter($bucket); $this->adapter = $adapter; } return $this->adapter; } + + public function fileExists(string $path): bool + { + return $this->getAdapter()->directoryExists($path); + } + + public function directoryExists(string $path): bool + { + return $this->getAdapter()->directoryExists($path); + } + + public function deleteDirectory(string $path): void + { + $this->getAdapter()->deleteDirectory($path); + } + + public function createDirectory(string $location, array $configParams = []): void + { + $config = new Config($configParams); + $this->getAdapter()->createDirectory($location, $config); + } + + public function visibility(string $path): string + { + return $this->getAdapter()->visibility($path)->visibility(); + } + + public function mimeType(string $path): string + { + return $this->getAdapter()->mimeType($path)->mimeType(); + } + + public function lastModified(string $path): int + { + return $this->getAdapter()->lastModified($path)->lastModified(); + } + + public function fileSize(string $path): int + { + return $this->getAdapter()->fileSize($path)->fileSize(); + } + + public function move(string $source, string $destination, array $configParams = []): void + { + $config = new Config($configParams); + $this->getAdapter()->move($source, $destination, $config); + } + + public function __call($name, $arguments) + { + return call_user_func($name, $this->getAdapter(), ...$arguments); + } + + public function has(string $location): bool + { + return $this->getAdapter()->fileExists($location); + } + + public function read(string $location): string + { + return $this->getAdapter()->read($location); + } + + public function readStream(string $location) + { + return $this->getAdapter()->readStream($location); + } + + /** + * @throws UnableToWriteFile + * @throws FilesystemException + */ + public function write(string $location, string $contents, array $config = []): void + { + $this->getAdapter()->write($location, $contents, new Config($config)); + } + + /** + * @param mixed $contents + * + * @throws UnableToWriteFile + * @throws FilesystemException + */ + public function writeStream(string $location, $contents, array $config = []): void + { + $this->getAdapter()->writeStream($location, $contents, new Config($config)); + } + + /** + * @throws UnableToSetVisibility + * @throws FilesystemException + */ + public function setVisibility(string $path, string $visibility): void + { + $this->getAdapter()->setVisibility($path, $visibility); + } + + /** + * @throws UnableToDeleteFile + * @throws FilesystemException + */ + public function delete(string $location): void + { + $this->getAdapter()->delete($location); + } + + /** + * @throws UnableToCopyFile + * @throws FilesystemException + */ + public function copy(string $source, string $destination, array $config = []): void + { + $this->getAdapter()->copy($source, $destination, new Config($config)); + } + + public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing + { + return new DirectoryListing($this->getAdapter()->listContents($location, $deep)); + } } From 1b6984468d5a9bca7a894ec37bd3dca456ea8f68 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 17:41:04 +0100 Subject: [PATCH 02/15] refactor: use official google bucket adapter --- common/oatbox/filesystem/FileSystem.php | 2 +- common/oatbox/filesystem/utils/FlyWrapperTrait.php | 4 ++-- composer.json | 12 +++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/common/oatbox/filesystem/FileSystem.php b/common/oatbox/filesystem/FileSystem.php index 85dde8a3e..71927f6fa 100644 --- a/common/oatbox/filesystem/FileSystem.php +++ b/common/oatbox/filesystem/FileSystem.php @@ -82,7 +82,7 @@ protected function getFileSystem() * * @return FilesystemAdapter adapter */ - private function getAdapter() + public function getAdapter() { return $this->getFileSystem()->getAdapter(); } diff --git a/common/oatbox/filesystem/utils/FlyWrapperTrait.php b/common/oatbox/filesystem/utils/FlyWrapperTrait.php index 5f54eb8e9..caf7a3498 100644 --- a/common/oatbox/filesystem/utils/FlyWrapperTrait.php +++ b/common/oatbox/filesystem/utils/FlyWrapperTrait.php @@ -36,7 +36,7 @@ public function writeStream($path, $resource, Config $config) /** * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::update() + * @see \League\Flysystem\FilesystemAdapter::write() */ public function update($path, $contents, Config $config) { @@ -47,7 +47,7 @@ public function update($path, $contents, Config $config) /** * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::updateStream() + * @see \League\Flysystem\FilesystemAdapter::writeStream() */ public function updateStream($path, $resource, Config $config) { diff --git a/composer.json b/composer.json index ec7e78591..bab286647 100755 --- a/composer.json +++ b/composer.json @@ -59,8 +59,9 @@ "doctrine/dbal": "^2.12", "doctrine/annotations": "^1.13", "laminas/laminas-servicemanager": "~2.5.0", - "league/flysystem": "~1.0", - "league/flysystem-memory": "~1.0", + "league/flysystem": "^2.0", + "league/flysystem-memory": "^2.0", + "league/flysystem-google-cloud-storage": "^2.0", "oat-sa/oatbox-extension-installer": "~1.1||dev-master", "oat-sa/lib-generis-search": "^2.3.0", "monolog/monolog": "^1.23.0", @@ -86,7 +87,7 @@ "php-mock/php-mock": "^2.0" }, "suggest": { - "superbalist/flysystem-google-storage": "Supports google flystore" + "league/flysystem-google-cloud-storage": "Supports google flystore" }, "autoload": { "psr-4": { @@ -107,5 +108,10 @@ "psr-4": { "oat\\generis\\test\\": "generis/test/" } + }, + "config": { + "allow-plugins": { + "oat-sa/oatbox-extension-installer": true + } } } From d16dd3100c3eeebc773a5feb302f45ebf2484318 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 17:56:26 +0100 Subject: [PATCH 03/15] fix: apply code styles --- common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php b/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php index 08b545e0b..1732a2f71 100644 --- a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php +++ b/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php @@ -183,7 +183,7 @@ public function delete(string $location): void */ public function copy(string $source, string $destination, array $config = []): void { - $this->getAdapter()->copy($source, $destination, new Config($config)); + $this->getAdapter()->copy($source, $destination, new Config($config)); } public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing From 233b6e64722bcc4a91e1684b0c3499927254c88a Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Wed, 28 Aug 2024 13:48:51 +0200 Subject: [PATCH 04/15] feat: require flysystem v3 --- common/oatbox/filesystem/Directory.php | 2 +- common/oatbox/filesystem/File.php | 4 +- .../utils/FileSystemWrapperTrait.php | 73 +++++++++++++++---- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/common/oatbox/filesystem/Directory.php b/common/oatbox/filesystem/Directory.php index be239d313..6ba4b35da 100644 --- a/common/oatbox/filesystem/Directory.php +++ b/common/oatbox/filesystem/Directory.php @@ -127,7 +127,7 @@ public function getRelPath($content) */ public function exists() { - return $this->getFileSystem()->has($this->getPrefix()); + return $this->getFileSystem()->directoryExists($this->getPrefix()); } /** diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index 7ccdba8fc..9ca656366 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -83,7 +83,7 @@ public function getMetadata() { try { $path = $this->getPrefix(); - if ($this->getFileSystem()->has($path)) { + if ($this->getFileSystem()->fileExists($path)) { return $this->getFileSystem()->get($path)->getMetadata(); } } catch (FileNotFoundException $e) { @@ -265,7 +265,7 @@ public function exists() try { $path = $this->getPrefix(); - if ($this->getFileSystem()->has($path)) { + if ($this->getFileSystem()->fileExists($path)) { $metadata = $this->getFileSystem()->getMetadata($this->getPrefix()); return $metadata['type'] === 'file'; } diff --git a/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php b/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php index 687c932ac..b93eaea9a 100644 --- a/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php +++ b/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php @@ -21,6 +21,7 @@ namespace oat\oatbox\filesystem\utils; +use League\Flysystem\DirectoryListing; use League\Flysystem\Filesystem; use League\Flysystem\Handler; use League\Flysystem\PluginInterface; @@ -36,9 +37,9 @@ trait FileSystemWrapperTrait * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::has() */ - public function has($path) + public function directoryExists($path) { - return $this->getFileSystem()->has($this->getFullPath($path)); + return $this->getFileSystem()->directoryExists($this->getFullPath($path)); } @@ -46,9 +47,9 @@ public function has($path) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::read() */ - public function read($path) + public function read(string $location): string { - return $this->getFileSystem()->read($this->getFullPath($path)); + return $this->getFileSystem()->read($this->getFullPath($location)); } @@ -66,9 +67,9 @@ public function readStream($path) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::listContents() */ - public function listContents($directory = '', $recursive = false) + public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing { - return $this->getFileSystem()->listContents($this->getFullPath($directory), $recursive); + return $this->getFileSystem()->listContents($this->getFullPath($location), $deep); } @@ -126,9 +127,9 @@ public function getVisibility($path) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::write() */ - public function write($path, $contents, array $config = []) + public function write(string $location, string $contents, array $config = []): void { - return $this->getFileSystem()->write($this->getFullPath($path), $contents, $config); + $this->getFileSystem()->write($this->getFullPath($location), $contents, $config); } @@ -136,9 +137,9 @@ public function write($path, $contents, array $config = []) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::writeStream() */ - public function writeStream($path, $resource, array $config = []) + public function writeStream(string $location, $contents, array $config = []): void { - return $this->getFileSystem()->writeStream($this->getFullPath($path), $resource, $config); + $this->getFileSystem()->writeStream($this->getFullPath($location), $contents, $config); } @@ -176,9 +177,9 @@ public function rename($path, $newpath) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::copy() */ - public function copy($path, $newpath) + public function copy(string $source, string $destination, array $config = []): void { - return $this->getFileSystem()->copy($this->getFullPath($path), $newpath); + $this->getFileSystem()->copy($this->getFullPath($source), $destination); } @@ -186,9 +187,9 @@ public function copy($path, $newpath) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::delete() */ - public function delete($path) + public function delete(string $location): void { - return $this->getFileSystem()->delete($this->getFullPath($path)); + $this->getFileSystem()->delete($this->getFullPath($location)); } @@ -216,9 +217,9 @@ public function createDir($dirname, array $config = []) * (non-PHPdoc) * @see \League\Flysystem\FilesystemInterface::setVisibility() */ - public function setVisibility($path, $visibility) + public function setVisibility(string $path, string $visibility): void { - return $this->getFileSystem()->setVisibility($this->getFullPath($path), $visibility); + $this->getFileSystem()->setVisibility($this->getFullPath($path), $visibility); } @@ -271,6 +272,46 @@ public function addPlugin(PluginInterface $plugin) return $this->getFileSystem()->addPlugin($plugin); } + public function fileExists(string $location): bool + { + return $this->getFileSystem()->fileExists($this->getFullPath($location)); + } + + public function lastModified(string $path): int + { + return $this->getFileSystem()->lastModified($this->getFullPath($path)); + } + + public function fileSize(string $path): int + { + return $this->getFileSystem()->fileSize($this->getFullPath($path)); + } + + public function mimeType(string $path): string + { + return $this->getFileSystem()->mimeType($this->getFullPath($path)); + } + + public function visibility(string $path): string + { + return $this->getFileSystem()->visibility($this->getFullPath($path)); + } + + public function deleteDirectory(string $location): void + { + $this->getFileSystem()->deleteDirectory($this->getFullPath($location)); + } + + public function createDirectory(string $location, array $config = []): void + { + $this->getFileSystem()->createDirectory($this->getFullPath($location), $config); + } + + public function move(string $source, string $destination, array $config = []): void + { + $this->getFileSystem()->move($this->getFullPath($source), $destination, $config); + } + /** * Return the underlying Filesystem * From f533fa83787cf1c84919e041a35778bf362154c9 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Wed, 28 Aug 2024 14:08:57 +0200 Subject: [PATCH 05/15] feat: require flysystem v3 --- composer.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index bab286647..923d02f98 100755 --- a/composer.json +++ b/composer.json @@ -59,9 +59,9 @@ "doctrine/dbal": "^2.12", "doctrine/annotations": "^1.13", "laminas/laminas-servicemanager": "~2.5.0", - "league/flysystem": "^2.0", - "league/flysystem-memory": "^2.0", - "league/flysystem-google-cloud-storage": "^2.0", + "league/flysystem": "^3.0", + "league/flysystem-memory": "^3.0", + "league/flysystem-google-cloud-storage": "^3.0", "oat-sa/oatbox-extension-installer": "~1.1||dev-master", "oat-sa/lib-generis-search": "^2.3.0", "monolog/monolog": "^1.23.0", @@ -111,7 +111,8 @@ }, "config": { "allow-plugins": { - "oat-sa/oatbox-extension-installer": true + "oat-sa/oatbox-extension-installer": true, + "php-http/discovery": true } } } From ada7d9988dd0535c93c058941c2d4a93c4501c5c Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Mon, 7 Oct 2024 11:19:32 +0200 Subject: [PATCH 06/15] feat!: update filesystem interfaces and their usage --- common/oatbox/filesystem/Directory.php | 23 +- common/oatbox/filesystem/File.php | 197 +++++--------- common/oatbox/filesystem/FileSystem.php | 3 +- .../oatbox/filesystem/FileSystemService.php | 15 +- .../utils/FileSystemWrapperTrait.php | 246 +++++------------- common/oatbox/install/Installer.php | 4 +- scripts/update/Updater.php | 8 +- test/FileSystemMockTrait.php | 4 +- .../filesystem/DirectoryFilesystemTest.php | 1 - 9 files changed, 152 insertions(+), 349 deletions(-) diff --git a/common/oatbox/filesystem/Directory.php b/common/oatbox/filesystem/Directory.php index 6ba4b35da..9947d239d 100644 --- a/common/oatbox/filesystem/Directory.php +++ b/common/oatbox/filesystem/Directory.php @@ -21,7 +21,7 @@ namespace oat\oatbox\filesystem; -use League\Flysystem\FileExistsException; +use League\Flysystem\FilesystemException; class Directory extends FileSystemHandler implements \IteratorAggregate { @@ -87,7 +87,7 @@ public function getFlyIterator($flags = null) $contents = $this->getFileSystem()->listContents($this->getPrefix(), $recursive); if (!empty($contents)) { - $dirPath = $this->getFileSystem()->get($this->getPrefix())->getPath(); + $dirPath = $this->getPrefix(); foreach ($contents as $content) { if ($withDirectories && $content['type'] == 'dir') { $iterator[] = $this->getDirectory(str_replace($dirPath, '', $content['path'])); @@ -137,7 +137,13 @@ public function exists() */ public function deleteSelf() { - return $this->getFileSystem()->deleteDir($this->getPrefix()); + try { + $this->getFileSystem()->deleteDirectory($this->getPrefix()); + return true; + } catch (FilesystemException $e) { + } + + return false; } /** @@ -185,15 +191,10 @@ public function rename($path) foreach ($filePaths as $renaming) { try { - if ($this->getFileSystem()->rename($renaming['source'], $renaming['destination']) === false) { - throw new \common_exception_FileSystemError( - "Unable to rename '" . $renaming['source'] . "' into '" . $renaming['destination'] . "'." - ); - } - } catch (FileExistsException $e) { + $this->getFileSystem()->move($renaming['source'], $renaming['destination']); + } catch (FilesystemException $e) { throw new \common_exception_FileSystemError( - "Unable to rename '" . $renaming['source'] . "' into '" . $renaming['destination'] - . "'. File already exists." + "Unable to rename '" . $renaming['source'] . "' into '" . $renaming['destination'] . "'." ); } } diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index 9ca656366..e7bc64cf3 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -23,19 +23,13 @@ use GuzzleHttp\Psr7\Stream; use GuzzleHttp\Psr7\StreamWrapper; -use League\Flysystem\FileNotFoundException; +use League\Flysystem\FilesystemException; use Psr\Http\Message\StreamInterface; -use League\Flysystem\FileExistsException; use tao_helpers_File; class File extends FileSystemHandler { - /** - * Get basename of $this file - * - * @return string - */ - public function getBasename() + public function getBasename(): string { return basename($this->getPrefix()); } @@ -48,7 +42,7 @@ public function getBasename() public function getMimeType() { try { - $mimeType = $this->getFileSystem()->getMimetype($this->getPrefix()); + $mimeType = $this->getFileSystem()->mimeType($this->getPrefix()); $suffix = substr($this->getPrefix(), -4); if ($mimeType === 'text/plain' && $suffix === '.css') { $mimeType = 'text/css'; @@ -59,7 +53,7 @@ public function getMimeType() } return $mimeType; - } catch (FileNotFoundException $e) { + } catch (FilesystemException $e) { } return false; } @@ -71,24 +65,7 @@ public function getMimeType() */ public function getSize() { - return $this->getFileSystem()->getSize($this->getPrefix()); - } - - /** - * Get metadata of $this file - * - * @return array|bool - */ - public function getMetadata() - { - try { - $path = $this->getPrefix(); - if ($this->getFileSystem()->fileExists($path)) { - return $this->getFileSystem()->get($path)->getMetadata(); - } - } catch (FileNotFoundException $e) { - } - return false; + return $this->getFileSystem()->fileSize($this->getPrefix()); } /** @@ -100,36 +77,41 @@ public function getMetadata() * @param null $mimeType * @return bool * @throws \common_Exception - * @throws FileExistsException */ public function write($mixed, $mimeType = null) { $config = (is_null($mimeType)) ? [] : ['ContentType' => $mimeType]; - if (is_string($mixed)) { - return $this->getFileSystem()->write($this->getPrefix(), $mixed, $config); - } elseif (is_resource($mixed)) { - return $this->getFileSystem()->writeStream($this->getPrefix(), $mixed, $config); - } elseif ($mixed instanceof StreamInterface) { - if (!$mixed->isReadable()) { - throw new \common_Exception('Stream is not readable. Write to filesystem aborted.'); - } - if (!$mixed->isSeekable()) { - throw new \common_Exception('Stream is not seekable. Write to filesystem aborted.'); - } - $mixed->rewind(); - - $resource = StreamWrapper::getResource($mixed); - if (!is_resource($resource)) { - throw new \common_Exception( - 'Unable to create resource from the given stream. Write to filesystem aborted.' - ); + try { + if (is_string($mixed)) { + $this->getFileSystem()->write($this->getPrefix(), $mixed, $config); + } elseif (is_resource($mixed)) { + $this->getFileSystem()->writeStream($this->getPrefix(), $mixed, $config); + } elseif ($mixed instanceof StreamInterface) { + if (!$mixed->isReadable()) { + throw new \common_Exception('Stream is not readable. Write to filesystem aborted.'); + } + if (!$mixed->isSeekable()) { + throw new \common_Exception('Stream is not seekable. Write to filesystem aborted.'); + } + $mixed->rewind(); + + $resource = StreamWrapper::getResource($mixed); + if (!is_resource($resource)) { + throw new \common_Exception( + 'Unable to create resource from the given stream. Write to filesystem aborted.' + ); + } + $this->getFileSystem()->writeStream($this->getPrefix(), $resource, $config); + } else { + throw new \InvalidArgumentException('Value to be written has to be: string, resource or StreamInterface, ' . + '"' . gettype($mixed) . '" given.'); } - return $this->getFileSystem()->writeStream($this->getPrefix(), $resource, $config); - } else { - throw new \InvalidArgumentException('Value to be written has to be: string, resource or StreamInterface, ' . - '"' . gettype($mixed) . '" given.'); + } catch (FilesystemException $e) { + return false; } + + return true; } /** @@ -140,45 +122,17 @@ public function write($mixed, $mimeType = null) * @param $mixed * @param null $mimeType * @return bool - * @throws \FileNotFoundException * @throws \common_Exception */ public function update($mixed, $mimeType = null) { if (!$this->exists()) { - throw new \FileNotFoundException('File "' . $this->getPrefix() . '" not found."'); - } - - \common_Logger::i('Writting in ' . $this->getPrefix()); - $config = (is_null($mimeType)) ? [] : ['ContentType' => $mimeType]; - - if (is_string($mixed)) { - return $this->getFileSystem()->update($this->getPrefix(), $mixed, $config); + throw new \RuntimeException('File "' . $this->getPrefix() . '" not found."'); } - if (is_resource($mixed)) { - return $this->getFileSystem()->updateStream($this->getPrefix(), $mixed, $config); - } - - if ($mixed instanceof StreamInterface) { - if (!$mixed->isReadable()) { - throw new \common_Exception('Stream is not readable. Write to filesystem aborted.'); - } - if (!$mixed->isSeekable()) { - throw new \common_Exception('Stream is not seekable. Write to filesystem aborted.'); - } - $mixed->rewind(); + \common_Logger::i('Writing in ' . $this->getPrefix()); - $resource = StreamWrapper::getResource($mixed); - if (!is_resource($resource)) { - throw new \common_Exception( - 'Unable to create resource from the given stream. Write to filesystem aborted.' - ); - } - return $this->getFileSystem()->updateStream($this->getPrefix(), $resource, $config); - } - - throw new \InvalidArgumentException('Value to be written has to be: string, resource or StreamInterface'); + return $this->write($mixed, $mimeType); } /** @@ -194,35 +148,8 @@ public function update($mixed, $mimeType = null) public function put($mixed, $mimeType = null) { \common_Logger::i('Writting in ' . $this->getPrefix()); - $config = (is_null($mimeType)) ? [] : ['ContentType' => $mimeType]; - if (is_string($mixed)) { - return $this->getFileSystem()->put($this->getPrefix(), $mixed, $config); - } - - if (is_resource($mixed)) { - return $this->getFileSystem()->putStream($this->getPrefix(), $mixed, $config); - } - - if ($mixed instanceof StreamInterface) { - if (!$mixed->isReadable()) { - throw new \common_Exception('Stream is not readable. Write to filesystem aborted.'); - } - if (!$mixed->isSeekable()) { - throw new \common_Exception('Stream is not seekable. Write to filesystem aborted.'); - } - $mixed->rewind(); - - $resource = StreamWrapper::getResource($mixed); - if (!is_resource($resource)) { - throw new \common_Exception( - 'Unable to create resource from the given stream. Write to filesystem aborted.' - ); - } - return $this->getFileSystem()->putStream($this->getPrefix(), $resource, $config); - } - - throw new \InvalidArgumentException('Value to be written has to be: string, resource or StreamInterface'); + return $this->write($mixed, $mimeType); } /** @@ -232,7 +159,12 @@ public function put($mixed, $mimeType = null) */ public function read() { - return $this->getFileSystem()->read($this->getPrefix()); + try { + return $this->getFileSystem()->read($this->getPrefix()); + } catch (FilesystemException $e) { + } + + return false; } /** @@ -242,7 +174,12 @@ public function read() */ public function readStream() { - return $this->getFileSystem()->readStream($this->getPrefix()); + try { + return $this->getFileSystem()->readStream($this->getPrefix()); + } catch (FilesystemException $e) { + } + + return false; } /** @@ -252,38 +189,30 @@ public function readStream() */ public function readPsrStream() { - return new Stream($this->getFileSystem()->readStream($this->getPrefix())); + $resource = null; + try { + $resource = $this->getFileSystem()->readStream($this->getPrefix()); + } catch (FilesystemException $e) { + } + + return new Stream($resource); } - /** - * Check if $this file exists && is file - * - * @return bool - */ - public function exists() + public function exists(): bool { try { - $path = $this->getPrefix(); - - if ($this->getFileSystem()->fileExists($path)) { - $metadata = $this->getFileSystem()->getMetadata($this->getPrefix()); - return $metadata['type'] === 'file'; - } - } catch (FileNotFoundException $e) { + return $this->getFileSystem()->fileExists($this->getPrefix()); + } catch (FilesystemException $e) { } return false; } - /** - * Delete $this file - * - * @return bool - */ - public function delete() + public function delete(): bool { try { - return $this->getFileSystem()->delete($this->getPrefix()); - } catch (FileNotFoundException $e) { + $this->getFileSystem()->delete($this->getPrefix()); + return true; + } catch (FilesystemException $e) { } return false; diff --git a/common/oatbox/filesystem/FileSystem.php b/common/oatbox/filesystem/FileSystem.php index 71927f6fa..b58af2d87 100644 --- a/common/oatbox/filesystem/FileSystem.php +++ b/common/oatbox/filesystem/FileSystem.php @@ -70,9 +70,8 @@ public function getId() /** * @return FilesystemOperator - * @throws \common_Exception */ - protected function getFileSystem() + protected function getFileSystem(): FilesystemOperator { return $this->filesystem; } diff --git a/common/oatbox/filesystem/FileSystemService.php b/common/oatbox/filesystem/FileSystemService.php index fd81374dd..a779afc51 100755 --- a/common/oatbox/filesystem/FileSystemService.php +++ b/common/oatbox/filesystem/FileSystemService.php @@ -21,6 +21,7 @@ namespace oat\oatbox\filesystem; +use League\Flysystem\Local\LocalFilesystemAdapter; use oat\oatbox\service\ConfigurableService; use League\Flysystem\FilesystemAdapter; use common_exception_Error; @@ -41,9 +42,7 @@ class FileSystemService extends ConfigurableService public const OPTION_DIRECTORIES = 'dirs'; - public const FLYSYSTEM_ADAPTER_NS = '\\League\\Flysystem\\Adapter\\'; - - public const FLYSYSTEM_LOCAL_ADAPTER = 'Local'; + private const FLYSYSTEM_NS = '\\League\\Flysystem\\'; private $filesystems = []; @@ -152,7 +151,7 @@ public function registerLocalFileSystem($id, $path) { $adapters = $this->hasOption(self::OPTION_ADAPTERS) ? $this->getOption(self::OPTION_ADAPTERS) : []; $adapters[$id] = [ - 'class' => self::FLYSYSTEM_LOCAL_ADAPTER, + 'class' => LocalFilesystemAdapter::class, 'options' => ['root' => $path] ]; $this->setOption(self::OPTION_ADAPTERS, $adapters); @@ -246,10 +245,10 @@ protected function getFlysystemAdapter($id) $options = isset($adapterConfig['options']) ? $adapterConfig['options'] : []; if (!class_exists($class)) { - if (class_exists(self::FLYSYSTEM_ADAPTER_NS . $class)) { - $class = self::FLYSYSTEM_ADAPTER_NS . $class; - } elseif (class_exists(self::FLYSYSTEM_ADAPTER_NS . $class . '\\' . $class . 'Adapter')) { - $class = self::FLYSYSTEM_ADAPTER_NS . $class . '\\' . $class . 'Adapter'; + if (class_exists(self::FLYSYSTEM_NS . $class)) { + $class = self::FLYSYSTEM_NS . $class; + } elseif (class_exists(self::FLYSYSTEM_NS . $class . '\\' . $class . 'FilesystemAdapter')) { + $class = self::FLYSYSTEM_NS . $class . '\\' . $class . 'FilesystemAdapter'; } else { throw new common_exception_Error('Unknown Flysystem adapter "' . $class . '"'); } diff --git a/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php b/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php index b93eaea9a..8d76b0405 100644 --- a/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php +++ b/common/oatbox/filesystem/utils/FileSystemWrapperTrait.php @@ -22,9 +22,7 @@ namespace oat\oatbox\filesystem\utils; use League\Flysystem\DirectoryListing; -use League\Flysystem\Filesystem; -use League\Flysystem\Handler; -use League\Flysystem\PluginInterface; +use League\Flysystem\FilesystemOperator; /** * A trait to facilitate creation of filesystem wrappers @@ -34,290 +32,168 @@ trait FileSystemWrapperTrait { /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::has() + * @see FilesystemOperator::has + * @inheritDoc */ - public function directoryExists($path) + public function has(string $location): bool { - return $this->getFileSystem()->directoryExists($this->getFullPath($path)); + return $this->getFileSystem()->has($this->getFullPath($location)); } + /** + * @see FilesystemOperator::directoryExists + * @inheritDoc + */ + public function directoryExists(string $location): bool + { + return $this->getFileSystem()->directoryExists($this->getFullPath($location)); + } /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::read() + * @see FilesystemOperator::read + * @inheritDoc */ public function read(string $location): string { return $this->getFileSystem()->read($this->getFullPath($location)); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::readStream() + * @see FilesystemOperator::readStream + * @inheritDoc */ public function readStream($path) { return $this->getFileSystem()->readStream($this->getFullPath($path)); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::listContents() + * @see FilesystemOperator::listContents + * @inheritDoc */ - public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing + public function listContents(string $location = '', bool $deep = self::LIST_SHALLOW): DirectoryListing { return $this->getFileSystem()->listContents($this->getFullPath($location), $deep); } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::getMetadata() - */ - public function getMetadata($path) - { - return $this->getFileSystem()->getMetadata($this->getFullPath($path)); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::getSize() - */ - public function getSize($path) - { - return $this->getFileSystem()->getSize($this->getFullPath($path)); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::getMimetype() - */ - public function getMimetype($path) - { - return $this->getFileSystem()->getMimetype($this->getFullPath($path)); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::getTimestamp() - */ - public function getTimestamp($path) - { - return $this->getFileSystem()->getTimestamp($this->getFullPath($path)); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::getVisibility() - */ - public function getVisibility($path) - { - return $this->getFileSystem()->getVisibility($this->getFullPath($path)); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::write() + * @see FilesystemOperator::write + * @inheritDoc */ public function write(string $location, string $contents, array $config = []): void { $this->getFileSystem()->write($this->getFullPath($location), $contents, $config); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::writeStream() + * @see FilesystemOperator::writeStream + * @inheritDoc */ public function writeStream(string $location, $contents, array $config = []): void { $this->getFileSystem()->writeStream($this->getFullPath($location), $contents, $config); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::update() - */ - public function update($path, $contents, array $config = []) - { - return $this->getFileSystem()->update($this->getFullPath($path), $contents, $config); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::updateStream() - */ - public function updateStream($path, $resource, array $config = []) - { - return $this->getFileSystem()->updateStream($this->getFullPath($path), $resource, $config); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::rename() - */ - public function rename($path, $newpath) - { - return $this->getFileSystem()->rename($this->getFullPath($path), $newpath); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::copy() + * @see FilesystemOperator::copy + * @inheritDoc */ public function copy(string $source, string $destination, array $config = []): void { $this->getFileSystem()->copy($this->getFullPath($source), $destination); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::delete() + * @see FilesystemOperator::delete + * @inheritDoc */ public function delete(string $location): void { $this->getFileSystem()->delete($this->getFullPath($location)); } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::deleteDir() - */ - public function deleteDir($dirname) - { - return $this->getFileSystem()->deleteDir($this->getFullPath($dirname)); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::createDir() - */ - public function createDir($dirname, array $config = []) - { - return $this->getFileSystem()->createDir($this->getFullPath($dirname), $config); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::setVisibility() + * @see FilesystemOperator::setVisibility + * @inheritDoc */ public function setVisibility(string $path, string $visibility): void { $this->getFileSystem()->setVisibility($this->getFullPath($path), $visibility); } - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::put() + * @see FilesystemOperator::fileExists + * @inheritDoc */ - public function put($path, $contents, array $config = []) - { - return $this->getFileSystem()->put($this->getFullPath($path), $contents, $config); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::putStream() - */ - public function putStream($path, $resource, array $config = []) - { - return $this->getFileSystem()->putStream($this->getFullPath($path), $resource, $config); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::readAndDelete() - */ - public function readAndDelete($path) - { - return $this->getFileSystem()->readAndDelete($this->getFullPath($path)); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::get() - */ - public function get($path, Handler $handler = null) - { - return $this->getFileSystem()->get($this->getFullPath($path), $handler); - } - - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemInterface::addPlugin() - */ - public function addPlugin(PluginInterface $plugin) - { - return $this->getFileSystem()->addPlugin($plugin); - } - public function fileExists(string $location): bool { return $this->getFileSystem()->fileExists($this->getFullPath($location)); } + /** + * @see FilesystemOperator::lastModified + * @inheritDoc + */ public function lastModified(string $path): int { return $this->getFileSystem()->lastModified($this->getFullPath($path)); } + /** + * @see FilesystemOperator::fileSize + * @inheritDoc + */ public function fileSize(string $path): int { return $this->getFileSystem()->fileSize($this->getFullPath($path)); } + /** + * @see FilesystemOperator::mimeType + * @inheritDoc + */ public function mimeType(string $path): string { return $this->getFileSystem()->mimeType($this->getFullPath($path)); } + /** + * @see FilesystemOperator::visibility + * @inheritDoc + */ public function visibility(string $path): string { return $this->getFileSystem()->visibility($this->getFullPath($path)); } + /** + * @see FilesystemOperator::deleteDirectory + * @inheritDoc + */ public function deleteDirectory(string $location): void { $this->getFileSystem()->deleteDirectory($this->getFullPath($location)); } + /** + * @see FilesystemOperator::createDirectory + * @inheritDoc + */ public function createDirectory(string $location, array $config = []): void { $this->getFileSystem()->createDirectory($this->getFullPath($location), $config); } + /** + * @see FilesystemOperator::move + * @inheritDoc + */ public function move(string $source, string $destination, array $config = []): void { $this->getFileSystem()->move($this->getFullPath($source), $destination, $config); } - /** - * Return the underlying Filesystem - * - * @return Filesystem - */ - abstract protected function getFileSystem(); + abstract protected function getFileSystem(): FilesystemOperator; abstract protected function getFullPath($path); } diff --git a/common/oatbox/install/Installer.php b/common/oatbox/install/Installer.php index 82767f475..ac7f790e3 100755 --- a/common/oatbox/install/Installer.php +++ b/common/oatbox/install/Installer.php @@ -21,6 +21,7 @@ namespace oat\oatbox\install; +use League\Flysystem\InMemory\InMemoryFilesystemAdapter; use oat\oatbox\service\ConfigurableService; use oat\oatbox\service\exception\InvalidService; use oat\oatbox\service\exception\InvalidServiceManagerException; @@ -29,7 +30,6 @@ use oat\oatbox\filesystem\FileSystemService; use oat\oatbox\service\ServiceNotFoundException; use common_report_Report as Report; -use League\Flysystem\Memory\MemoryAdapter; /** * A service to install oatbox functionality @@ -105,7 +105,7 @@ protected function installFilesystem() ] ], 'memory' => [ - 'class' => MemoryAdapter::class + 'class' => InMemoryFilesystemAdapter::class ] ] ]); diff --git a/scripts/update/Updater.php b/scripts/update/Updater.php index 772af36d2..9421ff73d 100644 --- a/scripts/update/Updater.php +++ b/scripts/update/Updater.php @@ -28,8 +28,8 @@ use common_ext_ExtensionUpdater; use core_kernel_impl_ApiModelOO; use core_kernel_persistence_smoothsql_SmoothModel; -use League\Flysystem\Adapter\Local; -use League\Flysystem\Memory\MemoryAdapter; +use League\Flysystem\InMemory\InMemoryFilesystemAdapter; +use League\Flysystem\Local\LocalFilesystemAdapter; use oat\generis\model\data\ModelManager; use oat\generis\model\data\Ontology; use oat\generis\model\fileReference\FileReferenceSerializer; @@ -464,7 +464,7 @@ public function update($initialVersion) if (get_class($fs) == FileSystemService::class) { // override default behavior to ensure an adapter and not a directory is created $adapters['default'] = [ - 'class' => Local::class, + 'class' => LocalFilesystemAdapter::class, 'options' => ['root' => $fs->getOption(FileSystemService::OPTION_FILE_PATH)] ]; $fs->setOption(FileSystemService::OPTION_ADAPTERS, $adapters); @@ -526,7 +526,7 @@ public function update($initialVersion) /** @var FileSystemService $fs */ $fs = $this->getServiceManager()->get(FileSystemService::SERVICE_ID); $adapters = $fs->getOption(FileSystemService::OPTION_ADAPTERS); - $adapters['memory'] = [ 'class' => MemoryAdapter::class, ]; + $adapters['memory'] = [ 'class' => InMemoryFilesystemAdapter::class, ]; $fs->setOption(FileSystemService::OPTION_ADAPTERS, $adapters); $this->getServiceManager()->register(FileSystemService::SERVICE_ID, $fs); diff --git a/test/FileSystemMockTrait.php b/test/FileSystemMockTrait.php index b5c95c58b..53d7814da 100644 --- a/test/FileSystemMockTrait.php +++ b/test/FileSystemMockTrait.php @@ -21,7 +21,7 @@ namespace oat\generis\test; -use League\Flysystem\Memory\MemoryAdapter; +use League\Flysystem\InMemory\InMemoryFilesystemAdapter; use oat\oatbox\filesystem\FileSystemService; trait FileSystemMockTrait @@ -30,7 +30,7 @@ protected function getFileSystemMock($dirs = []): FileSystemService { $adapterparam = [ 'testfs' => [ - 'class' => MemoryAdapter::class + 'class' => InMemoryFilesystemAdapter::class ] ]; $dirparam = []; diff --git a/test/integration/common/filesystem/DirectoryFilesystemTest.php b/test/integration/common/filesystem/DirectoryFilesystemTest.php index 5e04b8ddd..f79d7aff0 100644 --- a/test/integration/common/filesystem/DirectoryFilesystemTest.php +++ b/test/integration/common/filesystem/DirectoryFilesystemTest.php @@ -101,7 +101,6 @@ public function testGetFullPathFile() /** * @return bool - * @throws \League\Flysystem\FileExistsException * @throws \common_Exception */ private function generateFile($path) From 810ab968ea49aed9b0ff667f9d9fe3d13c56c3e9 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Tue, 15 Oct 2024 09:12:51 +0200 Subject: [PATCH 07/15] fix: iterator for local filesystems --- common/oatbox/filesystem/Directory.php | 11 +- .../oatbox/filesystem/FileSystemService.php | 2 +- .../filesystem/utils/FlyWrapperTrait.php | 211 ------------------ .../wrapper/GoogleStorageWrapper.php | 193 ---------------- common/oatbox/install/Installer.php | 2 +- 5 files changed, 10 insertions(+), 409 deletions(-) delete mode 100644 common/oatbox/filesystem/utils/FlyWrapperTrait.php delete mode 100644 common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php diff --git a/common/oatbox/filesystem/Directory.php b/common/oatbox/filesystem/Directory.php index 9947d239d..b801cba16 100644 --- a/common/oatbox/filesystem/Directory.php +++ b/common/oatbox/filesystem/Directory.php @@ -87,14 +87,13 @@ public function getFlyIterator($flags = null) $contents = $this->getFileSystem()->listContents($this->getPrefix(), $recursive); if (!empty($contents)) { - $dirPath = $this->getPrefix(); foreach ($contents as $content) { if ($withDirectories && $content['type'] == 'dir') { - $iterator[] = $this->getDirectory(str_replace($dirPath, '', $content['path'])); + $iterator[] = $this->getDirectory($this->stripDirectoryPath($content['path'])); } if ($withFiles && $content['type'] == 'file') { - $iterator[] = $this->getFile(str_replace($dirPath, '', $content['path'])); + $iterator[] = $this->getFile($this->stripDirectoryPath($content['path'])); } } } @@ -207,4 +206,10 @@ public function rename($path) return true; } + + private function stripDirectoryPath(string $path): string + { + $strippedPath = str_replace($this->getPrefix(), '', $path); + return str_replace($this->getFileSystemId(), '', $strippedPath); + } } diff --git a/common/oatbox/filesystem/FileSystemService.php b/common/oatbox/filesystem/FileSystemService.php index a779afc51..41d3365fd 100755 --- a/common/oatbox/filesystem/FileSystemService.php +++ b/common/oatbox/filesystem/FileSystemService.php @@ -152,7 +152,7 @@ public function registerLocalFileSystem($id, $path) $adapters = $this->hasOption(self::OPTION_ADAPTERS) ? $this->getOption(self::OPTION_ADAPTERS) : []; $adapters[$id] = [ 'class' => LocalFilesystemAdapter::class, - 'options' => ['root' => $path] + 'options' => ['location' => $path] ]; $this->setOption(self::OPTION_ADAPTERS, $adapters); return true; diff --git a/common/oatbox/filesystem/utils/FlyWrapperTrait.php b/common/oatbox/filesystem/utils/FlyWrapperTrait.php deleted file mode 100644 index caf7a3498..000000000 --- a/common/oatbox/filesystem/utils/FlyWrapperTrait.php +++ /dev/null @@ -1,211 +0,0 @@ -getAdapter()->write($path, $contents, $config); - - return $this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::writeStream() - */ - public function writeStream($path, $resource, Config $config) - { - $this->getAdapter()->writeStream($path, $resource, $config); - - return $this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::write() - */ - public function update($path, $contents, Config $config) - { - $this->getAdapter()->write($path, $contents, $config); - - return $this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::writeStream() - */ - public function updateStream($path, $resource, Config $config) - { - $this->getAdapter()->writeStream($path, $resource, $config); - - return $this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::rename() - */ - public function rename($path, $newpath, $config = []) - { - $this->getAdapter()->move($path, $newpath, $config); - - return $this->getAdapter()->fileExists($newpath); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::copy() - */ - public function copy($path, $newpath, $config = []) - { - $this->getAdapter()->copy($path, $newpath, $config); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::delete() - */ - public function delete($path) - { - $this->getAdapter()->delete($path); - - return !$this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::deleteDir() - */ - public function deleteDir($dirname) - { - $this->getAdapter()->deleteDirectory($dirname); - - return !$this->getAdapter()->directoryExists($dirname); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::createDir() - */ - public function createDir($dirname, Config $config) - { - $this->getAdapter()->createDirectory($dirname, $config); - - return $this->getAdapter()->directoryExists($dirname); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::setVisibility() - */ - public function setVisibility($path, $visibility) - { - $this->getAdapter()->setVisibility($path, $visibility); - return $this->getAdapter()->visibility($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\ReadInterface::has() - */ - public function has($path) - { - return $this->getAdapter()->fileExists($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::read() - */ - public function read($path) - { - return $this->getAdapter()->read($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::readStream() - */ - public function readStream($path) - { - return $this->getAdapter()->readStream($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::listContents() - */ - public function listContents($directory = '', $recursive = false) - { - return $this->getAdapter()->listContents($directory, $recursive); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::getMetadata() - */ - public function getMetadata($path) - { - $list = iterator_to_array($this->getAdapter()->listContents($path)); - return (array)$list[0]; - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::getSize() - */ - public function getSize($path) - { - return $this->getAdapter()->fileSize($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::getMimetype() - */ - public function getMimetype($path) - { - return $this->getAdapter()->mimeType($path); - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::getTimestamp() - */ - public function getTimestamp($path) - { - $list = iterator_to_array($this->getAdapter()->listContents($path)); - return (array)$list[0]['createdAt'] ?? (array)$list[0]['timestamp']; - } - - /** - * (non-PHPdoc) - * @see \League\Flysystem\FilesystemAdapter::getVisibility() - */ - public function getVisibility($path) - { - return $this->getAdapter()->visibility($path); - } - - /** - * Return the adapter implementation - * - * @return FilesystemAdapter - */ - abstract public function getAdapter(); -} diff --git a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php b/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php deleted file mode 100644 index 1732a2f71..000000000 --- a/common/oatbox/filesystem/wrapper/GoogleStorageWrapper.php +++ /dev/null @@ -1,193 +0,0 @@ -getOption(self::OPTION_CLIENT_CONFIG)); - } - - /** - * @return FilesystemAdapter - */ - public function getAdapter() - { - if (is_null($this->adapter)) { - $client = $this->getClient(); - $bucket = $client->bucket($this->getOption('bucket')); - $adapter = new GoogleCloudStorageAdapter($bucket); - $this->adapter = $adapter; - } - return $this->adapter; - } - - public function fileExists(string $path): bool - { - return $this->getAdapter()->directoryExists($path); - } - - public function directoryExists(string $path): bool - { - return $this->getAdapter()->directoryExists($path); - } - - public function deleteDirectory(string $path): void - { - $this->getAdapter()->deleteDirectory($path); - } - - public function createDirectory(string $location, array $configParams = []): void - { - $config = new Config($configParams); - $this->getAdapter()->createDirectory($location, $config); - } - - public function visibility(string $path): string - { - return $this->getAdapter()->visibility($path)->visibility(); - } - - public function mimeType(string $path): string - { - return $this->getAdapter()->mimeType($path)->mimeType(); - } - - public function lastModified(string $path): int - { - return $this->getAdapter()->lastModified($path)->lastModified(); - } - - public function fileSize(string $path): int - { - return $this->getAdapter()->fileSize($path)->fileSize(); - } - - public function move(string $source, string $destination, array $configParams = []): void - { - $config = new Config($configParams); - $this->getAdapter()->move($source, $destination, $config); - } - - public function __call($name, $arguments) - { - return call_user_func($name, $this->getAdapter(), ...$arguments); - } - - public function has(string $location): bool - { - return $this->getAdapter()->fileExists($location); - } - - public function read(string $location): string - { - return $this->getAdapter()->read($location); - } - - public function readStream(string $location) - { - return $this->getAdapter()->readStream($location); - } - - /** - * @throws UnableToWriteFile - * @throws FilesystemException - */ - public function write(string $location, string $contents, array $config = []): void - { - $this->getAdapter()->write($location, $contents, new Config($config)); - } - - /** - * @param mixed $contents - * - * @throws UnableToWriteFile - * @throws FilesystemException - */ - public function writeStream(string $location, $contents, array $config = []): void - { - $this->getAdapter()->writeStream($location, $contents, new Config($config)); - } - - /** - * @throws UnableToSetVisibility - * @throws FilesystemException - */ - public function setVisibility(string $path, string $visibility): void - { - $this->getAdapter()->setVisibility($path, $visibility); - } - - /** - * @throws UnableToDeleteFile - * @throws FilesystemException - */ - public function delete(string $location): void - { - $this->getAdapter()->delete($location); - } - - /** - * @throws UnableToCopyFile - * @throws FilesystemException - */ - public function copy(string $source, string $destination, array $config = []): void - { - $this->getAdapter()->copy($source, $destination, new Config($config)); - } - - public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing - { - return new DirectoryListing($this->getAdapter()->listContents($location, $deep)); - } -} diff --git a/common/oatbox/install/Installer.php b/common/oatbox/install/Installer.php index ac7f790e3..456ae0902 100755 --- a/common/oatbox/install/Installer.php +++ b/common/oatbox/install/Installer.php @@ -101,7 +101,7 @@ protected function installFilesystem() 'default' => [ 'class' => 'Local', 'options' => [ - 'root' => $this->getOption('file_path') + 'location' => $this->getOption('file_path') ] ], 'memory' => [ From bcc643e90ea874fc634b1ba18508eb21aab2efb9 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Tue, 15 Oct 2024 09:32:00 +0200 Subject: [PATCH 08/15] fix: ci code style --- common/oatbox/filesystem/File.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index e7bc64cf3..d2bf57b39 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -104,8 +104,10 @@ public function write($mixed, $mimeType = null) } $this->getFileSystem()->writeStream($this->getPrefix(), $resource, $config); } else { - throw new \InvalidArgumentException('Value to be written has to be: string, resource or StreamInterface, ' . - '"' . gettype($mixed) . '" given.'); + throw new \InvalidArgumentException(sprintf( + 'Value to be written has to be: string, resource or StreamInterface, "%s" given.', + gettype($mixed) + )); } } catch (FilesystemException $e) { return false; From 59c67651f6b768b9ff079b6b4aa888194f8d53e6 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Tue, 15 Oct 2024 09:47:34 +0200 Subject: [PATCH 09/15] chore: updated updater script --- scripts/update/Updater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update/Updater.php b/scripts/update/Updater.php index 9421ff73d..c8820c800 100644 --- a/scripts/update/Updater.php +++ b/scripts/update/Updater.php @@ -465,7 +465,7 @@ public function update($initialVersion) // override default behavior to ensure an adapter and not a directory is created $adapters['default'] = [ 'class' => LocalFilesystemAdapter::class, - 'options' => ['root' => $fs->getOption(FileSystemService::OPTION_FILE_PATH)] + 'options' => ['location' => $fs->getOption(FileSystemService::OPTION_FILE_PATH)] ]; $fs->setOption(FileSystemService::OPTION_ADAPTERS, $adapters); } else { From 2ea42135e8bc1e13056a15405fcaa1ff4c35e9c0 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Tue, 15 Oct 2024 22:59:04 +0200 Subject: [PATCH 10/15] chore: update ci php version runs --- .github/workflows/continuous-integration.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 7829b6f1f..21e227954 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -14,9 +14,9 @@ jobs: fail-fast: false matrix: operating-system: [ ubuntu-latest ] - php-version: [ '7.4', '8.0', '8.1' ] + php-version: [ '8.1', '8.2', '8.3' ] include: - - php-version: '8.1' + - php-version: '8.3' coverage: true steps: From 6b88264eabf8c48c33d057192a16d2e085a4cbd4 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Fri, 18 Oct 2024 09:49:49 +0200 Subject: [PATCH 11/15] feat: bring back the adapter wrapper --- .../filesystem/utils/FlyWrapperTrait.php | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 common/oatbox/filesystem/utils/FlyWrapperTrait.php diff --git a/common/oatbox/filesystem/utils/FlyWrapperTrait.php b/common/oatbox/filesystem/utils/FlyWrapperTrait.php new file mode 100644 index 000000000..cbbba1e4b --- /dev/null +++ b/common/oatbox/filesystem/utils/FlyWrapperTrait.php @@ -0,0 +1,175 @@ +getAdapter()->write($path, $contents, $config); + } + + /** + * @see FilesystemAdapter::writeStream() + * @inheritDoc + */ + public function writeStream(string $path, $contents, Config $config): void + { + $this->getAdapter()->writeStream($path, $contents, $config); + } + + /** + * @see FilesystemAdapter::move() + * @inheritDoc + */ + public function move(string $source, string $destination, Config $config): void + { + $this->getAdapter()->move($source, $destination, $config); + } + + /** + * @see FilesystemAdapter::copy() + * @inheritDoc + */ + public function copy(string $source, string $destination, Config $config): void + { + $this->getAdapter()->copy($source, $destination, $config); + } + + /** + * @see FilesystemAdapter::delete() + * @inheritDoc + */ + public function delete(string $path): void + { + $this->getAdapter()->delete($path); + } + + /** + * @see FilesystemAdapter::deleteDirectory() + * @inheritDoc + */ + public function deleteDirectory(string $path): void + { + $this->getAdapter()->deleteDirectory($path); + } + + /** + * @see FilesystemAdapter::createDirectory() + * @inheritDoc + */ + public function createDirectory(string $path, Config $config): void + { + $this->getAdapter()->createDirectory($path, $config); + } + + /** + * @see FilesystemAdapter::setVisibility() + * @inheritDoc + */ + public function setVisibility(string $path, string $visibility): void + { + $this->getAdapter()->setVisibility($path, $visibility); + } + + /** + * @see FilesystemAdapter::fileExists() + * @inheritDoc + */ + public function fileExists(string $path): bool + { + return $this->getAdapter()->fileExists($path); + } + + /** + * @see FilesystemAdapter::directoryExists() + * @inheritDoc + */ + public function directoryExists(string $path): bool + { + return $this->getAdapter()->directoryExists($path); + } + + /** + * @see FilesystemAdapter::read() + * @inheritDoc + */ + public function read(string $path): string + { + return $this->getAdapter()->read($path); + } + + /** + * @see FilesystemAdapter::readStream() + * @inheritDoc + */ + public function readStream($path) + { + return $this->getAdapter()->readStream($path); + } + + /** + * @see FilesystemAdapter::listContents() + * @inheritDoc + */ + public function listContents(string $path, bool $deep = false): iterable + { + return $this->getAdapter()->listContents($path, $deep); + } + + /** + * @see FilesystemAdapter::fileSize() + * @inheritDoc + */ + public function fileSize(string $path): FileAttributes + { + return $this->getAdapter()->fileSize($path); + } + + /** + * @see FilesystemAdapter::mimeType() + * @inheritDoc + */ + public function mimeType(string $path): FileAttributes + { + return $this->getAdapter()->mimeType($path); + } + + /** + * @see FilesystemAdapter::lastModified() + * @inheritDoc + */ + public function lastModified(string $path): FileAttributes + { + return $this->getAdapter()->lastModified($path); + } + + /** + * @see FilesystemAdapter::visibility() + * @inheritDoc + */ + public function visibility(string $path): FileAttributes + { + return $this->getAdapter()->visibility($path); + } + + /** + * Return the adapter implementation + * + * @return FilesystemAdapter + */ + abstract public function getAdapter(); +} \ No newline at end of file From 45e5f4778b8575a9129a041111e403343f59b132 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Wed, 23 Oct 2024 10:54:39 +0200 Subject: [PATCH 12/15] feat: create FilesystemInterface and FilesystemException --- common/oatbox/filesystem/Directory.php | 2 - common/oatbox/filesystem/File.php | 1 - common/oatbox/filesystem/FileSystem.php | 2 +- .../oatbox/filesystem/FileSystemService.php | 4 +- .../oatbox/filesystem/FilesystemException.php | 10 ++ .../oatbox/filesystem/FilesystemInterface.php | 10 ++ .../utils/FileSystemWrapperTrait.php | 119 ++++++++++++------ 7 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 common/oatbox/filesystem/FilesystemException.php create mode 100644 common/oatbox/filesystem/FilesystemInterface.php diff --git a/common/oatbox/filesystem/Directory.php b/common/oatbox/filesystem/Directory.php index b801cba16..e61e0046d 100644 --- a/common/oatbox/filesystem/Directory.php +++ b/common/oatbox/filesystem/Directory.php @@ -21,8 +21,6 @@ namespace oat\oatbox\filesystem; -use League\Flysystem\FilesystemException; - class Directory extends FileSystemHandler implements \IteratorAggregate { public const ITERATOR_RECURSIVE = '1'; diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index d2bf57b39..82c36b447 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -23,7 +23,6 @@ use GuzzleHttp\Psr7\Stream; use GuzzleHttp\Psr7\StreamWrapper; -use League\Flysystem\FilesystemException; use Psr\Http\Message\StreamInterface; use tao_helpers_File; diff --git a/common/oatbox/filesystem/FileSystem.php b/common/oatbox/filesystem/FileSystem.php index b58af2d87..de8eb19e5 100644 --- a/common/oatbox/filesystem/FileSystem.php +++ b/common/oatbox/filesystem/FileSystem.php @@ -28,7 +28,7 @@ /** * Class Filesystem */ -class FileSystem implements FilesystemOperator +class FileSystem implements FilesystemInterface { use FileSystemWrapperTrait; diff --git a/common/oatbox/filesystem/FileSystemService.php b/common/oatbox/filesystem/FileSystemService.php index 41d3365fd..66dcebf24 100755 --- a/common/oatbox/filesystem/FileSystemService.php +++ b/common/oatbox/filesystem/FileSystemService.php @@ -97,7 +97,7 @@ public function hasDirectory($id) * Retrieve an existing FileSystem by ID. * * @param string $id - * @return FilesystemOperator + * @return FileSystem * @throws \common_exception_Error * @throws \common_exception_NotFound */ @@ -117,7 +117,7 @@ public function getFileSystem($id) * * @param string $id * @param string $subPath - * @return FilesystemOperator + * @return FileSystem */ public function createFileSystem($id, $subPath = null) { diff --git a/common/oatbox/filesystem/FilesystemException.php b/common/oatbox/filesystem/FilesystemException.php new file mode 100644 index 000000000..0b9ffa4a7 --- /dev/null +++ b/common/oatbox/filesystem/FilesystemException.php @@ -0,0 +1,10 @@ +getFileSystem()->has($this->getFullPath($location)); + return $this->wrapFileSystemOperation(function () use ($location) { + return $this->getFileSystem()->has($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::directoryExists - * @inheritDoc + * @throws FilesystemException */ public function directoryExists(string $location): bool { - return $this->getFileSystem()->directoryExists($this->getFullPath($location)); + return $this->wrapFileSystemOperation(function () use ($location) { + return $this->getFileSystem()->directoryExists($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::read - * @inheritDoc + * @throws FilesystemException */ public function read(string $location): string { - return $this->getFileSystem()->read($this->getFullPath($location)); + return $this->wrapFileSystemOperation(function () use ($location) { + return $this->getFileSystem()->read($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::readStream - * @inheritDoc + * @throws FilesystemException */ public function readStream($path) { - return $this->getFileSystem()->readStream($this->getFullPath($path)); + return $this->wrapFileSystemOperation(function () use ($path) { + return $this->getFileSystem()->readStream($this->getFullPath($path)); + }); } /** * @see FilesystemOperator::listContents - * @inheritDoc + * @throws FilesystemException */ public function listContents(string $location = '', bool $deep = self::LIST_SHALLOW): DirectoryListing { - return $this->getFileSystem()->listContents($this->getFullPath($location), $deep); + return $this->wrapFileSystemOperation(function () use ($location, $deep) { + return $this->getFileSystem()->listContents($this->getFullPath($location), $deep); + }); } /** * @see FilesystemOperator::write - * @inheritDoc + * @throws FilesystemException */ public function write(string $location, string $contents, array $config = []): void { - $this->getFileSystem()->write($this->getFullPath($location), $contents, $config); + $this->wrapFileSystemOperation(function () use ($location, $contents, $config) { + $this->getFileSystem()->write($this->getFullPath($location), $contents, $config); + }); } /** * @see FilesystemOperator::writeStream - * @inheritDoc + * @throws FilesystemException */ public function writeStream(string $location, $contents, array $config = []): void { - $this->getFileSystem()->writeStream($this->getFullPath($location), $contents, $config); + $this->wrapFileSystemOperation(function () use ($location, $contents, $config) { + $this->getFileSystem()->writeStream($this->getFullPath($location), $contents, $config); + }); } /** * @see FilesystemOperator::copy - * @inheritDoc + * @throws FilesystemException */ public function copy(string $source, string $destination, array $config = []): void { - $this->getFileSystem()->copy($this->getFullPath($source), $destination); + $this->wrapFileSystemOperation(function () use ($source, $destination, $config) { + $this->getFileSystem()->copy($this->getFullPath($source), $destination, $config); + }); } /** * @see FilesystemOperator::delete - * @inheritDoc + * @throws FilesystemException */ public function delete(string $location): void { - $this->getFileSystem()->delete($this->getFullPath($location)); + $this->wrapFileSystemOperation(function () use ($location) { + $this->getFileSystem()->delete($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::setVisibility - * @inheritDoc + * @throws FilesystemException */ public function setVisibility(string $path, string $visibility): void { - $this->getFileSystem()->setVisibility($this->getFullPath($path), $visibility); + $this->wrapFileSystemOperation(function () use ($path, $visibility) { + $this->getFileSystem()->setVisibility($this->getFullPath($path), $visibility); + }); } /** * @see FilesystemOperator::fileExists - * @inheritDoc + * @throws FilesystemException */ public function fileExists(string $location): bool { - return $this->getFileSystem()->fileExists($this->getFullPath($location)); + return $this->wrapFileSystemOperation(function () use ($location) { + return $this->getFileSystem()->fileExists($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::lastModified - * @inheritDoc + * @throws FilesystemException */ public function lastModified(string $path): int { - return $this->getFileSystem()->lastModified($this->getFullPath($path)); + return $this->wrapFileSystemOperation(function () use ($path) { + return $this->getFileSystem()->lastModified($this->getFullPath($path)); + }); } /** * @see FilesystemOperator::fileSize - * @inheritDoc + * @throws FilesystemException */ public function fileSize(string $path): int { - return $this->getFileSystem()->fileSize($this->getFullPath($path)); + return $this->wrapFileSystemOperation(function () use ($path) { + return $this->getFileSystem()->fileSize($this->getFullPath($path)); + }); } /** * @see FilesystemOperator::mimeType - * @inheritDoc + * @throws FilesystemException */ public function mimeType(string $path): string { - return $this->getFileSystem()->mimeType($this->getFullPath($path)); + return $this->wrapFileSystemOperation(function () use ($path) { + return $this->getFileSystem()->mimeType($this->getFullPath($path)); + }); } /** * @see FilesystemOperator::visibility - * @inheritDoc + * @throws FilesystemException */ public function visibility(string $path): string { - return $this->getFileSystem()->visibility($this->getFullPath($path)); + return $this->wrapFileSystemOperation(function () use ($path) { + return $this->getFileSystem()->visibility($this->getFullPath($path)); + }); } /** * @see FilesystemOperator::deleteDirectory - * @inheritDoc + * @throws FilesystemException */ public function deleteDirectory(string $location): void { - $this->getFileSystem()->deleteDirectory($this->getFullPath($location)); + $this->wrapFileSystemOperation(function () use ($location) { + $this->getFileSystem()->deleteDirectory($this->getFullPath($location)); + }); } /** * @see FilesystemOperator::createDirectory - * @inheritDoc + * @throws FilesystemException */ public function createDirectory(string $location, array $config = []): void { - $this->getFileSystem()->createDirectory($this->getFullPath($location), $config); + $this->wrapFileSystemOperation(function () use ($location, $config) { + $this->getFileSystem()->createDirectory($this->getFullPath($location), $config); + }); } /** * @see FilesystemOperator::move - * @inheritDoc + * @throws FilesystemException */ public function move(string $source, string $destination, array $config = []): void { - $this->getFileSystem()->move($this->getFullPath($source), $destination, $config); + $this->wrapFileSystemOperation(function () use ($source, $destination, $config) { + $this->getFileSystem()->move($this->getFullPath($source), $destination, $config); + }); + } + + private function wrapFileSystemOperation(callable $operation) + { + try { + return $operation(); + } catch (FlyFilesystemException $e) { + throw new FilesystemException($e->getMessage(), $e->getCode(), $e); + } } abstract protected function getFileSystem(): FilesystemOperator; From 6e33eee92fcfc57be11b2711c05b4b82a723cda5 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Wed, 23 Oct 2024 22:07:18 +0200 Subject: [PATCH 13/15] chore: add error logging --- common/oatbox/filesystem/Directory.php | 1 + common/oatbox/filesystem/File.php | 12 ++++++++++-- common/oatbox/filesystem/FileSystemHandler.php | 4 +++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/common/oatbox/filesystem/Directory.php b/common/oatbox/filesystem/Directory.php index e61e0046d..8af006963 100644 --- a/common/oatbox/filesystem/Directory.php +++ b/common/oatbox/filesystem/Directory.php @@ -138,6 +138,7 @@ public function deleteSelf() $this->getFileSystem()->deleteDirectory($this->getPrefix()); return true; } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index 82c36b447..3167fdecb 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -21,6 +21,7 @@ namespace oat\oatbox\filesystem; +use common_Logger; use GuzzleHttp\Psr7\Stream; use GuzzleHttp\Psr7\StreamWrapper; use Psr\Http\Message\StreamInterface; @@ -53,6 +54,7 @@ public function getMimeType() return $mimeType; } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; } @@ -109,6 +111,7 @@ public function write($mixed, $mimeType = null) )); } } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); return false; } @@ -131,7 +134,7 @@ public function update($mixed, $mimeType = null) throw new \RuntimeException('File "' . $this->getPrefix() . '" not found."'); } - \common_Logger::i('Writing in ' . $this->getPrefix()); + common_Logger::i('Writing in ' . $this->getPrefix()); return $this->write($mixed, $mimeType); } @@ -148,7 +151,7 @@ public function update($mixed, $mimeType = null) */ public function put($mixed, $mimeType = null) { - \common_Logger::i('Writting in ' . $this->getPrefix()); + common_Logger::i('Writting in ' . $this->getPrefix()); return $this->write($mixed, $mimeType); } @@ -163,6 +166,7 @@ public function read() try { return $this->getFileSystem()->read($this->getPrefix()); } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; @@ -178,6 +182,7 @@ public function readStream() try { return $this->getFileSystem()->readStream($this->getPrefix()); } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; @@ -194,6 +199,7 @@ public function readPsrStream() try { $resource = $this->getFileSystem()->readStream($this->getPrefix()); } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return new Stream($resource); @@ -204,6 +210,7 @@ public function exists(): bool try { return $this->getFileSystem()->fileExists($this->getPrefix()); } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; } @@ -214,6 +221,7 @@ public function delete(): bool $this->getFileSystem()->delete($this->getPrefix()); return true; } catch (FilesystemException $e) { + $this->logWarning($e->getMessage()); } return false; diff --git a/common/oatbox/filesystem/FileSystemHandler.php b/common/oatbox/filesystem/FileSystemHandler.php index d9c63f6cd..efc6b310d 100644 --- a/common/oatbox/filesystem/FileSystemHandler.php +++ b/common/oatbox/filesystem/FileSystemHandler.php @@ -22,6 +22,7 @@ namespace oat\oatbox\filesystem; +use oat\oatbox\log\LoggerAwareTrait; use oat\oatbox\service\ServiceManager; use ReflectionClass; use ReflectionProperty; @@ -31,8 +32,9 @@ abstract class FileSystemHandler implements ServiceLocatorAwareInterface { use ServiceLocatorAwareTrait; + use LoggerAwareTrait; - private const NOT_SERIALIZABLE_PROPERTIES = ['fileSystem', 'serviceLocator']; + private const NOT_SERIALIZABLE_PROPERTIES = ['fileSystem', 'serviceLocator', 'logger']; /** * @var mixed From 7ac389812745aaf516d2a310ba2b3cb2b1919f56 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Mon, 4 Nov 2024 09:52:48 +0100 Subject: [PATCH 14/15] fix: only rewind seekable streams --- common/oatbox/filesystem/File.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/common/oatbox/filesystem/File.php b/common/oatbox/filesystem/File.php index 3167fdecb..25f6058c8 100644 --- a/common/oatbox/filesystem/File.php +++ b/common/oatbox/filesystem/File.php @@ -92,10 +92,13 @@ public function write($mixed, $mimeType = null) if (!$mixed->isReadable()) { throw new \common_Exception('Stream is not readable. Write to filesystem aborted.'); } - if (!$mixed->isSeekable()) { - throw new \common_Exception('Stream is not seekable. Write to filesystem aborted.'); + if ($mixed->isSeekable()) { + $mixed->rewind(); + } elseif ($mixed->eof()) { + throw new \common_Exception( + 'Stream is not seekable and is already processed. Write to filesystem aborted.' + ); } - $mixed->rewind(); $resource = StreamWrapper::getResource($mixed); if (!is_resource($resource)) { From 769be7743b0879abc521b58b2faaa9f678c22ddf Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Wed, 27 Nov 2024 11:09:19 +0100 Subject: [PATCH 15/15] chore: style updates for CI --- common/oatbox/filesystem/FilesystemException.php | 2 +- common/oatbox/filesystem/FilesystemInterface.php | 3 +-- common/oatbox/filesystem/utils/FlyWrapperTrait.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/common/oatbox/filesystem/FilesystemException.php b/common/oatbox/filesystem/FilesystemException.php index 0b9ffa4a7..886fb0439 100644 --- a/common/oatbox/filesystem/FilesystemException.php +++ b/common/oatbox/filesystem/FilesystemException.php @@ -7,4 +7,4 @@ class FilesystemException extends RuntimeException implements FlyFilesystemException { -} \ No newline at end of file +} diff --git a/common/oatbox/filesystem/FilesystemInterface.php b/common/oatbox/filesystem/FilesystemInterface.php index 9dc83ed30..e5ec90c18 100644 --- a/common/oatbox/filesystem/FilesystemInterface.php +++ b/common/oatbox/filesystem/FilesystemInterface.php @@ -6,5 +6,4 @@ interface FilesystemInterface extends FilesystemOperator { - -} \ No newline at end of file +} diff --git a/common/oatbox/filesystem/utils/FlyWrapperTrait.php b/common/oatbox/filesystem/utils/FlyWrapperTrait.php index cbbba1e4b..9762620a3 100644 --- a/common/oatbox/filesystem/utils/FlyWrapperTrait.php +++ b/common/oatbox/filesystem/utils/FlyWrapperTrait.php @@ -172,4 +172,4 @@ public function visibility(string $path): FileAttributes * @return FilesystemAdapter */ abstract public function getAdapter(); -} \ No newline at end of file +}