From 02dfb454d55f999dec0f928a13f14c3dc584bf22 Mon Sep 17 00:00:00 2001 From: william <21337627+wfeller@users.noreply.github.com> Date: Fri, 8 Apr 2022 04:08:00 +0200 Subject: [PATCH] Laravel 9 upgrade (#86) * laravel 9 wip - brainmaestro/composer-git-hooks removed until it supports symfony 6 https://github.com/BrainMaestro/composer-git-hooks/issues/123 * wip * comment out cghooks * rename * wip * wip * wip * remove cachedadapter * wip * wip * wip * Update README.md --- .github/workflows/main.yml | 7 +-- .php_cs => .php-cs-fixer.php | 16 ++++--- README.md | 8 +++- composer.json | 21 ++++----- src/Commands/SetCORSHeaders.php | 5 -- src/Commands/SetTempUrlKey.php | 5 -- src/OVHServiceProvider.php | 18 ++------ src/OVHSwiftAdapter.php | 25 +++++----- tests/Functional/CachedAdapterTest.php | 58 ------------------------ tests/Functional/ExpiringObjectsTest.php | 53 +++++++++------------- tests/Functional/UrlGenerationTest.php | 20 ++------ 11 files changed, 66 insertions(+), 170 deletions(-) rename .php_cs => .php-cs-fixer.php (91%) delete mode 100644 tests/Functional/CachedAdapterTest.php diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31e7686..779728d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,11 +6,8 @@ jobs: strategy: fail-fast: true matrix: - php: [7.4, 8.0] - illuminate: [7.*, 8.*] - exclude: - - illuminate: 7.* - php: 8.0 + php: [8.0, 8.1] + illuminate: [9.*] dependency-version: [prefer-stable] name: P${{ matrix.php }} - L${{ matrix.illuminate }} - ${{ matrix.dependency-version }} diff --git a/.php_cs b/.php-cs-fixer.php similarity index 91% rename from .php_cs rename to .php-cs-fixer.php index 2b01fa5..facd71b 100644 --- a/.php_cs +++ b/.php-cs-fixer.php @@ -28,7 +28,7 @@ 'indentation_type' => true, 'linebreak_after_opening_tag' => true, 'lowercase_cast' => true, - 'lowercase_constants' => true, + 'constant_case' => ['case' => 'lower'], 'lowercase_keywords' => true, 'magic_constant_casing' => true, 'method_argument_space' => true, @@ -63,9 +63,11 @@ 'normalize_index_brace' => true, 'not_operator_with_successor_space' => false, 'object_operator_without_whitespace' => true, - 'ordered_imports' => ['sortAlgorithm' => 'alpha'], + 'ordered_imports' => ['sort_algorithm' => 'alpha'], 'phpdoc_indent' => true, - 'phpdoc_inline_tag' => true, + 'general_phpdoc_tag_rename' => true, + 'phpdoc_inline_tag_normalizer' => true, + 'phpdoc_tag_type' => true, 'phpdoc_no_access' => true, 'phpdoc_no_package' => true, 'phpdoc_no_useless_inheritdoc' => true, @@ -78,7 +80,7 @@ 'phpdoc_var_without_name' => true, 'increment_style' => ['style' => 'post'], 'no_mixed_echo_print' => true, - 'psr4' => true, + 'psr_autoloading' => true, 'self_accessor' => true, 'array_syntax' => ['syntax' => 'short'], 'short_scalar_cast' => true, @@ -94,7 +96,7 @@ 'switch_case_semicolon_to_colon' => true, 'switch_case_space' => true, 'ternary_operator_spaces' => true, - 'trailing_comma_in_multiline_array' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'line_ending' => true, @@ -118,8 +120,8 @@ ->ignoreDotFiles(true) ->ignoreVCS(true); -return Config::create() +return (new Config) ->setFinder($finder) ->setRules($rules) ->setRiskyAllowed(true) - ->setUsingCache(true); \ No newline at end of file + ->setUsingCache(true); diff --git a/README.md b/README.md index 437948e..ce9d42a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Also, take note of the upgrade. | `4.x` | `>=7.2` | `>=5.4` | Above + Set private key on container | Deprecated | | `5.x` | `>=7.4` | `>=5.8` | Above + Config-based Expiring Objects + Form Post Signature + Prefix | Maintained | | `6.x` | `>=7.4` | `>=7.x` | PHP 8 support | Active | +| `7.x` | `>=8.0` | `>=9.x` | Laravel 9 support | Active | If you are using Laravel versions older than 5.5, add the service provider to the `providers` array in `config/app.php`: ```php @@ -71,9 +72,10 @@ as below // If you're not willing to DELETE uploaded objects by DEFAULT, leave it empty. // Really, if you don't know what you're doing, you should leave this empty as well. 'deleteAfter' => env('OS_DEFAULT_DELETE_AFTER', null), - + // Optional variable to cache your storage objects in memory // You must require league/flysystem-cached-adapter to enable caching + // This option is not available on laravel-ovh >= 7.0 'cache' => true, // Defaults to false // Optional variable to set a prefix on all paths @@ -118,6 +120,10 @@ file have been renamed to better correspond with the names used by OpenStack in is intended to give the developer a better understanding of the contents of each configuration key. If you're coming from `3.x`, updating the variable names in the `.env` might be essential to prevent failure. +### From 5.x/6.x to 7.x +Starting with `7.x` branch, only Laravel 9 and PHP 8 are supported. The `cache` option should be removed from +your config if you previously used it since Flysystem no longer supports "cached adapters". + # Usage Refer to the extensive [Laravel Storage Documentation](https://laravel.com/docs/7.x/filesystem) for usage. diff --git a/composer.json b/composer.json index fafd68f..6017682 100644 --- a/composer.json +++ b/composer.json @@ -24,18 +24,16 @@ } }, "require": { - "php": "^7.4|^8.0", - "illuminate/console": "^7.0|^8.0", - "illuminate/support": "^7.0|^8.0", - "nimbusoft/flysystem-openstack-swift": "^0.3.3" + "php": "^8.0", + "illuminate/console": "^9.0", + "illuminate/support": "^9.0", + "nimbusoft/flysystem-openstack-swift": "^1.0" }, "require-dev": { "phpunit/phpunit": "^9.5", "mockery/mockery": "^1.3 >= 1.3.1", - "friendsofphp/php-cs-fixer": "^2.18", - "brainmaestro/composer-git-hooks": "^2.8", - "league/flysystem-cached-adapter": "^1.0 >= 1.0.2", - "orchestra/testbench": "^5.0|^6.0" + "friendsofphp/php-cs-fixer": "^3.0", + "orchestra/testbench": "^7.0" }, "extra": { "laravel": { @@ -59,11 +57,11 @@ "scripts": { "post-install-cmd": [ "Sausin\\LaravelOvh\\Composer\\Scripts::devOnly", - "cghooks add --ignore-lock" + "# cghooks add --ignore-lock" ], "post-update-cmd": [ "Sausin\\LaravelOvh\\Composer\\Scripts::devOnly", - "cghooks update" + "# cghooks update" ], "lint": "php-cs-fixer fix", @@ -73,8 +71,5 @@ "@test:lint", "@test:unit" ] - }, - "suggest": { - "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0 >= 1.0.2)." } } diff --git a/src/Commands/SetCORSHeaders.php b/src/Commands/SetCORSHeaders.php index 6b9c484..b6a9e4f 100644 --- a/src/Commands/SetCORSHeaders.php +++ b/src/Commands/SetCORSHeaders.php @@ -7,7 +7,6 @@ use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Storage; use InvalidArgumentException; -use League\Flysystem\Cached\CachedAdapter; use OpenStack\ObjectStore\v1\Models\Container; class SetCORSHeaders extends Command @@ -55,10 +54,6 @@ public function handle(): void $adapter = Storage::disk($disk)->getAdapter(); - if ($adapter instanceof CachedAdapter) { - $adapter = $adapter->getAdapter(); - } - $this->container = $adapter->getContainer(); } catch (InvalidArgumentException $e) { $this->error($e->getMessage()); diff --git a/src/Commands/SetTempUrlKey.php b/src/Commands/SetTempUrlKey.php index 73df631..1a50403 100644 --- a/src/Commands/SetTempUrlKey.php +++ b/src/Commands/SetTempUrlKey.php @@ -7,7 +7,6 @@ use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Storage; use InvalidArgumentException; -use League\Flysystem\Cached\CachedAdapter; use OpenStack\ObjectStore\v1\Models\Container; class SetTempUrlKey extends Command @@ -57,10 +56,6 @@ public function handle(): void $adapter = Storage::disk($disk)->getAdapter(); - if ($adapter instanceof CachedAdapter) { - $adapter = $adapter->getAdapter(); - } - $this->container = $adapter->getContainer(); } catch (InvalidArgumentException $e) { $this->error($e->getMessage()); diff --git a/src/OVHServiceProvider.php b/src/OVHServiceProvider.php index c10a85e..ac5a739 100644 --- a/src/OVHServiceProvider.php +++ b/src/OVHServiceProvider.php @@ -2,11 +2,8 @@ namespace Sausin\LaravelOvh; -use Illuminate\Support\Arr; use Illuminate\Support\Facades\Storage; use Illuminate\Support\ServiceProvider; -use League\Flysystem\Cached\CachedAdapter; -use League\Flysystem\Cached\Storage\Memory as MemoryStore; use League\Flysystem\Filesystem; use OpenStack\ObjectStore\v1\Models\Container; use OpenStack\OpenStack; @@ -47,8 +44,6 @@ protected function configureCommands(): void protected function configureStorage(): void { Storage::extend('ovh', function ($app, array $config) { - $cache = Arr::pull($config, 'cache', false); - // Creates a Configuration instance. $this->config = OVHConfiguration::make($config); @@ -57,7 +52,7 @@ protected function configureStorage(): void // Get the Object Storage container. $container = $client->objectStoreV1()->getContainer($this->config->getContainerName()); - return $this->makeFileSystem($container, $cache); + return $this->makeFileSystem($container); }); } @@ -90,19 +85,12 @@ protected function makeOpenStackClient(): OpenStack * Creates a Filesystem instance for interaction with the Object Storage. * * @param Container $container - * @param bool * @return Filesystem */ - protected function makeFileSystem(Container $container, bool $cache): Filesystem + protected function makeFileSystem(Container $container): Filesystem { - $adapter = new OVHSwiftAdapter($container, $this->config, $this->config->getPrefix()); - - if ($cache) { - $adapter = new CachedAdapter($adapter, new MemoryStore); - } - return new Filesystem( - $adapter, + new OVHSwiftAdapter($container, $this->config, $this->config->getPrefix()), array_filter([ 'swiftLargeObjectThreshold' => $this->config->getSwiftLargeObjectThreshold(), 'swiftSegmentSize' => $this->config->getSwiftSegmentSize(), diff --git a/src/OVHSwiftAdapter.php b/src/OVHSwiftAdapter.php index 9abf817..18f511a 100644 --- a/src/OVHSwiftAdapter.php +++ b/src/OVHSwiftAdapter.php @@ -6,8 +6,9 @@ use DateTimeInterface; use InvalidArgumentException; use League\Flysystem\Config; +use League\Flysystem\UnableToCheckFileExistence; +use League\Flysystem\UnableToReadFile; use Nimbusoft\Flysystem\OpenStack\SwiftAdapter; -use OpenStack\Common\Error\BadResponseError; use OpenStack\ObjectStore\v1\Models\Container; class OVHSwiftAdapter extends SwiftAdapter @@ -24,7 +25,7 @@ class OVHSwiftAdapter extends SwiftAdapter */ public function __construct(Container $container, OVHConfiguration $config, ?string $prefix = null) { - parent::__construct($container, $prefix); + parent::__construct($container, $prefix ?? ''); $this->config = $config; } @@ -49,7 +50,7 @@ protected function getEndpoint(?string $path = null): string ); if (!empty($path)) { - $url .= $this->applyPathPrefix($path); + $url .= $this->prefixer->prefixPath($path); } return $url; @@ -72,15 +73,13 @@ public function getUrl($path) * * @param string $path * @return string - * @throws BadResponseError + * @throws UnableToReadFile|UnableToCheckFileExistence */ public function getUrlConfirm($path): string { // check if object exists - try { - $this->has($path); - } catch (BadResponseError $e) { - throw $e; + if (!$this->fileExists($path)) { + throw UnableToReadFile::fromLocation($path, 'File does not exist.'); } return $this->getEndpoint($path); @@ -114,7 +113,7 @@ public function getTemporaryUrl(string $path, DateTimeInterface $expiresAt, arra '/v1/AUTH_%s/%s/%s', $this->config->getProjectId(), $this->config->getContainerName(), - $this->applyPathPrefix($path) + $this->prefixer->prefixPath($path) ); // Body for the HMAC hash @@ -158,7 +157,7 @@ public function getFormPostSignature(string $path, DateTimeInterface $expiresAt, } // Ensure $path doesn't begin with a slash - $path = $this->applyPathPrefix($path); + $path = $this->prefixer->prefixPath($path); // The url on the OVH host $codePath = sprintf( @@ -193,14 +192,14 @@ public function getContainer(): Container * @return array * @see SwiftAdapter */ - protected function getWriteData($path, $config): array + protected function getWriteData(string $path, Config $config): array { $data = parent::getWriteData($path, $config); - if ($config->has('deleteAfter')) { + if (null !== $config->get('deleteAfter')) { // Apply object expiration timestamp if given $data['deleteAfter'] = $config->get('deleteAfter'); - } elseif ($config->has('deleteAt')) { + } elseif (null !== $config->get('deleteAt')) { // Apply object expiration time if given $data['deleteAt'] = $config->get('deleteAt'); } elseif (!empty($this->config->getDeleteAfter())) { diff --git a/tests/Functional/CachedAdapterTest.php b/tests/Functional/CachedAdapterTest.php deleted file mode 100644 index 950f608..0000000 --- a/tests/Functional/CachedAdapterTest.php +++ /dev/null @@ -1,58 +0,0 @@ -app]) - ->makePartial() - ->shouldAllowMockingProtectedMethods(); - - $serviceProvider - ->shouldReceive('makeOpenStackClient->objectStoreV1->getContainer') - ->with('my-container') - ->andReturn(\Mockery::mock(Container::class)); - - $this->app->register($serviceProvider, true); - - Config::set([ - 'filesystems.disks.ovh.driver' => 'ovh', - 'filesystems.disks.ovh.authUrl' => '', - 'filesystems.disks.ovh.projectId' => 'AwesomeProject', - 'filesystems.disks.ovh.region' => 'TestingGround', - 'filesystems.disks.ovh.userDomain' => 'Default', - 'filesystems.disks.ovh.username' => '', - 'filesystems.disks.ovh.password' => '', - 'filesystems.disks.ovh.container' => 'my-container', // To be removed - 'filesystems.disks.ovh.containerName' => 'my-container', - ]); - } - - public function testOvhDiskIsNotCached() - { - $this->assertInstanceOf(OVHSwiftAdapter::class, Storage::disk('ovh')->getAdapter()); - } - - public function testOvhDiskIsCached() - { - Config::set('filesystems.disks.ovh.cache', true); - - /** @var CachedAdapter $ovhDisk */ - $ovhDisk = Storage::disk('ovh')->getAdapter(); - - $this->assertInstanceOf(CachedAdapter::class, $ovhDisk); - $this->assertInstanceOf(OVHSwiftAdapter::class, $ovhDisk->getAdapter()); - } -} diff --git a/tests/Functional/ExpiringObjectsTest.php b/tests/Functional/ExpiringObjectsTest.php index f56ce3b..94f179b 100644 --- a/tests/Functional/ExpiringObjectsTest.php +++ b/tests/Functional/ExpiringObjectsTest.php @@ -26,17 +26,14 @@ public function testCanBeDeletedAtTimestamp() 'deleteAt' => $deleteAt->getTimestamp(), ])->andReturn($this->object); - $this->flySystemConfig->set('deleteAt', $deleteAt->getTimestamp()); - $response = $this->adapter->write('hello', 'world', $this->flySystemConfig); - - $this->assertEquals([ - 'type' => 'file', - 'dirname' => null, - 'path' => null, - 'timestamp' => null, - 'mimetype' => null, - 'size' => null, - ], $response); + $this->flySystemConfig = $this->flySystemConfig->extend([ + 'deleteAt' => $deleteAt->getTimestamp(), + ]); + + $this->adapter->write('hello', 'world', $this->flySystemConfig); + + // Prevent "no assertion error", we're just checking that the deleteAt is correctly passed to the container + $this->assertTrue(true); } public function testCanBeDeletedAfterSpecificTime() @@ -47,17 +44,14 @@ public function testCanBeDeletedAfterSpecificTime() 'deleteAfter' => 60, ])->andReturn($this->object); - $this->flySystemConfig->set('deleteAfter', 60); - $response = $this->adapter->write('hello', 'world', $this->flySystemConfig); - - $this->assertEquals([ - 'type' => 'file', - 'dirname' => null, - 'path' => null, - 'timestamp' => null, - 'mimetype' => null, - 'size' => null, - ], $response); + $this->flySystemConfig = $this->flySystemConfig->extend([ + 'deleteAfter' => 60, + ]); + + $this->adapter->write('hello', 'world', $this->flySystemConfig); + + // Prevent "no assertion error", we're just checking that the deleteAfter is correctly passed to the container + $this->assertTrue(true); } public function testCanBeDeleteAfterSpecificTimeFromGlobalConfig() @@ -69,15 +63,10 @@ public function testCanBeDeleteAfterSpecificTimeFromGlobalConfig() ])->andReturn($this->object); $this->config->setDeleteAfter(1800); - $response = $this->adapter->write('hello', 'world', $this->flySystemConfig); - - $this->assertEquals([ - 'type' => 'file', - 'dirname' => null, - 'path' => null, - 'timestamp' => null, - 'mimetype' => null, - 'size' => null, - ], $response); + + $this->adapter->write('hello', 'world', $this->flySystemConfig); + + // Prevent "no assertion error", we're just checking that the deleteAfter is correctly passed to the container + $this->assertTrue(true); } } diff --git a/tests/Functional/UrlGenerationTest.php b/tests/Functional/UrlGenerationTest.php index 7774ad6..77e84ef 100644 --- a/tests/Functional/UrlGenerationTest.php +++ b/tests/Functional/UrlGenerationTest.php @@ -30,17 +30,11 @@ public function testCanGenerateUrlOnCustomEndpoint() public function testCanGenerateUrlWithFileConfirmation() { - $this->object->shouldReceive('retrieve')->once(); - $this->object->name = 'hello/world'; - $this->object->lastModified = date('Y-m-d'); - $this->object->contentType = 'mimetype'; - $this->object->contentLength = 1234; - $this->container - ->shouldReceive('getObject') + ->shouldReceive('objectExists') ->once() ->with('hello') - ->andReturn($this->object); + ->andReturnTrue(); $url = $this->adapter->getUrlConfirm('hello'); @@ -51,17 +45,11 @@ public function testCanGenerateUrlWithFileConfirmationOnCustomEndpoint() { $this->config->setEndpoint('http://custom.endpoint'); - $this->object->shouldReceive('retrieve')->once(); - $this->object->name = 'hello/world'; - $this->object->lastModified = date('Y-m-d'); - $this->object->contentType = 'mimetype'; - $this->object->contentLength = 1234; - $this->container - ->shouldReceive('getObject') + ->shouldReceive('objectExists') ->once() ->with('hello') - ->andReturn($this->object); + ->andReturnTrue(); $url = $this->adapter->getUrlConfirm('hello');