diff --git a/composer.json b/composer.json
index 950b27d..faa3854 100644
--- a/composer.json
+++ b/composer.json
@@ -23,7 +23,8 @@
"phpoffice/phpexcel": "^1.8",
"overtrue/wechat": "~4.0",
"jaeger/querylist": "^4.2",
- "topthink/think-queue": "3.0"
+ "topthink/think-queue": "3.0",
+ "topthink/think-filesystem": "1.0.1"
},
"require-dev": {
"symfony/var-dumper": "^4.2",
diff --git a/composer.lock b/composer.lock
index a57cfbb..e2db277 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "1e8675185db7615e99f72a032d32a58c",
+ "content-hash": "1346841c35ed676c7f6819ff68f05fc1",
"packages": [
{
"name": "adbario/php-dot-notation",
@@ -1074,6 +1074,57 @@
],
"time": "2022-10-04T09:16:37+00:00"
},
+ {
+ "name": "league/flysystem-cached-adapter",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem-cached-adapter.git",
+ "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/d1925efb2207ac4be3ad0c40b8277175f99ffaff",
+ "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem": "~1.0",
+ "psr/cache": "^1.0.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "~0.9",
+ "phpspec/phpspec": "^3.4",
+ "phpunit/phpunit": "^5.7",
+ "predis/predis": "~1.0",
+ "tedivm/stash": "~0.12"
+ },
+ "suggest": {
+ "ext-phpredis": "Pure C implemented extension for PHP"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\Cached\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "frankdejonge",
+ "email": "info@frenky.net"
+ }
+ ],
+ "description": "An adapter decorator to enable meta-data caching.",
+ "support": {
+ "issues": "https://github.com/thephpleague/flysystem-cached-adapter/issues",
+ "source": "https://github.com/thephpleague/flysystem-cached-adapter/tree/master"
+ },
+ "time": "2020-07-25T15:56:04+00:00"
+ },
{
"name": "league/mime-type-detection",
"version": "1.12.0",
@@ -3688,6 +3739,54 @@
"abandoned": true,
"time": "2019-04-15T06:55:28+00:00"
},
+ {
+ "name": "topthink/think-filesystem",
+ "version": "v1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-filesystem.git",
+ "reference": "cfc510520db9bcd22d8d80f51d7e415a2f470af6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/cfc510520db9bcd22d8d80f51d7e415a2f470af6",
+ "reference": "cfc510520db9bcd22d8d80f51d7e415a2f470af6",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem": "^1.1.4",
+ "league/flysystem-cached-adapter": "^1.0",
+ "php": ">=7.2.5",
+ "topthink/framework": "^6.1"
+ },
+ "require-dev": {
+ "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.2",
+ "phpunit/phpunit": "^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "The ThinkPHP6.1 Filesystem Package",
+ "support": {
+ "issues": "https://github.com/top-think/think-filesystem/issues",
+ "source": "https://github.com/top-think/think-filesystem/tree/v1.0.1"
+ },
+ "time": "2022-10-26T03:50:24+00:00"
+ },
{
"name": "topthink/think-helper",
"version": "v3.1.6",
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
index c17d04a..4c039c7 100644
--- a/vendor/composer/autoload_files.php
+++ b/vendor/composer/autoload_files.php
@@ -8,11 +8,11 @@ $baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
- '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
- '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index 63dd27b..674b584 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -9,7 +9,7 @@ return array(
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
- 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-factory/src', $vendorDir . '/topthink/think-queue/src'),
+ 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-factory/src', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-queue/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-filesystem/src'),
'clagiordano\\weblibs\\configmanager\\' => array($vendorDir . '/clagiordano/weblibs-configmanager/src'),
'app\\' => array($baseDir . '/app'),
'Tightenco\\Collect\\' => array($vendorDir . '/tightenco/collect/src/Collect'),
@@ -41,6 +41,7 @@ return array(
'Overtrue\\Socialite\\' => array($vendorDir . '/overtrue/socialite/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
+ 'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
'Jaeger\\' => array($vendorDir . '/jaeger/g-http/src'),
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 3a07339..b9992db 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -9,11 +9,11 @@ class ComposerStaticInit221484bf0c47d5c5287b3869fd49b342
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
- '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
- '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
@@ -93,6 +93,7 @@ class ComposerStaticInit221484bf0c47d5c5287b3869fd49b342
'L' =>
array (
'League\\MimeTypeDetection\\' => 25,
+ 'League\\Flysystem\\Cached\\' => 24,
'League\\Flysystem\\' => 17,
),
'J' =>
@@ -142,11 +143,12 @@ class ComposerStaticInit221484bf0c47d5c5287b3869fd49b342
'think\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
- 1 => __DIR__ . '/..' . '/topthink/think-helper/src',
- 2 => __DIR__ . '/..' . '/topthink/think-orm/src',
- 3 => __DIR__ . '/..' . '/topthink/think-template/src',
- 4 => __DIR__ . '/..' . '/topthink/think-factory/src',
- 5 => __DIR__ . '/..' . '/topthink/think-queue/src',
+ 1 => __DIR__ . '/..' . '/topthink/think-factory/src',
+ 2 => __DIR__ . '/..' . '/topthink/think-helper/src',
+ 3 => __DIR__ . '/..' . '/topthink/think-orm/src',
+ 4 => __DIR__ . '/..' . '/topthink/think-queue/src',
+ 5 => __DIR__ . '/..' . '/topthink/think-template/src',
+ 6 => __DIR__ . '/..' . '/topthink/think-filesystem/src',
),
'clagiordano\\weblibs\\configmanager\\' =>
array (
@@ -273,6 +275,10 @@ class ComposerStaticInit221484bf0c47d5c5287b3869fd49b342
array (
0 => __DIR__ . '/..' . '/league/mime-type-detection/src',
),
+ 'League\\Flysystem\\Cached\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/league/flysystem-cached-adapter/src',
+ ),
'League\\Flysystem\\' =>
array (
0 => __DIR__ . '/..' . '/league/flysystem/src',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index f46eda9..7922978 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -1125,6 +1125,60 @@
],
"install-path": "../league/flysystem"
},
+ {
+ "name": "league/flysystem-cached-adapter",
+ "version": "1.1.0",
+ "version_normalized": "1.1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem-cached-adapter.git",
+ "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/d1925efb2207ac4be3ad0c40b8277175f99ffaff",
+ "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem": "~1.0",
+ "psr/cache": "^1.0.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "~0.9",
+ "phpspec/phpspec": "^3.4",
+ "phpunit/phpunit": "^5.7",
+ "predis/predis": "~1.0",
+ "tedivm/stash": "~0.12"
+ },
+ "suggest": {
+ "ext-phpredis": "Pure C implemented extension for PHP"
+ },
+ "time": "2020-07-25T15:56:04+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\Cached\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "frankdejonge",
+ "email": "info@frenky.net"
+ }
+ ],
+ "description": "An adapter decorator to enable meta-data caching.",
+ "support": {
+ "issues": "https://github.com/thephpleague/flysystem-cached-adapter/issues",
+ "source": "https://github.com/thephpleague/flysystem-cached-adapter/tree/master"
+ },
+ "install-path": "../league/flysystem-cached-adapter"
+ },
{
"name": "league/mime-type-detection",
"version": "1.12.0",
@@ -3895,6 +3949,57 @@
"abandoned": true,
"install-path": "../topthink/think-factory"
},
+ {
+ "name": "topthink/think-filesystem",
+ "version": "v1.0.1",
+ "version_normalized": "1.0.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/top-think/think-filesystem.git",
+ "reference": "cfc510520db9bcd22d8d80f51d7e415a2f470af6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/cfc510520db9bcd22d8d80f51d7e415a2f470af6",
+ "reference": "cfc510520db9bcd22d8d80f51d7e415a2f470af6",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem": "^1.1.4",
+ "league/flysystem-cached-adapter": "^1.0",
+ "php": ">=7.2.5",
+ "topthink/framework": "^6.1"
+ },
+ "require-dev": {
+ "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.2",
+ "phpunit/phpunit": "^8.0"
+ },
+ "time": "2022-10-26T03:50:24+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "description": "The ThinkPHP6.1 Filesystem Package",
+ "support": {
+ "issues": "https://github.com/top-think/think-filesystem/issues",
+ "source": "https://github.com/top-think/think-filesystem/tree/v1.0.1"
+ },
+ "install-path": "../topthink/think-filesystem"
+ },
{
"name": "topthink/think-helper",
"version": "v3.1.6",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 070593c..1bfa433 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -1,9 +1,9 @@
array(
'name' => 'hamm/y-admin',
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'reference' => NULL,
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '95d366412d3c3875146f9e30ccc76c567a4aae39',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -110,9 +110,9 @@
'dev_requirement' => false,
),
'hamm/y-admin' => array(
- 'pretty_version' => '1.0.0+no-version-set',
- 'version' => '1.0.0.0',
- 'reference' => NULL,
+ 'pretty_version' => 'dev-main',
+ 'version' => 'dev-main',
+ 'reference' => '95d366412d3c3875146f9e30ccc76c567a4aae39',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -154,6 +154,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
+ 'league/flysystem-cached-adapter' => array(
+ 'pretty_version' => '1.1.0',
+ 'version' => '1.1.0.0',
+ 'reference' => 'd1925efb2207ac4be3ad0c40b8277175f99ffaff',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../league/flysystem-cached-adapter',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
'league/mime-type-detection' => array(
'pretty_version' => '1.12.0',
'version' => '1.12.0.0',
@@ -564,6 +573,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
+ 'topthink/think-filesystem' => array(
+ 'pretty_version' => 'v1.0.1',
+ 'version' => '1.0.1.0',
+ 'reference' => 'cfc510520db9bcd22d8d80f51d7e415a2f470af6',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../topthink/think-filesystem',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
'topthink/think-helper' => array(
'pretty_version' => 'v3.1.6',
'version' => '3.1.6.0',
diff --git a/vendor/league/flysystem-cached-adapter/.editorconfig b/vendor/league/flysystem-cached-adapter/.editorconfig
new file mode 100644
index 0000000..153cf3e
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/.editorconfig
@@ -0,0 +1,10 @@
+; top-most EditorConfig file
+root = true
+
+; Unix-style newlines
+[*]
+end_of_line = LF
+
+[*.php]
+indent_style = space
+indent_size = 4
diff --git a/vendor/league/flysystem-cached-adapter/.gitignore b/vendor/league/flysystem-cached-adapter/.gitignore
new file mode 100644
index 0000000..7aea75f
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/.gitignore
@@ -0,0 +1,4 @@
+coverage
+coverage.xml
+composer.lock
+vendor
\ No newline at end of file
diff --git a/vendor/league/flysystem-cached-adapter/.php_cs b/vendor/league/flysystem-cached-adapter/.php_cs
new file mode 100644
index 0000000..6643a32
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/.php_cs
@@ -0,0 +1,7 @@
+level(Symfony\CS\FixerInterface::PSR2_LEVEL)
+ ->fixers(['-yoda_conditions', 'ordered_use', 'short_array_syntax'])
+ ->finder(Symfony\CS\Finder\DefaultFinder::create()
+ ->in(__DIR__.'/src/'));
\ No newline at end of file
diff --git a/vendor/league/flysystem-cached-adapter/.scrutinizer.yml b/vendor/league/flysystem-cached-adapter/.scrutinizer.yml
new file mode 100644
index 0000000..fa39b52
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/.scrutinizer.yml
@@ -0,0 +1,34 @@
+filter:
+ paths: [src/*]
+checks:
+ php:
+ code_rating: true
+ remove_extra_empty_lines: true
+ remove_php_closing_tag: true
+ remove_trailing_whitespace: true
+ fix_use_statements:
+ remove_unused: true
+ preserve_multiple: false
+ preserve_blanklines: true
+ order_alphabetically: true
+ fix_php_opening_tag: true
+ fix_linefeed: true
+ fix_line_ending: true
+ fix_identation_4spaces: true
+ fix_doc_comments: true
+tools:
+ external_code_coverage:
+ timeout: 900
+ runs: 6
+ php_code_coverage: false
+ php_code_sniffer:
+ config:
+ standard: PSR2
+ filter:
+ paths: ['src']
+ php_loc:
+ enabled: true
+ excluded_dirs: [vendor, spec, stubs]
+ php_cpd:
+ enabled: true
+ excluded_dirs: [vendor, spec, stubs]
\ No newline at end of file
diff --git a/vendor/league/flysystem-cached-adapter/.travis.yml b/vendor/league/flysystem-cached-adapter/.travis.yml
new file mode 100644
index 0000000..6706449
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/.travis.yml
@@ -0,0 +1,29 @@
+language: php
+
+php:
+ - 5.5
+ - 5.6
+ - 7.0
+ - 7.1
+ - 7.2
+
+matrix:
+ allow_failures:
+ - php: 5.5
+
+env:
+ - COMPOSER_OPTS=""
+ - COMPOSER_OPTS="--prefer-lowest"
+
+install:
+ - if [[ "${TRAVIS_PHP_VERSION}" == "5.5" ]]; then composer require phpunit/phpunit:^4.8.36 phpspec/phpspec:^2 --prefer-dist --update-with-dependencies; fi
+ - if [[ "${TRAVIS_PHP_VERSION}" == "7.2" ]]; then composer require phpunit/phpunit:^6.0 --prefer-dist --update-with-dependencies; fi
+ - travis_retry composer update --prefer-dist $COMPOSER_OPTS
+
+script:
+ - vendor/bin/phpspec run
+ - vendor/bin/phpunit
+
+after_script:
+ - wget https://scrutinizer-ci.com/ocular.phar'
+ - php ocular.phar code-coverage:upload --format=php-clover ./clover/phpunit.xml'
diff --git a/vendor/league/flysystem-cached-adapter/LICENSE b/vendor/league/flysystem-cached-adapter/LICENSE
new file mode 100644
index 0000000..666f6c8
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Frank de Jonge
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/league/flysystem-cached-adapter/clover/.gitignore b/vendor/league/flysystem-cached-adapter/clover/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/clover/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/vendor/league/flysystem-cached-adapter/composer.json b/vendor/league/flysystem-cached-adapter/composer.json
new file mode 100644
index 0000000..df7fb7f
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/composer.json
@@ -0,0 +1,30 @@
+{
+ "name": "league/flysystem-cached-adapter",
+ "description": "An adapter decorator to enable meta-data caching.",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\Cached\\": "src/"
+ }
+ },
+ "require": {
+ "league/flysystem": "~1.0",
+ "psr/cache": "^1.0.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "^3.4",
+ "phpunit/phpunit": "^5.7",
+ "mockery/mockery": "~0.9",
+ "predis/predis": "~1.0",
+ "tedivm/stash": "~0.12"
+ },
+ "suggest": {
+ "ext-phpredis": "Pure C implemented extension for PHP"
+ },
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "frankdejonge",
+ "email": "info@frenky.net"
+ }
+ ]
+}
diff --git a/vendor/league/flysystem-cached-adapter/phpspec.yml b/vendor/league/flysystem-cached-adapter/phpspec.yml
new file mode 100644
index 0000000..5eabcb2
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/phpspec.yml
@@ -0,0 +1,6 @@
+---
+suites:
+ cached_adapter_suite:
+ namespace: League\Flysystem\Cached
+ psr4_prefix: League\Flysystem\Cached
+formatter.name: pretty
diff --git a/vendor/league/flysystem-cached-adapter/phpunit.php b/vendor/league/flysystem-cached-adapter/phpunit.php
new file mode 100644
index 0000000..d109587
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/phpunit.php
@@ -0,0 +1,3 @@
+
+
+
+
+ ./tests/
+
+
+
+
+ ./src/
+
+
+
+
+
+
+
+
diff --git a/vendor/league/flysystem-cached-adapter/readme.md b/vendor/league/flysystem-cached-adapter/readme.md
new file mode 100644
index 0000000..dd1433d
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/readme.md
@@ -0,0 +1,20 @@
+# Flysystem Cached CachedAdapter
+
+[](https://twitter.com/frankdejonge)
+[](https://travis-ci.org/thephpleague/flysystem-cached-adapter)
+[](https://scrutinizer-ci.com/g/thephpleague/flysystem-cached-adapter/code-structure)
+[](https://scrutinizer-ci.com/g/thephpleague/flysystem-cached-adapter)
+[](LICENSE)
+[](https://packagist.org/packages/league/flysystem-cached-adapter)
+[](https://packagist.org/packages/league/flysystem-cached-adapter)
+
+
+The adapter decorator caches metadata and directory listings.
+
+```bash
+composer require league/flysystem-cached-adapter
+```
+
+## Usage
+
+[Check out the docs.](https://flysystem.thephpleague.com/docs/advanced/caching/)
diff --git a/vendor/league/flysystem-cached-adapter/spec/CachedAdapterSpec.php b/vendor/league/flysystem-cached-adapter/spec/CachedAdapterSpec.php
new file mode 100644
index 0000000..69428d9
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/spec/CachedAdapterSpec.php
@@ -0,0 +1,435 @@
+adapter = $adapter;
+ $this->cache = $cache;
+ $this->cache->load()->shouldBeCalled();
+ $this->beConstructedWith($adapter, $cache);
+ }
+
+ public function it_is_initializable()
+ {
+ $this->shouldHaveType('League\Flysystem\Cached\CachedAdapter');
+ $this->shouldHaveType('League\Flysystem\AdapterInterface');
+ }
+
+ public function it_should_forward_read_streams()
+ {
+ $path = 'path.txt';
+ $response = ['path' => $path];
+ $this->adapter->readStream($path)->willReturn($response);
+ $this->readStream($path)->shouldbe($response);
+ }
+
+ public function it_should_cache_writes()
+ {
+ $type = 'file';
+ $path = 'path.txt';
+ $contents = 'contents';
+ $config = new Config();
+ $response = compact('path', 'contents', 'type');
+ $this->adapter->write($path, $contents, $config)->willReturn($response);
+ $this->cache->updateObject($path, $response, true)->shouldBeCalled();
+ $this->write($path, $contents, $config)->shouldBe($response);
+ }
+
+ public function it_should_cache_streamed_writes()
+ {
+ $type = 'file';
+ $path = 'path.txt';
+ $stream = tmpfile();
+ $config = new Config();
+ $response = compact('path', 'stream', 'type');
+ $this->adapter->writeStream($path, $stream, $config)->willReturn($response);
+ $this->cache->updateObject($path, ['contents' => false] + $response, true)->shouldBeCalled();
+ $this->writeStream($path, $stream, $config)->shouldBe($response);
+ fclose($stream);
+ }
+
+ public function it_should_cache_streamed_updates()
+ {
+ $type = 'file';
+ $path = 'path.txt';
+ $stream = tmpfile();
+ $config = new Config();
+ $response = compact('path', 'stream', 'type');
+ $this->adapter->updateStream($path, $stream, $config)->willReturn($response);
+ $this->cache->updateObject($path, ['contents' => false] + $response, true)->shouldBeCalled();
+ $this->updateStream($path, $stream, $config)->shouldBe($response);
+ fclose($stream);
+ }
+
+ public function it_should_ignore_failed_writes()
+ {
+ $path = 'path.txt';
+ $contents = 'contents';
+ $config = new Config();
+ $this->adapter->write($path, $contents, $config)->willReturn(false);
+ $this->write($path, $contents, $config)->shouldBe(false);
+ }
+
+ public function it_should_ignore_failed_streamed_writes()
+ {
+ $path = 'path.txt';
+ $contents = tmpfile();
+ $config = new Config();
+ $this->adapter->writeStream($path, $contents, $config)->willReturn(false);
+ $this->writeStream($path, $contents, $config)->shouldBe(false);
+ fclose($contents);
+ }
+
+ public function it_should_cache_updated()
+ {
+ $type = 'file';
+ $path = 'path.txt';
+ $contents = 'contents';
+ $config = new Config();
+ $response = compact('path', 'contents', 'type');
+ $this->adapter->update($path, $contents, $config)->willReturn($response);
+ $this->cache->updateObject($path, $response, true)->shouldBeCalled();
+ $this->update($path, $contents, $config)->shouldBe($response);
+ }
+
+ public function it_should_ignore_failed_updates()
+ {
+ $path = 'path.txt';
+ $contents = 'contents';
+ $config = new Config();
+ $this->adapter->update($path, $contents, $config)->willReturn(false);
+ $this->update($path, $contents, $config)->shouldBe(false);
+ }
+
+ public function it_should_ignore_failed_streamed_updates()
+ {
+ $path = 'path.txt';
+ $contents = tmpfile();
+ $config = new Config();
+ $this->adapter->updateStream($path, $contents, $config)->willReturn(false);
+ $this->updateStream($path, $contents, $config)->shouldBe(false);
+ fclose($contents);
+ }
+
+ public function it_should_cache_renames()
+ {
+ $old = 'old.txt';
+ $new = 'new.txt';
+ $this->adapter->rename($old, $new)->willReturn(true);
+ $this->cache->rename($old, $new)->shouldBeCalled();
+ $this->rename($old, $new)->shouldBe(true);
+ }
+
+ public function it_should_ignore_rename_fails()
+ {
+ $old = 'old.txt';
+ $new = 'new.txt';
+ $this->adapter->rename($old, $new)->willReturn(false);
+ $this->rename($old, $new)->shouldBe(false);
+ }
+
+ public function it_should_cache_copies()
+ {
+ $old = 'old.txt';
+ $new = 'new.txt';
+ $this->adapter->copy($old, $new)->willReturn(true);
+ $this->cache->copy($old, $new)->shouldBeCalled();
+ $this->copy($old, $new)->shouldBe(true);
+ }
+
+ public function it_should_ignore_copy_fails()
+ {
+ $old = 'old.txt';
+ $new = 'new.txt';
+ $this->adapter->copy($old, $new)->willReturn(false);
+ $this->copy($old, $new)->shouldBe(false);
+ }
+
+ public function it_should_cache_deletes()
+ {
+ $delete = 'delete.txt';
+ $this->adapter->delete($delete)->willReturn(true);
+ $this->cache->delete($delete)->shouldBeCalled();
+ $this->delete($delete)->shouldBe(true);
+ }
+
+ public function it_should_ignore_delete_fails()
+ {
+ $delete = 'delete.txt';
+ $this->adapter->delete($delete)->willReturn(false);
+ $this->delete($delete)->shouldBe(false);
+ }
+
+ public function it_should_cache_dir_deletes()
+ {
+ $delete = 'delete';
+ $this->adapter->deleteDir($delete)->willReturn(true);
+ $this->cache->deleteDir($delete)->shouldBeCalled();
+ $this->deleteDir($delete)->shouldBe(true);
+ }
+
+ public function it_should_ignore_delete_dir_fails()
+ {
+ $delete = 'delete';
+ $this->adapter->deleteDir($delete)->willReturn(false);
+ $this->deleteDir($delete)->shouldBe(false);
+ }
+
+ public function it_should_cache_dir_creates()
+ {
+ $dirname = 'dirname';
+ $config = new Config();
+ $response = ['path' => $dirname, 'type' => 'dir'];
+ $this->adapter->createDir($dirname, $config)->willReturn($response);
+ $this->cache->updateObject($dirname, $response, true)->shouldBeCalled();
+ $this->createDir($dirname, $config)->shouldBe($response);
+ }
+
+ public function it_should_ignore_create_dir_fails()
+ {
+ $dirname = 'dirname';
+ $config = new Config();
+ $this->adapter->createDir($dirname, $config)->willReturn(false);
+ $this->createDir($dirname, $config)->shouldBe(false);
+ }
+
+ public function it_should_cache_set_visibility()
+ {
+ $path = 'path.txt';
+ $visibility = AdapterInterface::VISIBILITY_PUBLIC;
+ $this->adapter->setVisibility($path, $visibility)->willReturn(true);
+ $this->cache->updateObject($path, ['path' => $path, 'visibility' => $visibility], true)->shouldBeCalled();
+ $this->setVisibility($path, $visibility)->shouldBe(true);
+ }
+
+ public function it_should_ignore_set_visibility_fails()
+ {
+ $dirname = 'delete';
+ $visibility = AdapterInterface::VISIBILITY_PUBLIC;
+ $this->adapter->setVisibility($dirname, $visibility)->willReturn(false);
+ $this->setVisibility($dirname, $visibility)->shouldBe(false);
+ }
+
+ public function it_should_indicate_missing_files()
+ {
+ $this->cache->has($path = 'path.txt')->willReturn(false);
+ $this->has($path)->shouldBe(false);
+ }
+
+ public function it_should_indicate_file_existance()
+ {
+ $this->cache->has($path = 'path.txt')->willReturn(true);
+ $this->has($path)->shouldBe(true);
+ }
+
+ public function it_should_cache_missing_files()
+ {
+ $this->cache->has($path = 'path.txt')->willReturn(null);
+ $this->adapter->has($path)->willReturn(false);
+ $this->cache->storeMiss($path)->shouldBeCalled();
+ $this->has($path)->shouldBe(false);
+ }
+
+ public function it_should_delete_when_metadata_is_missing()
+ {
+ $path = 'path.txt';
+ $this->cache->has($path)->willReturn(true);
+ $this->cache->getSize($path)->willReturn(['path' => $path]);
+ $this->adapter->getSize($path)->willReturn($response = ['path' => $path, 'size' => 1024]);
+ $this->cache->updateObject($path, $response, true)->shouldBeCalled();
+ $this->getSize($path)->shouldBe($response);
+ }
+
+ public function it_should_cache_has()
+ {
+ $this->cache->has($path = 'path.txt')->willReturn(null);
+ $this->adapter->has($path)->willReturn(true);
+ $this->cache->updateObject($path, compact('path'), true)->shouldBeCalled();
+ $this->has($path)->shouldBe(true);
+ }
+
+ public function it_should_list_cached_contents()
+ {
+ $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(true);
+ $response = [['path' => 'path.txt']];
+ $this->cache->listContents($dirname, $recursive)->willReturn($response);
+ $this->listContents($dirname, $recursive)->shouldBe($response);
+ }
+
+ public function it_should_ignore_failed_list_contents()
+ {
+ $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(false);
+ $this->adapter->listContents($dirname, $recursive)->willReturn(false);
+ $this->listContents($dirname, $recursive)->shouldBe(false);
+ }
+
+ public function it_should_cache_contents_listings()
+ {
+ $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(false);
+ $response = [['path' => 'path.txt']];
+ $this->adapter->listContents($dirname, $recursive)->willReturn($response);
+ $this->cache->storeContents($dirname, $response, $recursive)->shouldBeCalled();
+ $this->listContents($dirname, $recursive)->shouldBe($response);
+ }
+
+ public function it_should_use_cached_visibility()
+ {
+ $this->make_it_use_getter_cache('getVisibility', 'path.txt', [
+ 'path' => 'path.txt',
+ 'visibility' => AdapterInterface::VISIBILITY_PUBLIC,
+ ]);
+ }
+
+ public function it_should_cache_get_visibility()
+ {
+ $path = 'path.txt';
+ $response = ['visibility' => AdapterInterface::VISIBILITY_PUBLIC, 'path' => $path];
+ $this->make_it_cache_getter('getVisibility', $path, $response);
+ }
+
+ public function it_should_ignore_failed_get_visibility()
+ {
+ $path = 'path.txt';
+ $this->make_it_ignore_failed_getter('getVisibility', $path);
+ }
+
+ public function it_should_use_cached_timestamp()
+ {
+ $this->make_it_use_getter_cache('getTimestamp', 'path.txt', [
+ 'path' => 'path.txt',
+ 'timestamp' => 1234,
+ ]);
+ }
+
+ public function it_should_cache_timestamps()
+ {
+ $this->make_it_cache_getter('getTimestamp', 'path.txt', [
+ 'path' => 'path.txt',
+ 'timestamp' => 1234,
+ ]);
+ }
+
+ public function it_should_ignore_failed_get_timestamps()
+ {
+ $this->make_it_ignore_failed_getter('getTimestamp', 'path.txt');
+ }
+
+ public function it_should_cache_get_metadata()
+ {
+ $path = 'path.txt';
+ $response = ['visibility' => AdapterInterface::VISIBILITY_PUBLIC, 'path' => $path];
+ $this->make_it_cache_getter('getMetadata', $path, $response);
+ }
+
+ public function it_should_use_cached_metadata()
+ {
+ $this->make_it_use_getter_cache('getMetadata', 'path.txt', [
+ 'path' => 'path.txt',
+ 'timestamp' => 1234,
+ ]);
+ }
+
+ public function it_should_ignore_failed_get_metadata()
+ {
+ $this->make_it_ignore_failed_getter('getMetadata', 'path.txt');
+ }
+
+ public function it_should_cache_get_size()
+ {
+ $path = 'path.txt';
+ $response = ['size' => 1234, 'path' => $path];
+ $this->make_it_cache_getter('getSize', $path, $response);
+ }
+
+ public function it_should_use_cached_size()
+ {
+ $this->make_it_use_getter_cache('getSize', 'path.txt', [
+ 'path' => 'path.txt',
+ 'size' => 1234,
+ ]);
+ }
+
+ public function it_should_ignore_failed_get_size()
+ {
+ $this->make_it_ignore_failed_getter('getSize', 'path.txt');
+ }
+
+ public function it_should_cache_get_mimetype()
+ {
+ $path = 'path.txt';
+ $response = ['mimetype' => 'text/plain', 'path' => $path];
+ $this->make_it_cache_getter('getMimetype', $path, $response);
+ }
+
+ public function it_should_use_cached_mimetype()
+ {
+ $this->make_it_use_getter_cache('getMimetype', 'path.txt', [
+ 'path' => 'path.txt',
+ 'mimetype' => 'text/plain',
+ ]);
+ }
+
+ public function it_should_ignore_failed_get_mimetype()
+ {
+ $this->make_it_ignore_failed_getter('getMimetype', 'path.txt');
+ }
+
+ public function it_should_cache_reads()
+ {
+ $path = 'path.txt';
+ $response = ['path' => $path, 'contents' => 'contents'];
+ $this->make_it_cache_getter('read', $path, $response);
+ }
+
+ public function it_should_use_cached_file_contents()
+ {
+ $this->make_it_use_getter_cache('read', 'path.txt', [
+ 'path' => 'path.txt',
+ 'contents' => 'contents'
+ ]);
+ }
+
+ public function it_should_ignore_failed_reads()
+ {
+ $this->make_it_ignore_failed_getter('read', 'path.txt');
+ }
+
+ protected function make_it_use_getter_cache($method, $path, $response)
+ {
+ $this->cache->{$method}($path)->willReturn($response);
+ $this->{$method}($path)->shouldBe($response);
+ }
+
+ protected function make_it_cache_getter($method, $path, $response)
+ {
+ $this->cache->{$method}($path)->willReturn(false);
+ $this->adapter->{$method}($path)->willReturn($response);
+ $this->cache->updateObject($path, $response, true)->shouldBeCalled();
+ $this->{$method}($path)->shouldBe($response);
+ }
+
+ protected function make_it_ignore_failed_getter($method, $path)
+ {
+ $this->cache->{$method}($path)->willReturn(false);
+ $this->adapter->{$method}($path)->willReturn(false);
+ $this->{$method}($path)->shouldBe(false);
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/CacheInterface.php b/vendor/league/flysystem-cached-adapter/src/CacheInterface.php
new file mode 100644
index 0000000..de3ab3d
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/CacheInterface.php
@@ -0,0 +1,101 @@
+adapter = $adapter;
+ $this->cache = $cache;
+ $this->cache->load();
+ }
+
+ /**
+ * Get the underlying Adapter implementation.
+ *
+ * @return AdapterInterface
+ */
+ public function getAdapter()
+ {
+ return $this->adapter;
+ }
+
+ /**
+ * Get the used Cache implementation.
+ *
+ * @return CacheInterface
+ */
+ public function getCache()
+ {
+ return $this->cache;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($path, $contents, Config $config)
+ {
+ $result = $this->adapter->write($path, $contents, $config);
+
+ if ($result !== false) {
+ $result['type'] = 'file';
+ $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function writeStream($path, $resource, Config $config)
+ {
+ $result = $this->adapter->writeStream($path, $resource, $config);
+
+ if ($result !== false) {
+ $result['type'] = 'file';
+ $contents = false;
+ $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update($path, $contents, Config $config)
+ {
+ $result = $this->adapter->update($path, $contents, $config);
+
+ if ($result !== false) {
+ $result['type'] = 'file';
+ $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function updateStream($path, $resource, Config $config)
+ {
+ $result = $this->adapter->updateStream($path, $resource, $config);
+
+ if ($result !== false) {
+ $result['type'] = 'file';
+ $contents = false;
+ $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rename($path, $newPath)
+ {
+ $result = $this->adapter->rename($path, $newPath);
+
+ if ($result !== false) {
+ $this->cache->rename($path, $newPath);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function copy($path, $newpath)
+ {
+ $result = $this->adapter->copy($path, $newpath);
+
+ if ($result !== false) {
+ $this->cache->copy($path, $newpath);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($path)
+ {
+ $result = $this->adapter->delete($path);
+
+ if ($result !== false) {
+ $this->cache->delete($path);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteDir($dirname)
+ {
+ $result = $this->adapter->deleteDir($dirname);
+
+ if ($result !== false) {
+ $this->cache->deleteDir($dirname);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createDir($dirname, Config $config)
+ {
+ $result = $this->adapter->createDir($dirname, $config);
+
+ if ($result !== false) {
+ $type = 'dir';
+ $path = $dirname;
+ $this->cache->updateObject($dirname, compact('path', 'type'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setVisibility($path, $visibility)
+ {
+ $result = $this->adapter->setVisibility($path, $visibility);
+
+ if ($result !== false) {
+ $this->cache->updateObject($path, compact('path', 'visibility'), true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($path)
+ {
+ $cacheHas = $this->cache->has($path);
+
+ if ($cacheHas !== null) {
+ return $cacheHas;
+ }
+
+ $adapterResponse = $this->adapter->has($path);
+
+ if (! $adapterResponse) {
+ $this->cache->storeMiss($path);
+ } else {
+ $cacheEntry = is_array($adapterResponse) ? $adapterResponse : compact('path');
+ $this->cache->updateObject($path, $cacheEntry, true);
+ }
+
+ return $adapterResponse;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($path)
+ {
+ return $this->callWithFallback('contents', $path, 'read');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function readStream($path)
+ {
+ return $this->adapter->readStream($path);
+ }
+
+ /**
+ * Get the path prefix.
+ *
+ * @return string|null path prefix or null if pathPrefix is empty
+ */
+ public function getPathPrefix()
+ {
+ return $this->adapter->getPathPrefix();
+ }
+
+ /**
+ * Prefix a path.
+ *
+ * @param string $path
+ *
+ * @return string prefixed path
+ */
+ public function applyPathPrefix($path)
+ {
+ return $this->adapter->applyPathPrefix($path);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function listContents($directory = '', $recursive = false)
+ {
+ if ($this->cache->isComplete($directory, $recursive)) {
+ return $this->cache->listContents($directory, $recursive);
+ }
+
+ $result = $this->adapter->listContents($directory, $recursive);
+
+ if ($result !== false) {
+ $this->cache->storeContents($directory, $result, $recursive);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata($path)
+ {
+ return $this->callWithFallback(null, $path, 'getMetadata');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSize($path)
+ {
+ return $this->callWithFallback('size', $path, 'getSize');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimetype($path)
+ {
+ return $this->callWithFallback('mimetype', $path, 'getMimetype');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTimestamp($path)
+ {
+ return $this->callWithFallback('timestamp', $path, 'getTimestamp');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVisibility($path)
+ {
+ return $this->callWithFallback('visibility', $path, 'getVisibility');
+ }
+
+ /**
+ * Call a method and cache the response.
+ *
+ * @param string $property
+ * @param string $path
+ * @param string $method
+ *
+ * @return mixed
+ */
+ protected function callWithFallback($property, $path, $method)
+ {
+ $result = $this->cache->{$method}($path);
+
+ if ($result !== false && ($property === null || array_key_exists($property, $result))) {
+ return $result;
+ }
+
+ $result = $this->adapter->{$method}($path);
+
+ if ($result) {
+ $object = $result + compact('path');
+ $this->cache->updateObject($path, $object, true);
+ }
+
+ return $result;
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php b/vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php
new file mode 100644
index 0000000..141b468
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php
@@ -0,0 +1,418 @@
+autosave) {
+ $this->save();
+ }
+ }
+
+ /**
+ * Get the autosave setting.
+ *
+ * @return bool autosave
+ */
+ public function getAutosave()
+ {
+ return $this->autosave;
+ }
+
+ /**
+ * Get the autosave setting.
+ *
+ * @param bool $autosave
+ */
+ public function setAutosave($autosave)
+ {
+ $this->autosave = $autosave;
+ }
+
+ /**
+ * Store the contents listing.
+ *
+ * @param string $directory
+ * @param array $contents
+ * @param bool $recursive
+ *
+ * @return array contents listing
+ */
+ public function storeContents($directory, array $contents, $recursive = false)
+ {
+ $directories = [$directory];
+
+ foreach ($contents as $object) {
+ $this->updateObject($object['path'], $object);
+ $object = $this->cache[$object['path']];
+
+ if ($recursive && $this->pathIsInDirectory($directory, $object['path'])) {
+ $directories[] = $object['dirname'];
+ }
+ }
+
+ foreach (array_unique($directories) as $directory) {
+ $this->setComplete($directory, $recursive);
+ }
+
+ $this->autosave();
+ }
+
+ /**
+ * Update the metadata for an object.
+ *
+ * @param string $path object path
+ * @param array $object object metadata
+ * @param bool $autosave whether to trigger the autosave routine
+ */
+ public function updateObject($path, array $object, $autosave = false)
+ {
+ if (! $this->has($path)) {
+ $this->cache[$path] = Util::pathinfo($path);
+ }
+
+ $this->cache[$path] = array_merge($this->cache[$path], $object);
+
+ if ($autosave) {
+ $this->autosave();
+ }
+
+ $this->ensureParentDirectories($path);
+ }
+
+ /**
+ * Store object hit miss.
+ *
+ * @param string $path
+ */
+ public function storeMiss($path)
+ {
+ $this->cache[$path] = false;
+ $this->autosave();
+ }
+
+ /**
+ * Get the contents listing.
+ *
+ * @param string $dirname
+ * @param bool $recursive
+ *
+ * @return array contents listing
+ */
+ public function listContents($dirname = '', $recursive = false)
+ {
+ $result = [];
+
+ foreach ($this->cache as $object) {
+ if ($object === false) {
+ continue;
+ }
+ if ($object['dirname'] === $dirname) {
+ $result[] = $object;
+ } elseif ($recursive && $this->pathIsInDirectory($dirname, $object['path'])) {
+ $result[] = $object;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($path)
+ {
+ if ($path !== false && array_key_exists($path, $this->cache)) {
+ return $this->cache[$path] !== false;
+ }
+
+ if ($this->isComplete(Util::dirname($path), false)) {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($path)
+ {
+ if (isset($this->cache[$path]['contents']) && $this->cache[$path]['contents'] !== false) {
+ return $this->cache[$path];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function readStream($path)
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rename($path, $newpath)
+ {
+ if ($this->has($path)) {
+ $object = $this->cache[$path];
+ unset($this->cache[$path]);
+ $object['path'] = $newpath;
+ $object = array_merge($object, Util::pathinfo($newpath));
+ $this->cache[$newpath] = $object;
+ $this->autosave();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function copy($path, $newpath)
+ {
+ if ($this->has($path)) {
+ $object = $this->cache[$path];
+ $object = array_merge($object, Util::pathinfo($newpath));
+ $this->updateObject($newpath, $object, true);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete($path)
+ {
+ $this->storeMiss($path);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteDir($dirname)
+ {
+ foreach ($this->cache as $path => $object) {
+ if ($this->pathIsInDirectory($dirname, $path) || $path === $dirname) {
+ unset($this->cache[$path]);
+ }
+ }
+
+ unset($this->complete[$dirname]);
+
+ $this->autosave();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMimetype($path)
+ {
+ if (isset($this->cache[$path]['mimetype'])) {
+ return $this->cache[$path];
+ }
+
+ if (! $result = $this->read($path)) {
+ return false;
+ }
+
+ $mimetype = Util::guessMimeType($path, $result['contents']);
+ $this->cache[$path]['mimetype'] = $mimetype;
+
+ return $this->cache[$path];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getSize($path)
+ {
+ if (isset($this->cache[$path]['size'])) {
+ return $this->cache[$path];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getTimestamp($path)
+ {
+ if (isset($this->cache[$path]['timestamp'])) {
+ return $this->cache[$path];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getVisibility($path)
+ {
+ if (isset($this->cache[$path]['visibility'])) {
+ return $this->cache[$path];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata($path)
+ {
+ if (isset($this->cache[$path]['type'])) {
+ return $this->cache[$path];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isComplete($dirname, $recursive)
+ {
+ if (! array_key_exists($dirname, $this->complete)) {
+ return false;
+ }
+
+ if ($recursive && $this->complete[$dirname] !== 'recursive') {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setComplete($dirname, $recursive)
+ {
+ $this->complete[$dirname] = $recursive ? 'recursive' : true;
+ }
+
+ /**
+ * Filter the contents from a listing.
+ *
+ * @param array $contents object listing
+ *
+ * @return array filtered contents
+ */
+ public function cleanContents(array $contents)
+ {
+ $cachedProperties = array_flip([
+ 'path', 'dirname', 'basename', 'extension', 'filename',
+ 'size', 'mimetype', 'visibility', 'timestamp', 'type',
+ 'md5',
+ ]);
+
+ foreach ($contents as $path => $object) {
+ if (is_array($object)) {
+ $contents[$path] = array_intersect_key($object, $cachedProperties);
+ }
+ }
+
+ return $contents;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function flush()
+ {
+ $this->cache = [];
+ $this->complete = [];
+ $this->autosave();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autosave()
+ {
+ if ($this->autosave) {
+ $this->save();
+ }
+ }
+
+ /**
+ * Retrieve serialized cache data.
+ *
+ * @return string serialized data
+ */
+ public function getForStorage()
+ {
+ $cleaned = $this->cleanContents($this->cache);
+
+ return json_encode([$cleaned, $this->complete]);
+ }
+
+ /**
+ * Load from serialized cache data.
+ *
+ * @param string $json
+ */
+ public function setFromStorage($json)
+ {
+ list($cache, $complete) = json_decode($json, true);
+
+ if (json_last_error() === JSON_ERROR_NONE && is_array($cache) && is_array($complete)) {
+ $this->cache = $cache;
+ $this->complete = $complete;
+ }
+ }
+
+ /**
+ * Ensure parent directories of an object.
+ *
+ * @param string $path object path
+ */
+ public function ensureParentDirectories($path)
+ {
+ $object = $this->cache[$path];
+
+ while ($object['dirname'] !== '' && ! isset($this->cache[$object['dirname']])) {
+ $object = Util::pathinfo($object['dirname']);
+ $object['type'] = 'dir';
+ $this->cache[$object['path']] = $object;
+ }
+ }
+
+ /**
+ * Determines if the path is inside the directory.
+ *
+ * @param string $directory
+ * @param string $path
+ *
+ * @return bool
+ */
+ protected function pathIsInDirectory($directory, $path)
+ {
+ return $directory === '' || strpos($path, $directory . '/') === 0;
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php b/vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php
new file mode 100644
index 0000000..649a60e
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php
@@ -0,0 +1,115 @@
+adapter = $adapter;
+ $this->file = $file;
+ $this->setExpire($expire);
+ }
+
+ /**
+ * Set the expiration time in seconds.
+ *
+ * @param int $expire relative expiration time
+ */
+ protected function setExpire($expire)
+ {
+ if ($expire) {
+ $this->expire = $this->getTime($expire);
+ }
+ }
+
+ /**
+ * Get expiration time in seconds.
+ *
+ * @param int $time relative expiration time
+ *
+ * @return int actual expiration time
+ */
+ protected function getTime($time = 0)
+ {
+ return intval(microtime(true)) + $time;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setFromStorage($json)
+ {
+ list($cache, $complete, $expire) = json_decode($json, true);
+
+ if (! $expire || $expire > $this->getTime()) {
+ $this->cache = is_array($cache) ? $cache : [];
+ $this->complete = is_array($complete) ? $complete : [];
+ } else {
+ $this->adapter->delete($this->file);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ if ($this->adapter->has($this->file)) {
+ $file = $this->adapter->read($this->file);
+ if ($file && !empty($file['contents'])) {
+ $this->setFromStorage($file['contents']);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getForStorage()
+ {
+ $cleaned = $this->cleanContents($this->cache);
+
+ return json_encode([$cleaned, $this->complete, $this->expire]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $config = new Config();
+ $contents = $this->getForStorage();
+
+ if ($this->adapter->has($this->file)) {
+ $this->adapter->update($this->file, $contents, $config);
+ } else {
+ $this->adapter->write($this->file, $contents, $config);
+ }
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Memcached.php b/vendor/league/flysystem-cached-adapter/src/Storage/Memcached.php
new file mode 100644
index 0000000..f67d271
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Memcached.php
@@ -0,0 +1,59 @@
+key = $key;
+ $this->expire = $expire;
+ $this->memcached = $memcached;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ $contents = $this->memcached->get($this->key);
+
+ if ($contents !== false) {
+ $this->setFromStorage($contents);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+ $expiration = $this->expire === null ? 0 : time() + $this->expire;
+ $this->memcached->set($this->key, $contents, $expiration);
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Memory.php b/vendor/league/flysystem-cached-adapter/src/Storage/Memory.php
new file mode 100644
index 0000000..d0914fa
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Memory.php
@@ -0,0 +1,22 @@
+client = $client ?: new Redis();
+ $this->key = $key;
+ $this->expire = $expire;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ $contents = $this->client->get($this->key);
+
+ if ($contents !== false) {
+ $this->setFromStorage($contents);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+ $this->client->set($this->key, $contents);
+
+ if ($this->expire !== null) {
+ $this->client->expire($this->key, $this->expire);
+ }
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Predis.php b/vendor/league/flysystem-cached-adapter/src/Storage/Predis.php
new file mode 100644
index 0000000..8a29574
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Predis.php
@@ -0,0 +1,75 @@
+client = $client ?: new Client();
+ $this->key = $key;
+ $this->expire = $expire;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ if (($contents = $this->executeCommand('get', [$this->key])) !== null) {
+ $this->setFromStorage($contents);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+ $this->executeCommand('set', [$this->key, $contents]);
+
+ if ($this->expire !== null) {
+ $this->executeCommand('expire', [$this->key, $this->expire]);
+ }
+ }
+
+ /**
+ * Execute a Predis command.
+ *
+ * @param string $name
+ * @param array $arguments
+ *
+ * @return string
+ */
+ protected function executeCommand($name, array $arguments)
+ {
+ $command = $this->client->createCommand($name, $arguments);
+
+ return $this->client->executeCommand($command);
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Psr6Cache.php b/vendor/league/flysystem-cached-adapter/src/Storage/Psr6Cache.php
new file mode 100644
index 0000000..43be87e
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Psr6Cache.php
@@ -0,0 +1,59 @@
+pool = $pool;
+ $this->key = $key;
+ $this->expire = $expire;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $item = $this->pool->getItem($this->key);
+ $item->set($this->getForStorage());
+ $item->expiresAfter($this->expire);
+ $this->pool->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ $item = $this->pool->getItem($this->key);
+ if ($item->isHit()) {
+ $this->setFromStorage($item->get());
+ }
+ }
+}
\ No newline at end of file
diff --git a/vendor/league/flysystem-cached-adapter/src/Storage/Stash.php b/vendor/league/flysystem-cached-adapter/src/Storage/Stash.php
new file mode 100644
index 0000000..e05b832
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/src/Storage/Stash.php
@@ -0,0 +1,60 @@
+key = $key;
+ $this->expire = $expire;
+ $this->pool = $pool;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function load()
+ {
+ $item = $this->pool->getItem($this->key);
+ $contents = $item->get();
+
+ if ($item->isMiss() === false) {
+ $this->setFromStorage($contents);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+ $item = $this->pool->getItem($this->key);
+ $item->set($contents, $this->expire);
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/AdapterCacheTests.php b/vendor/league/flysystem-cached-adapter/tests/AdapterCacheTests.php
new file mode 100644
index 0000000..b63cba7
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/AdapterCacheTests.php
@@ -0,0 +1,104 @@
+shouldReceive('has')->once()->with('file.json')->andReturn(false);
+ $cache = new Adapter($adapter, 'file.json', 10);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadExpired()
+ {
+ $response = ['contents' => json_encode([[], ['' => true], 1234567890]), 'path' => 'file.json'];
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->once()->with('file.json')->andReturn(true);
+ $adapter->shouldReceive('read')->once()->with('file.json')->andReturn($response);
+ $adapter->shouldReceive('delete')->once()->with('file.json');
+ $cache = new Adapter($adapter, 'file.json', 10);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = ['contents' => json_encode([[], ['' => true], 9876543210]), 'path' => 'file.json'];
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->once()->with('file.json')->andReturn(true);
+ $adapter->shouldReceive('read')->once()->with('file.json')->andReturn($response);
+ $cache = new Adapter($adapter, 'file.json', 10);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSaveExists()
+ {
+ $response = json_encode([[], [], null]);
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->once()->with('file.json')->andReturn(true);
+ $adapter->shouldReceive('update')->once()->with('file.json', $response, Mockery::any());
+ $cache = new Adapter($adapter, 'file.json', null);
+ $cache->save();
+ }
+
+ public function testSaveNew()
+ {
+ $response = json_encode([[], [], null]);
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->once()->with('file.json')->andReturn(false);
+ $adapter->shouldReceive('write')->once()->with('file.json', $response, Mockery::any());
+ $cache = new Adapter($adapter, 'file.json', null);
+ $cache->save();
+ }
+
+ public function testStoreContentsRecursive()
+ {
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->once()->with('file.json')->andReturn(false);
+ $adapter->shouldReceive('write')->once()->with('file.json', Mockery::any(), Mockery::any());
+
+ $cache = new Adapter($adapter, 'file.json', null);
+
+ $contents = [
+ ['path' => 'foo/bar', 'dirname' => 'foo'],
+ ['path' => 'afoo/bang', 'dirname' => 'afoo'],
+ ];
+
+ $cache->storeContents('foo', $contents, true);
+
+ $this->assertTrue($cache->isComplete('foo', true));
+ $this->assertFalse($cache->isComplete('afoo', true));
+ }
+
+ public function testDeleteDir()
+ {
+ $cache_data = [
+ 'foo' => ['path' => 'foo', 'type' => 'dir', 'dirname' => ''],
+ 'foo/bar' => ['path' => 'foo/bar', 'type' => 'file', 'dirname' => 'foo'],
+ 'foobaz' => ['path' => 'foobaz', 'type' => 'file', 'dirname' => ''],
+ ];
+
+ $response = [
+ 'contents' => json_encode([$cache_data, [], null]),
+ 'path' => 'file.json',
+ ];
+
+ $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+ $adapter->shouldReceive('has')->zeroOrMoreTimes()->with('file.json')->andReturn(true);
+ $adapter->shouldReceive('read')->once()->with('file.json')->andReturn($response);
+ $adapter->shouldReceive('update')->once()->with('file.json', Mockery::any(), Mockery::any())->andReturn(true);
+
+ $cache = new Adapter($adapter, 'file.json', null);
+ $cache->load();
+
+ $cache->deleteDir('foo', true);
+
+ $this->assertSame(1, count($cache->listContents('', true)));
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/InspectionTests.php b/vendor/league/flysystem-cached-adapter/tests/InspectionTests.php
new file mode 100644
index 0000000..40d4c91
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/InspectionTests.php
@@ -0,0 +1,16 @@
+shouldReceive('load')->once();
+ $cached_adapter = new CachedAdapter($adapter, $cache);
+ $this->assertInstanceOf('League\Flysystem\AdapterInterface', $cached_adapter->getAdapter());
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/MemcachedTests.php b/vendor/league/flysystem-cached-adapter/tests/MemcachedTests.php
new file mode 100644
index 0000000..e3d9ad9
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/MemcachedTests.php
@@ -0,0 +1,35 @@
+shouldReceive('get')->once()->andReturn(false);
+ $cache = new Memcached($client);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = json_encode([[], ['' => true]]);
+ $client = Mockery::mock('Memcached');
+ $client->shouldReceive('get')->once()->andReturn($response);
+ $cache = new Memcached($client);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSave()
+ {
+ $response = json_encode([[], []]);
+ $client = Mockery::mock('Memcached');
+ $client->shouldReceive('set')->once()->andReturn($response);
+ $cache = new Memcached($client);
+ $cache->save();
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/MemoryCacheTests.php b/vendor/league/flysystem-cached-adapter/tests/MemoryCacheTests.php
new file mode 100644
index 0000000..3ac58fd
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/MemoryCacheTests.php
@@ -0,0 +1,255 @@
+setAutosave(true);
+ $this->assertTrue($cache->getAutosave());
+ $cache->setAutosave(false);
+ $this->assertFalse($cache->getAutosave());
+ }
+
+ public function testCacheMiss()
+ {
+ $cache = new Memory();
+ $cache->storeMiss('path.txt');
+ $this->assertFalse($cache->has('path.txt'));
+ }
+
+ public function testIsComplete()
+ {
+ $cache = new Memory();
+ $this->assertFalse($cache->isComplete('dirname', false));
+ $cache->setComplete('dirname', false);
+ $this->assertFalse($cache->isComplete('dirname', true));
+ $cache->setComplete('dirname', true);
+ $this->assertTrue($cache->isComplete('dirname', true));
+ }
+
+ public function testCleanContents()
+ {
+ $cache = new Memory();
+ $input = [[
+ 'path' => 'path.txt',
+ 'visibility' => 'public',
+ 'invalid' => 'thing',
+ ]];
+
+ $expected = [[
+ 'path' => 'path.txt',
+ 'visibility' => 'public',
+ ]];
+
+ $output = $cache->cleanContents($input);
+ $this->assertEquals($expected, $output);
+ }
+
+ public function testGetForStorage()
+ {
+ $cache = new Memory();
+ $input = [[
+ 'path' => 'path.txt',
+ 'visibility' => 'public',
+ 'type' => 'file',
+ ]];
+
+ $cache->storeContents('', $input, true);
+ $contents = $cache->listContents('', true);
+ $cached = [];
+ foreach ($contents as $item) {
+ $cached[$item['path']] = $item;
+ }
+
+ $this->assertEquals(json_encode([$cached, ['' => 'recursive']]), $cache->getForStorage());
+ }
+
+ public function testParentCompleteIsUsedDuringHas()
+ {
+ $cache = new Memory();
+ $cache->setComplete('dirname', false);
+ $this->assertFalse($cache->has('dirname/path.txt'));
+ }
+
+ public function testFlush()
+ {
+ $cache = new Memory();
+ $cache->setComplete('dirname', true);
+ $cache->updateObject('path.txt', [
+ 'path' => 'path.txt',
+ 'visibility' => 'public',
+ ]);
+ $cache->flush();
+ $this->assertFalse($cache->isComplete('dirname', true));
+ $this->assertNull($cache->has('path.txt'));
+ }
+
+ public function testSetFromStorage()
+ {
+ $cache = new Memory();
+ $json = [[
+ 'path.txt' => ['path' => 'path.txt', 'type' => 'file'],
+ ], ['dirname' => 'recursive']];
+ $jsonString = json_encode($json);
+ $cache->setFromStorage($jsonString);
+ $this->assertTrue($cache->has('path.txt'));
+ $this->assertTrue($cache->isComplete('dirname', true));
+ }
+
+ public function testGetMetadataFail()
+ {
+ $cache = new Memory();
+ $this->assertFalse($cache->getMetadata('path.txt'));
+ }
+
+ public function metaGetterProvider()
+ {
+ return [
+ ['getTimestamp', 'timestamp', 12344],
+ ['getMimetype', 'mimetype', 'text/plain'],
+ ['getSize', 'size', 12],
+ ['getVisibility', 'visibility', 'private'],
+ ['read', 'contents', '__contents__'],
+ ];
+ }
+
+ /**
+ * @dataProvider metaGetterProvider
+ *
+ * @param $method
+ * @param $key
+ * @param $value
+ */
+ public function testMetaGetters($method, $key, $value)
+ {
+ $cache = new Memory();
+ $this->assertFalse($cache->{$method}('path.txt'));
+ $cache->updateObject('path.txt', $object = [
+ 'path' => 'path.txt',
+ 'type' => 'file',
+ $key => $value,
+ ] + Util::pathinfo('path.txt'), true);
+ $this->assertEquals($object, $cache->{$method}('path.txt'));
+ $this->assertEquals($object, $cache->getMetadata('path.txt'));
+ }
+
+ public function testGetDerivedMimetype()
+ {
+ $cache = new Memory();
+ $cache->updateObject('path.txt', [
+ 'contents' => 'something',
+ ]);
+ $response = $cache->getMimetype('path.txt');
+ $this->assertEquals('text/plain', $response['mimetype']);
+ }
+
+ public function testCopyFail()
+ {
+ $cache = new Memory();
+ $cache->copy('one', 'two');
+ $this->assertNull($cache->has('two'));
+ $this->assertNull($cache->load());
+ }
+
+ public function testStoreContents()
+ {
+ $cache = new Memory();
+ $cache->storeContents('dirname', [
+ ['path' => 'dirname', 'type' => 'dir'],
+ ['path' => 'dirname/nested', 'type' => 'dir'],
+ ['path' => 'dirname/nested/deep', 'type' => 'dir'],
+ ['path' => 'other/nested/deep', 'type' => 'dir'],
+ ], true);
+
+ $this->isTrue($cache->isComplete('other/nested', true));
+ }
+
+ public function testDelete()
+ {
+ $cache = new Memory();
+ $cache->updateObject('path.txt', ['type' => 'file']);
+ $this->assertTrue($cache->has('path.txt'));
+ $cache->delete('path.txt');
+ $this->assertFalse($cache->has('path.txt'));
+ }
+
+ public function testDeleteDir()
+ {
+ $cache = new Memory();
+ $cache->storeContents('dirname', [
+ ['path' => 'dirname/path.txt', 'type' => 'file'],
+ ]);
+ $this->assertTrue($cache->isComplete('dirname', false));
+ $this->assertTrue($cache->has('dirname/path.txt'));
+ $cache->deleteDir('dirname');
+ $this->assertFalse($cache->isComplete('dirname', false));
+ $this->assertNull($cache->has('dirname/path.txt'));
+ }
+
+ public function testReadStream()
+ {
+ $cache = new Memory();
+ $this->assertFalse($cache->readStream('path.txt'));
+ }
+
+ public function testRename()
+ {
+ $cache = new Memory();
+ $cache->updateObject('path.txt', ['type' => 'file']);
+ $cache->rename('path.txt', 'newpath.txt');
+ $this->assertTrue($cache->has('newpath.txt'));
+ }
+
+ public function testCopy()
+ {
+ $cache = new Memory();
+ $cache->updateObject('path.txt', ['type' => 'file']);
+ $cache->copy('path.txt', 'newpath.txt');
+ $this->assertTrue($cache->has('newpath.txt'));
+ }
+
+ public function testComplextListContents()
+ {
+ $cache = new Memory();
+ $cache->storeContents('', [
+ ['path' => 'dirname', 'type' => 'dir'],
+ ['path' => 'dirname/file.txt', 'type' => 'file'],
+ ['path' => 'other', 'type' => 'dir'],
+ ['path' => 'other/file.txt', 'type' => 'file'],
+ ['path' => 'other/nested/file.txt', 'type' => 'file'],
+ ]);
+
+ $this->assertCount(3, $cache->listContents('other', true));
+ }
+
+ public function testComplextListContentsWithDeletedFile()
+ {
+ $cache = new Memory();
+ $cache->storeContents('', [
+ ['path' => 'dirname', 'type' => 'dir'],
+ ['path' => 'dirname/file.txt', 'type' => 'file'],
+ ['path' => 'other', 'type' => 'dir'],
+ ['path' => 'other/file.txt', 'type' => 'file'],
+ ['path' => 'other/another_file.txt', 'type' => 'file'],
+ ]);
+
+ $cache->delete('other/another_file.txt');
+ $this->assertCount(4, $cache->listContents('', true));
+ }
+
+ public function testCacheMissIfContentsIsFalse()
+ {
+ $cache = new Memory();
+ $cache->updateObject('path.txt', [
+ 'path' => 'path.txt',
+ 'contents' => false,
+ ], true);
+
+ $this->assertFalse($cache->read('path.txt'));
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/NoopCacheTests.php b/vendor/league/flysystem-cached-adapter/tests/NoopCacheTests.php
new file mode 100644
index 0000000..148616f
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/NoopCacheTests.php
@@ -0,0 +1,35 @@
+assertEquals($cache, $cache->storeMiss('file.txt'));
+ $this->assertNull($cache->setComplete('', false));
+ $this->assertNull($cache->load());
+ $this->assertNull($cache->flush());
+ $this->assertNull($cache->has('path.txt'));
+ $this->assertNull($cache->autosave());
+ $this->assertFalse($cache->isComplete('', false));
+ $this->assertFalse($cache->read('something'));
+ $this->assertFalse($cache->readStream('something'));
+ $this->assertFalse($cache->getMetadata('something'));
+ $this->assertFalse($cache->getMimetype('something'));
+ $this->assertFalse($cache->getSize('something'));
+ $this->assertFalse($cache->getTimestamp('something'));
+ $this->assertFalse($cache->getVisibility('something'));
+ $this->assertEmpty($cache->listContents('', false));
+ $this->assertFalse($cache->rename('', ''));
+ $this->assertFalse($cache->copy('', ''));
+ $this->assertNull($cache->save());
+ $object = ['path' => 'path.ext'];
+ $this->assertEquals($object, $cache->updateObject('path.txt', $object));
+ $this->assertEquals([['path' => 'some/file.txt']], $cache->storeContents('unknwon', [
+ ['path' => 'some/file.txt'],
+ ], false));
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/PhpRedisTests.php b/vendor/league/flysystem-cached-adapter/tests/PhpRedisTests.php
new file mode 100644
index 0000000..d1ccb65
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/PhpRedisTests.php
@@ -0,0 +1,45 @@
+shouldReceive('get')->with('flysystem')->once()->andReturn(false);
+ $cache = new PhpRedis($client);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = json_encode([[], ['' => true]]);
+ $client = Mockery::mock('Redis');
+ $client->shouldReceive('get')->with('flysystem')->once()->andReturn($response);
+ $cache = new PhpRedis($client);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSave()
+ {
+ $data = json_encode([[], []]);
+ $client = Mockery::mock('Redis');
+ $client->shouldReceive('set')->with('flysystem', $data)->once();
+ $cache = new PhpRedis($client);
+ $cache->save();
+ }
+
+ public function testSaveWithExpire()
+ {
+ $data = json_encode([[], []]);
+ $client = Mockery::mock('Redis');
+ $client->shouldReceive('set')->with('flysystem', $data)->once();
+ $client->shouldReceive('expire')->with('flysystem', 20)->once();
+ $cache = new PhpRedis($client, 'flysystem', 20);
+ $cache->save();
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/PredisTests.php b/vendor/league/flysystem-cached-adapter/tests/PredisTests.php
new file mode 100644
index 0000000..e33e104
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/PredisTests.php
@@ -0,0 +1,55 @@
+shouldReceive('createCommand')->with('get', ['flysystem'])->once()->andReturn($command);
+ $client->shouldReceive('executeCommand')->with($command)->andReturn(null);
+ $cache = new Predis($client);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = json_encode([[], ['' => true]]);
+ $client = Mockery::mock('Predis\Client');
+ $command = Mockery::mock('Predis\Command\CommandInterface');
+ $client->shouldReceive('createCommand')->with('get', ['flysystem'])->once()->andReturn($command);
+ $client->shouldReceive('executeCommand')->with($command)->andReturn($response);
+ $cache = new Predis($client);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSave()
+ {
+ $data = json_encode([[], []]);
+ $client = Mockery::mock('Predis\Client');
+ $command = Mockery::mock('Predis\Command\CommandInterface');
+ $client->shouldReceive('createCommand')->with('set', ['flysystem', $data])->once()->andReturn($command);
+ $client->shouldReceive('executeCommand')->with($command)->once();
+ $cache = new Predis($client);
+ $cache->save();
+ }
+
+ public function testSaveWithExpire()
+ {
+ $data = json_encode([[], []]);
+ $client = Mockery::mock('Predis\Client');
+ $command = Mockery::mock('Predis\Command\CommandInterface');
+ $client->shouldReceive('createCommand')->with('set', ['flysystem', $data])->once()->andReturn($command);
+ $client->shouldReceive('executeCommand')->with($command)->once();
+ $expireCommand = Mockery::mock('Predis\Command\CommandInterface');
+ $client->shouldReceive('createCommand')->with('expire', ['flysystem', 20])->once()->andReturn($expireCommand);
+ $client->shouldReceive('executeCommand')->with($expireCommand)->once();
+ $cache = new Predis($client, 'flysystem', 20);
+ $cache->save();
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/Psr6CacheTest.php b/vendor/league/flysystem-cached-adapter/tests/Psr6CacheTest.php
new file mode 100644
index 0000000..d5e5700
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/Psr6CacheTest.php
@@ -0,0 +1,45 @@
+shouldReceive('isHit')->once()->andReturn(false);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $cache = new Psr6Cache($pool);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = json_encode([[], ['' => true]]);
+ $pool = Mockery::mock('Psr\Cache\CacheItemPoolInterface');
+ $item = Mockery::mock('Psr\Cache\CacheItemInterface');
+ $item->shouldReceive('get')->once()->andReturn($response);
+ $item->shouldReceive('isHit')->once()->andReturn(true);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $cache = new Psr6Cache($pool);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSave()
+ {
+ $response = json_encode([[], []]);
+ $ttl = 4711;
+ $pool = Mockery::mock('Psr\Cache\CacheItemPoolInterface');
+ $item = Mockery::mock('Psr\Cache\CacheItemInterface');
+ $item->shouldReceive('expiresAfter')->once()->with($ttl);
+ $item->shouldReceive('set')->once()->andReturn($response);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $pool->shouldReceive('save')->once()->with($item);
+ $cache = new Psr6Cache($pool, 'foo', $ttl);
+ $cache->save();
+ }
+}
diff --git a/vendor/league/flysystem-cached-adapter/tests/StashTest.php b/vendor/league/flysystem-cached-adapter/tests/StashTest.php
new file mode 100644
index 0000000..29e142d
--- /dev/null
+++ b/vendor/league/flysystem-cached-adapter/tests/StashTest.php
@@ -0,0 +1,43 @@
+shouldReceive('get')->once()->andReturn(null);
+ $item->shouldReceive('isMiss')->once()->andReturn(true);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $cache = new Stash($pool);
+ $cache->load();
+ $this->assertFalse($cache->isComplete('', false));
+ }
+
+ public function testLoadSuccess()
+ {
+ $response = json_encode([[], ['' => true]]);
+ $pool = Mockery::mock('Stash\Pool');
+ $item = Mockery::mock('Stash\Item');
+ $item->shouldReceive('get')->once()->andReturn($response);
+ $item->shouldReceive('isMiss')->once()->andReturn(false);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $cache = new Stash($pool);
+ $cache->load();
+ $this->assertTrue($cache->isComplete('', false));
+ }
+
+ public function testSave()
+ {
+ $response = json_encode([[], []]);
+ $pool = Mockery::mock('Stash\Pool');
+ $item = Mockery::mock('Stash\Item');
+ $item->shouldReceive('set')->once()->andReturn($response);
+ $pool->shouldReceive('getItem')->once()->andReturn($item);
+ $cache = new Stash($pool);
+ $cache->save();
+ }
+}
diff --git a/vendor/services.php b/vendor/services.php
index 2db7631..19d052d 100644
--- a/vendor/services.php
+++ b/vendor/services.php
@@ -1,5 +1,5 @@
'think\\app\\Service',
diff --git a/vendor/topthink/think-filesystem/.gitignore b/vendor/topthink/think-filesystem/.gitignore
new file mode 100644
index 0000000..25ad74d
--- /dev/null
+++ b/vendor/topthink/think-filesystem/.gitignore
@@ -0,0 +1,3 @@
+composer.lock
+/.idea
+/vendor
diff --git a/vendor/topthink/think-filesystem/README.md b/vendor/topthink/think-filesystem/README.md
new file mode 100644
index 0000000..90977dd
--- /dev/null
+++ b/vendor/topthink/think-filesystem/README.md
@@ -0,0 +1,5 @@
+# think-filesystem for ThinkPHP6.1
+
+## 安装
+
+> composer require topthink/think-filesystem
diff --git a/vendor/topthink/think-filesystem/composer.json b/vendor/topthink/think-filesystem/composer.json
new file mode 100644
index 0000000..040f4a3
--- /dev/null
+++ b/vendor/topthink/think-filesystem/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "topthink/think-filesystem",
+ "description": "The ThinkPHP6.1 Filesystem Package",
+ "type": "library",
+ "license": "Apache-2.0",
+ "authors": [
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "think\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "think\\tests\\": "tests/"
+ }
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "topthink/framework": "^6.1",
+ "league/flysystem": "^1.1.4",
+ "league/flysystem-cached-adapter": "^1.0"
+ },
+ "require-dev": {
+ "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.2",
+ "phpunit/phpunit": "^8.0"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/vendor/topthink/think-filesystem/phpunit.xml.dist b/vendor/topthink/think-filesystem/phpunit.xml.dist
new file mode 100644
index 0000000..e20a133
--- /dev/null
+++ b/vendor/topthink/think-filesystem/phpunit.xml.dist
@@ -0,0 +1,25 @@
+
+
+
+
+ ./tests
+
+
+
+
+ ./src/think
+
+
+
diff --git a/vendor/topthink/think-filesystem/src/Filesystem.php b/vendor/topthink/think-filesystem/src/Filesystem.php
new file mode 100644
index 0000000..0aee929
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/Filesystem.php
@@ -0,0 +1,89 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think;
+
+use InvalidArgumentException;
+use think\filesystem\Driver;
+use think\filesystem\driver\Local;
+use think\helper\Arr;
+
+/**
+ * Class Filesystem
+ * @package think
+ * @mixin Driver
+ * @mixin Local
+ */
+class Filesystem extends Manager
+{
+ protected $namespace = '\\think\\filesystem\\driver\\';
+
+ /**
+ * @param null|string $name
+ * @return Driver
+ */
+ public function disk(string $name = null): Driver
+ {
+ return $this->driver($name);
+ }
+
+ protected function resolveType(string $name)
+ {
+ return $this->getDiskConfig($name, 'type', 'local');
+ }
+
+ protected function resolveConfig(string $name)
+ {
+ return $this->getDiskConfig($name);
+ }
+
+ /**
+ * 获取缓存配置
+ * @access public
+ * @param null|string $name 名称
+ * @param mixed $default 默认值
+ * @return mixed
+ */
+ public function getConfig(string $name = null, $default = null)
+ {
+ if (!is_null($name)) {
+ return $this->app->config->get('filesystem.' . $name, $default);
+ }
+
+ return $this->app->config->get('filesystem');
+ }
+
+ /**
+ * 获取磁盘配置
+ * @param string $disk
+ * @param null $name
+ * @param null $default
+ * @return array
+ */
+ public function getDiskConfig($disk, $name = null, $default = null)
+ {
+ if ($config = $this->getConfig("disks.{$disk}")) {
+ return Arr::get($config, $name, $default);
+ }
+
+ throw new InvalidArgumentException("Disk [$disk] not found.");
+ }
+
+ /**
+ * 默认驱动
+ * @return string|null
+ */
+ public function getDefaultDriver()
+ {
+ return $this->getConfig('default');
+ }
+}
diff --git a/vendor/topthink/think-filesystem/src/facade/Filesystem.php b/vendor/topthink/think-filesystem/src/facade/Filesystem.php
new file mode 100644
index 0000000..0e32c2c
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/facade/Filesystem.php
@@ -0,0 +1,33 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\facade;
+
+use think\Facade;
+use think\filesystem\Driver;
+
+/**
+ * Class Filesystem
+ * @package think\facade
+ * @mixin \think\Filesystem
+ * @method static Driver disk(string $name = null) , null|string
+ * @method static mixed getConfig(null|string $name = null, mixed $default = null) 获取缓存配置
+ * @method static array getDiskConfig(string $disk, null $name = null, null $default = null) 获取磁盘配置
+ * @method static string|null getDefaultDriver() 默认驱动
+ */
+class Filesystem extends Facade
+{
+ protected static function getFacadeClass()
+ {
+ return \think\Filesystem::class;
+ }
+}
diff --git a/vendor/topthink/think-filesystem/src/filesystem/CacheStore.php b/vendor/topthink/think-filesystem/src/filesystem/CacheStore.php
new file mode 100644
index 0000000..0a62399
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/filesystem/CacheStore.php
@@ -0,0 +1,54 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\filesystem;
+
+use League\Flysystem\Cached\Storage\AbstractCache;
+use Psr\SimpleCache\CacheInterface;
+
+class CacheStore extends AbstractCache
+{
+ protected $store;
+
+ protected $key;
+
+ protected $expire;
+
+ public function __construct(CacheInterface $store, $key = 'flysystem', $expire = null)
+ {
+ $this->key = $key;
+ $this->store = $store;
+ $this->expire = $expire;
+ }
+
+ /**
+ * Store the cache.
+ */
+ public function save()
+ {
+ $contents = $this->getForStorage();
+
+ $this->store->set($this->key, $contents, $this->expire);
+ }
+
+ /**
+ * Load the cache.
+ */
+ public function load()
+ {
+ $contents = $this->store->get($this->key);
+
+ if (!is_null($contents)) {
+ $this->setFromStorage($contents);
+ }
+ }
+}
diff --git a/vendor/topthink/think-filesystem/src/filesystem/Driver.php b/vendor/topthink/think-filesystem/src/filesystem/Driver.php
new file mode 100644
index 0000000..0e61cf4
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/filesystem/Driver.php
@@ -0,0 +1,144 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\filesystem;
+
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Adapter\AbstractAdapter;
+use League\Flysystem\Cached\CachedAdapter;
+use League\Flysystem\Cached\Storage\Memory as MemoryStore;
+use League\Flysystem\Filesystem;
+use RuntimeException;
+use think\Cache;
+use think\File;
+
+/**
+ * Class Driver
+ * @package think\filesystem
+ * @mixin Filesystem
+ */
+abstract class Driver
+{
+
+ /** @var Cache */
+ protected $cache;
+
+ /** @var Filesystem */
+ protected $filesystem;
+
+ /**
+ * 配置参数
+ * @var array
+ */
+ protected $config = [];
+
+ public function __construct(Cache $cache, array $config)
+ {
+ $this->cache = $cache;
+ $this->config = array_merge($this->config, $config);
+
+ $adapter = $this->createAdapter();
+ $this->filesystem = $this->createFilesystem($adapter);
+ }
+
+ protected function createCacheStore($config)
+ {
+ if (true === $config) {
+ return new MemoryStore;
+ }
+
+ return new CacheStore(
+ $this->cache->store($config['store']),
+ $config['prefix'] ?? 'flysystem',
+ $config['expire'] ?? null
+ );
+ }
+
+ abstract protected function createAdapter(): AdapterInterface;
+
+ protected function createFilesystem(AdapterInterface $adapter): Filesystem
+ {
+ if (!empty($this->config['cache'])) {
+ $adapter = new CachedAdapter($adapter, $this->createCacheStore($this->config['cache']));
+ }
+
+ $config = array_intersect_key($this->config, array_flip(['visibility', 'disable_asserts', 'url']));
+
+ return new Filesystem($adapter, count($config) > 0 ? $config : null);
+ }
+
+ /**
+ * 获取文件完整路径
+ * @param string $path
+ * @return string
+ */
+ public function path(string $path): string
+ {
+ $adapter = $this->filesystem->getAdapter();
+
+ if ($adapter instanceof AbstractAdapter) {
+ return $adapter->applyPathPrefix($path);
+ }
+
+ return $path;
+ }
+
+ protected function concatPathToUrl($url, $path)
+ {
+ return rtrim($url, '/') . '/' . ltrim($path, '/');
+ }
+
+ public function url(string $path): string
+ {
+ throw new RuntimeException('This driver does not support retrieving URLs.');
+ }
+
+ /**
+ * 保存文件
+ * @param string $path 路径
+ * @param File $file 文件
+ * @param null|string|\Closure $rule 文件名规则
+ * @param array $options 参数
+ * @return bool|string
+ */
+ public function putFile(string $path, File $file, $rule = null, array $options = [])
+ {
+ return $this->putFileAs($path, $file, $file->hashName($rule), $options);
+ }
+
+ /**
+ * 指定文件名保存文件
+ * @param string $path 路径
+ * @param File $file 文件
+ * @param string $name 文件名
+ * @param array $options 参数
+ * @return bool|string
+ */
+ public function putFileAs(string $path, File $file, string $name, array $options = [])
+ {
+ $stream = fopen($file->getRealPath(), 'r');
+ $path = trim($path . '/' . $name, '/');
+
+ $result = $this->putStream($path, $stream, $options);
+
+ if (is_resource($stream)) {
+ fclose($stream);
+ }
+
+ return $result ? $path : false;
+ }
+
+ public function __call($method, $parameters)
+ {
+ return $this->filesystem->$method(...$parameters);
+ }
+}
diff --git a/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php
new file mode 100644
index 0000000..5749335
--- /dev/null
+++ b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php
@@ -0,0 +1,59 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types = 1);
+
+namespace think\filesystem\driver;
+
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Adapter\Local as LocalAdapter;
+use think\filesystem\Driver;
+
+class Local extends Driver
+{
+ /**
+ * 配置参数
+ * @var array
+ */
+ protected $config = [
+ 'root' => '',
+ ];
+
+ protected function createAdapter(): AdapterInterface
+ {
+ $permissions = $this->config['permissions'] ?? [];
+
+ $links = ($this->config['links'] ?? null) === 'skip'
+ ? LocalAdapter::SKIP_LINKS
+ : LocalAdapter::DISALLOW_LINKS;
+
+ return new LocalAdapter(
+ $this->config['root'],
+ LOCK_EX,
+ $links,
+ $permissions
+ );
+ }
+
+ /**
+ * 获取文件访问地址
+ * @param string $path 文件路径
+ * @return string
+ */
+ public function url(string $path): string
+ {
+ $path = str_replace('\\', '/', $path);
+
+ if (isset($this->config['url'])) {
+ return $this->concatPathToUrl($this->config['url'], $path);
+ }
+ return parent::url($path);
+ }
+}
diff --git a/vendor/topthink/think-filesystem/tests/FilesystemTest.php b/vendor/topthink/think-filesystem/tests/FilesystemTest.php
new file mode 100644
index 0000000..a589771
--- /dev/null
+++ b/vendor/topthink/think-filesystem/tests/FilesystemTest.php
@@ -0,0 +1,131 @@
+app = m::mock(App::class)->makePartial();
+ Container::setInstance($this->app);
+ $this->app->shouldReceive('make')->with(App::class)->andReturn($this->app);
+ $this->config = m::mock(Config::class);
+ $this->config->shouldReceive('get')->with('filesystem.default', null)->andReturn('local');
+ $this->app->shouldReceive('get')->with('config')->andReturn($this->config);
+ $this->filesystem = new Filesystem($this->app);
+
+ $this->root = vfsStream::setup('rootDir');
+ }
+
+ protected function tearDown(): void
+ {
+ m::close();
+ }
+
+ public function testDisk()
+ {
+ $this->config->shouldReceive('get')->with('filesystem.disks.local', null)->andReturn([
+ 'type' => 'local',
+ 'root' => $this->root->url(),
+ ]);
+
+ $this->config->shouldReceive('get')->with('filesystem.disks.foo', null)->andReturn([
+ 'type' => 'local',
+ 'root' => $this->root->url(),
+ ]);
+
+ $this->assertInstanceOf(Local::class, $this->filesystem->disk());
+
+ $this->assertInstanceOf(Local::class, $this->filesystem->disk('foo'));
+ }
+
+ public function testCache()
+ {
+ $this->config->shouldReceive('get')->with('filesystem.disks.local', null)->andReturn([
+ 'type' => 'local',
+ 'root' => $this->root->url(),
+ 'cache' => true,
+ ]);
+
+ $this->assertInstanceOf(Local::class, $this->filesystem->disk());
+
+ $this->config->shouldReceive('get')->with('filesystem.disks.cache', null)->andReturn([
+ 'type' => NullDriver::class,
+ 'root' => $this->root->url(),
+ 'cache' => [
+ 'store' => 'flysystem',
+ ],
+ ]);
+
+ $cache = m::mock(Cache::class);
+
+ $cacheDriver = m::mock(File::class);
+
+ $cache->shouldReceive('store')->once()->with('flysystem')->andReturn($cacheDriver);
+
+ $this->app->shouldReceive('make')->with(Cache::class)->andReturn($cache);
+
+ $cacheDriver->shouldReceive('get')->with('flysystem')->once()->andReturn(null);
+
+ $cacheDriver->shouldReceive('set')->withAnyArgs();
+
+ $this->filesystem->disk('cache')->put('test.txt', 'aa');
+ }
+
+ public function testPutFile()
+ {
+ $root = vfsStream::setup('rootDir', null, [
+ 'foo.jpg' => 'hello',
+ ]);
+
+ $this->config->shouldReceive('get')->with('filesystem.disks.local', null)->andReturn([
+ 'type' => NullDriver::class,
+ 'root' => $root->url(),
+ 'cache' => true,
+ ]);
+
+ $file = m::mock(\think\File::class);
+
+ $file->shouldReceive('hashName')->with(null)->once()->andReturn('foo.jpg');
+
+ $file->shouldReceive('getRealPath')->once()->andReturn($root->getChild('foo.jpg')->url());
+
+ $this->filesystem->putFile('test', $file);
+ }
+}
+
+class NullDriver extends Driver
+{
+ protected function createAdapter(): AdapterInterface
+ {
+ return new NullAdapter();
+ }
+}
diff --git a/vendor/topthink/think-filesystem/tests/bootstrap.php b/vendor/topthink/think-filesystem/tests/bootstrap.php
new file mode 100644
index 0000000..a4abe2d
--- /dev/null
+++ b/vendor/topthink/think-filesystem/tests/bootstrap.php
@@ -0,0 +1,2 @@
+