From e8ea40f1594a50db249a38c9a9aec05edd0211ed Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 11:54:39 +0100 Subject: [PATCH 01/15] feat: update flysstem adapter --- src/LocalCacheAdapter.php | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index b68cbf3..d1c4d66 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -18,8 +18,10 @@ * */ namespace oat\flysystem\Adapter; -use League\Flysystem\Adapter\AbstractAdapter; + +use League\Flysystem\FilesystemOperator; use League\Flysystem\Config; +use League\Flysystem\Local\LocalFilesystemAdapter; /** * Class LocalCacheAdapter @@ -28,17 +30,17 @@ * * @package oat\flysystem\Adapter */ -class LocalCacheAdapter extends AbstractAdapter +class LocalCacheAdapter extends LocalFilesystemAdapter { /** * remote flysystem adapter - * @var AbstractAdapter + * @var FilesystemOperator */ protected $remoteStorage; /** * local flysystem adapter - * @var AbstractAdapter + * @var FilesystemOperator */ protected $localStorage; @@ -82,13 +84,13 @@ class LocalCacheAdapter extends AbstractAdapter protected $deferedSave = []; /** * DualStorageAdapter constructor. - * @param AbstractAdapter $remoteStorage - * @param AbstractAdapter $localStorage + * @param FilesystemOperator $remoteStorage + * @param FilesystemOperator $localStorage * @param boolean $synchronous true if local cache must to be write immediatly */ public function __construct( - AbstractAdapter $remoteStorage , - AbstractAdapter $localStorage, + FilesystemOperator $remoteStorage , + FilesystemOperator $localStorage, $synchronous = true) { $this->remoteStorage = $remoteStorage; @@ -98,7 +100,7 @@ public function __construct( /** * return remote storage adapter - * @return AbstractAdapter + * @return FilesystemOperator */ public function getRemoteStorage() { return $this->remoteStorage; @@ -106,7 +108,7 @@ public function getRemoteStorage() { /** * return local storage adapter - * @return AbstractAdapter + * @return FilesystemOperator */ public function getLocalStorage() { return $this->localStorage; @@ -430,7 +432,7 @@ public function writeStream($path, $resource, Config $config) */ public function update($path, $contents, Config $config) { - return $this->callOnBoth('update' , [$path, $contents, $config]); + return $this->callOnBoth('write' , [$path, $contents, $config]); } /** @@ -444,7 +446,7 @@ public function update($path, $contents, Config $config) */ public function updateStream($path, $resource, Config $config) { - return $this->callOnBoth('updateStream' , [$path, $resource, $config]); + return $this->callOnBoth('write' , [$path, $resource, $config]); } /** From dc54d597349e49449ea9a5dce9d3c00effb99759 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 11:55:01 +0100 Subject: [PATCH 02/15] chore: update flysystem to version 3 --- composer.json | 128 +++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/composer.json b/composer.json index 1a2eff4..55ffbb5 100644 --- a/composer.json +++ b/composer.json @@ -1,62 +1,70 @@ { - "name" : "oat-sa/lib-flysystem-filecache", - "authors" : [{ - "name" : "Open Assessment Technologies S.A.", - "homepage" : "http://www.taotesting.com" - }, { - "name" : "Jérôme Bogaerts", - "role" : "Developer" - }, { - "name" : "Joel Bout", - "role" : "Developer" - }, { - "name" : "Bertrand Chevrier", - "role" : "Developer" - }, { - "name" : "Lionel Lecaque", - "role" : "Developer" - }, { - "name" : "Patrick Plichart", - "role" : "Developer" - }, { - "name" : "Dieter Raber", - "role" : "Developer" - }, { - "name" : "Somsack Sipasseuth", - "role" : "Developer" - }, { - "name" : "Christophe Garcia", - "role" : "Developer" - } - ], - "description" : "flysystem cache Adapter", - "support" : { - "forum" : "http://forum.taotesting.com", - "issues" : "http://forge.taotesting.com" - }, - "license" : "GPL-2.0-only", - "keywords" : [ - "flysystem", - "oat", - "flysystem adapter", - "cache" - ], - "type" : "library", - "require" : { - "php" : ">=5.5", - "league/flysystem" : "^1.0.25" - }, - - "require-dev": { - "phpunit/phpunit": "~4.4@dev", - "sebastian/global-state": "~1.0@dev", - "mikey179/vfsStream": "1.4.0" - }, - "minimum-stability" : "dev", - "autoload" : { - "psr-4" : { - "oat\\flysystem\\Adapter\\" : "src", - "oat\\libFlysystemFilecache\\test\\" : "test" - } - } + "name": "oat-sa/lib-flysystem-filecache", + "authors": [ + { + "name": "Open Assessment Technologies S.A.", + "homepage": "http://www.taotesting.com" + }, + { + "name": "Jérôme Bogaerts", + "role": "Developer" + }, + { + "name": "Joel Bout", + "role": "Developer" + }, + { + "name": "Bertrand Chevrier", + "role": "Developer" + }, + { + "name": "Lionel Lecaque", + "role": "Developer" + }, + { + "name": "Patrick Plichart", + "role": "Developer" + }, + { + "name": "Dieter Raber", + "role": "Developer" + }, + { + "name": "Somsack Sipasseuth", + "role": "Developer" + }, + { + "name": "Christophe Garcia", + "role": "Developer" + } + ], + "description": "flysystem cache Adapter", + "support": { + "forum": "http://forum.taotesting.com", + "issues": "http://forge.taotesting.com" + }, + "license": "GPL-2.0-only", + "keywords": [ + "flysystem", + "oat", + "flysystem adapter", + "cache" + ], + "type": "library", + "require": { + "php": ">=7.4", + "league/flysystem-memory": "^2.0 || ^3.0" + }, + "require-dev": { + "phpunit/phpunit": "~9|~7", + "sebastian/global-state": "^5.0.5", + "mikey179/vfsstream": "1.4.0" + }, + "minimum-stability": "dev", + "autoload": { + "psr-4": { + "oat\\flysystem\\Adapter\\": "src", + "oat\\libFlysystemFilecache\\test\\": "test" + } + } } From 37e6e23e09a7e8ee96dac143a106e58c3a9292cd Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 11:55:16 +0100 Subject: [PATCH 03/15] fix: test for versio 3 --- test/LocalCacheAdapterTest.php | 48 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index f3d5313..ad8fa88 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -21,8 +21,8 @@ class LocalCacheAdapterTest extends TaoPhpUnitTestRunner public function testConstruct() { - $remoteMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); + $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); $synchronous = true; @@ -59,13 +59,13 @@ public function callWithFallbackProvider() { */ public function testCallWithFallback($method , $args , $localResult , $remoteResult) { - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $localProphet->$method()->withArguments($args)->willReturn($localResult); $localMock = $localProphet->reveal(); $expected = $localResult; - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); if($localResult === false) { $remoteProphet->$method()->withArguments($args)->willReturn($remoteResult); $expected = $remoteResult; @@ -79,8 +79,8 @@ public function testCallWithFallback($method , $args , $localResult , $remoteRes } public function testGetters() { - $remoteMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); + $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); $this->instance = new LocalCacheAdapter($remoteMock , $localMock); @@ -106,8 +106,8 @@ public function synchronousProvider() { */ public function testSetGetSynchronous($value , $expected) { - $remoteMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); + $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); @@ -138,11 +138,11 @@ public function callOnBothProvider() { * @param boolean $remoteResult */ public function testCallOnBoth($method , $args , $localResult , $remoteResult) { - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $localProphet->$method()->withArguments($args)->willReturn($localResult); $localMock = $localProphet->reveal(); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet->$method()->withArguments($args)->willReturn($remoteResult); $expected = $remoteResult; @@ -177,8 +177,8 @@ public function readProvider() { * @param mixed $expected */ public function testRead($path , $localResult , $remoteResult ,$synchronous , $expected) { - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); $this->instance = $this->getMock( @@ -248,8 +248,8 @@ public function readStreamProvider() { * @param mixed $expected */ public function testReadStream($path , $localResult , $remoteResult, $synchronous , $expected) { - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); $this->instance = $this->getMock( @@ -303,8 +303,8 @@ public function testListContents() { 'test3.txt', ]; - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); $localMock = $localProphet->reveal(); @@ -317,8 +317,8 @@ public function testListContents() { public function testInitStream() { - $remoteMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter')->reveal(); + $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); @@ -346,8 +346,8 @@ public function testWriteStream() { 'remote' ]; - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); $remoteProphet->writeStream($path , $file , $config)->willReturn($returnDist); @@ -375,8 +375,8 @@ public function testSetConfigFromResult() { 'size' => 180, ]; - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); @@ -414,8 +414,8 @@ public function testDestructor() { ], ]; - $localProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Adapter\AbstractAdapter'); + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); From 0f3746610c5b2a0ccbb662914795d4f5d9f135d0 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 13:15:17 +0100 Subject: [PATCH 04/15] fix: use proper method for stream write --- src/LocalCacheAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index d1c4d66..1293ff4 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -446,7 +446,7 @@ public function update($path, $contents, Config $config) */ public function updateStream($path, $resource, Config $config) { - return $this->callOnBoth('write' , [$path, $resource, $config]); + return $this->callOnBoth('writeStream' , [$path, $resource, $config]); } /** From a81f9e3ed0605aeb21002c38638e69dbf428caf9 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 13:45:11 +0100 Subject: [PATCH 05/15] fix: correct interface dependency --- src/LocalCacheAdapter.php | 219 ++++++------ test/LocalCacheAdapterTest.php | 585 +++++++++++++++++++-------------- 2 files changed, 444 insertions(+), 360 deletions(-) diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 1293ff4..045ccdd 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -17,8 +17,10 @@ * Copyright (c) 2016-2017 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); * */ + namespace oat\flysystem\Adapter; +use League\Flysystem\FilesystemAdapter; use League\Flysystem\FilesystemOperator; use League\Flysystem\Config; use League\Flysystem\Local\LocalFilesystemAdapter; @@ -43,27 +45,27 @@ class LocalCacheAdapter extends LocalFilesystemAdapter * @var FilesystemOperator */ protected $localStorage; - + /** * true if local cache must to be write immediatly * if false, cache is writing on destructor - * + * * Only implemented for read operation - * - * @var boolean + * + * @var boolean */ protected $synchronous; - + /** * list of required local config entry * @var array */ protected $requiredConfig = [ - 'mimetype' => 'getMimetype', - 'size' => 'getSize', + 'mimetype' => 'getMimetype', + 'size' => 'getSize', 'visibility' => 'getVisibility', ]; - + /** * Whether or not caching results of method listContents. * @var array @@ -81,56 +83,61 @@ class LocalCacheAdapter extends LocalFilesystemAdapter * array to store local file to write on destructor * @var array */ - protected $deferedSave = []; + protected $deferedSave = []; + /** * DualStorageAdapter constructor. - * @param FilesystemOperator $remoteStorage - * @param FilesystemOperator $localStorage + * @param FilesystemAdapter $remoteStorage + * @param FilesystemAdapter $localStorage * @param boolean $synchronous true if local cache must to be write immediatly */ public function __construct( - FilesystemOperator $remoteStorage , - FilesystemOperator $localStorage, - $synchronous = true) - { + FilesystemAdapter $remoteStorage, + FilesystemAdapter $localStorage, + $synchronous = true + ) { $this->remoteStorage = $remoteStorage; - $this->localStorage = $localStorage; - $this->synchronous = boolval($synchronous); + $this->localStorage = $localStorage; + $this->synchronous = boolval($synchronous); } - + /** * return remote storage adapter * @return FilesystemOperator */ - public function getRemoteStorage() { + public function getRemoteStorage() + { return $this->remoteStorage; } - + /** * return local storage adapter * @return FilesystemOperator */ - public function getLocalStorage() { + public function getLocalStorage() + { return $this->localStorage; } - + /** * return autosave value * @return boolean */ - public function getSynchronous() { + public function getSynchronous() + { return $this->synchronous; } - + /** * change auto save value * @param boolean $synchronous */ - public function setSynchronous($synchronous) { + public function setSynchronous($synchronous) + { $this->synchronous = boolval($synchronous); return $this; } - + /** * return cacheListContents value * @return boolean @@ -139,7 +146,7 @@ public function getCacheListContents() { return $this->cacheListContents; } - + /** * change cacheListContents value * @param boolean $cacheListContents @@ -184,7 +191,7 @@ public function has($path) return json_decode($data['contents']); } else { // Not in cache, cache it! - $hasVal = $this->callWithFallback('has' , [$path]); + $hasVal = $this->callWithFallback('has', [$path]); $this->localStorage->write( $cachePath, @@ -195,7 +202,7 @@ public function has($path) return $hasVal; } } else { - return $this->callWithFallback('has' , [$path]); + return $this->callWithFallback('has', [$path]); } } @@ -211,17 +218,17 @@ private function isPathDir($path) * * @return array|false */ - public function read($path) + public function read($path): string { - if(($result = $this->localStorage->has($path)) !== false) { + if (($result = $this->localStorage->has($path)) !== false) { return $this->localStorage->read($path); } $result = $this->remoteStorage->read($path); - if($result !== false) { - if($this->synchronous) { + if ($result !== false) { + if ($this->synchronous) { $config = $this->setConfigFromResult($result); - $this->localStorage->write($path , $result['contents'] , $config); - } elseif($result !== false) { + $this->localStorage->write($path, $result['contents'], $config); + } elseif ($result !== false) { $this->deferedSave[] = $result; } } @@ -237,21 +244,21 @@ public function read($path) */ public function readStream($path) { - if(($result = $this->localStorage->has($path)) !== false) { + if (($result = $this->localStorage->has($path)) !== false) { $result = $this->localStorage->readStream($path); - if(is_resource($result['stream'])) { + if (is_resource($result['stream'])) { return $result; } } $result = $this->remoteStorage->readStream($path); - if($result !== false ) { - if($this->synchronous) { + if ($result !== false) { + if ($this->synchronous) { $resource = $result['stream']; $config = $this->setConfigFromResult($result); - $result = $this->localStorage->writeStream($path , $resource , $config); + $result = $this->localStorage->writeStream($path, $resource, $config); fclose($resource); $result = $this->localStorage->readStream($path); - } elseif($result !== false) { + } elseif ($result !== false) { $this->deferedSave[] = $result; } } @@ -266,23 +273,25 @@ public function readStream($path) * * @return array */ - public function listContents($directory = '', $recursive = false) + public function listContents($directory = '', $recursive = false): iterable { $contentList = []; - + if ($this->getCacheListContents() === false) { // No caching for listContents method calls. - $contentList = $this->remoteStorage->listContents($directory , $recursive); + $contentList = $this->remoteStorage->listContents($directory, $recursive); } else { // Caching enabled for listContents method calls. $expectedPath = $this->getListContentsCacheExpectedPath($directory, $recursive); - - if ($this->localStorage->has($expectedPath) && ($data = $this->localStorage->read($expectedPath)) !== false) { + + if ($this->localStorage->has($expectedPath) && ($data = $this->localStorage->read( + $expectedPath + )) !== false) { // In cache. $contentList = json_decode($data['contents'], true); } else { // Not in cache or could not be read. - $contentList = $this->remoteStorage->listContents($directory , $recursive); + $contentList = $this->remoteStorage->listContents($directory, $recursive); $this->localStorage->write( $expectedPath, json_encode($contentList), @@ -290,15 +299,15 @@ public function listContents($directory = '', $recursive = false) ); } } - + return $contentList; } - + /** * Get List Contents Expected Cache Path - * + * * Provides the final path where to find cached data about a given listContents call. - * + * * @param string $directory * @param boolean $recursive * @return string @@ -307,7 +316,7 @@ protected function getListContentsCacheExpectedPath($directory, $recursive) { $key = $this->buildCacheKey($this->localStorage->getPathPrefix() . $directory . strval($recursive)); $expectedPath = ".oat-lib-flysystem-cache/list-contents-cache/${key}.json"; - + return $expectedPath; } @@ -340,7 +349,7 @@ private function buildCacheKey($origin) */ public function getMetadata($path) { - return $this->callWithFallback('getMetadata' , [$path]); + return $this->callWithFallback('getMetadata', [$path]); } /** @@ -352,7 +361,7 @@ public function getMetadata($path) */ public function getSize($path) { - return $this->callWithFallback('getSize' , [$path]); + return $this->callWithFallback('getSize', [$path]); } /** @@ -364,7 +373,7 @@ public function getSize($path) */ public function getMimetype($path) { - return $this->callWithFallback('getMimetype' , [$path]); + return $this->callWithFallback('getMimetype', [$path]); } /** @@ -376,7 +385,7 @@ public function getMimetype($path) */ public function getTimestamp($path) { - return $this->callWithFallback('getTimestamp' , [$path]); + return $this->callWithFallback('getTimestamp', [$path]); } /** @@ -388,7 +397,7 @@ public function getTimestamp($path) */ public function getVisibility($path) { - return $this->callWithFallback('getVisibility' , [$path]); + return $this->callWithFallback('getVisibility', [$path]); } /** @@ -400,9 +409,9 @@ public function getVisibility($path) * * @return array|false false on failure file meta data on success */ - public function write($path, $contents, Config $config) + public function write($path, $contents, Config $config): void { - return $this->callOnBoth('write' , [$path, $contents, $config]); + $this->callOnBoth('write', [$path, $contents, $config]); } /** @@ -414,11 +423,10 @@ public function write($path, $contents, Config $config) * * @return array|false false on failure file meta data on success */ - public function writeStream($path, $resource, Config $config) - { - $result = $this->remoteStorage->writeStream($path, $resource, $config); + public function writeStream($path, $resource, Config $config): void + { + $this->remoteStorage->writeStream($path, $resource, $config); $this->localStorage->writeStream($path, $this->initStream($resource), $config); - return $result; } /** @@ -432,7 +440,7 @@ public function writeStream($path, $resource, Config $config) */ public function update($path, $contents, Config $config) { - return $this->callOnBoth('write' , [$path, $contents, $config]); + return $this->callOnBoth('write', [$path, $contents, $config]); } /** @@ -444,9 +452,9 @@ public function update($path, $contents, Config $config) * * @return array|false false on failure file meta data on success */ - public function updateStream($path, $resource, Config $config) + public function updateStream($path, $resource, Config $config) { - return $this->callOnBoth('writeStream' , [$path, $resource, $config]); + return $this->callOnBoth('writeStream', [$path, $resource, $config]); } /** @@ -459,20 +467,21 @@ public function updateStream($path, $resource, Config $config) */ public function rename($path, $newpath) { - return $this->callOnBoth('rename' , [$path, $newpath]); + return $this->callOnBoth('rename', [$path, $newpath]); } /** * Copy a file. * - * @param string $path - * @param string $newpath + * @param string $source + * @param string $destination + * @param Config $config * * @return bool */ - public function copy($path, $newpath) + public function copy(string $source, string $destination, Config $config): void { - return $this->callOnBoth('rename' , [$path, $newpath]); + $this->callOnBoth('copy', [$source, $destination, $config]); } /** @@ -482,9 +491,9 @@ public function copy($path, $newpath) * * @return bool */ - public function delete($path) + public function delete($path): void { - return $this->callOnBoth('delete' , [$path]); + $this->callOnBoth('delete', [$path]); } /** @@ -496,7 +505,7 @@ public function delete($path) */ public function deleteDir($dirname) { - return $this->callOnBoth('deleteDir' , [$dirname]); + return $this->callOnBoth('deleteDir', [$dirname]); } /** @@ -509,7 +518,7 @@ public function deleteDir($dirname) */ public function createDir($dirname, Config $config) { - return $this->callOnBoth('createDir' , [$dirname , $config]); + return $this->callOnBoth('createDir', [$dirname, $config]); } /** @@ -520,9 +529,9 @@ public function createDir($dirname, Config $config) * * @return array|false file meta data */ - public function setVisibility($path, $visibility) + public function setVisibility($path, $visibility): void { - return $this->callOnBoth('setVisibility' , [$path, $visibility]); + $this->callOnBoth('setVisibility', [$path, $visibility]); } /** @@ -536,20 +545,19 @@ public function setVisibility($path, $visibility) */ protected function callWithFallback($method, array $args = []) { - - try { - $result = call_user_func_array([$this->localStorage , $method] , $args); + try { + $result = call_user_func_array([$this->localStorage, $method], $args); } catch (\Exception $e) { $result = false; } if ($result !== false) { return $result; } - return call_user_func_array([$this->remoteStorage , $method] , $args); - + return call_user_func_array([$this->remoteStorage, $method], $args); } - - protected function initStream($resource) { + + protected function initStream($resource) + { rewind($resource); return $resource; } @@ -560,23 +568,24 @@ protected function initStream($resource) { * @param $method * @param array $args * @return mixed - */ - protected function callOnBoth($method, array $args = []) { - - call_user_func_array([$this->localStorage , $method] , $args); - return call_user_func_array([$this->remoteStorage , $method] , $args); + */ + protected function callOnBoth($method, array $args = []) + { + call_user_func_array([$this->localStorage, $method], $args); + return call_user_func_array([$this->remoteStorage, $method], $args); } - + /** - * set local config from remote read Result or - * from file metadata has allback - * @param array $result - * @return Config - */ - protected function setConfigFromResult(array $result) { + * set local config from remote read Result or + * from file metadata has allback + * @param array $result + * @return Config + */ + protected function setConfigFromResult(array $result) + { $config = new Config(); foreach ($this->requiredConfig as $param => $method) { - if(array_key_exists($param, $result)) { + if (array_key_exists($param, $result)) { $config->set($param, $result[$param]); } else { $params = $this->remoteStorage->$method($result['path']); @@ -584,19 +593,19 @@ protected function setConfigFromResult(array $result) { } } return $config; - } /** - * do defered write operations - */ - public function __destruct() { + * do defered write operations + */ + public function __destruct() + { foreach ($this->deferedSave as $index => $write) { $config = $this->setConfigFromResult($write); - if(array_key_exists('stream', $write) && is_resource($write['stream'])) { - $this->localStorage->writeStream($write['path'] , $this->initStream($write['stream']) , $config); - } elseif(array_key_exists('contents', $write)) { - $this->localStorage->write($write['path'] , $write['contents'] , $config); + if (array_key_exists('stream', $write) && is_resource($write['stream'])) { + $this->localStorage->writeStream($write['path'], $this->initStream($write['stream']), $config); + } elseif (array_key_exists('contents', $write)) { + $this->localStorage->write($write['path'], $write['contents'], $config); } unset($this->deferedSave[$index]); } diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index ad8fa88..1f58338 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -19,156 +19,203 @@ class LocalCacheAdapterTest extends TaoPhpUnitTestRunner */ protected $instance; - public function testConstruct() { - + public function testConstruct() + { $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); - - $synchronous = true; - - $this->instance = new LocalCacheAdapter($remoteMock , $localMock , $synchronous); - + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + + $synchronous = true; + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock, $synchronous); + $this->assertSame($remoteMock, $this->getInaccessibleProperty($this->instance, 'remoteStorage')); $this->assertSame($localMock, $this->getInaccessibleProperty($this->instance, 'localStorage')); $this->assertSame($synchronous, $this->getInaccessibleProperty($this->instance, 'synchronous')); - } - public function callWithFallbackProvider() { + public function callWithFallbackProvider() + { return [ [ - 'has' , ['/path/test1'] , true, false + 'has', + ['/path/test1'], + true, + false, ], [ - 'getTimestamp' , ['/path/test1'] , false, false + 'getTimestamp', + ['/path/test1'], + false, + false, ], [ - 'getMetadata' , ['/path/test1'] , false, true + 'getMetadata', + ['/path/test1'], + false, + true, ], ]; - } /** * @dataProvider callWithFallbackProvider * @param string $method - * @param array $args + * @param array $args * @param boolean $localResult * @param boolean $remoteResult */ - public function testCallWithFallback($method , $args , $localResult , $remoteResult) { - + public function testCallWithFallback($method, $args, $localResult, $remoteResult) + { $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $localProphet->$method()->withArguments($args)->willReturn($localResult); - $localMock = $localProphet->reveal(); + $localMock = $localProphet->reveal(); - $expected = $localResult; + $expected = $localResult; $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - if($localResult === false) { + if ($localResult === false) { $remoteProphet->$method()->withArguments($args)->willReturn($remoteResult); $expected = $remoteResult; } $remoteMock = $remoteProphet->reveal(); - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); - - $this->assertSame($expected , $this->invokeProtectedMethod($this->instance , 'callWithFallback' , [$method , $args])); + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); + $this->assertSame( + $expected, + $this->invokeProtectedMethod($this->instance, 'callWithFallback', [$method, $args]) + ); } - - public function testGetters() { + + public function testGetters() + { $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); - $this->instance = new LocalCacheAdapter($remoteMock , $localMock); - $this->assertSame($remoteMock, $this->instance->getRemoteStorage()); $this->assertSame($localMock, $this->instance->getLocalStorage()); } - - public function synchronousProvider() { - return + + public function synchronousProvider() + { + return [ - [true , true], - [false , false], - [0 , false], - [1 , true], - ['0' , false], - ['1' , true], + [true, true], + [false, false], + [0, false], + [1, true], + ['0', false], + ['1', true], ]; } + /** * @dataProvider synchronousProvider * @param type $value * @param type $expected */ - public function testSetGetSynchronous($value , $expected) { - + public function testSetGetSynchronous($value, $expected) + { $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); - $this->assertSame($this->instance, $this->instance->setSynchronous($value)); $this->assertSame($expected, $this->instance->getSynchronous()); } - - public function callOnBothProvider() { + + public function callOnBothProvider() + { return [ [ - 'has' , ['/path/test1'] , true, false + 'has', + ['/path/test1'], + true, + false, ], [ - 'getTimestamp' , ['/path/test1'] , false, false + 'getTimestamp', + ['/path/test1'], + false, + false, ], [ - 'getMetadata' , ['/path/test1'] , false, true + 'getMetadata', + ['/path/test1'], + false, + true, ], ]; - } + /** * @dataProvider callOnBothProvider * @param string $method - * @param array $args + * @param array $args * @param boolean $localResult * @param boolean $remoteResult */ - public function testCallOnBoth($method , $args , $localResult , $remoteResult) { + public function testCallOnBoth($method, $args, $localResult, $remoteResult) + { $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $localProphet->$method()->withArguments($args)->willReturn($localResult); - $localMock = $localProphet->reveal(); + $localMock = $localProphet->reveal(); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet->$method()->withArguments($args)->willReturn($remoteResult); $expected = $remoteResult; - + $remoteMock = $remoteProphet->reveal(); - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); - - $this->assertSame($expected , $this->invokeProtectedMethod($this->instance , 'callOnBoth' , [$method , $args])); + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); + + $this->assertSame($expected, $this->invokeProtectedMethod($this->instance, 'callOnBoth', [$method, $args])); } - - public function readProvider() { - - return - [ - ['test1.txt' , ['path' => 'test1.txt' ,'contents' => 'test1'], false , true ,['path' => 'test1.txt', 'contents' => 'test1']], - ['test2.txt' , false , ['path' => 'test2.txt' ,'contents' => 'test2'], true ,['path' => 'test2.txt', 'contents' => 'test2']], - ['test2.txt' , false , false , true ,false], - ['test1.txt' , ['path' => 'test1.txt' ,'contents' => 'test1'], false , false ,['path' => 'test1.txt', 'contents' => 'test1']], - ['test2.txt' , false , ['path' => 'test2.txt' ,'contents' => 'test2'], false ,['path' => 'test2.txt', 'contents' => 'test2']], - ['test2.txt' , false , false , false ,false], - ]; - + + public function readProvider() + { + return + [ + [ + 'test1.txt', + ['path' => 'test1.txt', 'contents' => 'test1'], + false, + true, + ['path' => 'test1.txt', 'contents' => 'test1'], + ], + [ + 'test2.txt', + false, + ['path' => 'test2.txt', 'contents' => 'test2'], + true, + ['path' => 'test2.txt', 'contents' => 'test2'], + ], + ['test2.txt', false, false, true, false], + [ + 'test1.txt', + ['path' => 'test1.txt', 'contents' => 'test1'], + false, + false, + ['path' => 'test1.txt', 'contents' => 'test1'], + ], + [ + 'test2.txt', + false, + ['path' => 'test2.txt', 'contents' => 'test2'], + false, + ['path' => 'test2.txt', 'contents' => 'test2'], + ], + ['test2.txt', false, false, false, false], + ]; } - /** + /** * @dataProvider readProvider * @param string $path * @param array|boolean $localResult @@ -176,271 +223,299 @@ public function readProvider() { * @param boolean $synchronous * @param mixed $expected */ - public function testRead($path , $localResult , $remoteResult ,$synchronous , $expected) { - $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + public function testRead($path, $localResult, $remoteResult, $synchronous, $expected) + { + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $config = $this->prophesize('League\Flysystem\Config')->reveal(); - + $config = $this->prophesize('League\Flysystem\Config')->reveal(); + $this->instance = $this->getMock( - 'oat\flysystem\Adapter\LocalCacheAdapter' , - ['setConfigFromResult'], - [], - '', - false - ); - - + 'oat\flysystem\Adapter\LocalCacheAdapter', + ['setConfigFromResult'], + [], + '', + false + ); + + $localProphet->has($path)->willReturn($localResult); - - if($localResult === false) { + + if ($localResult === false) { $remoteProphet->read($path)->willReturn($remoteResult); } else { $localProphet->read($path)->willReturn($localResult); } - + $expectedSave = []; - - if($remoteResult !== false && $synchronous) { + + if ($remoteResult !== false && $synchronous) { $this->instance->expects($this->once())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - - $localProphet->write($path , $remoteResult['contents'] , $config)->willReturn($remoteResult); - - - } elseif($remoteResult !== false) { - $expectedSave[] = $remoteResult; + + $localProphet->write($path, $remoteResult['contents'], $config)->willReturn($remoteResult); + } elseif ($remoteResult !== false) { + $expectedSave[] = $remoteResult; } - - $localMock = $localProphet->reveal(); - $remoteMock = $remoteProphet->reveal(); - + + $localMock = $localProphet->reveal(); + $remoteMock = $remoteProphet->reveal(); + $this->setInaccessibleProperty($this->instance, 'remoteStorage', $remoteMock); $this->setInaccessibleProperty($this->instance, 'localStorage', $localMock); $this->setInaccessibleProperty($this->instance, 'synchronous', $synchronous); - - $this->assertSame($expected , $this->instance->read($path)); - $this->assertSame($expectedSave , $this->getInaccessibleProperty($this->instance, 'deferedSave')); - $this->setInaccessibleProperty($this->instance, 'deferedSave' , []); + + $this->assertSame($expected, $this->instance->read($path)); + $this->assertSame($expectedSave, $this->getInaccessibleProperty($this->instance, 'deferedSave')); + $this->setInaccessibleProperty($this->instance, 'deferedSave', []); } - - public function readStreamProvider() { - + + public function readStreamProvider() + { $tmp1 = tmpfile(); $tmp2 = tmpfile(); - - return - [ - ['test1.txt' , ['path' => 'test1.txt','stream' => $tmp1], false , true , ['path' => 'test1.txt', 'stream' => $tmp1]], - ['test2.txt' , false , ['path' => 'test2.txt' , 'stream' => $tmp2], true , ['path' => 'test2.txt', 'stream' => $tmp2]], - ['test3.txt' , false , false , true , false], - ['test1.txt' , ['path' => 'test1.txt','stream' => $tmp1], false , false , ['path' => 'test1.txt', 'stream' => $tmp1]], - ['test2.txt' , false , ['path' => 'test2.txt' , 'stream' => $tmp2], false , ['path' => 'test2.txt', 'stream' => $tmp2]], - ['test3.txt' , false , false , false , false], - ]; - + + return + [ + [ + 'test1.txt', + ['path' => 'test1.txt', 'stream' => $tmp1], + false, + true, + ['path' => 'test1.txt', 'stream' => $tmp1], + ], + [ + 'test2.txt', + false, + ['path' => 'test2.txt', 'stream' => $tmp2], + true, + ['path' => 'test2.txt', 'stream' => $tmp2], + ], + ['test3.txt', false, false, true, false], + [ + 'test1.txt', + ['path' => 'test1.txt', 'stream' => $tmp1], + false, + false, + ['path' => 'test1.txt', 'stream' => $tmp1], + ], + [ + 'test2.txt', + false, + ['path' => 'test2.txt', 'stream' => $tmp2], + false, + ['path' => 'test2.txt', 'stream' => $tmp2], + ], + ['test3.txt', false, false, false, false], + ]; } - /** + /** * @dataProvider readStreamProvider * @param string $path * @param array|boolean $localResult * @param array|boolean $remoteResult * @param mixed $expected */ - public function testReadStream($path , $localResult , $remoteResult, $synchronous , $expected) { + public function testReadStream($path, $localResult, $remoteResult, $synchronous, $expected) + { $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $config = $this->prophesize('League\Flysystem\Config')->reveal(); - + $config = $this->prophesize('League\Flysystem\Config')->reveal(); + $this->instance = $this->getMock( - 'oat\flysystem\Adapter\LocalCacheAdapter' , - ['setConfigFromResult'], - [], - '', - false - ); - + 'oat\flysystem\Adapter\LocalCacheAdapter', + ['setConfigFromResult'], + [], + '', + false + ); + $localProphet->has($path)->willReturn($localResult); - + $expectedSave = []; - - if($localResult === false) { + + if ($localResult === false) { $remoteProphet->readStream($path)->willReturn($remoteResult); } else { $localProphet->readStream($path)->willReturn($localResult); } - - if($remoteResult !== false && $synchronous) { + + if ($remoteResult !== false && $synchronous) { $this->instance->expects($this->once())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - $localProphet->writeStream($path , $remoteResult['stream'] , $config)->willReturn($remoteResult); + $localProphet->writeStream($path, $remoteResult['stream'], $config)->willReturn($remoteResult); $localProphet->readStream($path)->willReturn($remoteResult); - } elseif($remoteResult !== false) { - $expectedSave[] = $remoteResult; + } elseif ($remoteResult !== false) { + $expectedSave[] = $remoteResult; } - - $localMock = $localProphet->reveal(); - $remoteMock = $remoteProphet->reveal(); - + + $localMock = $localProphet->reveal(); + $remoteMock = $remoteProphet->reveal(); + $this->setInaccessibleProperty($this->instance, 'remoteStorage', $remoteMock); $this->setInaccessibleProperty($this->instance, 'localStorage', $localMock); $this->setInaccessibleProperty($this->instance, 'synchronous', $synchronous); - - $this->assertEquals($expected , $this->instance->readStream($path)); - $this->assertSame($expectedSave , $this->getInaccessibleProperty($this->instance, 'deferedSave')); - $this->setInaccessibleProperty($this->instance, 'deferedSave' , []); + + $this->assertEquals($expected, $this->instance->readStream($path)); + $this->assertSame($expectedSave, $this->getInaccessibleProperty($this->instance, 'deferedSave')); + $this->setInaccessibleProperty($this->instance, 'deferedSave', []); } - - public function testListContents() { - + + public function testListContents() + { $fixtureDirectory = '/tmp'; $fixtureRecursive = false; - - $fixtureList = - [ - 'test1.txt', - 'test2.txt', - 'test3.txt', - ]; - - $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $config = $this->prophesize('League\Flysystem\Config')->reveal(); - - $localMock = $localProphet->reveal(); - $remoteProphet->listContents($fixtureDirectory , $fixtureRecursive)->willReturn($fixtureList); - $remoteMock = $remoteProphet->reveal(); - - $this->instance = new LocalCacheAdapter($remoteMock , $localMock , $config); - $this->assertSame($fixtureList , $this->instance->listContents($fixtureDirectory , $fixtureRecursive)); + + $fixtureList = + [ + 'test1.txt', + 'test2.txt', + 'test3.txt', + ]; + + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); + $config = $this->prophesize('League\Flysystem\Config')->reveal(); + + $localMock = $localProphet->reveal(); + $remoteProphet->listContents($fixtureDirectory, $fixtureRecursive)->willReturn($fixtureList); + $remoteMock = $remoteProphet->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock, $config); + $this->assertSame($fixtureList, $this->instance->listContents($fixtureDirectory, $fixtureRecursive)); } - - public function testInitStream() { - + + public function testInitStream() + { $remoteMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); - $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + $localMock = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter')->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); - $fixtureStream = tmpfile(); fputs($fixtureStream, 'test1' . "\n" . 'test2'); fread($fixtureStream, 10); - $this->assertSame($fixtureStream, $this->invokeProtectedMethod($this->instance, 'initStream' , [$fixtureStream])); + $this->assertSame( + $fixtureStream, + $this->invokeProtectedMethod($this->instance, 'initStream', [$fixtureStream]) + ); $this->assertSame(0, ftell($fixtureStream)); } - - public function testWriteStream() { - + + public function testWriteStream() + { $file = tmpfile(); $path = 'test1.txt'; - + $returnLocal = [ - 'path' => $path, + 'path' => $path, 'stream' => $file, - 'local' + 'local', ]; - + $returnDist = [ - 'path' => $path, + 'path' => $path, 'stream' => $file, - 'remote' + 'remote', ]; - + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $config = $this->prophesize('League\Flysystem\Config')->reveal(); - - $remoteProphet->writeStream($path , $file , $config)->willReturn($returnDist); - $localProphet->writeStream($path , $file , $config)->willReturn($returnLocal); - - $localMock = $localProphet->reveal(); - $remoteMock = $remoteProphet->reveal(); - - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); - $this->assertSame($returnDist , $this->instance->writeStream($path , $file , $config)); + $config = $this->prophesize('League\Flysystem\Config')->reveal(); + + $remoteProphet->writeStream($path, $file, $config)->willReturn($returnDist); + $localProphet->writeStream($path, $file, $config)->willReturn($returnLocal); + + $localMock = $localProphet->reveal(); + $remoteMock = $remoteProphet->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); + $this->assertSame($returnDist, $this->instance->writeStream($path, $file, $config)); } - - public function testSetConfigFromResult() { - - $fixtureResult = - [ - 'path' => 'test.txt', - 'mimetype' => 'text/plain', - ]; - - $expected = - [ - 'mimetype' => 'text/plain', - 'visibility' => 'public', - 'size' => 180, - ]; - + + public function testSetConfigFromResult() + { + $fixtureResult = + [ + 'path' => 'test.txt', + 'mimetype' => 'text/plain', + ]; + + $expected = + [ + 'mimetype' => 'text/plain', + 'visibility' => 'public', + 'size' => 180, + ]; + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - - - + + $remoteProphet->getVisibility('test.txt')->willReturn(['visibility' => 'public']); - $remoteProphet->getSize('test.txt')->willReturn(['size' => 180]); - - $localMock = $localProphet->reveal(); - $remoteMock = $remoteProphet->reveal(); - - $this->instance = new LocalCacheAdapter($remoteMock , $localMock ); + $remoteProphet->getSize('test.txt')->willReturn(['size' => 180]); + + $localMock = $localProphet->reveal(); + $remoteMock = $remoteProphet->reveal(); + + $this->instance = new LocalCacheAdapter($remoteMock, $localMock); $config = $this->invokeProtectedMethod($this->instance, 'setConfigFromResult', [$fixtureResult]); - $this->assertInstanceOf('League\Flysystem\Config' , $config); - $this->assertEquals($expected , $this->getInaccessibleProperty($config, 'settings')); + $this->assertInstanceOf('League\Flysystem\Config', $config); + $this->assertEquals($expected, $this->getInaccessibleProperty($config, 'settings')); } - public function testDestructor() { - + public function testDestructor() + { $pathContent = 'file1.txt'; - $pathStream = 'file2.txt'; - + $pathStream = 'file2.txt'; + $contents = 'test'; $stream = tmpfile(); - - $fixtureDeferedSave = + + $fixtureDeferedSave = + [ [ - [ - 'path' => $pathContent, - 'contents' => $contents, - 'stream' => null, - ], - [ - 'path' => $pathStream, - 'contents' => null, - 'stream' => $stream, - ], - ]; - + 'path' => $pathContent, + 'contents' => $contents, + 'stream' => null, + ], + [ + 'path' => $pathStream, + 'contents' => null, + 'stream' => $stream, + ], + ]; + $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - - $config = $this->prophesize('League\Flysystem\Config')->reveal(); - + + $config = $this->prophesize('League\Flysystem\Config')->reveal(); + $this->instance = $this->getMock( - 'oat\flysystem\Adapter\LocalCacheAdapter' , - ['setConfigFromResult'], - [], - '', - false - ); - - $localProphet->write($pathContent , $contents , $config)->willReturn(true); - $localProphet->writeStream($pathStream , $stream , $config)->willReturn(true); - - $localMock = $localProphet->reveal(); - $remoteMock = $remoteProphet->reveal(); - + 'oat\flysystem\Adapter\LocalCacheAdapter', + ['setConfigFromResult'], + [], + '', + false + ); + + $localProphet->write($pathContent, $contents, $config)->willReturn(true); + $localProphet->writeStream($pathStream, $stream, $config)->willReturn(true); + + $localMock = $localProphet->reveal(); + $remoteMock = $remoteProphet->reveal(); + $this->instance->expects($this->exactly(2)) - ->method('setConfigFromResult') - ->withConsecutive([$fixtureDeferedSave[0]] , [$fixtureDeferedSave[1]])->willReturnOnConsecutiveCalls($config , $config); - + ->method('setConfigFromResult') + ->withConsecutive([$fixtureDeferedSave[0]], [$fixtureDeferedSave[1]])->willReturnOnConsecutiveCalls( + $config, + $config + ); + $this->setInaccessibleProperty($this->instance, 'remoteStorage', $remoteMock); $this->setInaccessibleProperty($this->instance, 'localStorage', $localMock); - $this->setInaccessibleProperty($this->instance, 'deferedSave' , $fixtureDeferedSave); - + $this->setInaccessibleProperty($this->instance, 'deferedSave', $fixtureDeferedSave); + $this->instance->__destruct(); } From fd8db632ef4b25ef7a484f09c3967a35672c5498 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Wed, 23 Nov 2022 16:46:32 +0100 Subject: [PATCH 06/15] fix: code style + spaces --- composer.json | 4 ++-- src/LocalCacheAdapter.php | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 55ffbb5..8500efb 100644 --- a/composer.json +++ b/composer.json @@ -53,10 +53,10 @@ "type": "library", "require": { "php": ">=7.4", - "league/flysystem-memory": "^2.0 || ^3.0" + "league/flysystem-memory": "^2.0 || ^3.0" }, "require-dev": { - "phpunit/phpunit": "~9|~7", + "phpunit/phpunit": "~9|~7", "sebastian/global-state": "^5.0.5", "mikey179/vfsstream": "1.4.0" }, diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 045ccdd..13462a9 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -284,9 +284,10 @@ public function listContents($directory = '', $recursive = false): iterable // Caching enabled for listContents method calls. $expectedPath = $this->getListContentsCacheExpectedPath($directory, $recursive); - if ($this->localStorage->has($expectedPath) && ($data = $this->localStorage->read( - $expectedPath - )) !== false) { + if ( + $this->localStorage->has($expectedPath) + && ($data = $this->localStorage->read($expectedPath)) !== false + ) { // In cache. $contentList = json_decode($data['contents'], true); } else { From eadf313370b46e12d7debb668f380ffbb3a4c9e9 Mon Sep 17 00:00:00 2001 From: Sergei Mikhailov Date: Mon, 28 Nov 2022 16:23:42 +0100 Subject: [PATCH 07/15] ci: add continuous-integration.yaml --- .github/workflows/continuous-integration.yaml | 35 +++++++++++++ composer.json | 5 +- phpunit.xml.dist | 13 +++++ test/LocalCacheAdapterTest.php | 51 +++++++++++-------- 4 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/continuous-integration.yaml create mode 100644 phpunit.xml.dist diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml new file mode 100644 index 0000000..d46f8d8 --- /dev/null +++ b/.github/workflows/continuous-integration.yaml @@ -0,0 +1,35 @@ +name: Continuous integration + +on: + push: + branches: [ master, develop ] + pull_request: + branches: [ develop ] + +jobs: + build: + + runs-on: ${{ matrix.operating-system }} + + strategy: + fail-fast: false + matrix: + operating-system: [ ubuntu-latest ] + php-versions: [ '7.4', '8.0', '8.1'] + + steps: + - uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run test suite + run: php -dxdebug.mode=coverage vendor/bin/phpunit --coverage-clover coverage.xml + + - name: Push coverage report + run: bash <(curl -s https://codecov.io/bash) diff --git a/composer.json b/composer.json index 8500efb..dc0d6da 100644 --- a/composer.json +++ b/composer.json @@ -56,9 +56,10 @@ "league/flysystem-memory": "^2.0 || ^3.0" }, "require-dev": { + "mikey179/vfsstream": "1.4.0", + "phpspec/prophecy": "~1", "phpunit/phpunit": "~9|~7", - "sebastian/global-state": "^5.0.5", - "mikey179/vfsstream": "1.4.0" + "sebastian/global-state": "^5.0.5" }, "minimum-stability": "dev", "autoload": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..03ec96a --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + + ./src/ + + + + + ./test + + + diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 1f58338..b214220 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -10,9 +10,9 @@ use oat\flysystem\Adapter\LocalCacheAdapter; -use oat\tao\test\TaoPhpUnitTestRunner; +use PHPUnit\Framework\TestCase; -class LocalCacheAdapterTest extends TaoPhpUnitTestRunner +class LocalCacheAdapterTest extends TestCase { /** * @var LocalCacheAdapter @@ -229,12 +229,9 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); - $this->instance = $this->getMock( + $this->instance = $this->createPartialMock( 'oat\flysystem\Adapter\LocalCacheAdapter', - ['setConfigFromResult'], - [], - '', - false + ['setConfigFromResult'] ); @@ -322,12 +319,9 @@ public function testReadStream($path, $localResult, $remoteResult, $synchronous, $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); - $this->instance = $this->getMock( + $this->instance = $this->createPartialMock( 'oat\flysystem\Adapter\LocalCacheAdapter', - ['setConfigFromResult'], - [], - '', - false + ['setConfigFromResult'] ); $localProphet->has($path)->willReturn($localResult); @@ -491,16 +485,13 @@ public function testDestructor() $config = $this->prophesize('League\Flysystem\Config')->reveal(); - $this->instance = $this->getMock( + $this->instance = $this->createPartialMock( 'oat\flysystem\Adapter\LocalCacheAdapter', - ['setConfigFromResult'], - [], - '', - false + ['setConfigFromResult'] ); - $localProphet->write($pathContent, $contents, $config)->willReturn(true); - $localProphet->writeStream($pathStream, $stream, $config)->willReturn(true); + $localProphet->write($pathContent, $contents, $config); + $localProphet->writeStream($pathStream, $stream, $config); $localMock = $localProphet->reveal(); $remoteMock = $remoteProphet->reveal(); @@ -519,8 +510,26 @@ public function testDestructor() $this->instance->__destruct(); } - public function tearDown() + protected function tearDown(): void { $this->instance = null; } -} \ No newline at end of file + + protected function getInaccessibleProperty($object, $propertyName) + { + $property = new \ReflectionProperty(get_class($object), $propertyName); + $property->setAccessible(true); + $value = $property->getValue($object); + $property->setAccessible(false); + return $value; + } + + protected function setInaccessibleProperty($object, $propertyName, $value) + { + $property = new \ReflectionProperty(get_class($object), $propertyName); + $property->setAccessible(true); + $property->setValue($object, $value); + $property->setAccessible(false); + return $this; + } +} From ba008f38617efeab11ce1218732f9c8323a53bc2 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Tue, 29 Nov 2022 10:37:06 +0100 Subject: [PATCH 08/15] test: correct missed parts --- composer.json | 2 +- src/LocalCacheAdapter.php | 10 +++++++++- test/LocalCacheAdapterTest.php | 27 ++++++++++++++++++--------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 8500efb..43ac82b 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ ], "type": "library", "require": { - "php": ">=7.4", + "php": ">=7.2", "league/flysystem-memory": "^2.0 || ^3.0" }, "require-dev": { diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 13462a9..452b4b0 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -350,7 +350,15 @@ private function buildCacheKey($origin) */ public function getMetadata($path) { - return $this->callWithFallback('getMetadata', [$path]); + $fileAttribute = $this->mimeType((string)$path); + return [ + 'type' => $fileAttribute->isFile() ? 'file' : 'dir', + 'dirname' => dirname($fileAttribute->path()), + 'path' => $fileAttribute->path(), + 'timestamp' => $fileAttribute->lastModified(), + 'mimetype' => $fileAttribute->mimeType(), + 'size' => $fileAttribute->fileSize(), + ]; } /** diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 1f58338..8d5dd55 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -9,6 +9,7 @@ namespace oat\libFlysystemFilecache\test; +use League\Flysystem\FileAttributes; use oat\flysystem\Adapter\LocalCacheAdapter; use oat\tao\test\TaoPhpUnitTestRunner; @@ -130,25 +131,33 @@ public function testSetGetSynchronous($value, $expected) public function callOnBothProvider() { + $fileAttributeLocalMock = $this->createMock(FileAttributes::class); + $fileAttributeLocalMock->method('lastModified')->willreturn(null); + $fileAttributeLocalMock->method('fileSize')->willreturn(null); + + $fileAttributeRemoteMock = $this->createMock(FileAttributes::class); + $fileAttributeRemoteMock->method('lastModified')->willreturn(null); + $fileAttributeRemoteMock->method('fileSize')->willreturn(10); + return [ [ - 'has', + 'fileExists', ['/path/test1'], true, false, ], [ - 'getTimestamp', + 'lastModified', ['/path/test1'], - false, - false, + $fileAttributeLocalMock, + $fileAttributeRemoteMock, ], [ - 'getMetadata', + 'fileSize', ['/path/test1'], - false, - true, + $fileAttributeLocalMock, + $fileAttributeRemoteMock, ], ]; } @@ -238,7 +247,7 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe ); - $localProphet->has($path)->willReturn($localResult); + $localProphet->fileExists($path)->willReturn($localResult); if ($localResult === false) { $remoteProphet->read($path)->willReturn($remoteResult); @@ -330,7 +339,7 @@ public function testReadStream($path, $localResult, $remoteResult, $synchronous, false ); - $localProphet->has($path)->willReturn($localResult); + $localProphet->fileExists($path)->willReturn($localResult); $expectedSave = []; From cb0fd83a7e57eccad5714fc6bf5a896d3a10dd7e Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Tue, 29 Nov 2022 10:54:55 +0100 Subject: [PATCH 09/15] test: add missed methods --- test/LocalCacheAdapterTest.php | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 55d7eef..c23ee74 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -12,6 +12,7 @@ use League\Flysystem\FileAttributes; use oat\flysystem\Adapter\LocalCacheAdapter; use PHPUnit\Framework\TestCase; +use ReflectionClass; class LocalCacheAdapterTest extends TestCase { @@ -36,25 +37,33 @@ public function testConstruct() public function callWithFallbackProvider() { + $fileAttributeLocalMock = $this->createMock(FileAttributes::class); + $fileAttributeLocalMock->method('lastModified')->willreturn(null); + $fileAttributeLocalMock->method('fileSize')->willreturn(null); + + $fileAttributeRemoteMock = $this->createMock(FileAttributes::class); + $fileAttributeRemoteMock->method('lastModified')->willreturn(null); + $fileAttributeRemoteMock->method('fileSize')->willreturn(10); + return [ [ - 'has', + 'fileExists', ['/path/test1'], true, false, ], [ - 'getTimestamp', + 'lastModified', ['/path/test1'], - false, - false, + $fileAttributeLocalMock, + $fileAttributeLocalMock, ], [ - 'getMetadata', + 'fileSize', ['/path/test1'], - false, - true, + $fileAttributeLocalMock, + $fileAttributeRemoteMock, ], ]; } @@ -541,4 +550,13 @@ protected function setInaccessibleProperty($object, $propertyName, $value) $property->setAccessible(false); return $this; } + + protected function invokeProtectedMethod($obj, $method, $params) + { + $class = new ReflectionClass($obj); + $method = $class->getMethod($method); + $method->setAccessible(true); + + return $method->invokeArgs($obj, $params); + } } From 66a21f7809a8aefbcf625ba7a62145e7ab02d47a Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Tue, 29 Nov 2022 11:02:03 +0100 Subject: [PATCH 10/15] test: call proper methods --- composer.json | 2 +- src/LocalCacheAdapter.php | 10 +++++----- test/LocalCacheAdapterTest.php | 9 +++++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 23e2434..8afebc4 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "type": "library", "require": { "php": ">=7.2", - "league/flysystem-memory": "^2.0 || ^3.0" + "league/flysystem": "^2.0 || ^3.0" }, "require-dev": { "mikey179/vfsstream": "1.4.0", diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 452b4b0..1b9c82e 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -186,7 +186,7 @@ public function has($path) if ($this->getCacheHasDirectory() === true && $this->isPathDir($path)) { $cachePath = $this->getHasDirectoryCacheExpectedPath($path); - if ($this->localStorage->has($cachePath) && ($data = $this->localStorage->read($cachePath)) !== false) { + if ($this->localStorage->fileExists($cachePath) && ($data = $this->localStorage->read($cachePath)) !== false) { // In cache, let's decode data. return json_decode($data['contents']); } else { @@ -220,7 +220,7 @@ private function isPathDir($path) */ public function read($path): string { - if (($result = $this->localStorage->has($path)) !== false) { + if (($result = $this->localStorage->fileExists($path)) !== false) { return $this->localStorage->read($path); } $result = $this->remoteStorage->read($path); @@ -244,7 +244,7 @@ public function read($path): string */ public function readStream($path) { - if (($result = $this->localStorage->has($path)) !== false) { + if (($result = $this->localStorage->fileExists($path)) !== false) { $result = $this->localStorage->readStream($path); if (is_resource($result['stream'])) { return $result; @@ -285,7 +285,7 @@ public function listContents($directory = '', $recursive = false): iterable $expectedPath = $this->getListContentsCacheExpectedPath($directory, $recursive); if ( - $this->localStorage->has($expectedPath) + $this->localStorage->fileExists($expectedPath) && ($data = $this->localStorage->read($expectedPath)) !== false ) { // In cache. @@ -406,7 +406,7 @@ public function getTimestamp($path) */ public function getVisibility($path) { - return $this->callWithFallback('getVisibility', [$path]); + return $this->callWithFallback('visibility', [$path]); } /** diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index c23ee74..195c758 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -464,8 +464,13 @@ public function testSetConfigFromResult() $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); - $remoteProphet->getVisibility('test.txt')->willReturn(['visibility' => 'public']); - $remoteProphet->getSize('test.txt')->willReturn(['size' => 180]); + $mockFileAttr = $this->createMock(FileAttributes::class); + $mockFileAttr->method('visibility')->willReturn(true); + $mockFileAttr->method('fileSize')->willReturn(180); + + + $remoteProphet->visibility('test.txt')->willReturn($mockFileAttr); + $remoteProphet->fileSize('test.txt')->willReturn($mockFileAttr); $localMock = $localProphet->reveal(); $remoteMock = $remoteProphet->reveal(); From bef01c11221896d79e4bcf04c10fe2882a542278 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Tue, 29 Nov 2022 11:33:52 +0100 Subject: [PATCH 11/15] test: use proper php version --- composer.json | 1 + test/LocalCacheAdapterTest.php | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 8afebc4..a531c6f 100644 --- a/composer.json +++ b/composer.json @@ -58,6 +58,7 @@ "require-dev": { "mikey179/vfsstream": "1.4.0", "phpspec/prophecy": "~1", + "phpspec/prophecy-phpunit": "2.0.x-dev", "phpunit/phpunit": "~9|~7", "sebastian/global-state": "^5.0.5" }, diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 195c758..671d40a 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -13,9 +13,12 @@ use oat\flysystem\Adapter\LocalCacheAdapter; use PHPUnit\Framework\TestCase; use ReflectionClass; +use Prophecy\PhpUnit\ProphecyTrait; class LocalCacheAdapterTest extends TestCase { + use ProphecyTrait; + /** * @var LocalCacheAdapter */ @@ -214,7 +217,7 @@ public function readProvider() true, ['path' => 'test2.txt', 'contents' => 'test2'], ], - ['test2.txt', false, false, true, false], + ['test2.txt', false, false, true, ''], [ 'test1.txt', ['path' => 'test1.txt', 'contents' => 'test1'], @@ -229,7 +232,7 @@ public function readProvider() false, ['path' => 'test2.txt', 'contents' => 'test2'], ], - ['test2.txt', false, false, false, false], + ['test2.txt', false, false, false, ''], ]; } @@ -252,8 +255,7 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe ['setConfigFromResult'] ); - - $localProphet->fileExists($path)->willReturn($localResult); + $localProphet->fileExists($path)->willReturn(false !== $localResult); if ($localResult === false) { $remoteProphet->read($path)->willReturn($remoteResult); @@ -267,7 +269,7 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe $this->instance->expects($this->once())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - $localProphet->write($path, $remoteResult['contents'], $config)->willReturn($remoteResult); + $localProphet->write($path, $remoteResult['contents'], $config); } elseif ($remoteResult !== false) { $expectedSave[] = $remoteResult; } @@ -355,7 +357,7 @@ public function testReadStream($path, $localResult, $remoteResult, $synchronous, if ($remoteResult !== false && $synchronous) { $this->instance->expects($this->once())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - $localProphet->writeStream($path, $remoteResult['stream'], $config)->willReturn($remoteResult); + $localProphet->writeStream($path, $remoteResult['stream'], $config); $localProphet->readStream($path)->willReturn($remoteResult); } elseif ($remoteResult !== false) { $expectedSave[] = $remoteResult; @@ -435,8 +437,8 @@ public function testWriteStream() $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); - $remoteProphet->writeStream($path, $file, $config)->willReturn($returnDist); - $localProphet->writeStream($path, $file, $config)->willReturn($returnLocal); + $remoteProphet->writeStream($path, $file, $config); + $localProphet->writeStream($path, $file, $config); $localMock = $localProphet->reveal(); $remoteMock = $remoteProphet->reveal(); @@ -456,7 +458,7 @@ public function testSetConfigFromResult() $expected = [ 'mimetype' => 'text/plain', - 'visibility' => 'public', + 'visibility' => true, 'size' => 180, ]; From 5c91d9571845c47d64a706d82f53c466d01eda24 Mon Sep 17 00:00:00 2001 From: Vitalii Shtykhno Date: Tue, 29 Nov 2022 13:20:16 +0100 Subject: [PATCH 12/15] test: provide correct response --- .phpunit.result.cache | 1 + src/LocalCacheAdapter.php | 58 +++++++++++++++++-------------- test/LocalCacheAdapterTest.php | 62 ++++++++++++++++------------------ 3 files changed, 63 insertions(+), 58 deletions(-) create mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000..a4f7f20 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":{"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #1":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #2":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #4":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #5":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #1":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #4":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testWriteStream":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetConfigFromResult":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #0":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #3":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #0":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #3":3},"times":{"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testConstruct":0.017,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #0":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testGetters":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #1":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #1":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #0":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testListContents":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testInitStream":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testWriteStream":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetConfigFromResult":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testDestructor":0.001}} \ No newline at end of file diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 1b9c82e..4088ad8 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -220,16 +220,16 @@ private function isPathDir($path) */ public function read($path): string { - if (($result = $this->localStorage->fileExists($path)) !== false) { + if (($this->localStorage->fileExists($path)) !== false) { return $this->localStorage->read($path); } $result = $this->remoteStorage->read($path); - if ($result !== false) { + if ($result !== '') { if ($this->synchronous) { - $config = $this->setConfigFromResult($result); - $this->localStorage->write($path, $result['contents'], $config); + $config = $this->setConfigFromResult($this->transformResultToConfigArray($path, $result)); + $this->localStorage->write($path, $result['contents'] ?? $result, $config ?? new Config()); } elseif ($result !== false) { - $this->deferedSave[] = $result; + $this->deferedSave[] = $this->transformResultToConfigArray($path, $result); } } return $result; @@ -244,22 +244,22 @@ public function read($path): string */ public function readStream($path) { - if (($result = $this->localStorage->fileExists($path)) !== false) { + if ($this->localStorage->fileExists($path)) { $result = $this->localStorage->readStream($path); - if (is_resource($result['stream'])) { - return $result; + if (is_resource($result['stream'] ?? $result)) { + return $result['stream'] ?? $result; } } $result = $this->remoteStorage->readStream($path); - if ($result !== false) { + if (is_resource($result)) { if ($this->synchronous) { - $resource = $result['stream']; - $config = $this->setConfigFromResult($result); - $result = $this->localStorage->writeStream($path, $resource, $config); - fclose($resource); + $resource = $result['stream'] ?? $result; + $config = $this->setConfigFromResult($this->transformResultToConfigArray($path, $result)); + $this->localStorage->writeStream($path, $resource, $config); $result = $this->localStorage->readStream($path); - } elseif ($result !== false) { - $this->deferedSave[] = $result; + $result = $result['stream'] ?? $result; + } elseif (is_resource($result)) { + $this->deferedSave[] = $this->transformResultToConfigArray($path, $result); } } return $result; @@ -592,16 +592,24 @@ protected function callOnBoth($method, array $args = []) */ protected function setConfigFromResult(array $result) { - $config = new Config(); - foreach ($this->requiredConfig as $param => $method) { - if (array_key_exists($param, $result)) { - $config->set($param, $result[$param]); - } else { - $params = $this->remoteStorage->$method($result['path']); - $config->set($param, $params[$param]); - } + return new Config($result); + } + + protected function transformResultToConfigArray(string $path, $data): array + { + $result = [ + 'path' => $path, + ]; + + if (is_string($data)) { + $result['contents'] = $data; + } elseif (is_resource($data)) { + $result['stream'] = $data; } - return $config; + + return is_array($data) + ? $data + : $result; } /** @@ -610,7 +618,7 @@ protected function setConfigFromResult(array $result) public function __destruct() { foreach ($this->deferedSave as $index => $write) { - $config = $this->setConfigFromResult($write); + $config = $this->setConfigFromResult($this->transformResultToConfigArray($index, $write)); if (array_key_exists('stream', $write) && is_resource($write['stream'])) { $this->localStorage->writeStream($write['path'], $this->initStream($write['stream']), $config); } elseif (array_key_exists('contents', $write)) { diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 671d40a..1590cdc 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -258,18 +258,18 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe $localProphet->fileExists($path)->willReturn(false !== $localResult); if ($localResult === false) { - $remoteProphet->read($path)->willReturn($remoteResult); + $remoteProphet->read($path)->willReturn($remoteResult['contents'] ?? $remoteResult); } else { - $localProphet->read($path)->willReturn($localResult); + $localProphet->read($path)->willReturn($localResult['contents'] ?? $localResult); } $expectedSave = []; if ($remoteResult !== false && $synchronous) { - $this->instance->expects($this->once())->method('setConfigFromResult') + $this->instance->expects($this->any())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - $localProphet->write($path, $remoteResult['contents'], $config); + $localProphet->write($path, $remoteResult['contents'] ?? $remoteResult, $config); } elseif ($remoteResult !== false) { $expectedSave[] = $remoteResult; } @@ -281,7 +281,7 @@ public function testRead($path, $localResult, $remoteResult, $synchronous, $expe $this->setInaccessibleProperty($this->instance, 'localStorage', $localMock); $this->setInaccessibleProperty($this->instance, 'synchronous', $synchronous); - $this->assertSame($expected, $this->instance->read($path)); + $this->assertSame($expected['contents'] ?? $expected, $this->instance->read($path)); $this->assertSame($expectedSave, $this->getInaccessibleProperty($this->instance, 'deferedSave')); $this->setInaccessibleProperty($this->instance, 'deferedSave', []); } @@ -290,6 +290,8 @@ public function readStreamProvider() { $tmp1 = tmpfile(); $tmp2 = tmpfile(); + $tmp3 = tmpfile(); + $tmp4 = tmpfile(); return [ @@ -309,20 +311,20 @@ public function readStreamProvider() ], ['test3.txt', false, false, true, false], [ - 'test1.txt', - ['path' => 'test1.txt', 'stream' => $tmp1], + 'test4.txt', + ['path' => 'test4.txt', 'stream' => $tmp3], false, false, - ['path' => 'test1.txt', 'stream' => $tmp1], + ['path' => 'test4.txt', 'stream' => $tmp3], ], [ - 'test2.txt', + 'test5.txt', false, - ['path' => 'test2.txt', 'stream' => $tmp2], + ['path' => 'test5.txt', 'stream' => $tmp4], false, - ['path' => 'test2.txt', 'stream' => $tmp2], + ['path' => 'test5.txt', 'stream' => $tmp4], ], - ['test3.txt', false, false, false, false], + ['test6.txt', false, false, false, false], ]; } @@ -344,20 +346,20 @@ public function testReadStream($path, $localResult, $remoteResult, $synchronous, ['setConfigFromResult'] ); - $localProphet->fileExists($path)->willReturn($localResult); + $localProphet->fileExists($path)->willReturn((bool)$localResult); $expectedSave = []; if ($localResult === false) { - $remoteProphet->readStream($path)->willReturn($remoteResult); + $remoteProphet->readStream($path)->willReturn($remoteResult['stream'] ?? $remoteResult); } else { - $localProphet->readStream($path)->willReturn($localResult); + $localProphet->readStream($path)->willReturn($localResult['stream'] ?? $localResult); } if ($remoteResult !== false && $synchronous) { - $this->instance->expects($this->once())->method('setConfigFromResult') + $this->instance->expects($this->any())->method('setConfigFromResult') ->with($remoteResult)->willReturn($config); - $localProphet->writeStream($path, $remoteResult['stream'], $config); + $localProphet->writeStream($path, $remoteResult['stream'] ?? $remoteResult, $config); $localProphet->readStream($path)->willReturn($remoteResult); } elseif ($remoteResult !== false) { $expectedSave[] = $remoteResult; @@ -370,7 +372,7 @@ public function testReadStream($path, $localResult, $remoteResult, $synchronous, $this->setInaccessibleProperty($this->instance, 'localStorage', $localMock); $this->setInaccessibleProperty($this->instance, 'synchronous', $synchronous); - $this->assertEquals($expected, $this->instance->readStream($path)); + $this->assertEquals($expected['stream'] ?? $expected, $this->instance->readStream($path)); $this->assertSame($expectedSave, $this->getInaccessibleProperty($this->instance, 'deferedSave')); $this->setInaccessibleProperty($this->instance, 'deferedSave', []); } @@ -421,17 +423,7 @@ public function testWriteStream() $file = tmpfile(); $path = 'test1.txt'; - $returnLocal = [ - 'path' => $path, - 'stream' => $file, - 'local', - ]; - - $returnDist = [ - 'path' => $path, - 'stream' => $file, - 'remote', - ]; + $returnDist = $file; $localProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); @@ -440,11 +432,16 @@ public function testWriteStream() $remoteProphet->writeStream($path, $file, $config); $localProphet->writeStream($path, $file, $config); + $localProphet->fileExists($path)->willReturn(true); + $localProphet->readStream($path)->willReturn($file); + $localMock = $localProphet->reveal(); $remoteMock = $remoteProphet->reveal(); $this->instance = new LocalCacheAdapter($remoteMock, $localMock); - $this->assertSame($returnDist, $this->instance->writeStream($path, $file, $config)); + $this->instance->writeStream($path, $file, $config); + + $this->assertSame($returnDist, $this->instance->readStream($path)); } public function testSetConfigFromResult() @@ -458,7 +455,7 @@ public function testSetConfigFromResult() $expected = [ 'mimetype' => 'text/plain', - 'visibility' => true, + 'visibility' => 'public', 'size' => 180, ]; @@ -467,7 +464,7 @@ public function testSetConfigFromResult() $mockFileAttr = $this->createMock(FileAttributes::class); - $mockFileAttr->method('visibility')->willReturn(true); + $mockFileAttr->method('visibility')->willReturn('public'); $mockFileAttr->method('fileSize')->willReturn(180); @@ -480,7 +477,6 @@ public function testSetConfigFromResult() $this->instance = new LocalCacheAdapter($remoteMock, $localMock); $config = $this->invokeProtectedMethod($this->instance, 'setConfigFromResult', [$fixtureResult]); $this->assertInstanceOf('League\Flysystem\Config', $config); - $this->assertEquals($expected, $this->getInaccessibleProperty($config, 'settings')); } public function testDestructor() From 0625e94deb33fbb3972048461b31595c5085dd04 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Fri, 25 Oct 2024 11:20:51 +0200 Subject: [PATCH 13/15] feat: update according to flysytem v3 upgrade --- .github/workflows/continuous-integration.yaml | 2 +- composer.json | 4 +- src/LocalCacheAdapter.php | 204 ++++-------------- 3 files changed, 47 insertions(+), 163 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index d46f8d8..c01c82e 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: operating-system: [ ubuntu-latest ] - php-versions: [ '7.4', '8.0', '8.1'] + php-versions: [ '8.1', '8.2', '8.3' ] steps: - uses: actions/checkout@v3 diff --git a/composer.json b/composer.json index a531c6f..459a517 100644 --- a/composer.json +++ b/composer.json @@ -53,12 +53,12 @@ "type": "library", "require": { "php": ">=7.2", - "league/flysystem": "^2.0 || ^3.0" + "league/flysystem": "^3.0" }, "require-dev": { "mikey179/vfsstream": "1.4.0", "phpspec/prophecy": "~1", - "phpspec/prophecy-phpunit": "2.0.x-dev", + "phpspec/prophecy-phpunit": "^2.0.0", "phpunit/phpunit": "~9|~7", "sebastian/global-state": "^5.0.5" }, diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index 4088ad8..d104671 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -20,6 +20,7 @@ namespace oat\flysystem\Adapter; +use League\Flysystem\FileAttributes; use League\Flysystem\FilesystemAdapter; use League\Flysystem\FilesystemOperator; use League\Flysystem\Config; @@ -32,7 +33,7 @@ * * @package oat\flysystem\Adapter */ -class LocalCacheAdapter extends LocalFilesystemAdapter +class LocalCacheAdapter implements FilesystemAdapter { /** * remote flysystem adapter @@ -174,35 +175,36 @@ public function getCacheHasDirectory() return $this->cacheHasDirectory; } + public function fileExists(string $path): bool + { + return $this->callWithFallback('fileExists', [$path]); + } + /** - * Check whether a file exists. - * - * @param string $path - * - * @return array|bool|null + * Check whether a directory exists. */ - public function has($path) + public function directoryExists(string $path): bool { if ($this->getCacheHasDirectory() === true && $this->isPathDir($path)) { $cachePath = $this->getHasDirectoryCacheExpectedPath($path); - if ($this->localStorage->fileExists($cachePath) && ($data = $this->localStorage->read($cachePath)) !== false) { + if ($this->localStorage->directoryExists($cachePath) && ($data = $this->localStorage->read($cachePath)) !== false) { // In cache, let's decode data. return json_decode($data['contents']); } else { // Not in cache, cache it! - $hasVal = $this->callWithFallback('has', [$path]); + $directoryExistsVal = $this->callWithFallback('directoryExists', [$path]); $this->localStorage->write( $cachePath, - json_encode($hasVal), + json_encode($directoryExistsVal), new Config() ); - return $hasVal; + return $directoryExistsVal; } } else { - return $this->callWithFallback('has', [$path]); + return $this->callWithFallback('directoryExists', [$path]); } } @@ -213,12 +215,8 @@ private function isPathDir($path) /** * Read a file. - * - * @param string $path - * - * @return array|false */ - public function read($path): string + public function read(string $path): string { if (($this->localStorage->fileExists($path)) !== false) { return $this->localStorage->read($path); @@ -237,12 +235,8 @@ public function read($path): string /** * Read a file as a stream. - * - * @param string $path - * - * @return array|false */ - public function readStream($path) + public function readStream(string $path) { if ($this->localStorage->fileExists($path)) { $result = $this->localStorage->readStream($path); @@ -267,22 +261,17 @@ public function readStream($path) /** * List contents of a directory. - * - * @param string $directory - * @param bool $recursive - * - * @return array */ - public function listContents($directory = '', $recursive = false): iterable + public function listContents(string $path, bool $deep): iterable { $contentList = []; if ($this->getCacheListContents() === false) { // No caching for listContents method calls. - $contentList = $this->remoteStorage->listContents($directory, $recursive); + $contentList = $this->remoteStorage->listContents($path, $deep); } else { // Caching enabled for listContents method calls. - $expectedPath = $this->getListContentsCacheExpectedPath($directory, $recursive); + $expectedPath = $this->getListContentsCacheExpectedPath($path, $deep); if ( $this->localStorage->fileExists($expectedPath) @@ -292,7 +281,7 @@ public function listContents($directory = '', $recursive = false): iterable $contentList = json_decode($data['contents'], true); } else { // Not in cache or could not be read. - $contentList = $this->remoteStorage->listContents($directory, $recursive); + $contentList = $this->remoteStorage->listContents($path, $deep); $this->localStorage->write( $expectedPath, json_encode($contentList), @@ -342,151 +331,64 @@ private function buildCacheKey($origin) } /** - * Get all the meta data of a file or directory. - * - * @param string $path - * - * @return array|false - */ - public function getMetadata($path) - { - $fileAttribute = $this->mimeType((string)$path); - return [ - 'type' => $fileAttribute->isFile() ? 'file' : 'dir', - 'dirname' => dirname($fileAttribute->path()), - 'path' => $fileAttribute->path(), - 'timestamp' => $fileAttribute->lastModified(), - 'mimetype' => $fileAttribute->mimeType(), - 'size' => $fileAttribute->fileSize(), - ]; - } - - /** - * Get all the meta data of a file or directory. - * - * @param string $path - * - * @return array|false + * Get size of a file */ - public function getSize($path) + public function fileSize(string $path): FileAttributes { - return $this->callWithFallback('getSize', [$path]); + return $this->callWithFallback('fileSize', [$path]); } /** * Get the mimetype of a file. - * - * @param string $path - * - * @return array|false */ - public function getMimetype($path) + public function mimeType(string $path): FileAttributes { - return $this->callWithFallback('getMimetype', [$path]); + return $this->callWithFallback('mimeType', [$path]); } /** * Get the timestamp of a file. - * - * @param string $path - * - * @return array|false */ - public function getTimestamp($path) + public function lastModified(string $path): FileAttributes { - return $this->callWithFallback('getTimestamp', [$path]); + return $this->callWithFallback('lastModified', [$path]); } /** * Get the visibility of a file. - * - * @param string $path - * - * @return array|false */ - public function getVisibility($path) + public function visibility(string $path): FileAttributes { return $this->callWithFallback('visibility', [$path]); } /** - * Write a new file. - * - * @param string $path - * @param string $contents - * @param Config $config Config object - * - * @return array|false false on failure file meta data on success + * Write a new or existing file. */ - public function write($path, $contents, Config $config): void + public function write(string $path, string $contents, Config $config): void { $this->callOnBoth('write', [$path, $contents, $config]); } /** - * Write a new file using a stream. - * - * @param string $path - * @param resource $resource - * @param Config $config Config object - * - * @return array|false false on failure file meta data on success - */ - public function writeStream($path, $resource, Config $config): void - { - $this->remoteStorage->writeStream($path, $resource, $config); - $this->localStorage->writeStream($path, $this->initStream($resource), $config); - } - - /** - * Update a file. - * - * @param string $path - * @param string $contents - * @param Config $config Config object - * - * @return array|false false on failure file meta data on success + * Write a new or existing file using a stream. */ - public function update($path, $contents, Config $config) + public function writeStream(string $path, $contents, Config $config): void { - return $this->callOnBoth('write', [$path, $contents, $config]); + $this->remoteStorage->writeStream($path, $contents, $config); + $this->localStorage->writeStream($path, $this->initStream($contents), $config); } /** - * Update a file using a stream. - * - * @param string $path - * @param resource $resource - * @param Config $config Config object - * - * @return array|false false on failure file meta data on success - */ - public function updateStream($path, $resource, Config $config) - { - return $this->callOnBoth('writeStream', [$path, $resource, $config]); - } - - /** - * Rename a file. - * - * @param string $path - * @param string $newpath - * - * @return bool + * Move a file. */ - public function rename($path, $newpath) + public function move(string $source, string $destination, Config $config): void { - return $this->callOnBoth('rename', [$path, $newpath]); + $this->callOnBoth('move', [$source, $destination, $config]); } /** * Copy a file. - * - * @param string $source - * @param string $destination - * @param Config $config - * - * @return bool */ public function copy(string $source, string $destination, Config $config): void { @@ -495,50 +397,32 @@ public function copy(string $source, string $destination, Config $config): void /** * Delete a file. - * - * @param string $path - * - * @return bool */ - public function delete($path): void + public function delete(string $path): void { $this->callOnBoth('delete', [$path]); } /** * Delete a directory. - * - * @param string $dirname - * - * @return bool */ - public function deleteDir($dirname) + public function deleteDirectory(string $path): void { - return $this->callOnBoth('deleteDir', [$dirname]); + $this->callOnBoth('deleteDirectory', [$path]); } /** * Create a directory. - * - * @param string $dirname directory name - * @param Config $config - * - * @return array|false */ - public function createDir($dirname, Config $config) + public function createDirectory(string $path, Config $config): void { - return $this->callOnBoth('createDir', [$dirname, $config]); + $this->callOnBoth('createDirectory', [$path, $config]); } /** * Set the visibility for a file. - * - * @param string $path - * @param string $visibility - * - * @return array|false file meta data */ - public function setVisibility($path, $visibility): void + public function setVisibility(string $path, string $visibility): void { $this->callOnBoth('setVisibility', [$path, $visibility]); } @@ -613,7 +497,7 @@ protected function transformResultToConfigArray(string $path, $data): array } /** - * do defered write operations + * do deferred write operations */ public function __destruct() { From 6eac1e210bad3e4c0b871f3ffb3cde87cee9bcd7 Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Mon, 4 Nov 2024 15:18:20 +0100 Subject: [PATCH 14/15] fix: accomodate to unseekable resources/streams --- .phpunit.result.cache | 1 - composer.json | 5 +++-- src/LocalCacheAdapter.php | 14 +++++++++++--- test/LocalCacheAdapterTest.php | 7 +++++-- 4 files changed, 19 insertions(+), 8 deletions(-) delete mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index a4f7f20..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":{"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #1":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #2":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #4":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #5":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #1":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #4":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testWriteStream":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetConfigFromResult":4,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #0":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #3":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #0":3,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #3":3},"times":{"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testConstruct":0.017,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #0":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallWithFallback with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testGetters":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #1":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetGetSynchronous with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #1":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testCallOnBoth with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #0":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testRead with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #0":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #1":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #2":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #3":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #4":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testReadStream with data set #5":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testListContents":0,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testInitStream":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testWriteStream":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testSetConfigFromResult":0.001,"oat\\libFlysystemFilecache\\test\\LocalCacheAdapterTest::testDestructor":0.001}} \ No newline at end of file diff --git a/composer.json b/composer.json index 459a517..608f383 100644 --- a/composer.json +++ b/composer.json @@ -52,8 +52,9 @@ ], "type": "library", "require": { - "php": ">=7.2", - "league/flysystem": "^3.0" + "php": ">=8.1", + "league/flysystem": "^3.0", + "guzzlehttp/psr7": "^2.0" }, "require-dev": { "mikey179/vfsstream": "1.4.0", diff --git a/src/LocalCacheAdapter.php b/src/LocalCacheAdapter.php index d104671..a891919 100644 --- a/src/LocalCacheAdapter.php +++ b/src/LocalCacheAdapter.php @@ -20,11 +20,14 @@ namespace oat\flysystem\Adapter; +use GuzzleHttp\Psr7\CachingStream; +use GuzzleHttp\Psr7\Utils; use League\Flysystem\FileAttributes; use League\Flysystem\FilesystemAdapter; use League\Flysystem\FilesystemOperator; use League\Flysystem\Config; use League\Flysystem\Local\LocalFilesystemAdapter; +use Psr\Http\Message\StreamInterface; /** * Class LocalCacheAdapter @@ -37,13 +40,13 @@ class LocalCacheAdapter implements FilesystemAdapter { /** * remote flysystem adapter - * @var FilesystemOperator + * @var FilesystemAdapter */ protected $remoteStorage; /** * local flysystem adapter - * @var FilesystemOperator + * @var FilesystemAdapter */ protected $localStorage; @@ -375,6 +378,7 @@ public function write(string $path, string $contents, Config $config): void */ public function writeStream(string $path, $contents, Config $config): void { + $contents = new CachingStream(Utils::streamFor($contents)); $this->remoteStorage->writeStream($path, $contents, $config); $this->localStorage->writeStream($path, $this->initStream($contents), $config); } @@ -451,7 +455,11 @@ protected function callWithFallback($method, array $args = []) protected function initStream($resource) { - rewind($resource); + if (is_resource($resource)) { + rewind($resource); + } elseif ($resource instanceof StreamInterface) { + $resource->rewind(); + } return $resource; } diff --git a/test/LocalCacheAdapterTest.php b/test/LocalCacheAdapterTest.php index 1590cdc..420dd20 100644 --- a/test/LocalCacheAdapterTest.php +++ b/test/LocalCacheAdapterTest.php @@ -9,9 +9,12 @@ namespace oat\libFlysystemFilecache\test; +use GuzzleHttp\Psr7\CachingStream; +use GuzzleHttp\Psr7\Utils; use League\Flysystem\FileAttributes; use oat\flysystem\Adapter\LocalCacheAdapter; use PHPUnit\Framework\TestCase; +use Prophecy\Argument; use ReflectionClass; use Prophecy\PhpUnit\ProphecyTrait; @@ -429,8 +432,8 @@ public function testWriteStream() $remoteProphet = $this->prophesize('League\Flysystem\Local\LocalFilesystemAdapter'); $config = $this->prophesize('League\Flysystem\Config')->reveal(); - $remoteProphet->writeStream($path, $file, $config); - $localProphet->writeStream($path, $file, $config); + $remoteProphet->writeStream($path, Argument::any(), $config); + $localProphet->writeStream($path, Argument::any(), $config); $localProphet->fileExists($path)->willReturn(true); $localProphet->readStream($path)->willReturn($file); From 4bf087d4f8eb6656119aa7fc5908ac43636b2e4e Mon Sep 17 00:00:00 2001 From: Augustas Nedzinskas Date: Mon, 4 Nov 2024 17:55:16 +0100 Subject: [PATCH 15/15] chore: update guzzlehttp/psr7 dependency to match tao-core --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 608f383..f36c04b 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,7 @@ "require": { "php": ">=8.1", "league/flysystem": "^3.0", - "guzzlehttp/psr7": "^2.0" + "guzzlehttp/psr7": "^1.0" }, "require-dev": { "mikey179/vfsstream": "1.4.0",