Преглед на файлове

Signed-off-by: sgq <sgq@sugangqiang>

sgq преди 2 години
родител
ревизия
893a859fe6
променени са 100 файла, в които са добавени 10639 реда и са изтрити 507 реда
  1. 0 1
      .gitignore
  2. 30 0
      app/admin/controller/Dict.php
  3. 47 2
      app/admin/view/Talent/build_form.html
  4. 57 0
      app/common/api/UploadApi.php
  5. 4 0
      app/enterprise/controller/Talent.php
  6. 121 100
      app/enterprise/view/talent/add.html
  7. 2 1
      composer.json
  8. 91 403
      composer.lock
  9. 12 0
      vendor/autoload.php
  10. 117 0
      vendor/bin/var-dump-server
  11. 5 0
      vendor/bin/var-dump-server.bat
  12. 572 0
      vendor/composer/ClassLoader.php
  13. 352 0
      vendor/composer/InstalledVersions.php
  14. 21 0
      vendor/composer/LICENSE
  15. 15 0
      vendor/composer/autoload_classmap.php
  16. 15 0
      vendor/composer/autoload_files.php
  17. 11 0
      vendor/composer/autoload_namespaces.php
  18. 26 0
      vendor/composer/autoload_psr4.php
  19. 57 0
      vendor/composer/autoload_real.php
  20. 161 0
      vendor/composer/autoload_static.php
  21. 1006 0
      vendor/composer/installed.json
  22. 203 0
      vendor/composer/installed.php
  23. 26 0
      vendor/composer/platform_check.php
  24. 10 0
      vendor/league/flysystem-cached-adapter/.editorconfig
  25. 4 0
      vendor/league/flysystem-cached-adapter/.gitignore
  26. 7 0
      vendor/league/flysystem-cached-adapter/.php_cs
  27. 34 0
      vendor/league/flysystem-cached-adapter/.scrutinizer.yml
  28. 29 0
      vendor/league/flysystem-cached-adapter/.travis.yml
  29. 19 0
      vendor/league/flysystem-cached-adapter/LICENSE
  30. 2 0
      vendor/league/flysystem-cached-adapter/clover/.gitignore
  31. 30 0
      vendor/league/flysystem-cached-adapter/composer.json
  32. 6 0
      vendor/league/flysystem-cached-adapter/phpspec.yml
  33. 3 0
      vendor/league/flysystem-cached-adapter/phpunit.php
  34. 29 0
      vendor/league/flysystem-cached-adapter/phpunit.xml
  35. 20 0
      vendor/league/flysystem-cached-adapter/readme.md
  36. 435 0
      vendor/league/flysystem-cached-adapter/spec/CachedAdapterSpec.php
  37. 101 0
      vendor/league/flysystem-cached-adapter/src/CacheInterface.php
  38. 346 0
      vendor/league/flysystem-cached-adapter/src/CachedAdapter.php
  39. 418 0
      vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php
  40. 115 0
      vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php
  41. 59 0
      vendor/league/flysystem-cached-adapter/src/Storage/Memcached.php
  42. 22 0
      vendor/league/flysystem-cached-adapter/src/Storage/Memory.php
  43. 171 0
      vendor/league/flysystem-cached-adapter/src/Storage/Noop.php
  44. 62 0
      vendor/league/flysystem-cached-adapter/src/Storage/PhpRedis.php
  45. 75 0
      vendor/league/flysystem-cached-adapter/src/Storage/Predis.php
  46. 59 0
      vendor/league/flysystem-cached-adapter/src/Storage/Psr6Cache.php
  47. 60 0
      vendor/league/flysystem-cached-adapter/src/Storage/Stash.php
  48. 104 0
      vendor/league/flysystem-cached-adapter/tests/AdapterCacheTests.php
  49. 16 0
      vendor/league/flysystem-cached-adapter/tests/InspectionTests.php
  50. 35 0
      vendor/league/flysystem-cached-adapter/tests/MemcachedTests.php
  51. 255 0
      vendor/league/flysystem-cached-adapter/tests/MemoryCacheTests.php
  52. 35 0
      vendor/league/flysystem-cached-adapter/tests/NoopCacheTests.php
  53. 45 0
      vendor/league/flysystem-cached-adapter/tests/PhpRedisTests.php
  54. 55 0
      vendor/league/flysystem-cached-adapter/tests/PredisTests.php
  55. 45 0
      vendor/league/flysystem-cached-adapter/tests/Psr6CacheTest.php
  56. 43 0
      vendor/league/flysystem-cached-adapter/tests/StashTest.php
  57. 76 0
      vendor/league/flysystem/CODE_OF_CONDUCT.md
  58. 19 0
      vendor/league/flysystem/LICENSE
  59. 16 0
      vendor/league/flysystem/SECURITY.md
  60. 68 0
      vendor/league/flysystem/composer.json
  61. 19 0
      vendor/league/flysystem/deprecations.md
  62. 72 0
      vendor/league/flysystem/src/Adapter/AbstractAdapter.php
  63. 705 0
      vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php
  64. 12 0
      vendor/league/flysystem/src/Adapter/CanOverwriteFiles.php
  65. 584 0
      vendor/league/flysystem/src/Adapter/Ftp.php
  66. 48 0
      vendor/league/flysystem/src/Adapter/Ftpd.php
  67. 533 0
      vendor/league/flysystem/src/Adapter/Local.php
  68. 144 0
      vendor/league/flysystem/src/Adapter/NullAdapter.php
  69. 33 0
      vendor/league/flysystem/src/Adapter/Polyfill/NotSupportingVisibilityTrait.php
  70. 51 0
      vendor/league/flysystem/src/Adapter/Polyfill/StreamedCopyTrait.php
  71. 44 0
      vendor/league/flysystem/src/Adapter/Polyfill/StreamedReadingTrait.php
  72. 9 0
      vendor/league/flysystem/src/Adapter/Polyfill/StreamedTrait.php
  73. 60 0
      vendor/league/flysystem/src/Adapter/Polyfill/StreamedWritingTrait.php
  74. 8 0
      vendor/league/flysystem/src/Adapter/SynologyFtp.php
  75. 118 0
      vendor/league/flysystem/src/AdapterInterface.php
  76. 107 0
      vendor/league/flysystem/src/Config.php
  77. 49 0
      vendor/league/flysystem/src/ConfigAwareTrait.php
  78. 9 0
      vendor/league/flysystem/src/ConnectionErrorException.php
  79. 9 0
      vendor/league/flysystem/src/ConnectionRuntimeException.php
  80. 17 0
      vendor/league/flysystem/src/CorruptedPathDetected.php
  81. 31 0
      vendor/league/flysystem/src/Directory.php
  82. 8 0
      vendor/league/flysystem/src/Exception.php
  83. 205 0
      vendor/league/flysystem/src/File.php
  84. 37 0
      vendor/league/flysystem/src/FileExistsException.php
  85. 37 0
      vendor/league/flysystem/src/FileNotFoundException.php
  86. 409 0
      vendor/league/flysystem/src/Filesystem.php
  87. 7 0
      vendor/league/flysystem/src/FilesystemException.php
  88. 284 0
      vendor/league/flysystem/src/FilesystemInterface.php
  89. 12 0
      vendor/league/flysystem/src/FilesystemNotFoundException.php
  90. 137 0
      vendor/league/flysystem/src/Handler.php
  91. 9 0
      vendor/league/flysystem/src/InvalidRootException.php
  92. 648 0
      vendor/league/flysystem/src/MountManager.php
  93. 37 0
      vendor/league/flysystem/src/NotSupportedException.php
  94. 24 0
      vendor/league/flysystem/src/Plugin/AbstractPlugin.php
  95. 34 0
      vendor/league/flysystem/src/Plugin/EmptyDir.php
  96. 44 0
      vendor/league/flysystem/src/Plugin/ForcedCopy.php
  97. 44 0
      vendor/league/flysystem/src/Plugin/ForcedRename.php
  98. 51 0
      vendor/league/flysystem/src/Plugin/GetWithMetadata.php
  99. 35 0
      vendor/league/flysystem/src/Plugin/ListFiles.php
  100. 36 0
      vendor/league/flysystem/src/Plugin/ListPaths.php

+ 0 - 1
.gitignore

@@ -1,5 +1,4 @@
 /.idea
 /.vscode
-/vendor
 *.log
 .env

+ 30 - 0
app/admin/controller/Dict.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\api\DictApi;
+
+/**
+ * Description of Dict
+ *
+ * @author sgq
+ */
+class Dict {
+
+    public function index() {
+        
+    }
+
+    public function add() {
+        
+    }
+
+    public function edit() {
+        
+    }
+
+    public function delete() {
+        
+    }
+
+}

+ 47 - 2
app/admin/view/Talent/build_form.html

@@ -49,11 +49,41 @@
                             <legend>个人信息</legend>
                             <div class="row base">               
                                 <div class="col-sm-12">
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="talentType" class="form-check-input" value="" checked="" autocomplete="off">单位标签
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="companyName" class="form-check-input" value="" checked="" autocomplete="off">单位名称
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="address" class="form-check-input" value="" checked="" autocomplete="off">所属镇街
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="industryField" class="form-check-input" value="" checked="" autocomplete="off">产业领域
+                                        </label>
+                                    </div>
                                     <div class="form-check">
                                         <label class="form-check-label">
                                             <input type="checkbox" name="name" class="form-check-input" value="" checked="" autocomplete="off">姓名
                                         </label>
                                     </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="cardType" class="form-check-input" value="" checked="" autocomplete="off">证件类型
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="idCard" class="form-check-input" value="" checked="" autocomplete="off">证件号码
+                                        </label>
+                                    </div>
                                     <div class="form-check">
                                         <label class="form-check-label">
                                             <input type="checkbox" name="sex" class="form-check-input" value="" checked="" autocomplete="off">性别
@@ -61,12 +91,27 @@
                                     </div>
                                     <div class="form-check">
                                         <label class="form-check-label">
-                                            <input type="checkbox" name="sex" class="form-check-input" value="" checked="" autocomplete="off">单位标签
+                                            <input type="checkbox" name="politics" class="form-check-input" value="" checked="" autocomplete="off">政治面貌
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="birthday" class="form-check-input" value="" checked="" autocomplete="off">出生日期
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="birthday" class="form-check-input" value="" checked="" autocomplete="off">国籍/地区
+                                        </label>
+                                    </div>
+                                    <div class="form-check">
+                                        <label class="form-check-label">
+                                            <input type="checkbox" name="birthday" class="form-check-input" value="" checked="" autocomplete="off">出生日期
                                         </label>
                                     </div>
                                     <div class="form-check">
                                         <label class="form-check-label">
-                                            <input type="checkbox" name="sex" class="form-check-input" value="" checked="" autocomplete="off">单位名称
+                                            <input type="checkbox" name="photo" class="form-check-input" value="" checked="" autocomplete="off">头像
                                         </label>
                                     </div>
                                 </div>

+ 57 - 0
app/common/api/UploadApi.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace app\common\api;
+
+/**
+ * Description of UploadApi
+ *
+ * @author sgq
+ */
+class UploadApi {
+
+    protected $fileSize = 5 * 1024 * 1024;
+    protected $fileExt = "jpg,png,gif,pdf";
+    protected $fileMime = "image/jpg,image/png,image/gif,application/pdf";
+
+    public function __construct($config = []) {
+        $this->fileSize = $config["maxSize"] ?: $this->fileSize;
+        $this->fileExt = $config["fileExt"] ?: $this->fileExt;
+        $this->fileMime = $config["fileMime"] ?: $this->fileMime;
+    }
+
+    /**
+     * 批量上传文件
+     * @param type $files
+     * @return type
+     */
+    public function uploadList($files) {
+        try {
+            validate(['image' => 'fileSize:' . $this->maxSize . '|fileExt:' . $this->fileExt . '|fileMime:' . $this->fileMime])
+                    ->check($files);
+            $savename = [];
+            foreach ($files as $file) {
+                $savename[] = \think\facade\Filesystem::disk("public")->putFile('topic', $file);
+            }
+            return $savename;
+        } catch (\think\exception\ValidateException $e) {
+            echo $e->getMessage();
+        }
+    }
+
+    /**
+     * 单个文件上传
+     * @param type $file
+     * @return type
+     */
+    public function uploadOne($file) {
+        try {
+            validate(['image' => 'fileSize:' . $this->maxSize . '|fileExt:' . $this->fileExt . '|fileMime:' . $this->fileMime])
+                    ->check($file);
+            $savename = \think\facade\Filesystem::disk("public")->putFile('topic', $file);
+            return $savename;
+        } catch (\think\exception\ValidateException $e) {
+            echo $e->getMessage();
+        }
+    }
+
+}

+ 4 - 0
app/enterprise/controller/Talent.php

@@ -20,5 +20,9 @@ class Talent extends EnterpriseController {
         $res = TalentApi::getList($this->request);
         return json($res);
     }
+    
+    public function add(){
+        return view();
+    }
 
 }

+ 121 - 100
app/enterprise/view/talent/add.html

@@ -1,5 +1,5 @@
 {extend name="layout/content"}
-{blcok name="content"}
+{block name="content"}
 <style type="text/css">
     .spacing {
         margin-bottom: 10px;
@@ -43,7 +43,7 @@
                                 <div class="panel panel-default">
                                     <div class="panel-heading" onclick="$(this).next().toggle()">基础信息</div>
                                     <div class="panel-body">
-                                        <form id="talentInfoForm" class="form-horizontal" action="${ctxPath}/api/talentInfo/upsert" method="post" enctype="multipart/form-data" target="hiddenIframe">
+                                        <form id="talentInfoForm" class="form-horizontal" action="/api/talentInfo/upsert" method="post" enctype="multipart/form-data" target="hiddenIframe">
                                             <div class="col-sm-12 form-group-sm">
                                                 <input type="hidden" name="id" id="id" value="">
                                                 <input type="hidden" name="year" id="year" value="${year}">
@@ -58,10 +58,70 @@
                                                 <input type="hidden" name="hand" id="hand" value="${hand}">
                                                 <div class="row">
                                                     <div class="col-sm-11">
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class="control-label spacing"><span style="color: red">*</span>人才类型</label>
+                                                            <select class="form-control" id="source" name="source" onchange="TalentInfoInfoDlg.sourceChange()">
+                                                                <option value="">请选择</option>
+                                                                <option value="1">现有人才。含经晋江市认定且还在晋江市就业创业的人才,或在晋江市就业创业但未曾申报过晋江市优秀人才的人才。</option>
+                                                                <option value="2">新引进人才。含本办法出台后首次从晋江市以外引进认定的人才,或者流出晋江市满3年后又返回晋江市就业创业<不含企业集团内部人员调动>的人才。</option>
+                                                                <option value="3">预引进人才。含已经与晋江市用人单位达成就业意向且签订预引进意向合作协议(合同)的人才,或拟来我市创业且提交企业名称预先核准的人才。</option>                                                                
+                                                            </select>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>在我市缴交社会保险或个人所得税月份</label>
+                                                            <input type="text" class="form-control" id="name" name="name" />
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>劳动合同起止时间</label>
+                                                            <input type="text" class="form-control" id="name" name="name" />
+                                                        </div>                                                        
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class="control-label spacing"><span style="color: red">*</span>单位标签</label>
+                                                            <select class="form-control" id="talentType" name="talentType" onchange="TalentInfoInfoDlg.typeChange(this)" >
+                                                                <option value="">请选择</option>
+                                                                <option value="1">国字号平台</option>
+                                                                <option value="2">民营企业</option>
+                                                                <option value="3">媒体单位</option>
+                                                                <option value="4">民办非企业</option>
+                                                                <option value="5">国有企业(我市本级国有股比超过50%)</option>
+                                                                <option value="6">国有企业(我市本级国有股比未超过50%)</option>
+                                                                <option value="7">金融机构(银行保险)</option>
+                                                                <option value="8">金融机构(银行保险除外)</option>
+                                                                <option value="9">在站博士后”</option>
+                                                                <option value="10">事业单位(医疗教育除外)</option>
+                                                                <option value="11">其他</option>
+                                                            </select>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>单位名称</label>
+                                                            <input type="text" class="form-control" id="companyName"  name="companyName" readonly="readonly" value="${enterprise.name}" />
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>所属镇街</label>
+                                                            <select class="form-control" id="address" name="address" value="${enterprise.street}" disabled="disabled"></select>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>产业领域</label>
+                                                            <select type="text" class="form-control" id="industryField" value="${enterprise.industryField}" name="industryField" disabled="disabled">
+                                                            </select>
+                                                        </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class=" control-label spacing"><span style="color: red">*</span>姓名</label>
                                                             <input type="text" class="form-control" id="name" name="name" />
                                                         </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>证件类型</label>
+                                                            <select class="form-control" id="cardType" name="cardType">
+                                                                <option value="">请选择</option>
+                                                                <option value="1">身份证</option>
+                                                                <option value="2">通行证</option>
+                                                                <option value="3">护照</option>
+                                                            </select>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>证件号码</label>
+                                                            <input class="form-control" id="idCard" name="idCard">
+                                                        </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class=" control-label spacing"><span style="color: red">*</span>性别</label>
                                                             <select class="form-control" id="sex" name="sex">
@@ -96,67 +156,69 @@
                                                             <label class="control-label spacing"><span style="color: red">*</span>民族</label>
                                                             <select class="form-control" id="nation" name="nation">
                                                             </select>
-                                                        </div>
+                                                        </div>       
                                                         <div class="rowGroup col-sm-3">
                                                             <label class=" control-label spacing"><span style="color: red">*</span>政治面貌</label>
                                                             <select class="form-control" id="politics" name="politics">
                                                             </select>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>证件类型</label>
-                                                            <select class="form-control" id="cardType" name="cardType">
-                                                                <option value="">请选择</option>
-                                                                <option value="1">身份证</option>
-                                                                <option value="2">通行证</option>
-                                                                <option value="3">护照</option>
-                                                            </select>
-                                                        </div>
+                                                        </div>  
+                                                    </div>
+                                                    <div class="col-sm-1">
+                                                        <img id="photoImg" src="/static/img/photo.png" onclick="$('#photo').click()" style="height: 110px;width: 76px;padding-bottom: 5px;">
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </form>
+                                    </div>
+                                    <div class="panel-heading" onclick="$(this).next().toggle()">个人信息填报及人才认定申请</div>
+                                    <div class="panel-body">
+                                        <form id="talentInfoForm" class="form-horizontal" action="/api/talentInfo/upsert" method="post" enctype="multipart/form-data" target="hiddenIframe">
+                                            <div class="col-sm-12 form-group-sm">
+                                                <div class="row">
+                                                    <div class="col-sm-11">                          
                                                         <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>证件号码</label>
-                                                            <input class="form-control" id="idCard" name="idCard">
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>申报年度</label>
+                                                            <input type="text" class="form-control" name="year" id="year" value="${year}">
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class="control-label spacing"><span style="color: red">*</span>首次来晋工作时间</label>
                                                             <input type="text" class="form-control date" id="firstInJJTime" name="firstInJJTime"/>
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>单位名称</label>
-                                                            <input type="text" class="form-control" id="companyName"  name="companyName" readonly="readonly" value="${enterprise.name}" />
+                                                            <label class=" control-label spacing"><span style="color: red">*</span>引进方式</label>
+                                                            <select class="form-control" id="introductionMode" name="introductionMode" data-placeholder="引进方式">
+                                                            </select>
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>行业领域</label>
-                                                            <select type="text" class="form-control" id="industryField" value="${enterprise.industryField}" name="industryField" disabled="disabled">
-                                                            </select>
+                                                            <label class="control-label spacing"><span style="color: red">*</span>本单位入职时间</label>
+                                                            <input type="text" class="form-control date" id="entryTime" name="entryTime"/>
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>人才标签</label>
-                                                            <select class="form-control" id="talentType" name="talentType" onchange="TalentInfoInfoDlg.typeChange(this)" ></select>
+                                                            <label class="control-label spacing"><span style="color: red">*</span>本单位现任职务</label>
+                                                            <input type="text" class="form-control" id="post" name="post"/>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class="control-label spacing"><span style="color: red">*</span>上一年度年薪(元)</label>
+                                                            <input type="text" class="form-control" id="lastYearWages" name="lastYearWages"/>
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class="control-label spacing"><span style="color: red">*</span>申报来源</label>
                                                             <select class="form-control" id="source" name="source" onchange="TalentInfoInfoDlg.sourceChange()">
                                                                 <option value="">请选择</option>
-                                                                <option value="1">经我市申报并已经成功入选的泉州高层次人才</option>
-                                                                <option value="2">从我市以外的其他县(市、区)变动到我市工作的泉州市高层次人才</option>
-                                                                <option value="3">依据《晋江市优秀人才补充认定标准》申报认定</option>
-                                                            </select>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3" style="display: none">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>公布入选来源</label>
-                                                            <select class="form-control" id="ourCitySource" name="ourCitySource">
-                                                                <option value="">请选择</option>
-                                                                <option value="1">泉州市公布入选的泉州市第一至第五层次人才</option>
-                                                                <option value="2">晋江市公布入选的泉州市高层次第六七层次人才</option>
+                                                                <option value="1">经我市申报入选省级人才且符合我市产业人才认定标准。</option>
+                                                                <option value="2">经我市申报入选泉州市高层次人才且符合我市产业人才认定标准。</option>
+                                                                <option value="3">其他地级市入选省级人才申报认定。</option>
+                                                                <option value="4">其他县市区入选泉州市高层次人才申报认定。</option>
+                                                                <option value="5">依据晋江现代产业人才认定标准(晋江补充条款)申报认定。</option>
                                                             </select>
                                                         </div>
                                                         <div class="rowGroup col-sm-3" style="display: none">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>入选来源县市</label>
-                                                            <select class="form-control" id="fromCity" name="fromCity">
-                                                            </select>
+                                                            <label class=" control-label spacing" ><span style="color: red">*</span>福建省高层次人才证书发证日期</label>
+                                                            <input type="text" class="form-control date" id="certificateStartTime" name="certificateStartTime"/>
                                                         </div>
                                                         <div class="rowGroup col-sm-3" style="display: none">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>入选名单批次</label>
-                                                            <select type="text" class="form-control" id="qzBatch"  name="qzBatch"></select>
+                                                            <label class=" control-label spacing" ><span style="color: red">*</span>福建省高层次人才证书有效期</label>
+                                                            <input type="text" class="form-control date" id="qzgccrcActiveTime" name="qzgccrcActiveTime"/>
                                                         </div>
                                                         <div class="rowGroup col-sm-3" style="display: none">
                                                             <label class=" control-label spacing" ><span style="color: red">*</span>泉州高层次人才证书发证日期</label>
@@ -174,47 +236,10 @@
                                                             <label class="control-label spacing"><span style="color: red">*</span>认定条件</label>
                                                             <select class="chosen" id="identifyCondition" name="identifyCondition"></select>
                                                         </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>认定条件名称</label>
-                                                            <input type="text" class="form-control" id="identifyConditionName" name="identifyConditionName" placeholder="例:获得国家一级职业资格(汽车维修工)"/>
-                                                        </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class="control-label spacing"><span style="color: red">*</span>认定条件证书取得时间</label>
                                                             <input type="text" class="form-control date" id="identifyGetTime" name="identifyGetTime"/>
                                                         </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>所属镇街</label>
-                                                            <select class="form-control" id="address" name="address" value="${enterprise.street}" disabled="disabled"></select>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3" style="display: none">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>首次来晋行政介绍信时间</label>
-                                                            <input type="text" class="form-control date" id="letterTime" name="letterTime"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>引进方式</label>
-                                                            <select class="form-control" id="introductionMode" name="introductionMode" data-placeholder="引进方式">
-                                                            </select>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>本单位入职时间</label>
-                                                            <input type="text" class="form-control date" id="entryTime" name="entryTime"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>职务</label>
-                                                            <input type="text" class="form-control" id="post" name="post"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>工作合同开始时间</label>
-                                                            <input type="text" class="form-control date" id="startTime" name="startTime"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>工作合同结束时间</label>
-                                                            <input type="text" class="form-control date" id="endTime" name="endTime"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>上一年度年薪(元)</label>
-                                                            <input type="text" class="form-control" id="lastYearWages" name="lastYearWages"/>
-                                                        </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class="control-label spacing"><span style="color: red">*</span>最高学历</label>
                                                             <select class="form-control" id="highEducation" name="highEducation"></select>
@@ -235,21 +260,6 @@
                                                             <label class="control-label spacing">国家职业资格</label>
                                                             <input type="text" class="form-control" id="professionalQualifications" name="professionalQualifications"/>
                                                         </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing">是否有留学经历</label>
-                                                            <select class="form-control" id="studyAbroad" name="studyAbroad">
-                                                                <option value="2">否</option>
-                                                                <option value="1">是</option>
-                                                            </select>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>手机号码</label>
-                                                            <input type="text" class="form-control" id="phone" name="phone" maxlength="11"/>
-                                                        </div>
-                                                        <div class="rowGroup col-sm-3">
-                                                            <label class="control-label spacing"><span style="color: red">*</span>电子邮箱</label>
-                                                            <input type="text" class="form-control" id="email" name="email"/>
-                                                        </div>
                                                         <div class="rowGroup col-sm-3">
                                                             <label class="control-label spacing"><span style="color: red">*</span>开户银行</label>
                                                             <input type="text" class="form-control" onchange="TalentInfoInfoDlg.bankChange()" id="bank" name="bank" placeholder="XX银行"/>
@@ -267,15 +277,20 @@
                                                             <input type="text" class="form-control" id="bankAccount" name="bankAccount" />
                                                         </div>
                                                         <div class="rowGroup col-sm-3">
-                                                            <label class=" control-label spacing"><span style="color: red">*</span>是否曾被相关主管部门列为失信个人</label>
-                                                            <select class="form-control" id="breakFaith" name="breakFaith">
+                                                            <label class="control-label spacing">是否有留学经历</label>
+                                                            <select class="form-control" id="studyAbroad" name="studyAbroad">
                                                                 <option value="2">否</option>
                                                                 <option value="1">是</option>
                                                             </select>
                                                         </div>
-                                                    </div>
-                                                    <div class="col-sm-1">
-                                                        <img id="photoImg" src="${ctxPath}/static/img/photo.png" onclick="$('#photo').click()" style="height: 110px;width: 76px;padding-bottom: 5px;">
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class="control-label spacing"><span style="color: red">*</span>手机号码</label>
+                                                            <input type="text" class="form-control" id="phone" name="phone" maxlength="11"/>
+                                                        </div>
+                                                        <div class="rowGroup col-sm-3">
+                                                            <label class="control-label spacing"><span style="color: red">*</span>电子邮箱</label>
+                                                            <input type="text" class="form-control" id="email" name="email"/>
+                                                        </div>
                                                     </div>
                                                 </div>
                                                 <div class="row">
@@ -297,15 +312,21 @@
                                         </form>
                                     </div>
                                     <div class="panel-heading" onclick="$(this).next().toggle()">日志</div>
-                                        <table id="logTable">
+                                    <table id="logTable">
                                     </table>
                                 </div>
                             </div>
                         </div>
                         <div id="tab-2" class="tab-pane ">
-                            <#table id="fileTable" />
+                            <table id="fileTable" class="table-condensed" style="font-size: 10px;table-layout: fixed!important;" data-mobile-responsive="true" data-click-to-select="true">
+                                <thead>
+                                    <tr>
+                                        <th data-field="selectItem" data-checkbox="true"></th>
+                                    </tr>
+                                </thead>
+                            </table>
                             <label style="padding-top: 15px;color: red">*请根据上传的附件材料,编辑好相应的文件夹名称</label>
-                            <form id="uploadForm" action="${ctxPath}/api/talentInfo/addTalentFile" method="post" class="form-horizontal" enctype="multipart/form-data" target="hiddenIframe" style="display: none">
+                            <form id="uploadForm" action="/api/talentInfo/addTalentFile" method="post" class="form-horizontal" enctype="multipart/form-data" target="hiddenIframe" style="display: none">
                                 <input type='hidden' id="fileId" name="fileId" >
                                 <input type='file' id="upload_file" name="fileUrl" style='display: none'>
                                 <input type='hidden' id="mainId" name="mainId" >
@@ -324,7 +345,7 @@
 <iframe id="hiddenIframe" name="hiddenIframe" style="display: none;"></iframe>
 <!--<script src="${ctxPath}/static/modular/gate/talentInfo/talentInfo_info.js"></script>-->
 <script type="text/javascript">
-    document.write('<script src="${ctxPath}/static/modular/gate/talentInfo/talentInfo_info.js?v='+(new Date()).getTime()+'"><\/script>');
-    document.write('<script src="${ctxPath}/static/modular/common/config.js?v='+(new Date()).getTime()+'"><\/script>');
+    document.write('<script src="/static/modular/gate/talentInfo/talentInfo_info.js?v=' + (new Date()).getTime() + '"><\/script>');
+    document.write('<script src="/static/modular/common/config.js?v=' + (new Date()).getTime() + '"><\/script>');
 </script>
 {/block}

+ 2 - 1
composer.json

@@ -24,7 +24,8 @@
         "topthink/framework": "^6.0.0",
         "topthink/think-orm": "^2.0",
         "topthink/think-view": "^1.0",
-        "topthink/think-multi-app": "^1.0"
+        "topthink/think-multi-app": "^1.0",
+        "phpoffice/phpexcel": "^1.8"
     },
     "require-dev": {
         "symfony/var-dumper": "^4.2",

+ 91 - 403
composer.lock

@@ -4,27 +4,16 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "dfd7aef3ee01e0361a2d01950dff982a",
+    "content-hash": "103a60082d76ee0bba3decb2ed8b0297",
     "packages": [
         {
             "name": "league/flysystem",
             "version": "1.1.9",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/thephpleague/flysystem.git",
-                "reference": "094defdb4a7001845300334e7c1ee2335925ef99"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/094defdb4a7001845300334e7c1ee2335925ef99",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/league/flysystem/1.1.9/league-flysystem-1.1.9.zip",
                 "reference": "094defdb4a7001845300334e7c1ee2335925ef99",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "ext-fileinfo": "*",
@@ -64,7 +53,6 @@
                     "League\\Flysystem\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -94,37 +82,16 @@
                 "sftp",
                 "storage"
             ],
-            "support": {
-                "issues": "https://github.com/thephpleague/flysystem/issues",
-                "source": "https://github.com/thephpleague/flysystem/tree/1.1.9"
-            },
-            "funding": [
-                {
-                    "url": "https://offset.earth/frankdejonge",
-                    "type": "other"
-                }
-            ],
             "time": "2021-12-09T09:40:50+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",
+                "url": "https://mirrors.tencent.com/repository/composer/league/flysystem-cached-adapter/1.1.0/league-flysystem-cached-adapter-1.1.0.zip",
                 "reference": "d1925efb2207ac4be3ad0c40b8277175f99ffaff",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "league/flysystem": "~1.0",
@@ -146,7 +113,6 @@
                     "League\\Flysystem\\Cached\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -157,31 +123,16 @@
                 }
             ],
             "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.11.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/thephpleague/mime-type-detection.git",
-                "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/league/mime-type-detection/1.11.0/league-mime-type-detection-1.11.0.zip",
                 "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "ext-fileinfo": "*",
@@ -198,7 +149,6 @@
                     "League\\MimeTypeDetection\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -209,41 +159,72 @@
                 }
             ],
             "description": "Mime-type detection for Flysystem",
-            "support": {
-                "issues": "https://github.com/thephpleague/mime-type-detection/issues",
-                "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
+            "time": "2022-04-17T13:12:02+00:00"
+        },
+        {
+            "name": "phpoffice/phpexcel",
+            "version": "1.8.2",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/phpoffice/phpexcel/1.8.2/phpoffice-phpexcel-1.8.2.zip",
+                "reference": "1441011fb7ecdd8cc689878f54f8b58a6805f870",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "ext-xmlwriter": "*",
+                "php": "^5.2|^7.0"
+            },
+            "require-dev": {
+                "squizlabs/php_codesniffer": "2.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "PHPExcel": "Classes/"
+                }
             },
-            "funding": [
+            "license": [
+                "LGPL-2.1"
+            ],
+            "authors": [
+                {
+                    "name": "Maarten Balliauw",
+                    "homepage": "http://blog.maartenballiauw.be"
+                },
                 {
-                    "url": "https://github.com/frankdejonge",
-                    "type": "github"
+                    "name": "Erik Tilt"
                 },
                 {
-                    "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
-                    "type": "tidelift"
+                    "name": "Franck Lefevre",
+                    "homepage": "http://rootslabs.net"
+                },
+                {
+                    "name": "Mark Baker",
+                    "homepage": "http://markbakeruk.net"
                 }
             ],
-            "time": "2022-04-17T13:12:02+00:00"
+            "description": "PHPExcel - OpenXML - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+            "homepage": "https://github.com/PHPOffice/PHPExcel",
+            "keywords": [
+                "OpenXML",
+                "excel",
+                "php",
+                "spreadsheet",
+                "xls",
+                "xlsx"
+            ],
+            "time": "2018-11-22T23:07:24+00:00"
         },
         {
             "name": "psr/cache",
             "version": "1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/cache.git",
-                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/cache/1.0.1/psr-cache-1.0.1.zip",
                 "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=5.3.0"
@@ -259,7 +240,6 @@
                     "Psr\\Cache\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -275,30 +255,16 @@
                 "psr",
                 "psr-6"
             ],
-            "support": {
-                "source": "https://github.com/php-fig/cache/tree/master"
-            },
             "time": "2016-08-06T20:24:11+00:00"
         },
         {
             "name": "psr/container",
             "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/container.git",
-                "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/1.1.1/psr-container-1.1.1.zip",
                 "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.2.0"
@@ -309,7 +275,6 @@
                     "Psr\\Container\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -328,31 +293,16 @@
                 "container-interop",
                 "psr"
             ],
-            "support": {
-                "issues": "https://github.com/php-fig/container/issues",
-                "source": "https://github.com/php-fig/container/tree/1.1.1"
-            },
             "time": "2021-03-05T17:36:06+00:00"
         },
         {
             "name": "psr/http-message",
             "version": "1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/http-message.git",
-                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-message/1.0.1/psr-http-message-1.0.1.zip",
                 "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=5.3.0"
@@ -368,7 +318,6 @@
                     "Psr\\Http\\Message\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -388,30 +337,16 @@
                 "request",
                 "response"
             ],
-            "support": {
-                "source": "https://github.com/php-fig/http-message/tree/master"
-            },
             "time": "2016-08-06T14:39:51+00:00"
         },
         {
             "name": "psr/log",
             "version": "1.1.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/log.git",
-                "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/log/1.1.4/psr-log-1.1.4.zip",
                 "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=5.3.0"
@@ -427,7 +362,6 @@
                     "Psr\\Log\\": "Psr/Log/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -444,30 +378,16 @@
                 "psr",
                 "psr-3"
             ],
-            "support": {
-                "source": "https://github.com/php-fig/log/tree/1.1.4"
-            },
             "time": "2021-05-03T11:20:27+00:00"
         },
         {
             "name": "psr/simple-cache",
             "version": "1.0.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/php-fig/simple-cache.git",
-                "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/simple-cache/1.0.1/psr-simple-cache-1.0.1.zip",
                 "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=5.3.0"
@@ -483,7 +403,6 @@
                     "Psr\\SimpleCache\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -501,30 +420,16 @@
                 "psr-16",
                 "simple-cache"
             ],
-            "support": {
-                "source": "https://github.com/php-fig/simple-cache/tree/master"
-            },
             "time": "2017-10-23T01:57:42+00:00"
         },
         {
             "name": "topthink/framework",
             "version": "v6.0.13",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/framework.git",
-                "reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/framework/zipball/126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/framework/v6.0.13/topthink-framework-v6.0.13.zip",
                 "reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "ext-json": "*",
@@ -552,7 +457,6 @@
                     "think\\": "src/think/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -573,31 +477,16 @@
                 "orm",
                 "thinkphp"
             ],
-            "support": {
-                "issues": "https://github.com/top-think/framework/issues",
-                "source": "https://github.com/top-think/framework/tree/v6.0.13"
-            },
             "time": "2022-07-15T02:52:08+00:00"
         },
         {
             "name": "topthink/think-helper",
             "version": "v3.1.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-helper.git",
-                "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-helper/v3.1.6/topthink-think-helper-v3.1.6.zip",
                 "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.0"
@@ -614,7 +503,6 @@
                     "think\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -625,31 +513,16 @@
                 }
             ],
             "description": "The ThinkPHP6 Helper Package",
-            "support": {
-                "issues": "https://github.com/top-think/think-helper/issues",
-                "source": "https://github.com/top-think/think-helper/tree/v3.1.6"
-            },
             "time": "2021-12-15T04:27:55+00:00"
         },
         {
             "name": "topthink/think-multi-app",
             "version": "v1.0.14",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-multi-app.git",
-                "reference": "ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-multi-app/zipball/ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-multi-app/v1.0.14/topthink-think-multi-app-v1.0.14.zip",
                 "reference": "ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.0",
@@ -668,7 +541,6 @@
                     "think\\app\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -679,31 +551,16 @@
                 }
             ],
             "description": "thinkphp6 multi app support",
-            "support": {
-                "issues": "https://github.com/top-think/think-multi-app/issues",
-                "source": "https://github.com/top-think/think-multi-app/tree/master"
-            },
             "time": "2020-07-12T13:50:37+00:00"
         },
         {
             "name": "topthink/think-orm",
             "version": "v2.0.54",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-orm.git",
-                "reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-orm/zipball/97b061b47616301ff29fbd4c35ed9184e1162e4e",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-orm/v2.0.54/topthink-think-orm-v2.0.54.zip",
                 "reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "ext-json": "*",
@@ -725,7 +582,6 @@
                     "think\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -740,31 +596,16 @@
                 "database",
                 "orm"
             ],
-            "support": {
-                "issues": "https://github.com/top-think/think-orm/issues",
-                "source": "https://github.com/top-think/think-orm/tree/v2.0.54"
-            },
             "time": "2022-07-05T05:25:51+00:00"
         },
         {
             "name": "topthink/think-template",
             "version": "v2.0.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-template.git",
-                "reference": "abfc293f74f9ef5127b5c416310a01fe42e59368"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-template/zipball/abfc293f74f9ef5127b5c416310a01fe42e59368",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-template/v2.0.8/topthink-think-template-v2.0.8.zip",
                 "reference": "abfc293f74f9ef5127b5c416310a01fe42e59368",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.0",
@@ -776,7 +617,6 @@
                     "think\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -787,31 +627,16 @@
                 }
             ],
             "description": "the php template engine",
-            "support": {
-                "issues": "https://github.com/top-think/think-template/issues",
-                "source": "https://github.com/top-think/think-template/tree/v2.0.8"
-            },
             "time": "2020-12-10T07:52:03+00:00"
         },
         {
             "name": "topthink/think-view",
             "version": "v1.0.14",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-view.git",
-                "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-view/zipball/edce0ae2c9551ab65f9e94a222604b0dead3576d",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-view/v1.0.14/topthink-think-view-v1.0.14.zip",
                 "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.0",
@@ -823,7 +648,6 @@
                     "think\\view\\driver\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -834,10 +658,6 @@
                 }
             ],
             "description": "thinkphp template driver",
-            "support": {
-                "issues": "https://github.com/top-think/think-view/issues",
-                "source": "https://github.com/top-think/think-view/tree/v1.0.14"
-            },
             "time": "2019-11-06T11:40:13+00:00"
         }
     ],
@@ -845,22 +665,11 @@
         {
             "name": "symfony/polyfill-mbstring",
             "version": "v1.26.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.26.0/symfony-polyfill-mbstring-v1.26.0.zip",
                 "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1"
@@ -889,7 +698,6 @@
                     "Symfony\\Polyfill\\Mbstring\\": ""
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -912,44 +720,16 @@
                 "portable",
                 "shim"
             ],
-            "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
-            },
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
             "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php72",
             "version": "v1.26.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/polyfill-php72.git",
-                "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/bf44a9fd41feaac72b074de600314a93e2ae78e2",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/polyfill-php72/v1.26.0/symfony-polyfill-php72-v1.26.0.zip",
                 "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1"
@@ -972,7 +752,6 @@
                     "Symfony\\Polyfill\\Php72\\": ""
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -994,44 +773,16 @@
                 "portable",
                 "shim"
             ],
-            "support": {
-                "source": "https://github.com/symfony/polyfill-php72/tree/v1.26.0"
-            },
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
             "time": "2022-05-24T11:49:31+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
             "version": "v1.26.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/polyfill-php80/v1.26.0/symfony-polyfill-php80-v1.26.0.zip",
                 "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1"
@@ -1057,7 +808,6 @@
                     "Resources/stubs"
                 ]
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -1083,44 +833,16 @@
                 "portable",
                 "shim"
             ],
-            "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
-            },
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
             "time": "2022-05-10T07:21:04+00:00"
         },
         {
             "name": "symfony/var-dumper",
             "version": "v4.4.44",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/f19951007dae942cc79b979c1fe26bfdfbeb54ed",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/var-dumper/v4.4.44/symfony-var-dumper-v4.4.44.zip",
                 "reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.3",
@@ -1158,7 +880,6 @@
                     "/Tests/"
                 ]
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
@@ -1178,44 +899,16 @@
                 "debug",
                 "dump"
             ],
-            "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v4.4.44"
-            },
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
             "time": "2022-07-20T09:59:04+00:00"
         },
         {
             "name": "topthink/think-trace",
             "version": "v1.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/top-think/think-trace.git",
-                "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444"
-            },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/top-think/think-trace/zipball/9a9fa8f767b6c66c5a133ad21ca1bc96ad329444",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-trace/v1.4/topthink-think-trace-v1.4.zip",
                 "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "php": ">=7.1.0",
@@ -1237,7 +930,6 @@
                     "think\\trace\\": "src"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "Apache-2.0"
             ],
@@ -1248,10 +940,6 @@
                 }
             ],
             "description": "thinkphp debug trace",
-            "support": {
-                "issues": "https://github.com/top-think/think-trace/issues",
-                "source": "https://github.com/top-think/think-trace/tree/v1.4"
-            },
             "time": "2020-06-29T05:27:28+00:00"
         }
     ],
@@ -1264,5 +952,5 @@
         "php": ">=7.2.5"
     },
     "platform-dev": [],
-    "plugin-api-version": "2.2.0"
+    "plugin-api-version": "2.3.0"
 }

+ 12 - 0
vendor/autoload.php

@@ -0,0 +1,12 @@
+<?php
+
+// autoload.php @generated by Composer
+
+if (PHP_VERSION_ID < 50600) {
+    echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    exit(1);
+}
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit0767332e67f37ff78a6c5ac32275d5ac::getLoader();

+ 117 - 0
vendor/bin/var-dump-server

@@ -0,0 +1,117 @@
+#!/usr/bin/env php
+<?php
+
+/**
+ * Proxy PHP file generated by Composer
+ *
+ * This file includes the referenced bin path (../symfony/var-dumper/Resources/bin/var-dump-server)
+ * using a stream wrapper to prevent the shebang from being output on PHP<8
+ *
+ * @generated
+ */
+
+namespace Composer;
+
+$GLOBALS['_composer_bin_dir'] = __DIR__;
+$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
+
+if (PHP_VERSION_ID < 80000) {
+    if (!class_exists('Composer\BinProxyWrapper')) {
+        /**
+         * @internal
+         */
+        final class BinProxyWrapper
+        {
+            private $handle;
+            private $position;
+            private $realpath;
+
+            public function stream_open($path, $mode, $options, &$opened_path)
+            {
+                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
+                $opened_path = substr($path, 17);
+                $this->realpath = realpath($opened_path) ?: $opened_path;
+                $opened_path = $this->realpath;
+                $this->handle = fopen($this->realpath, $mode);
+                $this->position = 0;
+
+                return (bool) $this->handle;
+            }
+
+            public function stream_read($count)
+            {
+                $data = fread($this->handle, $count);
+
+                if ($this->position === 0) {
+                    $data = preg_replace('{^#!.*\r?\n}', '', $data);
+                }
+
+                $this->position += strlen($data);
+
+                return $data;
+            }
+
+            public function stream_cast($castAs)
+            {
+                return $this->handle;
+            }
+
+            public function stream_close()
+            {
+                fclose($this->handle);
+            }
+
+            public function stream_lock($operation)
+            {
+                return $operation ? flock($this->handle, $operation) : true;
+            }
+
+            public function stream_seek($offset, $whence)
+            {
+                if (0 === fseek($this->handle, $offset, $whence)) {
+                    $this->position = ftell($this->handle);
+                    return true;
+                }
+
+                return false;
+            }
+
+            public function stream_tell()
+            {
+                return $this->position;
+            }
+
+            public function stream_eof()
+            {
+                return feof($this->handle);
+            }
+
+            public function stream_stat()
+            {
+                return array();
+            }
+
+            public function stream_set_option($option, $arg1, $arg2)
+            {
+                return true;
+            }
+
+            public function url_stat($path, $flags)
+            {
+                $path = substr($path, 17);
+                if (file_exists($path)) {
+                    return stat($path);
+                }
+
+                return false;
+            }
+        }
+    }
+
+    if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
+        include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
+        exit(0);
+    }
+}
+
+include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';

+ 5 - 0
vendor/bin/var-dump-server.bat

@@ -0,0 +1,5 @@
+@ECHO OFF
+setlocal DISABLEDELAYEDEXPANSION
+SET BIN_TARGET=%~dp0/var-dump-server
+SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
+php "%BIN_TARGET%" %*

+ 572 - 0
vendor/composer/ClassLoader.php

@@ -0,0 +1,572 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see    https://www.php-fig.org/psr/psr-0/
+ * @see    https://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+    /** @var ?string */
+    private $vendorDir;
+
+    // PSR-4
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<string, int>>
+     */
+    private $prefixLengthsPsr4 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<int, string>>
+     */
+    private $prefixDirsPsr4 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, string>
+     */
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    /**
+     * @var array[]
+     * @psalm-var array<string, array<string, string[]>>
+     */
+    private $prefixesPsr0 = array();
+    /**
+     * @var array[]
+     * @psalm-var array<string, string>
+     */
+    private $fallbackDirsPsr0 = array();
+
+    /** @var bool */
+    private $useIncludePath = false;
+
+    /**
+     * @var string[]
+     * @psalm-var array<string, string>
+     */
+    private $classMap = array();
+
+    /** @var bool */
+    private $classMapAuthoritative = false;
+
+    /**
+     * @var bool[]
+     * @psalm-var array<string, bool>
+     */
+    private $missingClasses = array();
+
+    /** @var ?string */
+    private $apcuPrefix;
+
+    /**
+     * @var self[]
+     */
+    private static $registeredLoaders = array();
+
+    /**
+     * @param ?string $vendorDir
+     */
+    public function __construct($vendorDir = null)
+    {
+        $this->vendorDir = $vendorDir;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
+        }
+
+        return array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, array<int, string>>
+     */
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, string>
+     */
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return array<string, string>
+     */
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    /**
+     * @return string[] Array of classname => path
+     * @psalm-return array<string, string>
+     */
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param string[] $classMap Class to filename map
+     * @psalm-param array<string, string> $classMap
+     *
+     * @return void
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string          $prefix  The prefix
+     * @param string[]|string $paths   The PSR-0 root directories
+     * @param bool            $prepend Whether to prepend the directories
+     *
+     * @return void
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string          $prefix  The prefix/namespace, with trailing '\\'
+     * @param string[]|string $paths   The PSR-4 base directories
+     * @param bool            $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @return void
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string          $prefix The prefix
+     * @param string[]|string $paths  The PSR-0 base directories
+     *
+     * @return void
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string          $prefix The prefix/namespace, with trailing '\\'
+     * @param string[]|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     *
+     * @return void
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     *
+     * @return void
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     *
+     * @return void
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+     *
+     * @param string|null $apcuPrefix
+     *
+     * @return void
+     */
+    public function setApcuPrefix($apcuPrefix)
+    {
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+    }
+
+    /**
+     * The APCu prefix in use, or null if APCu caching is not enabled.
+     *
+     * @return string|null
+     */
+    public function getApcuPrefix()
+    {
+        return $this->apcuPrefix;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     *
+     * @return void
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+        if (null === $this->vendorDir) {
+            return;
+        }
+
+        if ($prepend) {
+            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+        } else {
+            unset(self::$registeredLoaders[$this->vendorDir]);
+            self::$registeredLoaders[$this->vendorDir] = $this;
+        }
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     *
+     * @return void
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+
+        if (null !== $this->vendorDir) {
+            unset(self::$registeredLoaders[$this->vendorDir]);
+        }
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return true|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+
+        return null;
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+            return false;
+        }
+        if (null !== $this->apcuPrefix) {
+            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+            if ($hit) {
+                return $file;
+            }
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if (false === $file && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if (null !== $this->apcuPrefix) {
+            apcu_add($this->apcuPrefix.$class, $file);
+        }
+
+        if (false === $file) {
+            // Remember that this class does not exist.
+            $this->missingClasses[$class] = true;
+        }
+
+        return $file;
+    }
+
+    /**
+     * Returns the currently registered loaders indexed by their corresponding vendor directories.
+     *
+     * @return self[]
+     */
+    public static function getRegisteredLoaders()
+    {
+        return self::$registeredLoaders;
+    }
+
+    /**
+     * @param  string       $class
+     * @param  string       $ext
+     * @return string|false
+     */
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            $subPath = $class;
+            while (false !== $lastPos = strrpos($subPath, '\\')) {
+                $subPath = substr($subPath, 0, $lastPos);
+                $search = $subPath . '\\';
+                if (isset($this->prefixDirsPsr4[$search])) {
+                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
+                        if (file_exists($file = $dir . $pathEnd)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+
+        return false;
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param  string $file
+ * @return void
+ * @private
+ */
+function includeFile($file)
+{
+    include $file;
+}

+ 352 - 0
vendor/composer/InstalledVersions.php

@@ -0,0 +1,352 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+    /**
+     * @var mixed[]|null
+     * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
+     */
+    private static $installed;
+
+    /**
+     * @var bool|null
+     */
+    private static $canGetVendors;
+
+    /**
+     * @var array[]
+     * @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    private static $installedByVendor = array();
+
+    /**
+     * Returns a list of all package names which are present, either by being installed, replaced or provided
+     *
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackages()
+    {
+        $packages = array();
+        foreach (self::getInstalled() as $installed) {
+            $packages[] = array_keys($installed['versions']);
+        }
+
+        if (1 === \count($packages)) {
+            return $packages[0];
+        }
+
+        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+    }
+
+    /**
+     * Returns a list of all package names with a specific type e.g. 'library'
+     *
+     * @param  string   $type
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackagesByType($type)
+    {
+        $packagesByType = array();
+
+        foreach (self::getInstalled() as $installed) {
+            foreach ($installed['versions'] as $name => $package) {
+                if (isset($package['type']) && $package['type'] === $type) {
+                    $packagesByType[] = $name;
+                }
+            }
+        }
+
+        return $packagesByType;
+    }
+
+    /**
+     * Checks whether the given package is installed
+     *
+     * This also returns true if the package name is provided or replaced by another package
+     *
+     * @param  string $packageName
+     * @param  bool   $includeDevRequirements
+     * @return bool
+     */
+    public static function isInstalled($packageName, $includeDevRequirements = true)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (isset($installed['versions'][$packageName])) {
+                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the given package satisfies a version constraint
+     *
+     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+     *
+     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+     *
+     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
+     * @param  string        $packageName
+     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+     * @return bool
+     */
+    public static function satisfies(VersionParser $parser, $packageName, $constraint)
+    {
+        $constraint = $parser->parseConstraints($constraint);
+        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+        return $provided->matches($constraint);
+    }
+
+    /**
+     * Returns a version constraint representing all the range(s) which are installed for a given package
+     *
+     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+     * whether a given version of a package is installed, and not just whether it exists
+     *
+     * @param  string $packageName
+     * @return string Version constraint usable with composer/semver
+     */
+    public static function getVersionRanges($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            $ranges = array();
+            if (isset($installed['versions'][$packageName]['pretty_version'])) {
+                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+            }
+            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+            }
+            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+            }
+            if (array_key_exists('provided', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+            }
+
+            return implode(' || ', $ranges);
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getPrettyVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['pretty_version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+     */
+    public static function getReference($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['reference'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['reference'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+     */
+    public static function getInstallPath($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @return array
+     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
+     */
+    public static function getRootPackage()
+    {
+        $installed = self::getInstalled();
+
+        return $installed[0]['root'];
+    }
+
+    /**
+     * Returns the raw installed.php data for custom implementations
+     *
+     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+     * @return array[]
+     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
+     */
+    public static function getRawData()
+    {
+        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = include __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        return self::$installed;
+    }
+
+    /**
+     * Returns the raw data of all installed.php which are currently loaded for custom implementations
+     *
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    public static function getAllRawData()
+    {
+        return self::getInstalled();
+    }
+
+    /**
+     * Lets you reload the static array from another file
+     *
+     * This is only useful for complex integrations in which a project needs to use
+     * this class but then also needs to execute another project's autoloader in process,
+     * and wants to ensure both projects have access to their version of installed.php.
+     *
+     * A typical case would be PHPUnit, where it would need to make sure it reads all
+     * the data it needs from this class, then call reload() with
+     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+     * the project in which it runs can then also use this class safely, without
+     * interference between PHPUnit's dependencies and the project's dependencies.
+     *
+     * @param  array[] $data A vendor/composer/installed.php data set
+     * @return void
+     *
+     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
+     */
+    public static function reload($data)
+    {
+        self::$installed = $data;
+        self::$installedByVendor = array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
+     */
+    private static function getInstalled()
+    {
+        if (null === self::$canGetVendors) {
+            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+        }
+
+        $installed = array();
+
+        if (self::$canGetVendors) {
+            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+                if (isset(self::$installedByVendor[$vendorDir])) {
+                    $installed[] = self::$installedByVendor[$vendorDir];
+                } elseif (is_file($vendorDir.'/composer/installed.php')) {
+                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+                        self::$installed = $installed[count($installed) - 1];
+                    }
+                }
+            }
+        }
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = require __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+        $installed[] = self::$installed;
+
+        return $installed;
+    }
+}

+ 21 - 0
vendor/composer/LICENSE

@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+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.
+

+ 15 - 0
vendor/composer/autoload_classmap.php

@@ -0,0 +1,15 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+return array(
+    'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
+    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+    'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
+    'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+    'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+    'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+);

+ 15 - 0
vendor/composer/autoload_files.php

@@ -0,0 +1,15 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+return array(
+    '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
+    '35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
+    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+    '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
+    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
+    '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
+);

+ 11 - 0
vendor/composer/autoload_namespaces.php

@@ -0,0 +1,11 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+return array(
+    'PHPExcel' => array($vendorDir . '/phpoffice/phpexcel/Classes'),
+    '' => array($baseDir . '/extend'),
+);

+ 26 - 0
vendor/composer/autoload_psr4.php

@@ -0,0 +1,26 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = dirname($vendorDir);
+
+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/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-template/src'),
+    'app\\' => array($baseDir . '/app'),
+    'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
+    'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
+    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+    'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
+    'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
+    'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
+    'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
+    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
+    'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
+    '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'),
+);

+ 57 - 0
vendor/composer/autoload_real.php

@@ -0,0 +1,57 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit0767332e67f37ff78a6c5ac32275d5ac
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    /**
+     * @return \Composer\Autoload\ClassLoader
+     */
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        require __DIR__ . '/platform_check.php';
+
+        spl_autoload_register(array('ComposerAutoloaderInit0767332e67f37ff78a6c5ac32275d5ac', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
+        spl_autoload_unregister(array('ComposerAutoloaderInit0767332e67f37ff78a6c5ac32275d5ac', 'loadClassLoader'));
+
+        require __DIR__ . '/autoload_static.php';
+        call_user_func(\Composer\Autoload\ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::getInitializer($loader));
+
+        $loader->register(true);
+
+        $includeFiles = \Composer\Autoload\ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$files;
+        foreach ($includeFiles as $fileIdentifier => $file) {
+            composerRequire0767332e67f37ff78a6c5ac32275d5ac($fileIdentifier, $file);
+        }
+
+        return $loader;
+    }
+}
+
+/**
+ * @param string $fileIdentifier
+ * @param string $file
+ * @return void
+ */
+function composerRequire0767332e67f37ff78a6c5ac32275d5ac($fileIdentifier, $file)
+{
+    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+        require $file;
+    }
+}

+ 161 - 0
vendor/composer/autoload_static.php

@@ -0,0 +1,161 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac
+{
+    public static $files = array (
+        '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
+        '35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
+        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+        '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
+        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
+        '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
+    );
+
+    public static $prefixLengthsPsr4 = array (
+        't' => 
+        array (
+            'think\\view\\driver\\' => 18,
+            'think\\trace\\' => 12,
+            'think\\app\\' => 10,
+            'think\\' => 6,
+        ),
+        'a' => 
+        array (
+            'app\\' => 4,
+        ),
+        'S' => 
+        array (
+            'Symfony\\Polyfill\\Php80\\' => 23,
+            'Symfony\\Polyfill\\Php72\\' => 23,
+            'Symfony\\Polyfill\\Mbstring\\' => 26,
+            'Symfony\\Component\\VarDumper\\' => 28,
+        ),
+        'P' => 
+        array (
+            'Psr\\SimpleCache\\' => 16,
+            'Psr\\Log\\' => 8,
+            'Psr\\Http\\Message\\' => 17,
+            'Psr\\Container\\' => 14,
+            'Psr\\Cache\\' => 10,
+        ),
+        'L' => 
+        array (
+            'League\\MimeTypeDetection\\' => 25,
+            'League\\Flysystem\\Cached\\' => 24,
+            'League\\Flysystem\\' => 17,
+        ),
+    );
+
+    public static $prefixDirsPsr4 = array (
+        'think\\view\\driver\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/topthink/think-view/src',
+        ),
+        'think\\trace\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/topthink/think-trace/src',
+        ),
+        'think\\app\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/topthink/think-multi-app/src',
+        ),
+        'think\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/topthink/think-helper/src',
+            1 => __DIR__ . '/..' . '/topthink/think-orm/src',
+            2 => __DIR__ . '/..' . '/topthink/framework/src/think',
+            3 => __DIR__ . '/..' . '/topthink/think-template/src',
+        ),
+        'app\\' => 
+        array (
+            0 => __DIR__ . '/../..' . '/app',
+        ),
+        'Symfony\\Polyfill\\Php80\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
+        ),
+        'Symfony\\Polyfill\\Php72\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
+        ),
+        'Symfony\\Polyfill\\Mbstring\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+        ),
+        'Symfony\\Component\\VarDumper\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/symfony/var-dumper',
+        ),
+        'Psr\\SimpleCache\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/simple-cache/src',
+        ),
+        'Psr\\Log\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
+        ),
+        'Psr\\Http\\Message\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/http-message/src',
+        ),
+        'Psr\\Container\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/container/src',
+        ),
+        'Psr\\Cache\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/cache/src',
+        ),
+        'League\\MimeTypeDetection\\' => 
+        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',
+        ),
+    );
+
+    public static $prefixesPsr0 = array (
+        'P' => 
+        array (
+            'PHPExcel' => 
+            array (
+                0 => __DIR__ . '/..' . '/phpoffice/phpexcel/Classes',
+            ),
+        ),
+    );
+
+    public static $fallbackDirsPsr0 = array (
+        0 => __DIR__ . '/../..' . '/extend',
+    );
+
+    public static $classMap = array (
+        'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
+        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+        'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
+        'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+        'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+        'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+    );
+
+    public static function getInitializer(ClassLoader $loader)
+    {
+        return \Closure::bind(function () use ($loader) {
+            $loader->prefixLengthsPsr4 = ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$prefixDirsPsr4;
+            $loader->prefixesPsr0 = ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$prefixesPsr0;
+            $loader->fallbackDirsPsr0 = ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$fallbackDirsPsr0;
+            $loader->classMap = ComposerStaticInit0767332e67f37ff78a6c5ac32275d5ac::$classMap;
+
+        }, null, ClassLoader::class);
+    }
+}

+ 1006 - 0
vendor/composer/installed.json

@@ -0,0 +1,1006 @@
+{
+    "packages": [
+        {
+            "name": "league/flysystem",
+            "version": "1.1.9",
+            "version_normalized": "1.1.9.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/league/flysystem/1.1.9/league-flysystem-1.1.9.zip",
+                "reference": "094defdb4a7001845300334e7c1ee2335925ef99",
+                "shasum": ""
+            },
+            "require": {
+                "ext-fileinfo": "*",
+                "league/mime-type-detection": "^1.3",
+                "php": "^7.2.5 || ^8.0"
+            },
+            "conflict": {
+                "league/flysystem-sftp": "<1.0.6"
+            },
+            "require-dev": {
+                "phpspec/prophecy": "^1.11.1",
+                "phpunit/phpunit": "^8.5.8"
+            },
+            "suggest": {
+                "ext-ftp": "Allows you to use FTP server storage",
+                "ext-openssl": "Allows you to use FTPS server storage",
+                "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
+                "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
+                "league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
+                "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
+                "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
+                "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
+                "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
+                "league/flysystem-webdav": "Allows you to use WebDAV storage",
+                "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
+                "spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
+                "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
+            },
+            "time": "2021-12-09T09:40:50+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "League\\Flysystem\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frenky.net"
+                }
+            ],
+            "description": "Filesystem abstraction: Many filesystems, one API.",
+            "keywords": [
+                "Cloud Files",
+                "WebDAV",
+                "abstraction",
+                "aws",
+                "cloud",
+                "copy.com",
+                "dropbox",
+                "file systems",
+                "files",
+                "filesystem",
+                "filesystems",
+                "ftp",
+                "rackspace",
+                "remote",
+                "s3",
+                "sftp",
+                "storage"
+            ],
+            "install-path": "../league/flysystem"
+        },
+        {
+            "name": "league/flysystem-cached-adapter",
+            "version": "1.1.0",
+            "version_normalized": "1.1.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/league/flysystem-cached-adapter/1.1.0/league-flysystem-cached-adapter-1.1.0.zip",
+                "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/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "frankdejonge",
+                    "email": "info@frenky.net"
+                }
+            ],
+            "description": "An adapter decorator to enable meta-data caching.",
+            "install-path": "../league/flysystem-cached-adapter"
+        },
+        {
+            "name": "league/mime-type-detection",
+            "version": "1.11.0",
+            "version_normalized": "1.11.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/league/mime-type-detection/1.11.0/league-mime-type-detection-1.11.0.zip",
+                "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
+                "shasum": ""
+            },
+            "require": {
+                "ext-fileinfo": "*",
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "phpstan/phpstan": "^0.12.68",
+                "phpunit/phpunit": "^8.5.8 || ^9.3"
+            },
+            "time": "2022-04-17T13:12:02+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "League\\MimeTypeDetection\\": "src"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Frank de Jonge",
+                    "email": "info@frankdejonge.nl"
+                }
+            ],
+            "description": "Mime-type detection for Flysystem",
+            "install-path": "../league/mime-type-detection"
+        },
+        {
+            "name": "phpoffice/phpexcel",
+            "version": "1.8.2",
+            "version_normalized": "1.8.2.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/phpoffice/phpexcel/1.8.2/phpoffice-phpexcel-1.8.2.zip",
+                "reference": "1441011fb7ecdd8cc689878f54f8b58a6805f870",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "ext-xmlwriter": "*",
+                "php": "^5.2|^7.0"
+            },
+            "require-dev": {
+                "squizlabs/php_codesniffer": "2.*"
+            },
+            "time": "2018-11-22T23:07:24+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-0": {
+                    "PHPExcel": "Classes/"
+                }
+            },
+            "license": [
+                "LGPL-2.1"
+            ],
+            "authors": [
+                {
+                    "name": "Maarten Balliauw",
+                    "homepage": "http://blog.maartenballiauw.be"
+                },
+                {
+                    "name": "Erik Tilt"
+                },
+                {
+                    "name": "Franck Lefevre",
+                    "homepage": "http://rootslabs.net"
+                },
+                {
+                    "name": "Mark Baker",
+                    "homepage": "http://markbakeruk.net"
+                }
+            ],
+            "description": "PHPExcel - OpenXML - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+            "homepage": "https://github.com/PHPOffice/PHPExcel",
+            "keywords": [
+                "OpenXML",
+                "excel",
+                "php",
+                "spreadsheet",
+                "xls",
+                "xlsx"
+            ],
+            "install-path": "../phpoffice/phpexcel"
+        },
+        {
+            "name": "psr/cache",
+            "version": "1.0.1",
+            "version_normalized": "1.0.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/cache/1.0.1/psr-cache-1.0.1.zip",
+                "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "time": "2016-08-06T20:24:11+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Cache\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for caching libraries",
+            "keywords": [
+                "cache",
+                "psr",
+                "psr-6"
+            ],
+            "install-path": "../psr/cache"
+        },
+        {
+            "name": "psr/container",
+            "version": "1.1.1",
+            "version_normalized": "1.1.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/1.1.1/psr-container-1.1.1.zip",
+                "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2.0"
+            },
+            "time": "2021-03-05T17:36:06+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "install-path": "../psr/container"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.0.1",
+            "version_normalized": "1.0.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-message/1.0.1/psr-http-message-1.0.1.zip",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "time": "2016-08-06T14:39:51+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "install-path": "../psr/http-message"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.1.4",
+            "version_normalized": "1.1.4.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/log/1.1.4/psr-log-1.1.4.zip",
+                "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "time": "2021-05-03T11:20:27+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "Psr/Log/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "install-path": "../psr/log"
+        },
+        {
+            "name": "psr/simple-cache",
+            "version": "1.0.1",
+            "version_normalized": "1.0.1.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/psr/simple-cache/1.0.1/psr-simple-cache-1.0.1.zip",
+                "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "time": "2017-10-23T01:57:42+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\SimpleCache\\": "src/"
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interfaces for simple caching",
+            "keywords": [
+                "cache",
+                "caching",
+                "psr",
+                "psr-16",
+                "simple-cache"
+            ],
+            "install-path": "../psr/simple-cache"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.26.0",
+            "version_normalized": "1.26.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.26.0/symfony-polyfill-mbstring-v1.26.0.zip",
+                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "provide": {
+                "ext-mbstring": "*"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "time": "2022-05-24T11:49:31+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.26-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "install-path": "../symfony/polyfill-mbstring"
+        },
+        {
+            "name": "symfony/polyfill-php72",
+            "version": "v1.26.0",
+            "version_normalized": "1.26.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/polyfill-php72/v1.26.0/symfony-polyfill-php72-v1.26.0.zip",
+                "reference": "bf44a9fd41feaac72b074de600314a93e2ae78e2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "time": "2022-05-24T11:49:31+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.26-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php72\\": ""
+                }
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "install-path": "../symfony/polyfill-php72"
+        },
+        {
+            "name": "symfony/polyfill-php80",
+            "version": "v1.26.0",
+            "version_normalized": "1.26.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/polyfill-php80/v1.26.0/symfony-polyfill-php80-v1.26.0.zip",
+                "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "time": "2022-05-10T07:21:04+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "1.26-dev"
+                },
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php80\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ion Bazan",
+                    "email": "ion.bazan@gmail.com"
+                },
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "install-path": "../symfony/polyfill-php80"
+        },
+        {
+            "name": "symfony/var-dumper",
+            "version": "v4.4.44",
+            "version_normalized": "4.4.44.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/symfony/var-dumper/v4.4.44/symfony-var-dumper-v4.4.44.zip",
+                "reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.3",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/polyfill-php72": "~1.5",
+                "symfony/polyfill-php80": "^1.16"
+            },
+            "conflict": {
+                "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
+                "symfony/console": "<3.4"
+            },
+            "require-dev": {
+                "ext-iconv": "*",
+                "symfony/console": "^3.4|^4.0|^5.0",
+                "symfony/process": "^4.4|^5.0",
+                "twig/twig": "^1.43|^2.13|^3.0.4"
+            },
+            "suggest": {
+                "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+                "ext-intl": "To show region name in time zone dump",
+                "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
+            },
+            "time": "2022-07-20T09:59:04+00:00",
+            "bin": [
+                "Resources/bin/var-dump-server"
+            ],
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "Resources/functions/dump.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Component\\VarDumper\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "debug",
+                "dump"
+            ],
+            "install-path": "../symfony/var-dumper"
+        },
+        {
+            "name": "topthink/framework",
+            "version": "v6.0.13",
+            "version_normalized": "6.0.13.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/framework/v6.0.13/topthink-framework-v6.0.13.zip",
+                "reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-mbstring": "*",
+                "league/flysystem": "^1.1.4",
+                "league/flysystem-cached-adapter": "^1.0",
+                "php": ">=7.2.5",
+                "psr/container": "~1.0",
+                "psr/http-message": "^1.0",
+                "psr/log": "~1.0",
+                "psr/simple-cache": "^1.0",
+                "topthink/think-helper": "^3.1.1",
+                "topthink/think-orm": "^2.0"
+            },
+            "require-dev": {
+                "guzzlehttp/psr7": "^2.1.0",
+                "mikey179/vfsstream": "^1.6",
+                "mockery/mockery": "^1.2",
+                "phpunit/phpunit": "^7.0"
+            },
+            "time": "2022-07-15T02:52:08+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "files": [],
+                "psr-4": {
+                    "think\\": "src/think/"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                },
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP Framework.",
+            "homepage": "http://thinkphp.cn/",
+            "keywords": [
+                "framework",
+                "orm",
+                "thinkphp"
+            ],
+            "install-path": "../topthink/framework"
+        },
+        {
+            "name": "topthink/think-helper",
+            "version": "v3.1.6",
+            "version_normalized": "3.1.6.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-helper/v3.1.6/topthink-think-helper-v3.1.6.zip",
+                "reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^9.5"
+            },
+            "time": "2021-12-15T04:27:55+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "src/helper.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "yunwuxin",
+                    "email": "448901948@qq.com"
+                }
+            ],
+            "description": "The ThinkPHP6 Helper Package",
+            "install-path": "../topthink/think-helper"
+        },
+        {
+            "name": "topthink/think-multi-app",
+            "version": "v1.0.14",
+            "version_normalized": "1.0.14.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-multi-app/v1.0.14/topthink-think-multi-app-v1.0.14.zip",
+                "reference": "ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0"
+            },
+            "time": "2020-07-12T13:50:37+00:00",
+            "type": "library",
+            "extra": {
+                "think": {
+                    "services": [
+                        "think\\app\\Service"
+                    ]
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "think\\app\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "thinkphp6 multi app support",
+            "install-path": "../topthink/think-multi-app"
+        },
+        {
+            "name": "topthink/think-orm",
+            "version": "v2.0.54",
+            "version_normalized": "2.0.54.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-orm/v2.0.54/topthink-think-orm-v2.0.54.zip",
+                "reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "ext-pdo": "*",
+                "php": ">=7.1.0",
+                "psr/log": "^1.0|^2.0",
+                "psr/simple-cache": "^1.0|^2.0",
+                "topthink/think-helper": "^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7|^8|^9.5"
+            },
+            "time": "2022-07-05T05:25:51+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "files": [
+                    "stubs/load_stubs.php"
+                ],
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "think orm",
+            "keywords": [
+                "database",
+                "orm"
+            ],
+            "install-path": "../topthink/think-orm"
+        },
+        {
+            "name": "topthink/think-template",
+            "version": "v2.0.8",
+            "version_normalized": "2.0.8.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-template/v2.0.8/topthink-think-template-v2.0.8.zip",
+                "reference": "abfc293f74f9ef5127b5c416310a01fe42e59368",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "psr/simple-cache": "^1.0"
+            },
+            "time": "2020-12-10T07:52:03+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "think\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "the php template engine",
+            "install-path": "../topthink/think-template"
+        },
+        {
+            "name": "topthink/think-trace",
+            "version": "v1.4",
+            "version_normalized": "1.4.0.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.cloud.tencent.com/repository/composer/topthink/think-trace/v1.4/topthink-think-trace-v1.4.zip",
+                "reference": "9a9fa8f767b6c66c5a133ad21ca1bc96ad329444",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "topthink/framework": "^6.0.0"
+            },
+            "time": "2020-06-29T05:27:28+00:00",
+            "type": "library",
+            "extra": {
+                "think": {
+                    "services": [
+                        "think\\trace\\Service"
+                    ],
+                    "config": {
+                        "trace": "src/config.php"
+                    }
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "think\\trace\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "thinkphp debug trace",
+            "install-path": "../topthink/think-trace"
+        },
+        {
+            "name": "topthink/think-view",
+            "version": "v1.0.14",
+            "version_normalized": "1.0.14.0",
+            "dist": {
+                "type": "zip",
+                "url": "https://mirrors.tencent.com/repository/composer/topthink/think-view/v1.0.14/topthink-think-view-v1.0.14.zip",
+                "reference": "edce0ae2c9551ab65f9e94a222604b0dead3576d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1.0",
+                "topthink/think-template": "^2.0"
+            },
+            "time": "2019-11-06T11:40:13+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "think\\view\\driver\\": "src"
+                }
+            },
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "liu21st",
+                    "email": "liu21st@gmail.com"
+                }
+            ],
+            "description": "thinkphp template driver",
+            "install-path": "../topthink/think-view"
+        }
+    ],
+    "dev": true,
+    "dev-package-names": [
+        "symfony/polyfill-mbstring",
+        "symfony/polyfill-php72",
+        "symfony/polyfill-php80",
+        "symfony/var-dumper",
+        "topthink/think-trace"
+    ]
+}

+ 203 - 0
vendor/composer/installed.php

@@ -0,0 +1,203 @@
+<?php return array(
+    'root' => array(
+        'pretty_version' => 'dev-master',
+        'version' => 'dev-master',
+        'type' => 'project',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'reference' => 'e9c0e9e209e6afbe48071401bde74757dc8e17c4',
+        'name' => 'topthink/think',
+        'dev' => true,
+    ),
+    'versions' => array(
+        'league/flysystem' => array(
+            'pretty_version' => '1.1.9',
+            'version' => '1.1.9.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/flysystem',
+            'aliases' => array(),
+            'reference' => '094defdb4a7001845300334e7c1ee2335925ef99',
+            'dev_requirement' => false,
+        ),
+        'league/flysystem-cached-adapter' => array(
+            'pretty_version' => '1.1.0',
+            'version' => '1.1.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/flysystem-cached-adapter',
+            'aliases' => array(),
+            'reference' => 'd1925efb2207ac4be3ad0c40b8277175f99ffaff',
+            'dev_requirement' => false,
+        ),
+        'league/mime-type-detection' => array(
+            'pretty_version' => '1.11.0',
+            'version' => '1.11.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/mime-type-detection',
+            'aliases' => array(),
+            'reference' => 'ff6248ea87a9f116e78edd6002e39e5128a0d4dd',
+            'dev_requirement' => false,
+        ),
+        'phpoffice/phpexcel' => array(
+            'pretty_version' => '1.8.2',
+            'version' => '1.8.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpoffice/phpexcel',
+            'aliases' => array(),
+            'reference' => '1441011fb7ecdd8cc689878f54f8b58a6805f870',
+            'dev_requirement' => false,
+        ),
+        'psr/cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/cache',
+            'aliases' => array(),
+            'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
+            'dev_requirement' => false,
+        ),
+        'psr/container' => array(
+            'pretty_version' => '1.1.1',
+            'version' => '1.1.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/container',
+            'aliases' => array(),
+            'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
+            'dev_requirement' => false,
+        ),
+        'psr/http-message' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-message',
+            'aliases' => array(),
+            'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
+            'dev_requirement' => false,
+        ),
+        'psr/log' => array(
+            'pretty_version' => '1.1.4',
+            'version' => '1.1.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/log',
+            'aliases' => array(),
+            'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
+            'dev_requirement' => false,
+        ),
+        'psr/simple-cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/simple-cache',
+            'aliases' => array(),
+            'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-mbstring' => array(
+            'pretty_version' => 'v1.26.0',
+            'version' => '1.26.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+            'aliases' => array(),
+            'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e',
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-php72' => array(
+            'pretty_version' => 'v1.26.0',
+            'version' => '1.26.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php72',
+            'aliases' => array(),
+            'reference' => 'bf44a9fd41feaac72b074de600314a93e2ae78e2',
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-php80' => array(
+            'pretty_version' => 'v1.26.0',
+            'version' => '1.26.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+            'aliases' => array(),
+            'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
+            'dev_requirement' => true,
+        ),
+        'symfony/var-dumper' => array(
+            'pretty_version' => 'v4.4.44',
+            'version' => '4.4.44.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/var-dumper',
+            'aliases' => array(),
+            'reference' => 'f19951007dae942cc79b979c1fe26bfdfbeb54ed',
+            'dev_requirement' => true,
+        ),
+        'topthink/framework' => array(
+            'pretty_version' => 'v6.0.13',
+            'version' => '6.0.13.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/framework',
+            'aliases' => array(),
+            'reference' => '126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6',
+            'dev_requirement' => false,
+        ),
+        'topthink/think' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'project',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'reference' => 'e9c0e9e209e6afbe48071401bde74757dc8e17c4',
+            'dev_requirement' => false,
+        ),
+        'topthink/think-helper' => array(
+            'pretty_version' => 'v3.1.6',
+            'version' => '3.1.6.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-helper',
+            'aliases' => array(),
+            'reference' => '769acbe50a4274327162f9c68ec2e89a38eb2aff',
+            'dev_requirement' => false,
+        ),
+        'topthink/think-multi-app' => array(
+            'pretty_version' => 'v1.0.14',
+            'version' => '1.0.14.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-multi-app',
+            'aliases' => array(),
+            'reference' => 'ccaad7c2d33f42cb1cc2a78d6610aaec02cea4c3',
+            'dev_requirement' => false,
+        ),
+        'topthink/think-orm' => array(
+            'pretty_version' => 'v2.0.54',
+            'version' => '2.0.54.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-orm',
+            'aliases' => array(),
+            'reference' => '97b061b47616301ff29fbd4c35ed9184e1162e4e',
+            'dev_requirement' => false,
+        ),
+        'topthink/think-template' => array(
+            'pretty_version' => 'v2.0.8',
+            'version' => '2.0.8.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-template',
+            'aliases' => array(),
+            'reference' => 'abfc293f74f9ef5127b5c416310a01fe42e59368',
+            'dev_requirement' => false,
+        ),
+        'topthink/think-trace' => array(
+            'pretty_version' => 'v1.4',
+            'version' => '1.4.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-trace',
+            'aliases' => array(),
+            'reference' => '9a9fa8f767b6c66c5a133ad21ca1bc96ad329444',
+            'dev_requirement' => true,
+        ),
+        'topthink/think-view' => array(
+            'pretty_version' => 'v1.0.14',
+            'version' => '1.0.14.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-view',
+            'aliases' => array(),
+            'reference' => 'edce0ae2c9551ab65f9e94a222604b0dead3576d',
+            'dev_requirement' => false,
+        ),
+    ),
+);

+ 26 - 0
vendor/composer/platform_check.php

@@ -0,0 +1,26 @@
+<?php
+
+// platform_check.php @generated by Composer
+
+$issues = array();
+
+if (!(PHP_VERSION_ID >= 70205)) {
+    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+    if (!headers_sent()) {
+        header('HTTP/1.1 500 Internal Server Error');
+    }
+    if (!ini_get('display_errors')) {
+        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+        } elseif (!headers_sent()) {
+            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+        }
+    }
+    trigger_error(
+        'Composer detected issues in your platform: ' . implode(' ', $issues),
+        E_USER_ERROR
+    );
+}

+ 10 - 0
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

+ 4 - 0
vendor/league/flysystem-cached-adapter/.gitignore

@@ -0,0 +1,4 @@
+coverage
+coverage.xml
+composer.lock
+vendor

+ 7 - 0
vendor/league/flysystem-cached-adapter/.php_cs

@@ -0,0 +1,7 @@
+<?php
+
+return Symfony\CS\Config\Config::create()
+    ->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
+    ->fixers(['-yoda_conditions', 'ordered_use', 'short_array_syntax'])
+    ->finder(Symfony\CS\Finder\DefaultFinder::create()
+        ->in(__DIR__.'/src/'));

+ 34 - 0
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]

+ 29 - 0
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'

+ 19 - 0
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.

+ 2 - 0
vendor/league/flysystem-cached-adapter/clover/.gitignore

@@ -0,0 +1,2 @@
+*
+!.gitignore

+ 30 - 0
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"
+        }
+    ]
+}

+ 6 - 0
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

+ 3 - 0
vendor/league/flysystem-cached-adapter/phpunit.php

@@ -0,0 +1,3 @@
+<?php
+
+include __DIR__.'/vendor/autoload.php';

+ 29 - 0
vendor/league/flysystem-cached-adapter/phpunit.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+         backupStaticAttributes="false"
+         bootstrap="./phpunit.php"
+         colors="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false"
+         syntaxCheck="true"
+         verbose="true"
+>
+    <testsuites>
+        <testsuite name="flysystem/tests">
+            <directory suffix=".php">./tests/</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist>
+            <directory suffix=".php">./src/</directory>
+        </whitelist>
+    </filter>
+    <logging>
+        <log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
+        <log type="coverage-html" target="coverage" showUncoveredFiles="true"/>
+        <log type="coverage-clover" target="clover/phpunit.xml" showUncoveredFiles="true"/>
+    </logging>
+</phpunit>

+ 20 - 0
vendor/league/flysystem-cached-adapter/readme.md

@@ -0,0 +1,20 @@
+# Flysystem Cached CachedAdapter
+
+[![Author](http://img.shields.io/badge/author-@frankdejonge-blue.svg?style=flat-square)](https://twitter.com/frankdejonge)
+[![Build Status](https://img.shields.io/travis/thephpleague/flysystem-cached-adapter/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/flysystem-cached-adapter)
+[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/flysystem-cached-adapter.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/flysystem-cached-adapter/code-structure)
+[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/flysystem-cached-adapter.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/flysystem-cached-adapter)
+[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
+[![Packagist Version](https://img.shields.io/packagist/v/league/flysystem-cached-adapter.svg?style=flat-square)](https://packagist.org/packages/league/flysystem-cached-adapter)
+[![Total Downloads](https://img.shields.io/packagist/dt/league/flysystem-cached-adapter.svg?style=flat-square)](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/)

+ 435 - 0
vendor/league/flysystem-cached-adapter/spec/CachedAdapterSpec.php

@@ -0,0 +1,435 @@
+<?php
+
+namespace spec\League\Flysystem\Cached;
+
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Cached\CacheInterface;
+use League\Flysystem\Config;
+use PhpSpec\ObjectBehavior;
+
+class CachedAdapterSpec extends ObjectBehavior
+{
+    /**
+     * @var AdapterInterface
+     */
+    private $adapter;
+
+    /**
+     * @var CacheInterface
+     */
+    private $cache;
+
+    public function let(AdapterInterface $adapter, CacheInterface $cache)
+    {
+        $this->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);
+    }
+}

+ 101 - 0
vendor/league/flysystem-cached-adapter/src/CacheInterface.php

@@ -0,0 +1,101 @@
+<?php
+
+namespace League\Flysystem\Cached;
+
+use League\Flysystem\ReadInterface;
+
+interface CacheInterface extends ReadInterface
+{
+    /**
+     * Check whether the directory listing of a given directory is complete.
+     *
+     * @param string $dirname
+     * @param bool   $recursive
+     *
+     * @return bool
+     */
+    public function isComplete($dirname, $recursive);
+
+    /**
+     * Set a directory to completely listed.
+     *
+     * @param string $dirname
+     * @param bool   $recursive
+     */
+    public function setComplete($dirname, $recursive);
+
+    /**
+     * Store the contents of a directory.
+     *
+     * @param string $directory
+     * @param array  $contents
+     * @param bool   $recursive
+     */
+    public function storeContents($directory, array $contents, $recursive);
+
+    /**
+     * Flush the cache.
+     */
+    public function flush();
+
+    /**
+     * Autosave trigger.
+     */
+    public function autosave();
+
+    /**
+     * Store the cache.
+     */
+    public function save();
+
+    /**
+     * Load the cache.
+     */
+    public function load();
+
+    /**
+     * Rename a file.
+     *
+     * @param string $path
+     * @param string $newpath
+     */
+    public function rename($path, $newpath);
+
+    /**
+     * Copy a file.
+     *
+     * @param string $path
+     * @param string $newpath
+     */
+    public function copy($path, $newpath);
+
+    /**
+     * Delete an object from cache.
+     *
+     * @param string $path object path
+     */
+    public function delete($path);
+
+    /**
+     * Delete all objects from from a directory.
+     *
+     * @param string $dirname directory path
+     */
+    public function deleteDir($dirname);
+
+    /**
+     * 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);
+
+    /**
+     * Store object hit miss.
+     *
+     * @param string $path
+     */
+    public function storeMiss($path);
+}

+ 346 - 0
vendor/league/flysystem-cached-adapter/src/CachedAdapter.php

@@ -0,0 +1,346 @@
+<?php
+
+namespace League\Flysystem\Cached;
+
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Config;
+
+class CachedAdapter implements AdapterInterface
+{
+    /**
+     * @var AdapterInterface
+     */
+    private $adapter;
+
+    /**
+     * @var CacheInterface
+     */
+    private $cache;
+
+    /**
+     * Constructor.
+     *
+     * @param AdapterInterface $adapter
+     * @param CacheInterface   $cache
+     */
+    public function __construct(AdapterInterface $adapter, CacheInterface $cache)
+    {
+        $this->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;
+    }
+}

+ 418 - 0
vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php

@@ -0,0 +1,418 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use League\Flysystem\Cached\CacheInterface;
+use League\Flysystem\Util;
+
+abstract class AbstractCache implements CacheInterface
+{
+    /**
+     * @var bool
+     */
+    protected $autosave = true;
+
+    /**
+     * @var array
+     */
+    protected $cache = [];
+
+    /**
+     * @var array
+     */
+    protected $complete = [];
+
+    /**
+     * Destructor.
+     */
+    public function __destruct()
+    {
+        if (! $this->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;
+    }
+}

+ 115 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php

@@ -0,0 +1,115 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Config;
+
+class Adapter extends AbstractCache
+{
+    /**
+     * @var AdapterInterface An adapter
+     */
+    protected $adapter;
+
+    /**
+     * @var string the file to cache to
+     */
+    protected $file;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire = null;
+
+    /**
+     * Constructor.
+     *
+     * @param AdapterInterface $adapter adapter
+     * @param string           $file    the file to cache to
+     * @param int|null         $expire  seconds until cache expiration
+     */
+    public function __construct(AdapterInterface $adapter, $file, $expire = null)
+    {
+        $this->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);
+        }
+    }
+}

+ 59 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Memcached.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use Memcached as NativeMemcached;
+
+class Memcached extends AbstractCache
+{
+    /**
+     * @var string storage key
+     */
+    protected $key;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire;
+
+    /**
+     * @var \Memcached Memcached instance
+     */
+    protected $memcached;
+
+    /**
+     * Constructor.
+     *
+     * @param \Memcached $memcached
+     * @param string     $key       storage key
+     * @param int|null   $expire    seconds until cache expiration
+     */
+    public function __construct(NativeMemcached $memcached, $key = 'flysystem', $expire = null)
+    {
+        $this->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);
+    }
+}

+ 22 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Memory.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+class Memory extends AbstractCache
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        // There is nothing to save
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function load()
+    {
+        // There is nothing to load
+    }
+}

+ 171 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Noop.php

@@ -0,0 +1,171 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+class Noop extends AbstractCache
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected $autosave = false;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function updateObject($path, array $object, $autosave = false)
+    {
+        return $object;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function isComplete($dirname, $recursive)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setComplete($dirname, $recursive)
+    {
+        //
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function copy($path, $newpath)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rename($path, $newpath)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function storeContents($directory, array $contents, $recursive = false)
+    {
+        return $contents;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function storeMiss($path)
+    {
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function flush()
+    {
+        //
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function autosave()
+    {
+        //
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function save()
+    {
+        //
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function load()
+    {
+        //
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function has($path)
+    {
+        return;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function read($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function readStream($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        return [];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getMetadata($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSize($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getMimetype($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTimestamp($path)
+    {
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getVisibility($path)
+    {
+        return false;
+    }
+}

+ 62 - 0
vendor/league/flysystem-cached-adapter/src/Storage/PhpRedis.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use Redis;
+
+class PhpRedis extends AbstractCache
+{
+    /**
+     * @var Redis PhpRedis Client
+     */
+    protected $client;
+
+    /**
+     * @var string storage key
+     */
+    protected $key;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire;
+
+    /**
+     * Constructor.
+     *
+     * @param Redis|null $client phpredis client
+     * @param string     $key    storage key
+     * @param int|null   $expire seconds until cache expiration
+     */
+    public function __construct(Redis $client = null, $key = 'flysystem', $expire = null)
+    {
+        $this->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);
+        }
+    }
+}

+ 75 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Predis.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use Predis\Client;
+
+class Predis extends AbstractCache
+{
+    /**
+     * @var \Predis\Client Predis Client
+     */
+    protected $client;
+
+    /**
+     * @var string storage key
+     */
+    protected $key;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire;
+
+    /**
+     * Constructor.
+     *
+     * @param \Predis\Client $client predis client
+     * @param string         $key    storage key
+     * @param int|null       $expire seconds until cache expiration
+     */
+    public function __construct(Client $client = null, $key = 'flysystem', $expire = null)
+    {
+        $this->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);
+    }
+}

+ 59 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Psr6Cache.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use Psr\Cache\CacheItemPoolInterface;
+
+class Psr6Cache extends AbstractCache
+{
+    /**
+     * @var CacheItemPoolInterface
+     */
+    private $pool;
+
+    /**
+     * @var string storage key
+     */
+    protected $key;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire;
+
+    /**
+     * Constructor.
+     *
+     * @param CacheItemPoolInterface $pool
+     * @param string                 $key    storage key
+     * @param int|null               $expire seconds until cache expiration
+     */
+    public function __construct(CacheItemPoolInterface $pool, $key = 'flysystem', $expire = null)
+    {
+        $this->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());
+        }
+    }
+}

+ 60 - 0
vendor/league/flysystem-cached-adapter/src/Storage/Stash.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace League\Flysystem\Cached\Storage;
+
+use Stash\Pool;
+
+class Stash extends AbstractCache
+{
+    /**
+     * @var string storage key
+     */
+    protected $key;
+
+    /**
+     * @var int|null seconds until cache expiration
+     */
+    protected $expire;
+
+    /**
+     * @var \Stash\Pool Stash pool instance
+     */
+    protected $pool;
+
+    /**
+     * Constructor.
+     *
+     * @param \Stash\Pool $pool
+     * @param string      $key    storage key
+     * @param int|null    $expire seconds until cache expiration
+     */
+    public function __construct(Pool $pool, $key = 'flysystem', $expire = null)
+    {
+        $this->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);
+    }
+}

+ 104 - 0
vendor/league/flysystem-cached-adapter/tests/AdapterCacheTests.php

@@ -0,0 +1,104 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Adapter;
+use PHPUnit\Framework\TestCase;
+
+class AdapterCacheTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+        $adapter->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)));
+    }
+}

+ 16 - 0
vendor/league/flysystem-cached-adapter/tests/InspectionTests.php

@@ -0,0 +1,16 @@
+<?php
+
+use League\Flysystem\Cached\CachedAdapter;
+use PHPUnit\Framework\TestCase;
+
+class InspectionTests extends TestCase {
+
+    public function testGetAdapter()
+    {
+        $adapter = Mockery::mock('League\Flysystem\AdapterInterface');
+        $cache = Mockery::mock('League\Flysystem\Cached\CacheInterface');
+        $cache->shouldReceive('load')->once();
+        $cached_adapter = new CachedAdapter($adapter, $cache);
+        $this->assertInstanceOf('League\Flysystem\AdapterInterface', $cached_adapter->getAdapter());
+    }
+}

+ 35 - 0
vendor/league/flysystem-cached-adapter/tests/MemcachedTests.php

@@ -0,0 +1,35 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Memcached;
+use PHPUnit\Framework\TestCase;
+
+class MemcachedTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $client = Mockery::mock('Memcached');
+        $client->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();
+    }
+}

+ 255 - 0
vendor/league/flysystem-cached-adapter/tests/MemoryCacheTests.php

@@ -0,0 +1,255 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Memory;
+use League\Flysystem\Util;
+use PHPUnit\Framework\TestCase;
+
+class MemoryCacheTests extends TestCase
+{
+    public function testAutosave()
+    {
+        $cache = new Memory();
+        $cache->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'));
+    }
+}

+ 35 - 0
vendor/league/flysystem-cached-adapter/tests/NoopCacheTests.php

@@ -0,0 +1,35 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Noop;
+use PHPUnit\Framework\TestCase;
+
+class NoopCacheTests extends TestCase
+{
+    public function testNoop()
+    {
+        $cache = new Noop();
+        $this->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));
+    }
+}

+ 45 - 0
vendor/league/flysystem-cached-adapter/tests/PhpRedisTests.php

@@ -0,0 +1,45 @@
+<?php
+
+use League\Flysystem\Cached\Storage\PhpRedis;
+use PHPUnit\Framework\TestCase;
+
+class PhpRedisTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $client = Mockery::mock('Redis');
+        $client->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();
+    }
+}

+ 55 - 0
vendor/league/flysystem-cached-adapter/tests/PredisTests.php

@@ -0,0 +1,55 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Predis;
+use PHPUnit\Framework\TestCase;
+
+class PredisTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $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(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();
+    }
+}

+ 45 - 0
vendor/league/flysystem-cached-adapter/tests/Psr6CacheTest.php

@@ -0,0 +1,45 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Psr6Cache;
+use PHPUnit\Framework\TestCase;
+
+class Psr6CacheTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $pool = Mockery::mock('Psr\Cache\CacheItemPoolInterface');
+        $item = Mockery::mock('Psr\Cache\CacheItemInterface');
+        $item->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();
+    }
+}

+ 43 - 0
vendor/league/flysystem-cached-adapter/tests/StashTest.php

@@ -0,0 +1,43 @@
+<?php
+
+use League\Flysystem\Cached\Storage\Stash;
+use PHPUnit\Framework\TestCase;
+
+class StashTests extends TestCase
+{
+    public function testLoadFail()
+    {
+        $pool = Mockery::mock('Stash\Pool');
+        $item = Mockery::mock('Stash\Item');
+        $item->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();
+    }
+}

+ 76 - 0
vendor/league/flysystem/CODE_OF_CONDUCT.md

@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at info+flysystem@frankdejonge.nl. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq

+ 19 - 0
vendor/league/flysystem/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2013-2019 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.

+ 16 - 0
vendor/league/flysystem/SECURITY.md

@@ -0,0 +1,16 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported          |
+| ------- | ------------------ |
+| 1.0.x   | :white_check_mark: |
+| 2.0.x   | :x:                |
+
+## Reporting a Vulnerability
+
+When you've encountered a security vulnerability, please disclose it securely.
+
+The security process is described at: 
+[https://flysystem.thephpleague.com/docs/security/](https://flysystem.thephpleague.com/docs/security/)
+

+ 68 - 0
vendor/league/flysystem/composer.json

@@ -0,0 +1,68 @@
+{
+    "name": "league/flysystem",
+    "type": "library",
+    "description": "Filesystem abstraction: Many filesystems, one API.",
+    "keywords": [
+        "filesystem", "filesystems", "files", "storage", "dropbox", "aws",
+        "abstraction", "s3", "ftp", "sftp", "remote", "webdav",
+        "file systems", "cloud", "cloud files", "rackspace", "copy.com"
+    ],
+    "funding": [
+        {
+            "type": "other",
+            "url": "https://offset.earth/frankdejonge"
+        }
+    ],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Frank de Jonge",
+            "email": "info@frenky.net"
+        }
+    ],
+    "require": {
+        "php": "^7.2.5 || ^8.0",
+        "ext-fileinfo": "*",
+        "league/mime-type-detection": "^1.3"
+    },
+    "require-dev": {
+        "phpspec/prophecy": "^1.11.1",
+        "phpunit/phpunit": "^8.5.8"
+    },
+    "autoload": {
+        "psr-4": {
+            "League\\Flysystem\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "League\\Flysystem\\Stub\\": "stub/"
+        }
+    },
+    "suggest": {
+        "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
+        "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
+        "league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
+        "league/flysystem-webdav": "Allows you to use WebDAV storage",
+        "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
+        "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
+        "spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
+        "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications",
+        "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
+        "ext-ftp": "Allows you to use FTP server storage",
+        "ext-openssl": "Allows you to use FTPS server storage",
+        "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
+        "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter"
+    },
+    "conflict": {
+        "league/flysystem-sftp": "<1.0.6"
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "1.1-dev"
+        }
+    },
+    "scripts": {
+        "phpstan": "php phpstan.php"
+    }
+}

+ 19 - 0
vendor/league/flysystem/deprecations.md

@@ -0,0 +1,19 @@
+# Deprecations
+
+This document lists all the planned deprecations.
+
+## Handlers will be removed in 2.0
+
+The `Handler` type and associated calls will be removed in version 2.0.
+
+### Upgrade path
+
+You should create your own implementation for handling OOP usage,
+but it's recommended to move away from using an OOP-style wrapper entirely.
+
+The reason for this is that it's too easy for implementation details (for
+your application this is Flysystem) to leak into the application. The most
+important part for Flysystem is that it improves portability and creates a
+solid boundary between your application core and the infrastructure you use.
+The OOP-style handling breaks this principle, therefore I want to stop
+promoting it. 

+ 72 - 0
vendor/league/flysystem/src/Adapter/AbstractAdapter.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+use League\Flysystem\AdapterInterface;
+
+abstract class AbstractAdapter implements AdapterInterface
+{
+    /**
+     * @var string|null path prefix
+     */
+    protected $pathPrefix;
+
+    /**
+     * @var string
+     */
+    protected $pathSeparator = '/';
+
+    /**
+     * Set the path prefix.
+     *
+     * @param string $prefix
+     *
+     * @return void
+     */
+    public function setPathPrefix($prefix)
+    {
+        $prefix = (string) $prefix;
+
+        if ($prefix === '') {
+            $this->pathPrefix = null;
+
+            return;
+        }
+
+        $this->pathPrefix = rtrim($prefix, '\\/') . $this->pathSeparator;
+    }
+
+    /**
+     * Get the path prefix.
+     *
+     * @return string|null path prefix or null if pathPrefix is empty
+     */
+    public function getPathPrefix()
+    {
+        return $this->pathPrefix;
+    }
+
+    /**
+     * Prefix a path.
+     *
+     * @param string $path
+     *
+     * @return string prefixed path
+     */
+    public function applyPathPrefix($path)
+    {
+        return $this->getPathPrefix() . ltrim($path, '\\/');
+    }
+
+    /**
+     * Remove a path prefix.
+     *
+     * @param string $path
+     *
+     * @return string path without the prefix
+     */
+    public function removePathPrefix($path)
+    {
+        return substr($path, strlen((string) $this->getPathPrefix()));
+    }
+}

+ 705 - 0
vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php

@@ -0,0 +1,705 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+use DateTime;
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Config;
+use League\Flysystem\NotSupportedException;
+use League\Flysystem\SafeStorage;
+use RuntimeException;
+
+abstract class AbstractFtpAdapter extends AbstractAdapter
+{
+    /**
+     * @var mixed
+     */
+    protected $connection;
+
+    /**
+     * @var string
+     */
+    protected $host;
+
+    /**
+     * @var int
+     */
+    protected $port = 21;
+
+    /**
+     * @var bool
+     */
+    protected $ssl = false;
+
+    /**
+     * @var int
+     */
+    protected $timeout = 90;
+
+    /**
+     * @var bool
+     */
+    protected $passive = true;
+
+    /**
+     * @var string
+     */
+    protected $separator = '/';
+
+    /**
+     * @var string|null
+     */
+    protected $root;
+
+    /**
+     * @var int
+     */
+    protected $permPublic = 0744;
+
+    /**
+     * @var int
+     */
+    protected $permPrivate = 0700;
+
+    /**
+     * @var array
+     */
+    protected $configurable = [];
+
+    /**
+     * @var string
+     */
+    protected $systemType;
+
+    /**
+     * @var SafeStorage
+     */
+    protected $safeStorage;
+
+    /**
+     * True to enable timestamps for FTP servers that return unix-style listings.
+     *
+     * @var bool
+     */
+    protected $enableTimestampsOnUnixListings = false;
+
+    /**
+     * Constructor.
+     *
+     * @param array $config
+     */
+    public function __construct(array $config)
+    {
+        $this->safeStorage = new SafeStorage();
+        $this->setConfig($config);
+    }
+
+    /**
+     * Set the config.
+     *
+     * @param array $config
+     *
+     * @return $this
+     */
+    public function setConfig(array $config)
+    {
+        foreach ($this->configurable as $setting) {
+            if ( ! isset($config[$setting])) {
+                continue;
+            }
+
+            $method = 'set' . ucfirst($setting);
+
+            if (method_exists($this, $method)) {
+                $this->$method($config[$setting]);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns the host.
+     *
+     * @return string
+     */
+    public function getHost()
+    {
+        return $this->host;
+    }
+
+    /**
+     * Set the host.
+     *
+     * @param string $host
+     *
+     * @return $this
+     */
+    public function setHost($host)
+    {
+        $this->host = $host;
+
+        return $this;
+    }
+
+    /**
+     * Set the public permission value.
+     *
+     * @param int $permPublic
+     *
+     * @return $this
+     */
+    public function setPermPublic($permPublic)
+    {
+        $this->permPublic = $permPublic;
+
+        return $this;
+    }
+
+    /**
+     * Set the private permission value.
+     *
+     * @param int $permPrivate
+     *
+     * @return $this
+     */
+    public function setPermPrivate($permPrivate)
+    {
+        $this->permPrivate = $permPrivate;
+
+        return $this;
+    }
+
+    /**
+     * Returns the ftp port.
+     *
+     * @return int
+     */
+    public function getPort()
+    {
+        return $this->port;
+    }
+
+    /**
+     * Returns the root folder to work from.
+     *
+     * @return string
+     */
+    public function getRoot()
+    {
+        return $this->root;
+    }
+
+    /**
+     * Set the ftp port.
+     *
+     * @param int|string $port
+     *
+     * @return $this
+     */
+    public function setPort($port)
+    {
+        $this->port = (int) $port;
+
+        return $this;
+    }
+
+    /**
+     * Set the root folder to work from.
+     *
+     * @param string $root
+     *
+     * @return $this
+     */
+    public function setRoot($root)
+    {
+        $this->root = rtrim($root, '\\/') . $this->separator;
+
+        return $this;
+    }
+
+    /**
+     * Returns the ftp username.
+     *
+     * @return string username
+     */
+    public function getUsername()
+    {
+        $username = $this->safeStorage->retrieveSafely('username');
+
+        return $username !== null ? $username : 'anonymous';
+    }
+
+    /**
+     * Set ftp username.
+     *
+     * @param string $username
+     *
+     * @return $this
+     */
+    public function setUsername($username)
+    {
+        $this->safeStorage->storeSafely('username', $username);
+
+        return $this;
+    }
+
+    /**
+     * Returns the password.
+     *
+     * @return string password
+     */
+    public function getPassword()
+    {
+        return $this->safeStorage->retrieveSafely('password');
+    }
+
+    /**
+     * Set the ftp password.
+     *
+     * @param string $password
+     *
+     * @return $this
+     */
+    public function setPassword($password)
+    {
+        $this->safeStorage->storeSafely('password', $password);
+
+        return $this;
+    }
+
+    /**
+     * Returns the amount of seconds before the connection will timeout.
+     *
+     * @return int
+     */
+    public function getTimeout()
+    {
+        return $this->timeout;
+    }
+
+    /**
+     * Set the amount of seconds before the connection should timeout.
+     *
+     * @param int $timeout
+     *
+     * @return $this
+     */
+    public function setTimeout($timeout)
+    {
+        $this->timeout = (int) $timeout;
+
+        return $this;
+    }
+
+    /**
+     * Return the FTP system type.
+     *
+     * @return string
+     */
+    public function getSystemType()
+    {
+        return $this->systemType;
+    }
+
+    /**
+     * Set the FTP system type (windows or unix).
+     *
+     * @param string $systemType
+     *
+     * @return $this
+     */
+    public function setSystemType($systemType)
+    {
+        $this->systemType = strtolower($systemType);
+
+        return $this;
+    }
+
+    /**
+     * True to enable timestamps for FTP servers that return unix-style listings.
+     *
+     * @param bool $bool
+     *
+     * @return $this
+     */
+    public function setEnableTimestampsOnUnixListings($bool = false)
+    {
+        $this->enableTimestampsOnUnixListings = $bool;
+
+        return $this;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        return $this->listDirectoryContents($directory, $recursive);
+    }
+
+    abstract protected function listDirectoryContents($directory, $recursive = false);
+
+    /**
+     * Normalize a directory listing.
+     *
+     * @param array  $listing
+     * @param string $prefix
+     *
+     * @return array directory listing
+     */
+    protected function normalizeListing(array $listing, $prefix = '')
+    {
+        $base = $prefix;
+        $result = [];
+        $listing = $this->removeDotDirectories($listing);
+
+        while ($item = array_shift($listing)) {
+            if (preg_match('#^.*:$#', $item)) {
+                $base = preg_replace('~^\./*|:$~', '', $item);
+                continue;
+            }
+
+            $result[] = $this->normalizeObject($item, $base);
+        }
+
+        return $this->sortListing($result);
+    }
+
+    /**
+     * Sort a directory listing.
+     *
+     * @param array $result
+     *
+     * @return array sorted listing
+     */
+    protected function sortListing(array $result)
+    {
+        $compare = function ($one, $two) {
+            return strnatcmp($one['path'], $two['path']);
+        };
+
+        usort($result, $compare);
+
+        return $result;
+    }
+
+    /**
+     * Normalize a file entry.
+     *
+     * @param string $item
+     * @param string $base
+     *
+     * @return array normalized file array
+     *
+     * @throws NotSupportedException
+     */
+    protected function normalizeObject($item, $base)
+    {
+        $systemType = $this->systemType ?: $this->detectSystemType($item);
+
+        if ($systemType === 'unix') {
+            return $this->normalizeUnixObject($item, $base);
+        } elseif ($systemType === 'windows') {
+            return $this->normalizeWindowsObject($item, $base);
+        }
+
+        throw NotSupportedException::forFtpSystemType($systemType);
+    }
+
+    /**
+     * Normalize a Unix file entry.
+     *
+     * Given $item contains:
+     *    '-rw-r--r--   1 ftp      ftp           409 Aug 19 09:01 file1.txt'
+     *
+     * This function will return:
+     * [
+     *   'type' => 'file',
+     *   'path' => 'file1.txt',
+     *   'visibility' => 'public',
+     *   'size' => 409,
+     *   'timestamp' => 1566205260
+     * ]
+     *
+     * @param string $item
+     * @param string $base
+     *
+     * @return array normalized file array
+     */
+    protected function normalizeUnixObject($item, $base)
+    {
+        $item = preg_replace('#\s+#', ' ', trim($item), 7);
+
+        if (count(explode(' ', $item, 9)) !== 9) {
+            throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
+        }
+
+        list($permissions, /* $number */, /* $owner */, /* $group */, $size, $month, $day, $timeOrYear, $name) = explode(' ', $item, 9);
+        $type = $this->detectType($permissions);
+        $path = $base === '' ? $name : $base . $this->separator . $name;
+
+        if ($type === 'dir') {
+            $result = compact('type', 'path');
+            if ($this->enableTimestampsOnUnixListings) {
+                $timestamp = $this->normalizeUnixTimestamp($month, $day, $timeOrYear);
+                $result += compact('timestamp');
+            }
+
+            return $result;
+        }
+
+        $permissions = $this->normalizePermissions($permissions);
+        $visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
+        $size = (int) $size;
+
+        $result = compact('type', 'path', 'visibility', 'size');
+        if ($this->enableTimestampsOnUnixListings) {
+            $timestamp = $this->normalizeUnixTimestamp($month, $day, $timeOrYear);
+            $result += compact('timestamp');
+        }
+
+        return $result;
+    }
+
+    /**
+     * Only accurate to the minute (current year), or to the day.
+     *
+     * Inadequacies in timestamp accuracy are due to limitations of the FTP 'LIST' command
+     *
+     * Note: The 'MLSD' command is a machine-readable replacement for 'LIST'
+     * but many FTP servers do not support it :(
+     *
+     * @param string $month      e.g. 'Aug'
+     * @param string $day        e.g. '19'
+     * @param string $timeOrYear e.g. '09:01' OR '2015'
+     *
+     * @return int
+     */
+    protected function normalizeUnixTimestamp($month, $day, $timeOrYear)
+    {
+        if (is_numeric($timeOrYear)) {
+            $year = $timeOrYear;
+            $hour = '00';
+            $minute = '00';
+            $seconds = '00';
+        } else {
+            $year = date('Y');
+            list($hour, $minute) = explode(':', $timeOrYear);
+            $seconds = '00';
+        }
+        $dateTime = DateTime::createFromFormat('Y-M-j-G:i:s', "{$year}-{$month}-{$day}-{$hour}:{$minute}:{$seconds}");
+
+        return $dateTime->getTimestamp();
+    }
+
+    /**
+     * Normalize a Windows/DOS file entry.
+     *
+     * @param string $item
+     * @param string $base
+     *
+     * @return array normalized file array
+     */
+    protected function normalizeWindowsObject($item, $base)
+    {
+        $item = preg_replace('#\s+#', ' ', trim($item), 3);
+
+        if (count(explode(' ', $item, 4)) !== 4) {
+            throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
+        }
+
+        list($date, $time, $size, $name) = explode(' ', $item, 4);
+        $path = $base === '' ? $name : $base . $this->separator . $name;
+
+        // Check for the correct date/time format
+        $format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
+        $dt = DateTime::createFromFormat($format, $date . $time);
+        $timestamp = $dt ? $dt->getTimestamp() : (int) strtotime("$date $time");
+
+        if ($size === '<DIR>') {
+            $type = 'dir';
+
+            return compact('type', 'path', 'timestamp');
+        }
+
+        $type = 'file';
+        $visibility = AdapterInterface::VISIBILITY_PUBLIC;
+        $size = (int) $size;
+
+        return compact('type', 'path', 'visibility', 'size', 'timestamp');
+    }
+
+    /**
+     * Get the system type from a listing item.
+     *
+     * @param string $item
+     *
+     * @return string the system type
+     */
+    protected function detectSystemType($item)
+    {
+        return preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', trim($item)) ? 'windows' : 'unix';
+    }
+
+    /**
+     * Get the file type from the permissions.
+     *
+     * @param string $permissions
+     *
+     * @return string file type
+     */
+    protected function detectType($permissions)
+    {
+        return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';
+    }
+
+    /**
+     * Normalize a permissions string.
+     *
+     * @param string $permissions
+     *
+     * @return int
+     */
+    protected function normalizePermissions($permissions)
+    {
+        if (is_numeric($permissions)) {
+            return ((int) $permissions) & 0777;
+        }
+
+        // remove the type identifier
+        $permissions = substr($permissions, 1);
+
+        // map the string rights to the numeric counterparts
+        $map = ['-' => '0', 'r' => '4', 'w' => '2', 'x' => '1'];
+        $permissions = strtr($permissions, $map);
+
+        // split up the permission groups
+        $parts = str_split($permissions, 3);
+
+        // convert the groups
+        $mapper = function ($part) {
+            return array_sum(str_split($part));
+        };
+
+        // converts to decimal number
+        return octdec(implode('', array_map($mapper, $parts)));
+    }
+
+    /**
+     * Filter out dot-directories.
+     *
+     * @param array $list
+     *
+     * @return array
+     */
+    public function removeDotDirectories(array $list)
+    {
+        $filter = function ($line) {
+            return $line !== '' && ! preg_match('#.* \.(\.)?$|^total#', $line);
+        };
+
+        return array_filter($list, $filter);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function has($path)
+    {
+        return $this->getMetadata($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSize($path)
+    {
+        return $this->getMetadata($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getVisibility($path)
+    {
+        return $this->getMetadata($path);
+    }
+
+    /**
+     * Ensure a directory exists.
+     *
+     * @param string $dirname
+     */
+    public function ensureDirectory($dirname)
+    {
+        $dirname = (string) $dirname;
+
+        if ($dirname !== '' && ! $this->has($dirname)) {
+            $this->createDir($dirname, new Config());
+        }
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getConnection()
+    {
+        if ( ! $this->isConnected()) {
+            $this->disconnect();
+            $this->connect();
+        }
+
+        return $this->connection;
+    }
+
+    /**
+     * Get the public permission value.
+     *
+     * @return int
+     */
+    public function getPermPublic()
+    {
+        return $this->permPublic;
+    }
+
+    /**
+     * Get the private permission value.
+     *
+     * @return int
+     */
+    public function getPermPrivate()
+    {
+        return $this->permPrivate;
+    }
+
+    /**
+     * Disconnect on destruction.
+     */
+    public function __destruct()
+    {
+        $this->disconnect();
+    }
+
+    /**
+     * Establish a connection.
+     */
+    abstract public function connect();
+
+    /**
+     * Close the connection.
+     */
+    abstract public function disconnect();
+
+    /**
+     * Check if a connection is active.
+     *
+     * @return bool
+     */
+    abstract public function isConnected();
+
+    protected function escapePath($path)
+    {
+        return str_replace(['*', '[', ']'], ['\\*', '\\[', '\\]'], $path);
+    }
+}

+ 12 - 0
vendor/league/flysystem/src/Adapter/CanOverwriteFiles.php

@@ -0,0 +1,12 @@
+<?php
+
+
+namespace League\Flysystem\Adapter;
+
+/**
+ * Adapters that implement this interface let the Filesystem know that files can be overwritten using the write
+ * functions and don't need the update function to be called. This can help improve performance when asserts are disabled.
+ */
+interface CanOverwriteFiles
+{
+}

+ 584 - 0
vendor/league/flysystem/src/Adapter/Ftp.php

@@ -0,0 +1,584 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
+use League\Flysystem\AdapterInterface;
+use League\Flysystem\Config;
+use League\Flysystem\ConnectionErrorException;
+use League\Flysystem\ConnectionRuntimeException;
+use League\Flysystem\InvalidRootException;
+use League\Flysystem\Util;
+use League\Flysystem\Util\MimeType;
+
+use function in_array;
+
+class Ftp extends AbstractFtpAdapter
+{
+    use StreamedCopyTrait;
+
+    /**
+     * @var int
+     */
+    protected $transferMode = FTP_BINARY;
+
+    /**
+     * @var null|bool
+     */
+    protected $ignorePassiveAddress = null;
+
+    /**
+     * @var bool
+     */
+    protected $recurseManually = false;
+
+    /**
+     * @var bool
+     */
+    protected $utf8 = false;
+
+    /**
+     * @var array
+     */
+    protected $configurable = [
+        'host',
+        'port',
+        'username',
+        'password',
+        'ssl',
+        'timeout',
+        'root',
+        'permPrivate',
+        'permPublic',
+        'passive',
+        'transferMode',
+        'systemType',
+        'ignorePassiveAddress',
+        'recurseManually',
+        'utf8',
+        'enableTimestampsOnUnixListings',
+    ];
+
+    /**
+     * @var bool
+     */
+    protected $isPureFtpd;
+
+    /**
+     * Set the transfer mode.
+     *
+     * @param int $mode
+     *
+     * @return $this
+     */
+    public function setTransferMode($mode)
+    {
+        $this->transferMode = $mode;
+
+        return $this;
+    }
+
+    /**
+     * Set if Ssl is enabled.
+     *
+     * @param bool $ssl
+     *
+     * @return $this
+     */
+    public function setSsl($ssl)
+    {
+        $this->ssl = (bool) $ssl;
+
+        return $this;
+    }
+
+    /**
+     * Set if passive mode should be used.
+     *
+     * @param bool $passive
+     */
+    public function setPassive($passive = true)
+    {
+        $this->passive = $passive;
+    }
+
+    /**
+     * @param bool $ignorePassiveAddress
+     */
+    public function setIgnorePassiveAddress($ignorePassiveAddress)
+    {
+        $this->ignorePassiveAddress = $ignorePassiveAddress;
+    }
+
+    /**
+     * @param bool $recurseManually
+     */
+    public function setRecurseManually($recurseManually)
+    {
+        $this->recurseManually = $recurseManually;
+    }
+
+    /**
+     * @param bool $utf8
+     */
+    public function setUtf8($utf8)
+    {
+        $this->utf8 = (bool) $utf8;
+    }
+
+    /**
+     * Connect to the FTP server.
+     */
+    public function connect()
+    {
+        $tries = 3;
+        start_connecting:
+
+        if ($this->ssl) {
+            $this->connection = @ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
+        } else {
+            $this->connection = @ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
+        }
+
+        if ( ! $this->connection) {
+            $tries--;
+
+            if ($tries > 0) goto start_connecting;
+
+            throw new ConnectionRuntimeException('Could not connect to host: ' . $this->getHost() . ', port:' . $this->getPort());
+        }
+
+        $this->login();
+        $this->setUtf8Mode();
+        $this->setConnectionPassiveMode();
+        $this->setConnectionRoot();
+        $this->isPureFtpd = $this->isPureFtpdServer();
+    }
+
+    /**
+     * Set the connection to UTF-8 mode.
+     */
+    protected function setUtf8Mode()
+    {
+        if ($this->utf8) {
+            $response = ftp_raw($this->connection, "OPTS UTF8 ON");
+            if (!in_array(substr($response[0], 0, 3), ['200', '202'])) {
+                throw new ConnectionRuntimeException(
+                    'Could not set UTF-8 mode for connection: ' . $this->getHost() . '::' . $this->getPort()
+                );
+            }
+        }
+    }
+
+    /**
+     * Set the connections to passive mode.
+     *
+     * @throws ConnectionRuntimeException
+     */
+    protected function setConnectionPassiveMode()
+    {
+        if (is_bool($this->ignorePassiveAddress) && defined('FTP_USEPASVADDRESS')) {
+            ftp_set_option($this->connection, FTP_USEPASVADDRESS, ! $this->ignorePassiveAddress);
+        }
+
+        if ( ! ftp_pasv($this->connection, $this->passive)) {
+            throw new ConnectionRuntimeException(
+                'Could not set passive mode for connection: ' . $this->getHost() . '::' . $this->getPort()
+            );
+        }
+    }
+
+    /**
+     * Set the connection root.
+     */
+    protected function setConnectionRoot()
+    {
+        $root = $this->getRoot();
+        $connection = $this->connection;
+
+        if ($root && ! ftp_chdir($connection, $root)) {
+            throw new InvalidRootException('Root is invalid or does not exist: ' . $this->getRoot());
+        }
+
+        // Store absolute path for further reference.
+        // This is needed when creating directories and
+        // initial root was a relative path, else the root
+        // would be relative to the chdir'd path.
+        $this->root = ftp_pwd($connection);
+    }
+
+    /**
+     * Login.
+     *
+     * @throws ConnectionRuntimeException
+     */
+    protected function login()
+    {
+        set_error_handler(function () {
+        });
+        $isLoggedIn = ftp_login(
+            $this->connection,
+            $this->getUsername(),
+            $this->getPassword()
+        );
+        restore_error_handler();
+
+        if ( ! $isLoggedIn) {
+            $this->disconnect();
+            throw new ConnectionRuntimeException(
+                'Could not login with connection: ' . $this->getHost() . '::' . $this->getPort(
+                ) . ', username: ' . $this->getUsername()
+            );
+        }
+    }
+
+    /**
+     * Disconnect from the FTP server.
+     */
+    public function disconnect()
+    {
+        if ($this->hasFtpConnection()) {
+            @ftp_close($this->connection);
+        }
+
+        $this->connection = null;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function write($path, $contents, Config $config)
+    {
+        $stream = fopen('php://temp', 'w+b');
+        fwrite($stream, $contents);
+        rewind($stream);
+        $result = $this->writeStream($path, $stream, $config);
+        fclose($stream);
+
+        if ($result === false) {
+            return false;
+        }
+
+        $result['contents'] = $contents;
+        $result['mimetype'] = $config->get('mimetype') ?: Util::guessMimeType($path, $contents);
+
+        return $result;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function writeStream($path, $resource, Config $config)
+    {
+        $this->ensureDirectory(Util::dirname($path));
+
+        if ( ! ftp_fput($this->getConnection(), $path, $resource, $this->transferMode)) {
+            return false;
+        }
+
+        if ($visibility = $config->get('visibility')) {
+            $this->setVisibility($path, $visibility);
+        }
+
+        $type = 'file';
+
+        return compact('type', 'path', 'visibility');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function update($path, $contents, Config $config)
+    {
+        return $this->write($path, $contents, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function updateStream($path, $resource, Config $config)
+    {
+        return $this->writeStream($path, $resource, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rename($path, $newpath)
+    {
+        return ftp_rename($this->getConnection(), $path, $newpath);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function delete($path)
+    {
+        return ftp_delete($this->getConnection(), $path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function deleteDir($dirname)
+    {
+        $connection = $this->getConnection();
+        $contents = array_reverse($this->listDirectoryContents($dirname, false));
+
+        foreach ($contents as $object) {
+            if ($object['type'] === 'file') {
+                if ( ! ftp_delete($connection, $object['path'])) {
+                    return false;
+                }
+            } elseif ( ! $this->deleteDir($object['path'])) {
+                return false;
+            }
+        }
+
+        return ftp_rmdir($connection, $dirname);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function createDir($dirname, Config $config)
+    {
+        $connection = $this->getConnection();
+        $directories = explode('/', $dirname);
+
+        foreach ($directories as $directory) {
+            if (false === $this->createActualDirectory($directory, $connection)) {
+                $this->setConnectionRoot();
+
+                return false;
+            }
+
+            ftp_chdir($connection, $directory);
+        }
+
+        $this->setConnectionRoot();
+
+        return ['type' => 'dir', 'path' => $dirname];
+    }
+
+    /**
+     * Create a directory.
+     *
+     * @param string   $directory
+     * @param resource $connection
+     *
+     * @return bool
+     */
+    protected function createActualDirectory($directory, $connection)
+    {
+        // List the current directory
+        $listing = ftp_nlist($connection, '.') ?: [];
+
+        foreach ($listing as $key => $item) {
+            if (preg_match('~^\./.*~', $item)) {
+                $listing[$key] = substr($item, 2);
+            }
+        }
+
+        if (in_array($directory, $listing, true)) {
+            return true;
+        }
+
+        return (boolean) ftp_mkdir($connection, $directory);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMetadata($path)
+    {
+        if ($path === '') {
+            return ['type' => 'dir', 'path' => ''];
+        }
+
+        if (@ftp_chdir($this->getConnection(), $path) === true) {
+            $this->setConnectionRoot();
+
+            return ['type' => 'dir', 'path' => $path];
+        }
+
+        $listing = $this->ftpRawlist('-A', $path);
+
+        if (empty($listing) || in_array('total 0', $listing, true)) {
+            return false;
+        }
+
+        if (preg_match('/.* not found/', $listing[0])) {
+            return false;
+        }
+
+        if (preg_match('/^total [0-9]*$/', $listing[0])) {
+            array_shift($listing);
+        }
+
+        return $this->normalizeObject($listing[0], '');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMimetype($path)
+    {
+        if ( ! $metadata = $this->getMetadata($path)) {
+            return false;
+        }
+
+        $metadata['mimetype'] = MimeType::detectByFilename($path);
+
+        return $metadata;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getTimestamp($path)
+    {
+        $timestamp = ftp_mdtm($this->getConnection(), $path);
+
+        return ($timestamp !== -1) ? ['path' => $path, 'timestamp' => $timestamp] : false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function read($path)
+    {
+        if ( ! $object = $this->readStream($path)) {
+            return false;
+        }
+
+        $object['contents'] = stream_get_contents($object['stream']);
+        fclose($object['stream']);
+        unset($object['stream']);
+
+        return $object;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function readStream($path)
+    {
+        $stream = fopen('php://temp', 'w+b');
+        $result = ftp_fget($this->getConnection(), $stream, $path, $this->transferMode);
+        rewind($stream);
+
+        if ( ! $result) {
+            fclose($stream);
+
+            return false;
+        }
+
+        return ['type' => 'file', 'path' => $path, 'stream' => $stream];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function setVisibility($path, $visibility)
+    {
+        $mode = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? $this->getPermPublic() : $this->getPermPrivate();
+
+        if ( ! ftp_chmod($this->getConnection(), $mode, $path)) {
+            return false;
+        }
+
+        return compact('path', 'visibility');
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @param string $directory
+     */
+    protected function listDirectoryContents($directory, $recursive = true)
+    {
+        if ($recursive && $this->recurseManually) {
+            return $this->listDirectoryContentsRecursive($directory);
+        }
+
+        $options = $recursive ? '-alnR' : '-aln';
+        $listing = $this->ftpRawlist($options, $directory);
+
+        return $listing ? $this->normalizeListing($listing, $directory) : [];
+    }
+
+    /**
+     * @inheritdoc
+     *
+     * @param string $directory
+     */
+    protected function listDirectoryContentsRecursive($directory)
+    {
+        $listing = $this->normalizeListing($this->ftpRawlist('-aln', $directory) ?: [], $directory);
+        $output = [];
+
+        foreach ($listing as $item) {
+            $output[] = $item;
+            if ($item['type'] !== 'dir') {
+                continue;
+            }
+            $output = array_merge($output, $this->listDirectoryContentsRecursive($item['path']));
+        }
+
+        return $output;
+    }
+
+    /**
+     * Check if the connection is open.
+     *
+     * @return bool
+     *
+     * @throws ConnectionErrorException
+     */
+    public function isConnected()
+    {
+        return $this->hasFtpConnection() && $this->getRawExecResponseCode('NOOP') === 200;
+    }
+
+    /**
+     * @return bool
+     */
+    protected function isPureFtpdServer()
+    {
+        $response = ftp_raw($this->connection, 'HELP');
+
+        return stripos(implode(' ', $response), 'Pure-FTPd') !== false;
+    }
+
+    /**
+     * The ftp_rawlist function with optional escaping.
+     *
+     * @param string $options
+     * @param string $path
+     *
+     * @return array
+     */
+    protected function ftpRawlist($options, $path)
+    {
+        $connection = $this->getConnection();
+
+        if ($this->isPureFtpd) {
+            $path = str_replace([' ', '[', ']'], ['\ ', '\\[', '\\]'], $path);
+        }
+
+        return ftp_rawlist($connection, $options . ' ' . $this->escapePath($path));
+    }
+
+    private function getRawExecResponseCode($command)
+    {
+        $response = @ftp_raw($this->connection, trim($command));
+
+        return (int) preg_replace('/\D/', '', implode(' ', $response));
+    }
+
+    private function hasFtpConnection(): bool
+    {
+        return is_resource($this->connection) || $this->connection instanceof \FTP\Connection;
+    }
+}

+ 48 - 0
vendor/league/flysystem/src/Adapter/Ftpd.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+class Ftpd extends Ftp
+{
+    /**
+     * @inheritdoc
+     */
+    public function getMetadata($path)
+    {
+        if ($path === '') {
+            return ['type' => 'dir', 'path' => ''];
+        }
+
+        if (@ftp_chdir($this->getConnection(), $path) === true) {
+            $this->setConnectionRoot();
+
+            return ['type' => 'dir', 'path' => $path];
+        }
+
+        $object = ftp_raw($this->getConnection(), 'STAT ' . $this->escapePath($path));
+
+        if ( ! $object || count($object) < 3) {
+            return false;
+        }
+
+        if (substr($object[1], 0, 5) === "ftpd:") {
+            return false;
+        }
+
+        return $this->normalizeObject($object[1], '');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function listDirectoryContents($directory, $recursive = true)
+    {
+        $listing = ftp_rawlist($this->getConnection(), $this->escapePath($directory), $recursive);
+
+        if ($listing === false || ( ! empty($listing) && substr($listing[0], 0, 5) === "ftpd:")) {
+            return [];
+        }
+
+        return $this->normalizeListing($listing, $directory);
+    }
+}

+ 533 - 0
vendor/league/flysystem/src/Adapter/Local.php

@@ -0,0 +1,533 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+use DirectoryIterator;
+use FilesystemIterator;
+use finfo as Finfo;
+use League\Flysystem\Config;
+use League\Flysystem\Exception;
+use League\Flysystem\NotSupportedException;
+use League\Flysystem\UnreadableFileException;
+use League\Flysystem\Util;
+use LogicException;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+use SplFileInfo;
+
+class Local extends AbstractAdapter
+{
+    /**
+     * @var int
+     */
+    const SKIP_LINKS = 0001;
+
+    /**
+     * @var int
+     */
+    const DISALLOW_LINKS = 0002;
+
+    /**
+     * @var array
+     */
+    protected static $permissions = [
+        'file' => [
+            'public' => 0644,
+            'private' => 0600,
+        ],
+        'dir' => [
+            'public' => 0755,
+            'private' => 0700,
+        ],
+    ];
+
+    /**
+     * @var string
+     */
+    protected $pathSeparator = DIRECTORY_SEPARATOR;
+
+    /**
+     * @var array
+     */
+    protected $permissionMap;
+
+    /**
+     * @var int
+     */
+    protected $writeFlags;
+
+    /**
+     * @var int
+     */
+    private $linkHandling;
+
+    /**
+     * Constructor.
+     *
+     * @param string $root
+     * @param int    $writeFlags
+     * @param int    $linkHandling
+     * @param array  $permissions
+     *
+     * @throws LogicException
+     */
+    public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])
+    {
+        $root = is_link($root) ? realpath($root) : $root;
+        $this->permissionMap = array_replace_recursive(static::$permissions, $permissions);
+        $this->ensureDirectory($root);
+
+        if ( ! is_dir($root) || ! is_readable($root)) {
+            throw new LogicException('The root path ' . $root . ' is not readable.');
+        }
+
+        $this->setPathPrefix($root);
+        $this->writeFlags = $writeFlags;
+        $this->linkHandling = $linkHandling;
+    }
+
+    /**
+     * Ensure the root directory exists.
+     *
+     * @param string $root root directory path
+     *
+     * @return void
+     *
+     * @throws Exception in case the root directory can not be created
+     */
+    protected function ensureDirectory($root)
+    {
+        if ( ! is_dir($root)) {
+            $umask = umask(0);
+
+            if ( ! @mkdir($root, $this->permissionMap['dir']['public'], true)) {
+                $mkdirError = error_get_last();
+            }
+
+            umask($umask);
+            clearstatcache(false, $root);
+
+            if ( ! is_dir($root)) {
+                $errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : '';
+                throw new Exception(sprintf('Impossible to create the root directory "%s". %s', $root, $errorMessage));
+            }
+        }
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function has($path)
+    {
+        $location = $this->applyPathPrefix($path);
+
+        return file_exists($location);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function write($path, $contents, Config $config)
+    {
+        $location = $this->applyPathPrefix($path);
+        $this->ensureDirectory(dirname($location));
+
+        if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {
+            return false;
+        }
+
+        $type = 'file';
+        $result = compact('contents', 'type', 'size', 'path');
+
+        if ($visibility = $config->get('visibility')) {
+            $result['visibility'] = $visibility;
+            $this->setVisibility($path, $visibility);
+        }
+
+        return $result;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function writeStream($path, $resource, Config $config)
+    {
+        $location = $this->applyPathPrefix($path);
+        $this->ensureDirectory(dirname($location));
+        $stream = fopen($location, 'w+b');
+
+        if ( ! $stream || stream_copy_to_stream($resource, $stream) === false || ! fclose($stream)) {
+            return false;
+        }
+
+        $type = 'file';
+        $result = compact('type', 'path');
+
+        if ($visibility = $config->get('visibility')) {
+            $this->setVisibility($path, $visibility);
+            $result['visibility'] = $visibility;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function readStream($path)
+    {
+        $location = $this->applyPathPrefix($path);
+        $stream = fopen($location, 'rb');
+
+        return ['type' => 'file', 'path' => $path, 'stream' => $stream];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function updateStream($path, $resource, Config $config)
+    {
+        return $this->writeStream($path, $resource, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function update($path, $contents, Config $config)
+    {
+        $location = $this->applyPathPrefix($path);
+        $size = file_put_contents($location, $contents, $this->writeFlags);
+
+        if ($size === false) {
+            return false;
+        }
+
+        $type = 'file';
+
+        $result = compact('type', 'path', 'size', 'contents');
+
+        if ($visibility = $config->get('visibility')) {
+            $this->setVisibility($path, $visibility);
+            $result['visibility'] = $visibility;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function read($path)
+    {
+        $location = $this->applyPathPrefix($path);
+        $contents = @file_get_contents($location);
+
+        if ($contents === false) {
+            return false;
+        }
+
+        return ['type' => 'file', 'path' => $path, 'contents' => $contents];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rename($path, $newpath)
+    {
+        $location = $this->applyPathPrefix($path);
+        $destination = $this->applyPathPrefix($newpath);
+        $parentDirectory = $this->applyPathPrefix(Util::dirname($newpath));
+        $this->ensureDirectory($parentDirectory);
+
+        return rename($location, $destination);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function copy($path, $newpath)
+    {
+        $location = $this->applyPathPrefix($path);
+        $destination = $this->applyPathPrefix($newpath);
+        $this->ensureDirectory(dirname($destination));
+
+        return copy($location, $destination);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function delete($path)
+    {
+        $location = $this->applyPathPrefix($path);
+
+        return @unlink($location);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        $result = [];
+        $location = $this->applyPathPrefix($directory);
+
+        if ( ! is_dir($location)) {
+            return [];
+        }
+
+        $iterator = $recursive ? $this->getRecursiveDirectoryIterator($location) : $this->getDirectoryIterator($location);
+
+        foreach ($iterator as $file) {
+            $path = $this->getFilePath($file);
+
+            if (preg_match('#(^|/|\\\\)\.{1,2}$#', $path)) {
+                continue;
+            }
+
+            $result[] = $this->normalizeFileInfo($file);
+        }
+
+        unset($iterator);
+
+        return array_filter($result);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMetadata($path)
+    {
+        $location = $this->applyPathPrefix($path);
+        clearstatcache(false, $location);
+        $info = new SplFileInfo($location);
+
+        return $this->normalizeFileInfo($info);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSize($path)
+    {
+        return $this->getMetadata($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMimetype($path)
+    {
+        $location = $this->applyPathPrefix($path);
+        $finfo = new Finfo(FILEINFO_MIME_TYPE);
+        $mimetype = $finfo->file($location);
+
+        if (in_array($mimetype, ['application/octet-stream', 'inode/x-empty', 'application/x-empty'])) {
+            $mimetype = Util\MimeType::detectByFilename($location);
+        }
+
+        return ['path' => $path, 'type' => 'file', 'mimetype' => $mimetype];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getTimestamp($path)
+    {
+        return $this->getMetadata($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getVisibility($path)
+    {
+        $location = $this->applyPathPrefix($path);
+        clearstatcache(false, $location);
+        $permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));
+        $type = is_dir($location) ? 'dir' : 'file';
+
+        foreach ($this->permissionMap[$type] as $visibility => $visibilityPermissions) {
+            if ($visibilityPermissions == $permissions) {
+                return compact('path', 'visibility');
+            }
+        }
+
+        $visibility = substr(sprintf('%o', fileperms($location)), -4);
+
+        return compact('path', 'visibility');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function setVisibility($path, $visibility)
+    {
+        $location = $this->applyPathPrefix($path);
+        $type = is_dir($location) ? 'dir' : 'file';
+        $success = chmod($location, $this->permissionMap[$type][$visibility]);
+
+        if ($success === false) {
+            return false;
+        }
+
+        return compact('path', 'visibility');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function createDir($dirname, Config $config)
+    {
+        $location = $this->applyPathPrefix($dirname);
+        $umask = umask(0);
+        $visibility = $config->get('visibility', 'public');
+        $return = ['path' => $dirname, 'type' => 'dir'];
+
+        if ( ! is_dir($location)) {
+            if (false === @mkdir($location, $this->permissionMap['dir'][$visibility], true)
+                || false === is_dir($location)) {
+                $return = false;
+            }
+        }
+
+        umask($umask);
+
+        return $return;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function deleteDir($dirname)
+    {
+        $location = $this->applyPathPrefix($dirname);
+
+        if ( ! is_dir($location)) {
+            return false;
+        }
+
+        $contents = $this->getRecursiveDirectoryIterator($location, RecursiveIteratorIterator::CHILD_FIRST);
+
+        /** @var SplFileInfo $file */
+        foreach ($contents as $file) {
+            $this->guardAgainstUnreadableFileInfo($file);
+            $this->deleteFileInfoObject($file);
+        }
+
+        unset($contents);
+
+        return rmdir($location);
+    }
+
+    /**
+     * @param SplFileInfo $file
+     */
+    protected function deleteFileInfoObject(SplFileInfo $file)
+    {
+        switch ($file->getType()) {
+            case 'dir':
+                rmdir($file->getRealPath());
+                break;
+            case 'link':
+                unlink($file->getPathname());
+                break;
+            default:
+                unlink($file->getRealPath());
+        }
+    }
+
+    /**
+     * Normalize the file info.
+     *
+     * @param SplFileInfo $file
+     *
+     * @return array|void
+     *
+     * @throws NotSupportedException
+     */
+    protected function normalizeFileInfo(SplFileInfo $file)
+    {
+        if ( ! $file->isLink()) {
+            return $this->mapFileInfo($file);
+        }
+
+        if ($this->linkHandling & self::DISALLOW_LINKS) {
+            throw NotSupportedException::forLink($file);
+        }
+    }
+
+    /**
+     * Get the normalized path from a SplFileInfo object.
+     *
+     * @param SplFileInfo $file
+     *
+     * @return string
+     */
+    protected function getFilePath(SplFileInfo $file)
+    {
+        $location = $file->getPathname();
+        $path = $this->removePathPrefix($location);
+
+        return trim(str_replace('\\', '/', $path), '/');
+    }
+
+    /**
+     * @param string $path
+     * @param int    $mode
+     *
+     * @return RecursiveIteratorIterator
+     */
+    protected function getRecursiveDirectoryIterator($path, $mode = RecursiveIteratorIterator::SELF_FIRST)
+    {
+        return new RecursiveIteratorIterator(
+            new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
+            $mode
+        );
+    }
+
+    /**
+     * @param string $path
+     *
+     * @return DirectoryIterator
+     */
+    protected function getDirectoryIterator($path)
+    {
+        $iterator = new DirectoryIterator($path);
+
+        return $iterator;
+    }
+
+    /**
+     * @param SplFileInfo $file
+     *
+     * @return array
+     */
+    protected function mapFileInfo(SplFileInfo $file)
+    {
+        $normalized = [
+            'type' => $file->getType(),
+            'path' => $this->getFilePath($file),
+        ];
+
+        $normalized['timestamp'] = $file->getMTime();
+
+        if ($normalized['type'] === 'file') {
+            $normalized['size'] = $file->getSize();
+        }
+
+        return $normalized;
+    }
+
+    /**
+     * @param SplFileInfo $file
+     *
+     * @throws UnreadableFileException
+     */
+    protected function guardAgainstUnreadableFileInfo(SplFileInfo $file)
+    {
+        if ( ! $file->isReadable()) {
+            throw UnreadableFileException::forFileInfo($file);
+        }
+    }
+}

+ 144 - 0
vendor/league/flysystem/src/Adapter/NullAdapter.php

@@ -0,0 +1,144 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+use League\Flysystem\Adapter\Polyfill\StreamedCopyTrait;
+use League\Flysystem\Adapter\Polyfill\StreamedTrait;
+use League\Flysystem\Config;
+
+class NullAdapter extends AbstractAdapter
+{
+    use StreamedTrait;
+    use StreamedCopyTrait;
+
+    /**
+     * Check whether a file is present.
+     *
+     * @param string $path
+     *
+     * @return bool
+     */
+    public function has($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function write($path, $contents, Config $config)
+    {
+        $type = 'file';
+        $result = compact('contents', 'type', 'path');
+
+        if ($visibility = $config->get('visibility')) {
+            $result['visibility'] = $visibility;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function update($path, $contents, Config $config)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function read($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rename($path, $newpath)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function delete($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        return [];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMetadata($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSize($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMimetype($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getTimestamp($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getVisibility($path)
+    {
+        return false;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function setVisibility($path, $visibility)
+    {
+        return compact('visibility');
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function createDir($dirname, Config $config)
+    {
+        return ['path' => $dirname, 'type' => 'dir'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function deleteDir($dirname)
+    {
+        return false;
+    }
+}

+ 33 - 0
vendor/league/flysystem/src/Adapter/Polyfill/NotSupportingVisibilityTrait.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace League\Flysystem\Adapter\Polyfill;
+
+use LogicException;
+
+trait NotSupportingVisibilityTrait
+{
+    /**
+     * Get the visibility of a file.
+     *
+     * @param string $path
+     *
+     * @throws LogicException
+     */
+    public function getVisibility($path)
+    {
+        throw new LogicException(get_class($this) . ' does not support visibility. Path: ' . $path);
+    }
+
+    /**
+     * Set the visibility for a file.
+     *
+     * @param string $path
+     * @param string $visibility
+     *
+     * @throws LogicException
+     */
+    public function setVisibility($path, $visibility)
+    {
+        throw new LogicException(get_class($this) . ' does not support visibility. Path: ' . $path . ', visibility: ' . $visibility);
+    }
+}

+ 51 - 0
vendor/league/flysystem/src/Adapter/Polyfill/StreamedCopyTrait.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace League\Flysystem\Adapter\Polyfill;
+
+use League\Flysystem\Config;
+
+trait StreamedCopyTrait
+{
+    /**
+     * Copy a file.
+     *
+     * @param string $path
+     * @param string $newpath
+     *
+     * @return bool
+     */
+    public function copy($path, $newpath)
+    {
+        $response = $this->readStream($path);
+
+        if ($response === false || ! is_resource($response['stream'])) {
+            return false;
+        }
+
+        $result = $this->writeStream($newpath, $response['stream'], new Config());
+
+        if ($result !== false && is_resource($response['stream'])) {
+            fclose($response['stream']);
+        }
+
+        return $result !== false;
+    }
+
+    // Required abstract method
+
+    /**
+     * @param string $path
+     *
+     * @return resource
+     */
+    abstract public function readStream($path);
+
+    /**
+     * @param string   $path
+     * @param resource $resource
+     * @param Config   $config
+     *
+     * @return resource
+     */
+    abstract public function writeStream($path, $resource, Config $config);
+}

+ 44 - 0
vendor/league/flysystem/src/Adapter/Polyfill/StreamedReadingTrait.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace League\Flysystem\Adapter\Polyfill;
+
+/**
+ * A helper for adapters that only handle strings to provide read streams.
+ */
+trait StreamedReadingTrait
+{
+    /**
+     * Reads a file as a stream.
+     *
+     * @param string $path
+     *
+     * @return array|false
+     *
+     * @see League\Flysystem\ReadInterface::readStream()
+     */
+    public function readStream($path)
+    {
+        if ( ! $data = $this->read($path)) {
+            return false;
+        }
+
+        $stream = fopen('php://temp', 'w+b');
+        fwrite($stream, $data['contents']);
+        rewind($stream);
+        $data['stream'] = $stream;
+        unset($data['contents']);
+
+        return $data;
+    }
+
+    /**
+     * Reads a file.
+     *
+     * @param string $path
+     *
+     * @return array|false
+     *
+     * @see League\Flysystem\ReadInterface::read()
+     */
+    abstract public function read($path);
+}

+ 9 - 0
vendor/league/flysystem/src/Adapter/Polyfill/StreamedTrait.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace League\Flysystem\Adapter\Polyfill;
+
+trait StreamedTrait
+{
+    use StreamedReadingTrait;
+    use StreamedWritingTrait;
+}

+ 60 - 0
vendor/league/flysystem/src/Adapter/Polyfill/StreamedWritingTrait.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace League\Flysystem\Adapter\Polyfill;
+
+use League\Flysystem\Config;
+use League\Flysystem\Util;
+
+trait StreamedWritingTrait
+{
+    /**
+     * Stream fallback delegator.
+     *
+     * @param string   $path
+     * @param resource $resource
+     * @param Config   $config
+     * @param string   $fallback
+     *
+     * @return mixed fallback result
+     */
+    protected function stream($path, $resource, Config $config, $fallback)
+    {
+        Util::rewindStream($resource);
+        $contents = stream_get_contents($resource);
+        $fallbackCall = [$this, $fallback];
+
+        return call_user_func($fallbackCall, $path, $contents, $config);
+    }
+
+    /**
+     * Write using a stream.
+     *
+     * @param string   $path
+     * @param resource $resource
+     * @param Config   $config
+     *
+     * @return mixed false or file metadata
+     */
+    public function writeStream($path, $resource, Config $config)
+    {
+        return $this->stream($path, $resource, $config, 'write');
+    }
+
+    /**
+     * Update a file using a stream.
+     *
+     * @param string   $path
+     * @param resource $resource
+     * @param Config   $config   Config object or visibility setting
+     *
+     * @return mixed false of file metadata
+     */
+    public function updateStream($path, $resource, Config $config)
+    {
+        return $this->stream($path, $resource, $config, 'update');
+    }
+
+    // Required abstract methods
+    abstract public function write($pash, $contents, Config $config);
+    abstract public function update($pash, $contents, Config $config);
+}

+ 8 - 0
vendor/league/flysystem/src/Adapter/SynologyFtp.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace League\Flysystem\Adapter;
+
+class SynologyFtp extends Ftpd
+{
+    // This class merely exists because of BC.
+}

+ 118 - 0
vendor/league/flysystem/src/AdapterInterface.php

@@ -0,0 +1,118 @@
+<?php
+
+namespace League\Flysystem;
+
+interface AdapterInterface extends ReadInterface
+{
+    /**
+     * @const  VISIBILITY_PUBLIC  public visibility
+     */
+    const VISIBILITY_PUBLIC = 'public';
+
+    /**
+     * @const  VISIBILITY_PRIVATE  private visibility
+     */
+    const VISIBILITY_PRIVATE = 'private';
+
+    /**
+     * 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
+     */
+    public function write($path, $contents, Config $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);
+
+    /**
+     * 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
+     */
+    public function update($path, $contents, Config $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);
+
+    /**
+     * Rename a file.
+     *
+     * @param string $path
+     * @param string $newpath
+     *
+     * @return bool
+     */
+    public function rename($path, $newpath);
+
+    /**
+     * Copy a file.
+     *
+     * @param string $path
+     * @param string $newpath
+     *
+     * @return bool
+     */
+    public function copy($path, $newpath);
+
+    /**
+     * Delete a file.
+     *
+     * @param string $path
+     *
+     * @return bool
+     */
+    public function delete($path);
+
+    /**
+     * Delete a directory.
+     *
+     * @param string $dirname
+     *
+     * @return bool
+     */
+    public function deleteDir($dirname);
+
+    /**
+     * Create a directory.
+     *
+     * @param string $dirname directory name
+     * @param Config $config
+     *
+     * @return array|false
+     */
+    public function createDir($dirname, Config $config);
+
+    /**
+     * Set the visibility for a file.
+     *
+     * @param string $path
+     * @param string $visibility
+     *
+     * @return array|false file meta data
+     */
+    public function setVisibility($path, $visibility);
+}

+ 107 - 0
vendor/league/flysystem/src/Config.php

@@ -0,0 +1,107 @@
+<?php
+
+namespace League\Flysystem;
+
+class Config
+{
+    /**
+     * @var array
+     */
+    protected $settings = [];
+
+    /**
+     * @var Config|null
+     */
+    protected $fallback;
+
+    /**
+     * Constructor.
+     *
+     * @param array $settings
+     */
+    public function __construct(array $settings = [])
+    {
+        $this->settings = $settings;
+    }
+
+    /**
+     * Get a setting.
+     *
+     * @param string $key
+     * @param mixed  $default
+     *
+     * @return mixed config setting or default when not found
+     */
+    public function get($key, $default = null)
+    {
+        if ( ! array_key_exists($key, $this->settings)) {
+            return $this->getDefault($key, $default);
+        }
+
+        return $this->settings[$key];
+    }
+
+    /**
+     * Check if an item exists by key.
+     *
+     * @param string $key
+     *
+     * @return bool
+     */
+    public function has($key)
+    {
+        if (array_key_exists($key, $this->settings)) {
+            return true;
+        }
+
+        return $this->fallback instanceof Config
+            ? $this->fallback->has($key)
+            : false;
+    }
+
+    /**
+     * Try to retrieve a default setting from a config fallback.
+     *
+     * @param string $key
+     * @param mixed  $default
+     *
+     * @return mixed config setting or default when not found
+     */
+    protected function getDefault($key, $default)
+    {
+        if ( ! $this->fallback) {
+            return $default;
+        }
+
+        return $this->fallback->get($key, $default);
+    }
+
+    /**
+     * Set a setting.
+     *
+     * @param string $key
+     * @param mixed  $value
+     *
+     * @return $this
+     */
+    public function set($key, $value)
+    {
+        $this->settings[$key] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Set the fallback.
+     *
+     * @param Config $fallback
+     *
+     * @return $this
+     */
+    public function setFallback(Config $fallback)
+    {
+        $this->fallback = $fallback;
+
+        return $this;
+    }
+}

+ 49 - 0
vendor/league/flysystem/src/ConfigAwareTrait.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace League\Flysystem;
+
+/**
+ * @internal
+ */
+trait ConfigAwareTrait
+{
+    /**
+     * @var Config
+     */
+    protected $config;
+
+    /**
+     * Set the config.
+     *
+     * @param Config|array|null $config
+     */
+    protected function setConfig($config)
+    {
+        $this->config = $config ? Util::ensureConfig($config) : new Config;
+    }
+
+    /**
+     * Get the Config.
+     *
+     * @return Config config object
+     */
+    public function getConfig()
+    {
+        return $this->config;
+    }
+
+    /**
+     * Convert a config array to a Config object with the correct fallback.
+     *
+     * @param array $config
+     *
+     * @return Config
+     */
+    protected function prepareConfig(array $config)
+    {
+        $config = new Config($config);
+        $config->setFallback($this->getConfig());
+
+        return $config;
+    }
+}

+ 9 - 0
vendor/league/flysystem/src/ConnectionErrorException.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace League\Flysystem;
+
+use ErrorException;
+
+class ConnectionErrorException extends ErrorException implements FilesystemException
+{
+}

+ 9 - 0
vendor/league/flysystem/src/ConnectionRuntimeException.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+class ConnectionRuntimeException extends RuntimeException implements FilesystemException
+{
+}

+ 17 - 0
vendor/league/flysystem/src/CorruptedPathDetected.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace League\Flysystem;
+
+use LogicException;
+
+class CorruptedPathDetected extends LogicException implements FilesystemException
+{
+    /**
+     * @param string $path
+     * @return CorruptedPathDetected
+     */
+    public static function forPath($path)
+    {
+        return new CorruptedPathDetected("Corrupted path detected: " . $path);
+    }
+}

+ 31 - 0
vendor/league/flysystem/src/Directory.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace League\Flysystem;
+
+/**
+ * @deprecated
+ */
+class Directory extends Handler
+{
+    /**
+     * Delete the directory.
+     *
+     * @return bool
+     */
+    public function delete()
+    {
+        return $this->filesystem->deleteDir($this->path);
+    }
+
+    /**
+     * List the directory contents.
+     *
+     * @param bool $recursive
+     *
+     * @return array|bool directory contents or false
+     */
+    public function getContents($recursive = false)
+    {
+        return $this->filesystem->listContents($this->path, $recursive);
+    }
+}

+ 8 - 0
vendor/league/flysystem/src/Exception.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace League\Flysystem;
+
+class Exception extends \Exception implements FilesystemException
+{
+    //
+}

+ 205 - 0
vendor/league/flysystem/src/File.php

@@ -0,0 +1,205 @@
+<?php
+
+namespace League\Flysystem;
+
+/**
+ * @deprecated
+ */
+class File extends Handler
+{
+    /**
+     * Check whether the file exists.
+     *
+     * @return bool
+     */
+    public function exists()
+    {
+        return $this->filesystem->has($this->path);
+    }
+
+    /**
+     * Read the file.
+     *
+     * @return string|false file contents
+     */
+    public function read()
+    {
+        return $this->filesystem->read($this->path);
+    }
+
+    /**
+     * Read the file as a stream.
+     *
+     * @return resource|false file stream
+     */
+    public function readStream()
+    {
+        return $this->filesystem->readStream($this->path);
+    }
+
+    /**
+     * Write the new file.
+     *
+     * @param string $content
+     *
+     * @return bool success boolean
+     */
+    public function write($content)
+    {
+        return $this->filesystem->write($this->path, $content);
+    }
+
+    /**
+     * Write the new file using a stream.
+     *
+     * @param resource $resource
+     *
+     * @return bool success boolean
+     */
+    public function writeStream($resource)
+    {
+        return $this->filesystem->writeStream($this->path, $resource);
+    }
+
+    /**
+     * Update the file contents.
+     *
+     * @param string $content
+     *
+     * @return bool success boolean
+     */
+    public function update($content)
+    {
+        return $this->filesystem->update($this->path, $content);
+    }
+
+    /**
+     * Update the file contents with a stream.
+     *
+     * @param resource $resource
+     *
+     * @return bool success boolean
+     */
+    public function updateStream($resource)
+    {
+        return $this->filesystem->updateStream($this->path, $resource);
+    }
+
+    /**
+     * Create the file or update if exists.
+     *
+     * @param string $content
+     *
+     * @return bool success boolean
+     */
+    public function put($content)
+    {
+        return $this->filesystem->put($this->path, $content);
+    }
+
+    /**
+     * Create the file or update if exists using a stream.
+     *
+     * @param resource $resource
+     *
+     * @return bool success boolean
+     */
+    public function putStream($resource)
+    {
+        return $this->filesystem->putStream($this->path, $resource);
+    }
+
+    /**
+     * Rename the file.
+     *
+     * @param string $newpath
+     *
+     * @return bool success boolean
+     */
+    public function rename($newpath)
+    {
+        if ($this->filesystem->rename($this->path, $newpath)) {
+            $this->path = $newpath;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Copy the file.
+     *
+     * @param string $newpath
+     *
+     * @return File|false new file or false
+     */
+    public function copy($newpath)
+    {
+        if ($this->filesystem->copy($this->path, $newpath)) {
+            return new File($this->filesystem, $newpath);
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the file's timestamp.
+     *
+     * @return string|false The timestamp or false on failure.
+     */
+    public function getTimestamp()
+    {
+        return $this->filesystem->getTimestamp($this->path);
+    }
+
+    /**
+     * Get the file's mimetype.
+     *
+     * @return string|false The file mime-type or false on failure.
+     */
+    public function getMimetype()
+    {
+        return $this->filesystem->getMimetype($this->path);
+    }
+
+    /**
+     * Get the file's visibility.
+     *
+     * @return string|false The visibility (public|private) or false on failure.
+     */
+    public function getVisibility()
+    {
+        return $this->filesystem->getVisibility($this->path);
+    }
+
+    /**
+     * Get the file's metadata.
+     *
+     * @return array|false The file metadata or false on failure.
+     */
+    public function getMetadata()
+    {
+        return $this->filesystem->getMetadata($this->path);
+    }
+
+    /**
+     * Get the file size.
+     *
+     * @return int|false The file size or false on failure.
+     */
+    public function getSize()
+    {
+        return $this->filesystem->getSize($this->path);
+    }
+
+    /**
+     * Delete the file.
+     *
+     * @return bool success boolean
+     */
+    public function delete()
+    {
+        return $this->filesystem->delete($this->path);
+    }
+}

+ 37 - 0
vendor/league/flysystem/src/FileExistsException.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace League\Flysystem;
+
+use Exception as BaseException;
+
+class FileExistsException extends Exception
+{
+    /**
+     * @var string
+     */
+    protected $path;
+
+    /**
+     * Constructor.
+     *
+     * @param string        $path
+     * @param int           $code
+     * @param BaseException $previous
+     */
+    public function __construct($path, $code = 0, BaseException $previous = null)
+    {
+        $this->path = $path;
+
+        parent::__construct('File already exists at path: ' . $this->getPath(), $code, $previous);
+    }
+
+    /**
+     * Get the path which was found.
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+}

+ 37 - 0
vendor/league/flysystem/src/FileNotFoundException.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace League\Flysystem;
+
+use Exception as BaseException;
+
+class FileNotFoundException extends Exception
+{
+    /**
+     * @var string
+     */
+    protected $path;
+
+    /**
+     * Constructor.
+     *
+     * @param string     $path
+     * @param int        $code
+     * @param \Exception $previous
+     */
+    public function __construct($path, $code = 0, BaseException $previous = null)
+    {
+        $this->path = $path;
+
+        parent::__construct('File not found at path: ' . $this->getPath(), $code, $previous);
+    }
+
+    /**
+     * Get the path which was not found.
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+}

+ 409 - 0
vendor/league/flysystem/src/Filesystem.php

@@ -0,0 +1,409 @@
+<?php
+
+namespace League\Flysystem;
+
+use InvalidArgumentException;
+use League\Flysystem\Adapter\CanOverwriteFiles;
+use League\Flysystem\Plugin\PluggableTrait;
+use League\Flysystem\Util\ContentListingFormatter;
+
+/**
+ * @method void        emptyDir(string $dirname)
+ * @method array|false getWithMetadata(string $path, string[] $metadata)
+ * @method bool        forceCopy(string $path, string $newpath)
+ * @method bool        forceRename(string $path, string $newpath)
+ * @method array       listFiles(string $path = '', boolean $recursive = false)
+ * @method string[]    listPaths(string $path = '', boolean $recursive = false)
+ * @method array       listWith(string[] $keys = [], $directory = '', $recursive = false)
+ */
+class Filesystem implements FilesystemInterface
+{
+    use PluggableTrait;
+    use ConfigAwareTrait;
+
+    /**
+     * @var AdapterInterface
+     */
+    protected $adapter;
+
+    /**
+     * Constructor.
+     *
+     * @param AdapterInterface $adapter
+     * @param Config|array     $config
+     */
+    public function __construct(AdapterInterface $adapter, $config = null)
+    {
+        $this->adapter = $adapter;
+        $this->setConfig($config);
+    }
+
+    /**
+     * Get the Adapter.
+     *
+     * @return AdapterInterface adapter
+     */
+    public function getAdapter()
+    {
+        return $this->adapter;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function has($path)
+    {
+        $path = Util::normalizePath($path);
+
+        return strlen($path) === 0 ? false : (bool) $this->getAdapter()->has($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function write($path, $contents, array $config = [])
+    {
+        $path = Util::normalizePath($path);
+        $this->assertAbsent($path);
+        $config = $this->prepareConfig($config);
+
+        return (bool) $this->getAdapter()->write($path, $contents, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function writeStream($path, $resource, array $config = [])
+    {
+        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {
+            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
+        }
+
+        $path = Util::normalizePath($path);
+        $this->assertAbsent($path);
+        $config = $this->prepareConfig($config);
+
+        Util::rewindStream($resource);
+
+        return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function put($path, $contents, array $config = [])
+    {
+        $path = Util::normalizePath($path);
+        $config = $this->prepareConfig($config);
+
+        if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {
+            return (bool) $this->getAdapter()->update($path, $contents, $config);
+        }
+
+        return (bool) $this->getAdapter()->write($path, $contents, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function putStream($path, $resource, array $config = [])
+    {
+        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {
+            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
+        }
+
+        $path = Util::normalizePath($path);
+        $config = $this->prepareConfig($config);
+        Util::rewindStream($resource);
+
+        if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {
+            return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
+        }
+
+        return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function readAndDelete($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+        $contents = $this->read($path);
+
+        if ($contents === false) {
+            return false;
+        }
+
+        $this->delete($path);
+
+        return $contents;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function update($path, $contents, array $config = [])
+    {
+        $path = Util::normalizePath($path);
+        $config = $this->prepareConfig($config);
+
+        $this->assertPresent($path);
+
+        return (bool) $this->getAdapter()->update($path, $contents, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function updateStream($path, $resource, array $config = [])
+    {
+        if ( ! is_resource($resource) || get_resource_type($resource) !== 'stream') {
+            throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
+        }
+
+        $path = Util::normalizePath($path);
+        $config = $this->prepareConfig($config);
+        $this->assertPresent($path);
+        Util::rewindStream($resource);
+
+        return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function read($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if ( ! ($object = $this->getAdapter()->read($path))) {
+            return false;
+        }
+
+        return $object['contents'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function readStream($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if ( ! $object = $this->getAdapter()->readStream($path)) {
+            return false;
+        }
+
+        return $object['stream'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rename($path, $newpath)
+    {
+        $path = Util::normalizePath($path);
+        $newpath = Util::normalizePath($newpath);
+        $this->assertPresent($path);
+        $this->assertAbsent($newpath);
+
+        return (bool) $this->getAdapter()->rename($path, $newpath);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function copy($path, $newpath)
+    {
+        $path = Util::normalizePath($path);
+        $newpath = Util::normalizePath($newpath);
+        $this->assertPresent($path);
+        $this->assertAbsent($newpath);
+
+        return $this->getAdapter()->copy($path, $newpath);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function delete($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        return $this->getAdapter()->delete($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function deleteDir($dirname)
+    {
+        $dirname = Util::normalizePath($dirname);
+
+        if ($dirname === '') {
+            throw new RootViolationException('Root directories can not be deleted.');
+        }
+
+        return (bool) $this->getAdapter()->deleteDir($dirname);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function createDir($dirname, array $config = [])
+    {
+        $dirname = Util::normalizePath($dirname);
+        $config = $this->prepareConfig($config);
+
+        return (bool) $this->getAdapter()->createDir($dirname, $config);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        $directory = Util::normalizePath($directory);
+        $contents = $this->getAdapter()->listContents($directory, $recursive);
+
+        return (new ContentListingFormatter($directory, $recursive, $this->config->get('case_sensitive', true)))
+            ->formatListing($contents);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMimetype($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if (( ! $object = $this->getAdapter()->getMimetype($path)) || ! array_key_exists('mimetype', $object)) {
+            return false;
+        }
+
+        return $object['mimetype'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getTimestamp($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if (( ! $object = $this->getAdapter()->getTimestamp($path)) || ! array_key_exists('timestamp', $object)) {
+            return false;
+        }
+
+        return (int) $object['timestamp'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getVisibility($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if (( ! $object = $this->getAdapter()->getVisibility($path)) || ! array_key_exists('visibility', $object)) {
+            return false;
+        }
+
+        return $object['visibility'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getSize($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        if (( ! $object = $this->getAdapter()->getSize($path)) || ! array_key_exists('size', $object)) {
+            return false;
+        }
+
+        return (int) $object['size'];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function setVisibility($path, $visibility)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        return (bool) $this->getAdapter()->setVisibility($path, $visibility);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function getMetadata($path)
+    {
+        $path = Util::normalizePath($path);
+        $this->assertPresent($path);
+
+        return $this->getAdapter()->getMetadata($path);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function get($path, Handler $handler = null)
+    {
+        $path = Util::normalizePath($path);
+
+        if ( ! $handler) {
+            $metadata = $this->getMetadata($path);
+            $handler = ($metadata && $metadata['type'] === 'file') ? new File($this, $path) : new Directory($this, $path);
+        }
+
+        $handler->setPath($path);
+        $handler->setFilesystem($this);
+
+        return $handler;
+    }
+
+    /**
+     * Assert a file is present.
+     *
+     * @param string $path path to file
+     *
+     * @throws FileNotFoundException
+     *
+     * @return void
+     */
+    public function assertPresent($path)
+    {
+        if ($this->config->get('disable_asserts', false) === false && ! $this->has($path)) {
+            throw new FileNotFoundException($path);
+        }
+    }
+
+    /**
+     * Assert a file is absent.
+     *
+     * @param string $path path to file
+     *
+     * @throws FileExistsException
+     *
+     * @return void
+     */
+    public function assertAbsent($path)
+    {
+        if ($this->config->get('disable_asserts', false) === false && $this->has($path)) {
+            throw new FileExistsException($path);
+        }
+    }
+}

+ 7 - 0
vendor/league/flysystem/src/FilesystemException.php

@@ -0,0 +1,7 @@
+<?php
+
+namespace League\Flysystem;
+
+interface FilesystemException
+{
+}

+ 284 - 0
vendor/league/flysystem/src/FilesystemInterface.php

@@ -0,0 +1,284 @@
+<?php
+
+namespace League\Flysystem;
+
+use InvalidArgumentException;
+
+interface FilesystemInterface
+{
+    /**
+     * Check whether a file exists.
+     *
+     * @param string $path
+     *
+     * @return bool
+     */
+    public function has($path);
+
+    /**
+     * Read a file.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file contents or false on failure.
+     */
+    public function read($path);
+
+    /**
+     * Retrieves a read-stream for a path.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return resource|false The path resource or false on failure.
+     */
+    public function readStream($path);
+
+    /**
+     * List contents of a directory.
+     *
+     * @param string $directory The directory to list.
+     * @param bool   $recursive Whether to list recursively.
+     *
+     * @return array A list of file metadata.
+     */
+    public function listContents($directory = '', $recursive = false);
+
+    /**
+     * Get a file's metadata.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return array|false The file metadata or false on failure.
+     */
+    public function getMetadata($path);
+
+    /**
+     * Get a file's size.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return int|false The file size or false on failure.
+     */
+    public function getSize($path);
+
+    /**
+     * Get a file's mime-type.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file mime-type or false on failure.
+     */
+    public function getMimetype($path);
+
+    /**
+     * Get a file's timestamp.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return int|false The timestamp or false on failure.
+     */
+    public function getTimestamp($path);
+
+    /**
+     * Get a file's visibility.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The visibility (public|private) or false on failure.
+     */
+    public function getVisibility($path);
+
+    /**
+     * Write a new file.
+     *
+     * @param string $path     The path of the new file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @throws FileExistsException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function write($path, $contents, array $config = []);
+
+    /**
+     * Write a new file using a stream.
+     *
+     * @param string   $path     The path of the new file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException If $resource is not a file handle.
+     * @throws FileExistsException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function writeStream($path, $resource, array $config = []);
+
+    /**
+     * Update an existing file.
+     *
+     * @param string $path     The path of the existing file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function update($path, $contents, array $config = []);
+
+    /**
+     * Update an existing file using a stream.
+     *
+     * @param string   $path     The path of the existing file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException If $resource is not a file handle.
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function updateStream($path, $resource, array $config = []);
+
+    /**
+     * Rename a file.
+     *
+     * @param string $path    Path to the existing file.
+     * @param string $newpath The new path of the file.
+     *
+     * @throws FileExistsException   Thrown if $newpath exists.
+     * @throws FileNotFoundException Thrown if $path does not exist.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function rename($path, $newpath);
+
+    /**
+     * Copy a file.
+     *
+     * @param string $path    Path to the existing file.
+     * @param string $newpath The new path of the file.
+     *
+     * @throws FileExistsException   Thrown if $newpath exists.
+     * @throws FileNotFoundException Thrown if $path does not exist.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function copy($path, $newpath);
+
+    /**
+     * Delete a file.
+     *
+     * @param string $path
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function delete($path);
+
+    /**
+     * Delete a directory.
+     *
+     * @param string $dirname
+     *
+     * @throws RootViolationException Thrown if $dirname is empty.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function deleteDir($dirname);
+
+    /**
+     * Create a directory.
+     *
+     * @param string $dirname The name of the new directory.
+     * @param array  $config  An optional configuration array.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function createDir($dirname, array $config = []);
+
+    /**
+     * Set the visibility for a file.
+     *
+     * @param string $path       The path to the file.
+     * @param string $visibility One of 'public' or 'private'.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function setVisibility($path, $visibility);
+
+    /**
+     * Create a file or update if exists.
+     *
+     * @param string $path     The path to the file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function put($path, $contents, array $config = []);
+
+    /**
+     * Create a file or update if exists.
+     *
+     * @param string   $path     The path to the file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException Thrown if $resource is not a resource.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function putStream($path, $resource, array $config = []);
+
+    /**
+     * Read and delete a file.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file contents, or false on failure.
+     */
+    public function readAndDelete($path);
+
+    /**
+     * Get a file/directory handler.
+     *
+     * @deprecated
+     *
+     * @param string  $path    The path to the file.
+     * @param Handler $handler An optional existing handler to populate.
+     *
+     * @return Handler Either a file or directory handler.
+     */
+    public function get($path, Handler $handler = null);
+
+    /**
+     * Register a plugin.
+     *
+     * @param PluginInterface $plugin The plugin to register.
+     *
+     * @return $this
+     */
+    public function addPlugin(PluginInterface $plugin);
+}

+ 12 - 0
vendor/league/flysystem/src/FilesystemNotFoundException.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace League\Flysystem;
+
+use LogicException;
+
+/**
+ * Thrown when the MountManager cannot find a filesystem.
+ */
+class FilesystemNotFoundException extends LogicException implements FilesystemException
+{
+}

+ 137 - 0
vendor/league/flysystem/src/Handler.php

@@ -0,0 +1,137 @@
+<?php
+
+namespace League\Flysystem;
+
+use BadMethodCallException;
+
+/**
+ * @deprecated
+ */
+abstract class Handler
+{
+    /**
+     * @var string
+     */
+    protected $path;
+
+    /**
+     * @var FilesystemInterface
+     */
+    protected $filesystem;
+
+    /**
+     * Constructor.
+     *
+     * @param FilesystemInterface $filesystem
+     * @param string              $path
+     */
+    public function __construct(FilesystemInterface $filesystem = null, $path = null)
+    {
+        $this->path = $path;
+        $this->filesystem = $filesystem;
+    }
+
+    /**
+     * Check whether the entree is a directory.
+     *
+     * @return bool
+     */
+    public function isDir()
+    {
+        return $this->getType() === 'dir';
+    }
+
+    /**
+     * Check whether the entree is a file.
+     *
+     * @return bool
+     */
+    public function isFile()
+    {
+        return $this->getType() === 'file';
+    }
+
+    /**
+     * Retrieve the entree type (file|dir).
+     *
+     * @return string file or dir
+     */
+    public function getType()
+    {
+        $metadata = $this->filesystem->getMetadata($this->path);
+
+        return $metadata ? $metadata['type'] : 'dir';
+    }
+
+    /**
+     * Set the Filesystem object.
+     *
+     * @param FilesystemInterface $filesystem
+     *
+     * @return $this
+     */
+    public function setFilesystem(FilesystemInterface $filesystem)
+    {
+        $this->filesystem = $filesystem;
+
+        return $this;
+    }
+    
+    /**
+     * Retrieve the Filesystem object.
+     *
+     * @return FilesystemInterface
+     */
+    public function getFilesystem()
+    {
+        return $this->filesystem;
+    }
+
+    /**
+     * Set the entree path.
+     *
+     * @param string $path
+     *
+     * @return $this
+     */
+    public function setPath($path)
+    {
+        $this->path = $path;
+
+        return $this;
+    }
+
+    /**
+     * Retrieve the entree path.
+     *
+     * @return string path
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Plugins pass-through.
+     *
+     * @param string $method
+     * @param array  $arguments
+     *
+     * @return mixed
+     */
+    public function __call($method, array $arguments)
+    {
+        array_unshift($arguments, $this->path);
+        $callback = [$this->filesystem, $method];
+
+        try {
+            return call_user_func_array($callback, $arguments);
+        } catch (BadMethodCallException $e) {
+            throw new BadMethodCallException(
+                'Call to undefined method '
+                . get_called_class()
+                . '::' . $method
+            );
+        }
+    }
+}

+ 9 - 0
vendor/league/flysystem/src/InvalidRootException.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace League\Flysystem;
+
+use RuntimeException;
+
+class InvalidRootException extends RuntimeException implements FilesystemException
+{
+}

+ 648 - 0
vendor/league/flysystem/src/MountManager.php

@@ -0,0 +1,648 @@
+<?php
+
+namespace League\Flysystem;
+
+use InvalidArgumentException;
+use League\Flysystem\Plugin\PluggableTrait;
+use League\Flysystem\Plugin\PluginNotFoundException;
+
+/**
+ * Class MountManager.
+ *
+ * Proxies methods to Filesystem (@see __call):
+ *
+ * @method AdapterInterface getAdapter($prefix)
+ * @method Config getConfig($prefix)
+ * @method array listFiles($directory = '', $recursive = false)
+ * @method array listPaths($directory = '', $recursive = false)
+ * @method array getWithMetadata($path, array $metadata)
+ * @method Filesystem flushCache()
+ * @method void assertPresent($path)
+ * @method void assertAbsent($path)
+ * @method Filesystem addPlugin(PluginInterface $plugin)
+ */
+class MountManager implements FilesystemInterface
+{
+    use PluggableTrait;
+
+    /**
+     * @var FilesystemInterface[]
+     */
+    protected $filesystems = [];
+
+    /**
+     * Constructor.
+     *
+     * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]
+     *
+     * @throws InvalidArgumentException
+     */
+    public function __construct(array $filesystems = [])
+    {
+        $this->mountFilesystems($filesystems);
+    }
+
+    /**
+     * Mount filesystems.
+     *
+     * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,]
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return $this
+     */
+    public function mountFilesystems(array $filesystems)
+    {
+        foreach ($filesystems as $prefix => $filesystem) {
+            $this->mountFilesystem($prefix, $filesystem);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Mount filesystems.
+     *
+     * @param string              $prefix
+     * @param FilesystemInterface $filesystem
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return $this
+     */
+    public function mountFilesystem($prefix, FilesystemInterface $filesystem)
+    {
+        if ( ! is_string($prefix)) {
+            throw new InvalidArgumentException(__METHOD__ . ' expects argument #1 to be a string.');
+        }
+
+        $this->filesystems[$prefix] = $filesystem;
+
+        return $this;
+    }
+
+    /**
+     * Get the filesystem with the corresponding prefix.
+     *
+     * @param string $prefix
+     *
+     * @throws FilesystemNotFoundException
+     *
+     * @return FilesystemInterface
+     */
+    public function getFilesystem($prefix)
+    {
+        if ( ! isset($this->filesystems[$prefix])) {
+            throw new FilesystemNotFoundException('No filesystem mounted with prefix ' . $prefix);
+        }
+
+        return $this->filesystems[$prefix];
+    }
+
+    /**
+     * Retrieve the prefix from an arguments array.
+     *
+     * @param array $arguments
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return array [:prefix, :arguments]
+     */
+    public function filterPrefix(array $arguments)
+    {
+        if (empty($arguments)) {
+            throw new InvalidArgumentException('At least one argument needed');
+        }
+
+        $path = array_shift($arguments);
+
+        if ( ! is_string($path)) {
+            throw new InvalidArgumentException('First argument should be a string');
+        }
+
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+        array_unshift($arguments, $path);
+
+        return [$prefix, $arguments];
+    }
+
+    /**
+     * @param string $directory
+     * @param bool   $recursive
+     *
+     * @throws InvalidArgumentException
+     * @throws FilesystemNotFoundException
+     *
+     * @return array
+     */
+    public function listContents($directory = '', $recursive = false)
+    {
+        list($prefix, $directory) = $this->getPrefixAndPath($directory);
+        $filesystem = $this->getFilesystem($prefix);
+        $result = $filesystem->listContents($directory, $recursive);
+
+        foreach ($result as &$file) {
+            $file['filesystem'] = $prefix;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Call forwarder.
+     *
+     * @param string $method
+     * @param array  $arguments
+     *
+     * @throws InvalidArgumentException
+     * @throws FilesystemNotFoundException
+     *
+     * @return mixed
+     */
+    public function __call($method, $arguments)
+    {
+        list($prefix, $arguments) = $this->filterPrefix($arguments);
+
+        return $this->invokePluginOnFilesystem($method, $arguments, $prefix);
+    }
+
+    /**
+     * @param string $from
+     * @param string $to
+     * @param array  $config
+     *
+     * @throws InvalidArgumentException
+     * @throws FilesystemNotFoundException
+     * @throws FileExistsException
+     *
+     * @return bool
+     */
+    public function copy($from, $to, array $config = [])
+    {
+        list($prefixFrom, $from) = $this->getPrefixAndPath($from);
+
+        $buffer = $this->getFilesystem($prefixFrom)->readStream($from);
+
+        if ($buffer === false) {
+            return false;
+        }
+
+        list($prefixTo, $to) = $this->getPrefixAndPath($to);
+
+        $result = $this->getFilesystem($prefixTo)->writeStream($to, $buffer, $config);
+
+        if (is_resource($buffer)) {
+            fclose($buffer);
+        }
+
+        return $result;
+    }
+
+    /**
+     * List with plugin adapter.
+     *
+     * @param array  $keys
+     * @param string $directory
+     * @param bool   $recursive
+     *
+     * @throws InvalidArgumentException
+     * @throws FilesystemNotFoundException
+     *
+     * @return array
+     */
+    public function listWith(array $keys = [], $directory = '', $recursive = false)
+    {
+        list($prefix, $directory) = $this->getPrefixAndPath($directory);
+        $arguments = [$keys, $directory, $recursive];
+
+        return $this->invokePluginOnFilesystem('listWith', $arguments, $prefix);
+    }
+
+    /**
+     * Move a file.
+     *
+     * @param string $from
+     * @param string $to
+     * @param array  $config
+     *
+     * @throws InvalidArgumentException
+     * @throws FilesystemNotFoundException
+     *
+     * @return bool
+     */
+    public function move($from, $to, array $config = [])
+    {
+        list($prefixFrom, $pathFrom) = $this->getPrefixAndPath($from);
+        list($prefixTo, $pathTo) = $this->getPrefixAndPath($to);
+
+        if ($prefixFrom === $prefixTo) {
+            $filesystem = $this->getFilesystem($prefixFrom);
+            $renamed = $filesystem->rename($pathFrom, $pathTo);
+
+            if ($renamed && isset($config['visibility'])) {
+                return $filesystem->setVisibility($pathTo, $config['visibility']);
+            }
+
+            return $renamed;
+        }
+
+        $copied = $this->copy($from, $to, $config);
+
+        if ($copied) {
+            return $this->delete($from);
+        }
+
+        return false;
+    }
+
+    /**
+     * Invoke a plugin on a filesystem mounted on a given prefix.
+     *
+     * @param string $method
+     * @param array  $arguments
+     * @param string $prefix
+     *
+     * @throws FilesystemNotFoundException
+     *
+     * @return mixed
+     */
+    public function invokePluginOnFilesystem($method, $arguments, $prefix)
+    {
+        $filesystem = $this->getFilesystem($prefix);
+
+        try {
+            return $this->invokePlugin($method, $arguments, $filesystem);
+        } catch (PluginNotFoundException $e) {
+            // Let it pass, it's ok, don't panic.
+        }
+
+        $callback = [$filesystem, $method];
+
+        return call_user_func_array($callback, $arguments);
+    }
+
+    /**
+     * @param string $path
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return string[] [:prefix, :path]
+     */
+    protected function getPrefixAndPath($path)
+    {
+        if (strpos($path, '://') < 1) {
+            throw new InvalidArgumentException('No prefix detected in path: ' . $path);
+        }
+
+        return explode('://', $path, 2);
+    }
+
+    /**
+     * Check whether a file exists.
+     *
+     * @param string $path
+     *
+     * @return bool
+     */
+    public function has($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->has($path);
+    }
+
+    /**
+     * Read a file.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file contents or false on failure.
+     */
+    public function read($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->read($path);
+    }
+
+    /**
+     * Retrieves a read-stream for a path.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return resource|false The path resource or false on failure.
+     */
+    public function readStream($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->readStream($path);
+    }
+
+    /**
+     * Get a file's metadata.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return array|false The file metadata or false on failure.
+     */
+    public function getMetadata($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->getMetadata($path);
+    }
+
+    /**
+     * Get a file's size.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return int|false The file size or false on failure.
+     */
+    public function getSize($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->getSize($path);
+    }
+
+    /**
+     * Get a file's mime-type.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file mime-type or false on failure.
+     */
+    public function getMimetype($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->getMimetype($path);
+    }
+
+    /**
+     * Get a file's timestamp.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The timestamp or false on failure.
+     */
+    public function getTimestamp($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->getTimestamp($path);
+    }
+
+    /**
+     * Get a file's visibility.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The visibility (public|private) or false on failure.
+     */
+    public function getVisibility($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->getVisibility($path);
+    }
+
+    /**
+     * Write a new file.
+     *
+     * @param string $path     The path of the new file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @throws FileExistsException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function write($path, $contents, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->write($path, $contents, $config);
+    }
+
+    /**
+     * Write a new file using a stream.
+     *
+     * @param string   $path     The path of the new file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException If $resource is not a file handle.
+     * @throws FileExistsException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function writeStream($path, $resource, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->writeStream($path, $resource, $config);
+    }
+
+    /**
+     * Update an existing file.
+     *
+     * @param string $path     The path of the existing file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function update($path, $contents, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->update($path, $contents, $config);
+    }
+
+    /**
+     * Update an existing file using a stream.
+     *
+     * @param string   $path     The path of the existing file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException If $resource is not a file handle.
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function updateStream($path, $resource, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->updateStream($path, $resource, $config);
+    }
+
+    /**
+     * Rename a file.
+     *
+     * @param string $path    Path to the existing file.
+     * @param string $newpath The new path of the file.
+     *
+     * @throws FileExistsException   Thrown if $newpath exists.
+     * @throws FileNotFoundException Thrown if $path does not exist.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function rename($path, $newpath)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->rename($path, $newpath);
+    }
+
+    /**
+     * Delete a file.
+     *
+     * @param string $path
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function delete($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->delete($path);
+    }
+
+    /**
+     * Delete a directory.
+     *
+     * @param string $dirname
+     *
+     * @throws RootViolationException Thrown if $dirname is empty.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function deleteDir($dirname)
+    {
+        list($prefix, $dirname) = $this->getPrefixAndPath($dirname);
+
+        return $this->getFilesystem($prefix)->deleteDir($dirname);
+    }
+
+    /**
+     * Create a directory.
+     *
+     * @param string $dirname The name of the new directory.
+     * @param array  $config  An optional configuration array.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function createDir($dirname, array $config = [])
+    {
+        list($prefix, $dirname) = $this->getPrefixAndPath($dirname);
+
+        return $this->getFilesystem($prefix)->createDir($dirname);
+    }
+
+    /**
+     * Set the visibility for a file.
+     *
+     * @param string $path       The path to the file.
+     * @param string $visibility One of 'public' or 'private'.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function setVisibility($path, $visibility)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->setVisibility($path, $visibility);
+    }
+
+    /**
+     * Create a file or update if exists.
+     *
+     * @param string $path     The path to the file.
+     * @param string $contents The file contents.
+     * @param array  $config   An optional configuration array.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function put($path, $contents, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->put($path, $contents, $config);
+    }
+
+    /**
+     * Create a file or update if exists.
+     *
+     * @param string   $path     The path to the file.
+     * @param resource $resource The file handle.
+     * @param array    $config   An optional configuration array.
+     *
+     * @throws InvalidArgumentException Thrown if $resource is not a resource.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function putStream($path, $resource, array $config = [])
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->putStream($path, $resource, $config);
+    }
+
+    /**
+     * Read and delete a file.
+     *
+     * @param string $path The path to the file.
+     *
+     * @throws FileNotFoundException
+     *
+     * @return string|false The file contents, or false on failure.
+     */
+    public function readAndDelete($path)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->readAndDelete($path);
+    }
+
+    /**
+     * Get a file/directory handler.
+     *
+     * @deprecated
+     *
+     * @param string  $path    The path to the file.
+     * @param Handler $handler An optional existing handler to populate.
+     *
+     * @return Handler Either a file or directory handler.
+     */
+    public function get($path, Handler $handler = null)
+    {
+        list($prefix, $path) = $this->getPrefixAndPath($path);
+
+        return $this->getFilesystem($prefix)->get($path);
+    }
+}

+ 37 - 0
vendor/league/flysystem/src/NotSupportedException.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace League\Flysystem;
+
+use RuntimeException;
+use SplFileInfo;
+
+class NotSupportedException extends RuntimeException implements FilesystemException
+{
+    /**
+     * Create a new exception for a link.
+     *
+     * @param SplFileInfo $file
+     *
+     * @return static
+     */
+    public static function forLink(SplFileInfo $file)
+    {
+        $message = 'Links are not supported, encountered link at ';
+
+        return new static($message . $file->getPathname());
+    }
+
+    /**
+     * Create a new exception for a link.
+     *
+     * @param string $systemType
+     *
+     * @return static
+     */
+    public static function forFtpSystemType($systemType)
+    {
+        $message = "The FTP system type '$systemType' is currently not supported.";
+
+        return new static($message);
+    }
+}

+ 24 - 0
vendor/league/flysystem/src/Plugin/AbstractPlugin.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+use League\Flysystem\FilesystemInterface;
+use League\Flysystem\PluginInterface;
+
+abstract class AbstractPlugin implements PluginInterface
+{
+    /**
+     * @var FilesystemInterface
+     */
+    protected $filesystem;
+
+    /**
+     * Set the Filesystem object.
+     *
+     * @param FilesystemInterface $filesystem
+     */
+    public function setFilesystem(FilesystemInterface $filesystem)
+    {
+        $this->filesystem = $filesystem;
+    }
+}

+ 34 - 0
vendor/league/flysystem/src/Plugin/EmptyDir.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+class EmptyDir extends AbstractPlugin
+{
+    /**
+     * Get the method name.
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'emptyDir';
+    }
+
+    /**
+     * Empty a directory's contents.
+     *
+     * @param string $dirname
+     */
+    public function handle($dirname)
+    {
+        $listing = $this->filesystem->listContents($dirname, false);
+
+        foreach ($listing as $item) {
+            if ($item['type'] === 'dir') {
+                $this->filesystem->deleteDir($item['path']);
+            } else {
+                $this->filesystem->delete($item['path']);
+            }
+        }
+    }
+}

+ 44 - 0
vendor/league/flysystem/src/Plugin/ForcedCopy.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+use League\Flysystem\FileExistsException;
+use League\Flysystem\FileNotFoundException;
+
+class ForcedCopy extends AbstractPlugin
+{
+    /**
+     * @inheritdoc
+     */
+    public function getMethod()
+    {
+        return 'forceCopy';
+    }
+
+    /**
+     * Copies a file, overwriting any existing files.
+     *
+     * @param string $path    Path to the existing file.
+     * @param string $newpath The new path of the file.
+     *
+     * @throws FileExistsException
+     * @throws FileNotFoundException Thrown if $path does not exist.
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function handle($path, $newpath)
+    {
+        try {
+            $deleted = $this->filesystem->delete($newpath);
+        } catch (FileNotFoundException $e) {
+            // The destination path does not exist. That's ok.
+            $deleted = true;
+        }
+
+        if ($deleted) {
+            return $this->filesystem->copy($path, $newpath);
+        }
+
+        return false;
+    }
+}

+ 44 - 0
vendor/league/flysystem/src/Plugin/ForcedRename.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+use League\Flysystem\FileExistsException;
+use League\Flysystem\FileNotFoundException;
+
+class ForcedRename extends AbstractPlugin
+{
+    /**
+     * @inheritdoc
+     */
+    public function getMethod()
+    {
+        return 'forceRename';
+    }
+
+    /**
+     * Renames a file, overwriting the destination if it exists.
+     *
+     * @param string $path    Path to the existing file.
+     * @param string $newpath The new path of the file.
+     *
+     * @throws FileNotFoundException Thrown if $path does not exist.
+     * @throws FileExistsException
+     *
+     * @return bool True on success, false on failure.
+     */
+    public function handle($path, $newpath)
+    {
+        try {
+            $deleted = $this->filesystem->delete($newpath);
+        } catch (FileNotFoundException $e) {
+            // The destination path does not exist. That's ok.
+            $deleted = true;
+        }
+
+        if ($deleted) {
+            return $this->filesystem->rename($path, $newpath);
+        }
+
+        return false;
+    }
+}

+ 51 - 0
vendor/league/flysystem/src/Plugin/GetWithMetadata.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+use InvalidArgumentException;
+use League\Flysystem\FileNotFoundException;
+
+class GetWithMetadata extends AbstractPlugin
+{
+    /**
+     * Get the method name.
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'getWithMetadata';
+    }
+
+    /**
+     * Get metadata for an object with required metadata.
+     *
+     * @param string   $path     path to file
+     * @param string[] $metadata metadata keys
+     *
+     * @throws InvalidArgumentException
+     * @throws FileNotFoundException
+     *
+     * @return array|false metadata
+     */
+    public function handle($path, array $metadata)
+    {
+        $object = $this->filesystem->getMetadata($path);
+
+        if ( ! $object) {
+            return false;
+        }
+
+        $keys = array_diff($metadata, array_keys($object));
+
+        foreach ($keys as $key) {
+            if ( ! method_exists($this->filesystem, $method = 'get' . ucfirst($key))) {
+                throw new InvalidArgumentException('Could not fetch metadata: ' . $key);
+            }
+
+            $object[$key] = $this->filesystem->{$method}($path);
+        }
+
+        return $object;
+    }
+}

+ 35 - 0
vendor/league/flysystem/src/Plugin/ListFiles.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+class ListFiles extends AbstractPlugin
+{
+    /**
+     * Get the method name.
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'listFiles';
+    }
+
+    /**
+     * List all files in the directory.
+     *
+     * @param string $directory
+     * @param bool   $recursive
+     *
+     * @return array
+     */
+    public function handle($directory = '', $recursive = false)
+    {
+        $contents = $this->filesystem->listContents($directory, $recursive);
+
+        $filter = function ($object) {
+            return $object['type'] === 'file';
+        };
+
+        return array_values(array_filter($contents, $filter));
+    }
+}

+ 36 - 0
vendor/league/flysystem/src/Plugin/ListPaths.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace League\Flysystem\Plugin;
+
+class ListPaths extends AbstractPlugin
+{
+    /**
+     * Get the method name.
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'listPaths';
+    }
+
+    /**
+     * List all paths.
+     *
+     * @param string $directory
+     * @param bool   $recursive
+     *
+     * @return string[] paths
+     */
+    public function handle($directory = '', $recursive = false)
+    {
+        $result = [];
+        $contents = $this->filesystem->listContents($directory, $recursive);
+
+        foreach ($contents as $object) {
+            $result[] = $object['path'];
+        }
+
+        return $result;
+    }
+}

Някои файлове не бяха показани, защото твърде много файлове са промени