From a420104b037afb05b0f2fada6e9b4b3ff0cbfbb9 Mon Sep 17 00:00:00 2001 From: taoser Date: Sun, 12 Feb 2023 18:22:24 +0800 Subject: [PATCH] flysystem --- app/BaseController.php | 4 +- app/admin/view/login/login.html | 6 +- app/admin/view/public/base.html | 1 + app/common.php | 108 --- app/common/lib/Arts.php | 373 ++++++++ composer.json | 3 +- composer.lock | 130 ++- config/taoler.php | 2 +- vendor/autoload.php | 17 +- vendor/composer/autoload_psr4.php | 2 +- vendor/composer/autoload_static.php | 7 +- vendor/composer/installed.json | 131 ++- vendor/composer/installed.php | 19 +- vendor/league/flysystem/INFO.md | 2 + vendor/league/flysystem/LICENSE | 2 +- vendor/league/flysystem/composer.json | 94 +- .../flysystem/config.subsplit-publish.json | 49 + vendor/league/flysystem/docker-compose.yml | 58 ++ vendor/league/flysystem/readme.md | 45 + vendor/league/flysystem/src/Config.php | 100 +- .../flysystem/src/CorruptedPathDetected.php | 10 +- .../flysystem/src/DirectoryAttributes.php | 110 +++ .../league/flysystem/src/DirectoryListing.php | 84 ++ .../league/flysystem/src/FileAttributes.php | 139 +++ vendor/league/flysystem/src/Filesystem.php | 520 +++------- .../flysystem/src/FilesystemAdapter.php | 108 +++ .../flysystem/src/FilesystemException.php | 6 +- .../src/FilesystemOperationFailed.php | 22 + .../flysystem/src/FilesystemOperator.php | 9 + .../league/flysystem/src/FilesystemReader.php | 66 ++ .../league/flysystem/src/FilesystemWriter.php | 58 ++ .../flysystem/src/InvalidStreamProvided.php | 11 + .../src/InvalidVisibilityProvided.php | 20 + .../src/Local/LocalFilesystemAdapter.php | 419 ++++++++ vendor/league/flysystem/src/MountManager.php | 894 ++++++------------ .../league/flysystem/src/PathNormalizer.php | 10 + vendor/league/flysystem/src/PathPrefixer.php | 60 ++ .../flysystem/src/PathTraversalDetected.php | 28 + .../flysystem/src/PortableVisibilityGuard.php | 19 + .../src/ProxyArrayAccessToProperties.php | 62 ++ .../flysystem/src/StorageAttributes.php | 40 + .../flysystem/src/SymbolicLinkEncountered.php | 28 + .../src/UnableToCheckFileExistence.php | 21 + .../league/flysystem/src/UnableToCopyFile.php | 48 + .../flysystem/src/UnableToCreateDirectory.php | 44 + .../flysystem/src/UnableToDeleteDirectory.php | 48 + .../flysystem/src/UnableToDeleteFile.php | 45 + .../flysystem/src/UnableToMountFilesystem.php | 32 + .../league/flysystem/src/UnableToMoveFile.php | 48 + .../league/flysystem/src/UnableToReadFile.php | 45 + .../src/UnableToResolveFilesystemMount.php | 20 + .../src/UnableToRetrieveMetadata.php | 76 ++ .../flysystem/src/UnableToSetVisibility.php | 49 + .../flysystem/src/UnableToWriteFile.php | 45 + .../PortableVisibilityConverter.php | 109 +++ .../UnixVisibility/VisibilityConverter.php | 14 + .../src/UnreadableFileEncountered.php | 28 + vendor/league/flysystem/src/Visibility.php | 11 + .../src/WhitespacePathNormalizer.php | 49 + vendor/services.php | 2 +- vendor/topthink/think-filesystem/.gitignore | 3 + vendor/topthink/think-filesystem/README.md | 5 + .../topthink/think-filesystem/composer.json | 33 + .../think-filesystem/phpunit.xml.dist | 25 + .../think-filesystem/src/Filesystem.php | 89 ++ .../src/facade/Filesystem.php | 33 + .../src/filesystem/Driver.php | 130 +++ .../src/filesystem/driver/Local.php | 98 ++ .../think-filesystem/tests/FilesystemTest.php | 66 ++ .../think-filesystem/tests/bootstrap.php | 2 + 70 files changed, 3740 insertions(+), 1354 deletions(-) create mode 100644 app/common/lib/Arts.php create mode 100644 vendor/league/flysystem/INFO.md create mode 100644 vendor/league/flysystem/config.subsplit-publish.json create mode 100644 vendor/league/flysystem/docker-compose.yml create mode 100644 vendor/league/flysystem/readme.md create mode 100644 vendor/league/flysystem/src/DirectoryAttributes.php create mode 100644 vendor/league/flysystem/src/DirectoryListing.php create mode 100644 vendor/league/flysystem/src/FileAttributes.php create mode 100644 vendor/league/flysystem/src/FilesystemAdapter.php create mode 100644 vendor/league/flysystem/src/FilesystemOperationFailed.php create mode 100644 vendor/league/flysystem/src/FilesystemOperator.php create mode 100644 vendor/league/flysystem/src/FilesystemReader.php create mode 100644 vendor/league/flysystem/src/FilesystemWriter.php create mode 100644 vendor/league/flysystem/src/InvalidStreamProvided.php create mode 100644 vendor/league/flysystem/src/InvalidVisibilityProvided.php create mode 100644 vendor/league/flysystem/src/Local/LocalFilesystemAdapter.php create mode 100644 vendor/league/flysystem/src/PathNormalizer.php create mode 100644 vendor/league/flysystem/src/PathPrefixer.php create mode 100644 vendor/league/flysystem/src/PathTraversalDetected.php create mode 100644 vendor/league/flysystem/src/PortableVisibilityGuard.php create mode 100644 vendor/league/flysystem/src/ProxyArrayAccessToProperties.php create mode 100644 vendor/league/flysystem/src/StorageAttributes.php create mode 100644 vendor/league/flysystem/src/SymbolicLinkEncountered.php create mode 100644 vendor/league/flysystem/src/UnableToCheckFileExistence.php create mode 100644 vendor/league/flysystem/src/UnableToCopyFile.php create mode 100644 vendor/league/flysystem/src/UnableToCreateDirectory.php create mode 100644 vendor/league/flysystem/src/UnableToDeleteDirectory.php create mode 100644 vendor/league/flysystem/src/UnableToDeleteFile.php create mode 100644 vendor/league/flysystem/src/UnableToMountFilesystem.php create mode 100644 vendor/league/flysystem/src/UnableToMoveFile.php create mode 100644 vendor/league/flysystem/src/UnableToReadFile.php create mode 100644 vendor/league/flysystem/src/UnableToResolveFilesystemMount.php create mode 100644 vendor/league/flysystem/src/UnableToRetrieveMetadata.php create mode 100644 vendor/league/flysystem/src/UnableToSetVisibility.php create mode 100644 vendor/league/flysystem/src/UnableToWriteFile.php create mode 100644 vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php create mode 100644 vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php create mode 100644 vendor/league/flysystem/src/UnreadableFileEncountered.php create mode 100644 vendor/league/flysystem/src/Visibility.php create mode 100644 vendor/league/flysystem/src/WhitespacePathNormalizer.php create mode 100644 vendor/topthink/think-filesystem/.gitignore create mode 100644 vendor/topthink/think-filesystem/README.md create mode 100644 vendor/topthink/think-filesystem/composer.json create mode 100644 vendor/topthink/think-filesystem/phpunit.xml.dist create mode 100644 vendor/topthink/think-filesystem/src/Filesystem.php create mode 100644 vendor/topthink/think-filesystem/src/facade/Filesystem.php create mode 100644 vendor/topthink/think-filesystem/src/filesystem/Driver.php create mode 100644 vendor/topthink/think-filesystem/src/filesystem/driver/Local.php create mode 100644 vendor/topthink/think-filesystem/tests/FilesystemTest.php create mode 100644 vendor/topthink/think-filesystem/tests/bootstrap.php diff --git a/app/BaseController.php b/app/BaseController.php index 13747d2..0b67da4 100644 --- a/app/BaseController.php +++ b/app/BaseController.php @@ -243,8 +243,8 @@ abstract class BaseController /** * 获取文章链接地址 - * - * @param integer $aid + * @param int $aid + * @param string $ename * @return string */ protected function getRouteUrl(int $aid,string $ename = '') : string diff --git a/app/admin/view/login/login.html b/app/admin/view/login/login.html index 36599fb..d22e1cb 100644 --- a/app/admin/view/login/login.html +++ b/app/admin/view/login/login.html @@ -77,15 +77,13 @@ {/block} {block name="js"} -{:hook('bacimghook')} - +{:hook('bacimghook')} {/block} \ No newline at end of file diff --git a/app/admin/view/public/base.html b/app/admin/view/public/base.html index c247358..1650ff9 100644 --- a/app/admin/view/public/base.html +++ b/app/admin/view/public/base.html @@ -28,6 +28,7 @@ var AdminLogin = "{:url('Login/index')}", AdminLogout = "{:url('Admin/logout')}", adminClearCache = "{:url('Admin/clearCache')}", sysCy = "{$clevel}"; var menuNav = "{:url('menu/getMenuNavbar')}"; +var $ = layui.jquery; {block name="js"}js文件{/block} diff --git a/app/common.php b/app/common.php index c528423..0bbf57b 100644 --- a/app/common.php +++ b/app/common.php @@ -330,112 +330,4 @@ if (!function_exists('__')) { } } -if (!function_exists('setKeywords')) { - /** - * 关键词 - * 通过百度分词接口获取关键词或者标签 - * flag 1.为word时获取分词,2.为tag时获取标签 - * - * @return string - */ - function setKeywords($flag, $title, $content) - { - $keywords = []; - // 百度分词自动生成关键词 - if(!empty(config('taoler.baidu.client_id')) == true) { - //headers数组内的格式 - $headers = array(); - $headers[] = "Content-Type:application/json"; - - switch($flag) { - //分词 - case 'word': - $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); - $body = ["text" => $title]; - break; - //标签 - case 'tag': - $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); - $body = ['title' => $title, 'content'=> $content]; - break; - default: - $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); - $body = ["text" => $title]; - } - - $postBody = json_encode($body); - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//设置请求头 - curl_setopt($curl, CURLOPT_POSTFIELDS, $postBody);//设置请求体 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');//使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。(这个加不加没啥影响) - $datas = curl_exec($curl); - if($datas == false) { - echo '接口无法链接'; - } else { - $res = stripos($datas,'error_code'); - // 接收返回的数据 - $dataItem = json_decode($datas); - if($res == false) { - // 数据正常 - $items = $dataItem->items; - foreach($items as $item) { - - switch($flag) { - case 'word': - if($item->pos == 'n' && !in_array($item->item,$keywords)){ - $keywords[] = $item->item; - } - break; - case 'tag': - if(!in_array($item->tag,$keywords)){ - $keywords[] = $item->tag; - } - break; - default: - if($item->pos == 'n' && !in_array($item->item,$keywords)){ - $keywords[] = $item->item; - } - } - } - } else { - // 接口正常但获取数据失败,可能参数错误,重新获取token - $url = 'https://aip.baidubce.com/oauth/2.0/token'; - $post_data['grant_type'] = config('taoler.baidu.grant_type');; - $post_data['client_id'] = config('taoler.baidu.client_id'); - $post_data['client_secret'] = config('taoler.baidu.client_secret'); - - $o = ""; - foreach ( $post_data as $k => $v ) - { - $o.= "$k=" . urlencode( $v ). "&" ; - } - $postData = substr($o,0,-1); - - $curl = curl_init();//初始化curl - curl_setopt($curl, CURLOPT_URL,$url);//抓取指定网页 - curl_setopt($curl, CURLOPT_HEADER, 0);//设置header - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上 - curl_setopt($curl, CURLOPT_POST, 1);//post提交方式 - curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); - $data = curl_exec($curl);//运行curl - curl_close($curl); - - // 写入token - SetArr::name('taoler')->edit([ - 'baidu'=> [ - 'access_token' => json_decode($data)->access_token, - ] - ]); - //echo 'api接口数据错误 - '; - //echo $dataItem->error_msg; - } - } - } - return implode(",", $keywords); - } - -} diff --git a/app/common/lib/Arts.php b/app/common/lib/Arts.php new file mode 100644 index 0000000..67e6f4f --- /dev/null +++ b/app/common/lib/Arts.php @@ -0,0 +1,373 @@ +cache('system',3600)->find(1); + + } + + //域名协议转换 把数据库中的带HTTP或不带协议的域名转换为当前协议的域名前缀 + protected function getHttpUrl($url) + { + //域名转换为无http协议 + $www = stripos($url,'://') ? substr(stristr($url,'://'),3) : $url; + return Request::scheme().'://'. $www; + } + + //得到当前系统安装前台域名 + protected function getIndexUrl() + { + $sys = $this->getSystem(); + return $this->getHttpUrl($sys['domain']); + } + + /** + * 获取文章链接地址 + * @param int $aid + * @param string $ename + * @return string + */ + public function getRouteUrl(int $aid,string $ename = '') : string + { + $indexUrl = $this->getIndexUrl(); + if(config('taoler.url_rewrite.article_as') == '/'){ + // 分类可变路由 + $artUrl = (string) url('article_detail', ['id' => (int) $aid, 'ename'=> $ename]); + //$artUrl = (string) Route::buildUrl('article_detail', ['id' => $aid, 'ename'=> $ename]); + } else { + $artUrl = (string) url('article_detail', ['id' => $aid]); + } + //dump($artUrl); + + // 判断是否开启绑定 + //$domain_bind = array_key_exists('domain_bind',config('app')); + + // 判断index应用是否绑定域名 + $bind_index = array_search('index',config('app.domain_bind')); + // 判断admin应用是否绑定域名 + $bind_admin = array_search('admin',config('app.domain_bind')); + + // 判断index应用是否域名映射 + $map_index = array_search('index',config('app.app_map')); + // 判断admin应用是否域名映射 + $map_admin = array_search('admin',config('app.app_map')); + + $index = $map_index ? $map_index : 'index'; // index应用名 + $admin = $map_admin ? $map_admin : 'admin'; // admin应用名 + + if($bind_index) { + // index绑定域名 + $url = $indexUrl . str_replace($admin.'/','',$artUrl); + } else { // index未绑定域名 + // admin绑定域名 + if($bind_admin) { + $url = $indexUrl .'/' . $index . $artUrl; + } else { + $url = $indexUrl . str_replace($admin,$index,$artUrl); + } + + } + + return $url; + } + + /** + * 关键词 + * 通过百度分词接口获取关键词或者标签 + * @param $flag string 为word时获取分词,2.为tag时获取标签 + * @param $title string + * @param $content string + * @return array + */ + public function setKeywords(string $flag,string $title,string $content) :array + { + $keywords = []; + // 百度分词自动生成关键词 + if(!empty(config('taoler.baidu.client_id'))) { + //headers数组内的格式 + $headers = []; + $headers[] = "Content-Type:application/json"; + + switch($flag) { + //分词 + case 'word': + $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); + $body = ["text" => $title]; + break; + //标签 + case 'tag': + $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); + $body = ['title' => $title, 'content' => $content]; + break; + default: + $url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token'); + $body = ["text" => $title]; + } + + $postBody = json_encode($body); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//设置请求头 + curl_setopt($curl, CURLOPT_POSTFIELDS, $postBody);//设置请求体 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');//使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。(这个加不加没啥影响) + $datas = curl_exec($curl); + if($datas == false) { + echo '接口无法链接'; + } else { + $res = stripos($datas,'error_code'); + // 接收返回的数据 + $dataItem = json_decode($datas); + if($res == false) { + // 数据正常 + $items = $dataItem->items; + foreach($items as $item) { + + switch($flag) { + case 'word': + if($item->pos == 'n' && !in_array($item->item,$keywords)){ + $keywords[] = $item->item; + } + break; + case 'tag': + if(!in_array($item->tag,$keywords)){ + $keywords[] = $item->tag; + } + break; + default: + if($item->pos == 'n' && !in_array($item->item,$keywords)){ + $keywords[] = $item->item; + } + } + } + } else { + // 接口正常但获取数据失败,可能参数错误,重新获取token + $url = 'https://aip.baidubce.com/oauth/2.0/token'; + $post_data['grant_type'] = config('taoler.baidu.grant_type');; + $post_data['client_id'] = config('taoler.baidu.client_id'); + $post_data['client_secret'] = config('taoler.baidu.client_secret'); + + $o = ""; + foreach ( $post_data as $k => $v ) + { + $o.= "$k=" . urlencode( $v ). "&" ; + } + $post_data = substr($o,0,-1); + $res = $this->request_post($url, $post_data); + // 写入token + SetArr::name('taoler')->edit([ + 'baidu'=> [ + 'access_token' => json_decode($res)->access_token, + ] + ]); + echo 'api接口数据错误 - '; + echo $dataItem->error_msg; + } + } + } + return $keywords; + } + + // api_post接口 + function request_post($url = '', $param = '') + { + if (empty($url) || empty($param)) { + return false; + } + + $postUrl = $url; + $curlPost = $param; + $curl = curl_init();//初始化curl + curl_setopt($curl, CURLOPT_URL,$postUrl);//抓取指定网页 + curl_setopt($curl, CURLOPT_HEADER, 0);//设置header + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上 + curl_setopt($curl, CURLOPT_POST, 1);//post提交方式 + curl_setopt($curl, CURLOPT_POSTFIELDS, $curlPost); + $data = curl_exec($curl);//运行curl + curl_close($curl); + return $data; + } + + /** + * 标题调用百度关键词词条 + * + * @return Json + */ + public function getBdiduSearchWordList($words) + { + if(empty($words)) return json(['code'=>-1,'msg'=>'null']); + $url = 'https://www.baidu.com/sugrec?prod=pc&from=pc_web&wd='.$words; + //$result = Api::urlGet($url); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $datas = curl_exec($curl); + curl_close($curl); + $data = json_decode($datas,true); + if(isset($data['g'])) { + return json(['code'=>0,'msg'=>'success','data'=>$data['g']]); + } else { + return json(['code'=>-1,'msg'=>'null']); + } + + } + + /** + * baidu push api + * + * @param string $link + * @return void + */ + public function baiduPushUrl(string $link) + { + // baidu 接口 + $api = config('taoler.baidu.push_api'); + if(!empty($api)) { + $url[] = $link; + $ch = curl_init(); + $options = array( + CURLOPT_URL => $api, + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POSTFIELDS => implode("\n", $url), + CURLOPT_HTTPHEADER => array('Content-Type: text/plain'), + ); + curl_setopt_array($ch, $options); + curl_exec($ch); + curl_close($ch); + } + + } + + /** + * 上传接口 + * + * @return void + */ + public function uploadFiles($type) + { + $uploads = new Uploads(); + switch ($type){ + case 'image': + $upRes = $uploads->put('file','article_pic',2048,'image'); + break; + case 'zip': + $upRes = $uploads->put('file','article_zip',1024,'application|image'); + break; + case 'video': + $upRes = $uploads->put('file','article_video',102400,'video|audio'); + break; + case 'audio': + $upRes = $uploads->put('file','article_audio',102400,'audio'); + break; + default: + $upRes = $uploads->put('file','article_file',2048,'image'); + break; + } + return $upRes; + } + + //获取artcile内容所有图片,返回数组 + protected function getArticleAllpic($str) + { + //正则匹配 + $pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png]))[\'|\"].*?[\/]?>/"; + preg_match_all($pattern,$str,$matchContent); + if(isset($matchContent[1])){ + $img = $matchContent[1]; + }else{ + $temp = "./images/no-image.jpg";//在相应位置放置一张命名为no-image的jpg图片 + } + + return $img; + + } + + + //下载远程图片 + private function downloadImage($url) + { + $ch = curl_init(); + curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, 'GET' ); + curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false ); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); + $file = curl_exec($ch); + curl_close($ch); + return $this->saveAsImage($url, $file); + + } + + //把图片保存到本地 + private function saveAsImage($url, $file) + { + $filename = pathinfo($url, PATHINFO_BASENAME); + //$dirname = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_DIRNAME); + $dirname = date('Ymd',time()); + //路径 + $path = 'storage/' . $this->uid . '/article_pic/' . $dirname . '/'; + //绝对文件夹 + $fileDir = public_path() . $path; + //文件绝对路径 + $filePath = $fileDir . $filename; + //相对路径文件名 + $realFile = '/' . $path . $filename; + // 如果目录不存在,则创建 + + if(!is_dir($fileDir)) { + mkdir($fileDir, 0777, true); + } + + if(file_exists($filePath)) { + //$this->output->writeln("【已存在】输出路径" . $fullpath); + return $realFile; + + } else { + $resource = fopen($filePath, 'a'); + $res = fwrite($resource, $file); + fclose($resource); + if($res !== false) { + return $realFile; + } + } + } + + //下载网络图片到本地并替换 + public function downUrlPicsReaplace($content) + { + // 批量下载网络图片并替换 + $images = $this->getArticleAllpic($content); + if(count($images)) { + foreach($images as $image){ + //1.带http地址的图片,2.非本站的网络图片 3.非带有?号等参数的图片 + if((stripos($image,'http') !== false) && (stripos($image, Request::domain()) === false) && (stripos($image, '?') === false)) { + // 如果图片中没有带参数或者加密可下载 + //下载远程图片(可下载) + $newImageUrl = $this->downloadImage($image); + //替换图片链接 + $content = str_replace($image,Request::domain().$newImageUrl,$content); + } + } + //不可下载的图片,如加密或者带有参数的图片如?type=jpeg,直接返回content + } + + return $content; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json index fbd5924..a0d25bf 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,8 @@ "workerman/phpsocket.io": "^1.1", "jaeger/querylist": "^4.2", "symfony/var-exporter": "^5.4", - "yzh52521/easyhttp": "^1.0" + "yzh52521/easyhttp": "^1.0", + "topthink/think-filesystem": "^2.0" }, "require-dev": { "symfony/var-dumper": "^4.2", diff --git a/composer.lock b/composer.lock index 60d1ffe..5ae85a6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "20e9c0c21d94d1cbf1c29c69868ebe38", + "content-hash": "76842e3f55a3ecc7f87e51236f14622d", "packages": [ { "name": "bacon/bacon-qr-code", @@ -140,7 +140,7 @@ }, "require": { "cache/adapter-common": "^1.0", - "league/flysystem": "^1.0", + "league/flysystem": "^1.0 || ^2.0", "php": ">=7.4", "psr/cache": "^1.0 || ^2.0", "psr/simple-cache": "^1.0" @@ -920,54 +920,44 @@ }, { "name": "league/flysystem", - "version": "1.1.10", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1" + "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3239285c825c152bcc315fe0e87d6b55f5972ed1", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", + "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "league/mime-type-detection": "^1.3", - "php": "^7.2.5 || ^8.0" + "ext-json": "*", + "league/mime-type-detection": "^1.0.0", + "php": "^7.2 || ^8.0" }, "conflict": { - "league/flysystem-sftp": "<1.0.6" + "guzzlehttp/ringphp": "<1.1.1" }, "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" + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.0", + "aws/aws-sdk-php": "^3.132.4", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "friendsofphp/php-cs-fixer": "^3.2", + "google/cloud-storage": "^1.23", + "phpseclib/phpseclib": "^2.0", + "phpstan/phpstan": "^0.12.26", + "phpunit/phpunit": "^8.5 || ^9.4", + "sabre/dav": "^4.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { "psr-4": { - "League\\Flysystem\\": "src/" + "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -977,40 +967,42 @@ "authors": [ { "name": "Frank de Jonge", - "email": "info@frenky.net" + "email": "info@frankdejonge.nl" } ], - "description": "Filesystem abstraction: Many filesystems, one API.", + "description": "File storage abstraction for PHP", "keywords": [ - "Cloud Files", "WebDAV", - "abstraction", "aws", "cloud", - "copy.com", - "dropbox", - "file systems", + "file", "files", "filesystem", "filesystems", "ftp", - "rackspace", - "remote", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/1.1.10" + "source": "https://github.com/thephpleague/flysystem/tree/2.5.0" }, "funding": [ { - "url": "https://offset.earth/frankdejonge", - "type": "other" + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" } ], - "time": "2022-10-04T09:16:37+00:00" + "time": "2022-09-17T21:02:32+00:00" }, { "name": "league/mime-type-detection", @@ -2561,6 +2553,52 @@ }, "time": "2022-10-26T07:59:42+00:00" }, + { + "name": "topthink/think-filesystem", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-filesystem.git", + "reference": "63e525fd74f451b2df1df060c3194e9b6e724730" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/63e525fd74f451b2df1df060c3194e9b6e724730", + "reference": "63e525fd74f451b2df1df060c3194e9b6e724730", + "shasum": "" + }, + "require": { + "league/flysystem": "^2.0", + "topthink/framework": "^6.1" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP6.1 Filesystem Package", + "support": { + "issues": "https://github.com/top-think/think-filesystem/issues", + "source": "https://github.com/top-think/think-filesystem/tree/v2.0.0" + }, + "time": "2022-10-26T04:51:41+00:00" + }, { "name": "topthink/think-helper", "version": "v3.1.6", diff --git a/config/taoler.php b/config/taoler.php index b4fc172..512cbba 100644 --- a/config/taoler.php +++ b/config/taoler.php @@ -16,7 +16,7 @@ return [ // 应用名,此项不可更改 'appname' => 'TaoLer', // 版本配置 - 'version' => '2.0.8', + 'version' => '2.0.9', // 加盐 'salt' => 'taoler', // 数据库备份目录 diff --git a/vendor/autoload.php b/vendor/autoload.php index 99bc5f3..6a8a999 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -3,8 +3,21 @@ // 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); + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = '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; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 7b87eb4..f5c2f43 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -14,7 +14,7 @@ return array( 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), 'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'), - 'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/framework/src/think'), + 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-filesystem/src'), 'taoser\\think\\' => array($vendorDir . '/taoser/think-auth/src'), 'taoser\\' => array($vendorDir . '/taoser/think-addons/src', $vendorDir . '/taoser/think-setarr/src'), 'phpspirit\\databackup\\' => array($vendorDir . '/lotofbadcode/phpspirit_databackup/src'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 2402b2e..d440b07 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -180,10 +180,11 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2 ), 'think\\' => array ( - 0 => __DIR__ . '/..' . '/topthink/think-helper/src', - 1 => __DIR__ . '/..' . '/topthink/think-template/src', + 0 => __DIR__ . '/..' . '/topthink/framework/src/think', + 1 => __DIR__ . '/..' . '/topthink/think-helper/src', 2 => __DIR__ . '/..' . '/topthink/think-orm/src', - 3 => __DIR__ . '/..' . '/topthink/framework/src/think', + 3 => __DIR__ . '/..' . '/topthink/think-template/src', + 4 => __DIR__ . '/..' . '/topthink/think-filesystem/src', ), 'taoser\\think\\' => array ( diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 65d3597..ef12727 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -962,57 +962,47 @@ }, { "name": "league/flysystem", - "version": "1.1.10", - "version_normalized": "1.1.10.0", + "version": "2.5.0", + "version_normalized": "2.5.0.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1" + "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3239285c825c152bcc315fe0e87d6b55f5972ed1", - "reference": "3239285c825c152bcc315fe0e87d6b55f5972ed1", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", + "reference": "8aaffb653c5777781b0f7f69a5d937baf7ab6cdb", "shasum": "" }, "require": { - "ext-fileinfo": "*", - "league/mime-type-detection": "^1.3", - "php": "^7.2.5 || ^8.0" + "ext-json": "*", + "league/mime-type-detection": "^1.0.0", + "php": "^7.2 || ^8.0" }, "conflict": { - "league/flysystem-sftp": "<1.0.6" + "guzzlehttp/ringphp": "<1.1.1" }, "require-dev": { - "phpspec/prophecy": "^1.11.1", - "phpunit/phpunit": "^8.5.8" + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.0", + "aws/aws-sdk-php": "^3.132.4", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "friendsofphp/php-cs-fixer": "^3.2", + "google/cloud-storage": "^1.23", + "phpseclib/phpseclib": "^2.0", + "phpstan/phpstan": "^0.12.26", + "phpunit/phpunit": "^8.5 || ^9.4", + "sabre/dav": "^4.1" }, - "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": "2022-10-04T09:16:37+00:00", + "time": "2022-09-17T21:02:32+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { - "League\\Flysystem\\": "src/" + "League\\Flysystem\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1022,37 +1012,39 @@ "authors": [ { "name": "Frank de Jonge", - "email": "info@frenky.net" + "email": "info@frankdejonge.nl" } ], - "description": "Filesystem abstraction: Many filesystems, one API.", + "description": "File storage abstraction for PHP", "keywords": [ - "Cloud Files", "WebDAV", - "abstraction", "aws", "cloud", - "copy.com", - "dropbox", - "file systems", + "file", "files", "filesystem", "filesystems", "ftp", - "rackspace", - "remote", "s3", "sftp", "storage" ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/1.1.10" + "source": "https://github.com/thephpleague/flysystem/tree/2.5.0" }, "funding": [ { - "url": "https://offset.earth/frankdejonge", - "type": "other" + "url": "https://ecologi.com/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" } ], "install-path": "../league/flysystem" @@ -2716,6 +2708,55 @@ }, "install-path": "../topthink/think-captcha" }, + { + "name": "topthink/think-filesystem", + "version": "v2.0.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/top-think/think-filesystem.git", + "reference": "63e525fd74f451b2df1df060c3194e9b6e724730" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/top-think/think-filesystem/zipball/63e525fd74f451b2df1df060c3194e9b6e724730", + "reference": "63e525fd74f451b2df1df060c3194e9b6e724730", + "shasum": "" + }, + "require": { + "league/flysystem": "^2.0", + "topthink/framework": "^6.1" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^8.0" + }, + "time": "2022-10-26T04:51:41+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "think\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "description": "The ThinkPHP6.1 Filesystem Package", + "support": { + "issues": "https://github.com/top-think/think-filesystem/issues", + "source": "https://github.com/top-think/think-filesystem/tree/v2.0.0" + }, + "install-path": "../topthink/think-filesystem" + }, { "name": "topthink/think-helper", "version": "v3.1.6", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index c003842..6fc6fc5 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'taoser/taoler', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'd0f1021f8dc728187d75d1722deac92d73a25d82', + 'reference' => '6bb4a77619f0244cc914b917f5a95ade44c7500f', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -137,9 +137,9 @@ 'dev_requirement' => false, ), 'league/flysystem' => array( - 'pretty_version' => '1.1.10', - 'version' => '1.1.10.0', - 'reference' => '3239285c825c152bcc315fe0e87d6b55f5972ed1', + 'pretty_version' => '2.5.0', + 'version' => '2.5.0.0', + 'reference' => '8aaffb653c5777781b0f7f69a5d937baf7ab6cdb', 'type' => 'library', 'install_path' => __DIR__ . '/../league/flysystem', 'aliases' => array(), @@ -358,7 +358,7 @@ 'taoser/taoler' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'd0f1021f8dc728187d75d1722deac92d73a25d82', + 'reference' => '6bb4a77619f0244cc914b917f5a95ade44c7500f', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -418,6 +418,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'topthink/think-filesystem' => array( + 'pretty_version' => 'v2.0.0', + 'version' => '2.0.0.0', + 'reference' => '63e525fd74f451b2df1df060c3194e9b6e724730', + 'type' => 'library', + 'install_path' => __DIR__ . '/../topthink/think-filesystem', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'topthink/think-helper' => array( 'pretty_version' => 'v3.1.6', 'version' => '3.1.6.0', diff --git a/vendor/league/flysystem/INFO.md b/vendor/league/flysystem/INFO.md new file mode 100644 index 0000000..8a44d14 --- /dev/null +++ b/vendor/league/flysystem/INFO.md @@ -0,0 +1,2 @@ +View the docs at: https://flysystem.thephpleague.com/v2/ +Changelog at: https://github.com/thephpleague/flysystem/blob/2.x/CHANGELOG.md diff --git a/vendor/league/flysystem/LICENSE b/vendor/league/flysystem/LICENSE index f2684c8..1f01652 100644 --- a/vendor/league/flysystem/LICENSE +++ b/vendor/league/flysystem/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013-2019 Frank de Jonge +Copyright (c) 2013-2022 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 diff --git a/vendor/league/flysystem/composer.json b/vendor/league/flysystem/composer.json index 32ec81d..9c244f8 100644 --- a/vendor/league/flysystem/composer.json +++ b/vendor/league/flysystem/composer.json @@ -1,68 +1,48 @@ { "name": "league/flysystem", - "type": "library", - "description": "Filesystem abstraction: Many filesystems, one API.", + "description": "File storage abstraction for PHP", "keywords": [ - "filesystem", "filesystems", "files", "storage", "dropbox", "aws", - "abstraction", "s3", "ftp", "sftp", "remote", "webdav", - "file systems", "cloud", "cloud files", "rackspace", "copy.com" + "filesystem", "filesystems", "files", "storage", "aws", + "s3", "ftp", "sftp", "webdav", "file", "cloud" ], - "funding": [ - { - "type": "other", - "url": "https://offset.earth/frankdejonge" + "scripts": { + "phpstan": "vendor/bin/phpstan analyse -l 6 src" + }, + "type": "library", + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" } - ], + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-json": "*", + "league/mime-type-detection": "^1.0.0" + }, + "require-dev": { + "ext-fileinfo": "*", + "ext-ftp": "*", + "phpunit/phpunit": "^8.5 || ^9.4", + "phpstan/phpstan": "^0.12.26", + "phpseclib/phpseclib": "^2.0", + "aws/aws-sdk-php": "^3.132.4", + "composer/semver": "^3.0", + "friendsofphp/php-cs-fixer": "^3.2", + "google/cloud-storage": "^1.23", + "async-aws/s3": "^1.5", + "async-aws/simple-s3": "^1.0", + "sabre/dav": "^4.1" + }, + "conflict": { + "guzzlehttp/ringphp": "<1.1.1" + }, "license": "MIT", "authors": [ { "name": "Frank de Jonge", - "email": "info@frenky.net" + "email": "info@frankdejonge.nl" } - ], - "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" - } + ] } diff --git a/vendor/league/flysystem/config.subsplit-publish.json b/vendor/league/flysystem/config.subsplit-publish.json new file mode 100644 index 0000000..b0de91e --- /dev/null +++ b/vendor/league/flysystem/config.subsplit-publish.json @@ -0,0 +1,49 @@ +{ + "sub-splits": [ + { + "name": "ftp", + "directory": "src/Ftp", + "target": "git@github.com:thephpleague/flysystem-ftp.git" + }, + { + "name": "sftp", + "directory": "src/PhpseclibV2", + "target": "git@github.com:thephpleague/flysystem-sftp.git" + }, + { + "name": "sftp-v3", + "directory": "src/PhpseclibV3", + "target": "git@github.com:thephpleague/flysystem-sftp-v3.git" + }, + { + "name": "memory", + "directory": "src/InMemory", + "target": "git@github.com:thephpleague/flysystem-memory.git" + }, + { + "name": "ziparchive", + "directory": "src/ZipArchive", + "target": "git@github.com:thephpleague/flysystem-ziparchive.git" + }, + { + "name": "aws-s3-v3", + "directory": "src/AwsS3V3", + "target": "git@github.com:thephpleague/flysystem-aws-s3-v3.git" + }, + { + "name": "async-aws-s3", + "directory": "src/AsyncAwsS3", + "target": "git@github.com:thephpleague/flysystem-async-aws-s3.git" + }, + { + "name": "google-cloud-storage", + "directory": "src/GoogleCloudStorage", + "target": "git@github.com:thephpleague/flysystem-google-cloud-storage.git" + }, + { + "name": "adapter-test-utilities", + "directory": "src/AdapterTestUtilities", + "target": "git@github.com:thephpleague/flysystem-adapter-test-utilities.git" + } + ] +} diff --git a/vendor/league/flysystem/docker-compose.yml b/vendor/league/flysystem/docker-compose.yml new file mode 100644 index 0000000..3ab6b77 --- /dev/null +++ b/vendor/league/flysystem/docker-compose.yml @@ -0,0 +1,58 @@ +--- +version: "3" +services: + webdav: + image: bytemark/webdav + restart: always + ports: + - "80:80" + environment: + AUTH_TYPE: Digest + USERNAME: alice + PASSWORD: secret1234 + sftp: + container_name: sftp + restart: always + image: atmoz/sftp + volumes: + - ./test_files/sftp/users.conf:/etc/sftp/users.conf + - ./test_files/sftp/ssh_host_ed25519_key:/etc/ssh/ssh_host_ed25519_key + - ./test_files/sftp/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key + - ./test_files/sftp/id_rsa.pub:/home/bar/.ssh/keys/id_rsa.pub + ports: + - "2222:22" + ftp: + container_name: ftp + restart: always + image: delfer/alpine-ftp-server + environment: + USERS: 'foo|pass|/home/foo/upload' + ADDRESS: 'localhost' + ports: + - "2121:21" + - "21000-21010:21000-21010" + ftpd: + container_name: ftpd + restart: always + environment: + PUBLICHOST: localhost + FTP_USER_NAME: foo + FTP_USER_PASS: pass + FTP_USER_HOME: /home/foo + image: stilliard/pure-ftpd + ports: + - "2122:21" + - "30000-30009:30000-30009" + command: "/run.sh -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -P localhost" + toxiproxy: + container_name: toxiproxy + restart: unless-stopped + image: ghcr.io/shopify/toxiproxy + command: "-host 0.0.0.0 -config /opt/toxiproxy/config.json" + volumes: + - ./test_files/toxiproxy/toxiproxy.json:/opt/toxiproxy/config.json:ro + ports: + - "8474:8474" # HTTP API + - "8222:8222" # SFTP + - "8121:8121" # FTP + - "8122:8122" # FTPD diff --git a/vendor/league/flysystem/readme.md b/vendor/league/flysystem/readme.md new file mode 100644 index 0000000..0c0b98e --- /dev/null +++ b/vendor/league/flysystem/readme.md @@ -0,0 +1,45 @@ +# League\Flysystem + +[![Author](https://img.shields.io/badge/author-@frankdejonge-blue.svg)](https://twitter.com/frankdejonge) +[![Source Code](https://img.shields.io/badge/source-thephpleague/flysystem-blue.svg)](https://github.com/thephpleague/flysystem) +[![Latest Version](https://img.shields.io/github/tag/thephpleague/flysystem.svg)](https://github.com/thephpleague/flysystem/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/thephpleague/flysystem/blob/master/LICENSE) +[![Quality Assurance](https://github.com/thephpleague/flysystem/workflows/Quality%20Assurance/badge.svg?branch=2.x)](https://github.com/thephpleague/flysystem/actions?query=workflow%3A%22Quality+Assurance%22) +[![Total Downloads](https://img.shields.io/packagist/dt/league/flysystem.svg)](https://packagist.org/packages/league/flysystem) +![php 7.2+](https://img.shields.io/badge/php-min%207.2-red.svg) + +## About Flysystem + +Flysystem is a file storage library for PHP. It provides one interface to +interact with many types of filesystems. When you use Flysystem, you're +not only protected from vendor lock-in, you'll also have a consistent experience +for which ever storage is right for you. + +## Getting Started + +* **[New in V2](https://flysystem.thephpleague.com/v2/docs/what-is-new/)**: What it new in Flysystem V2? +* **[Architecture](https://flysystem.thephpleague.com/v2/docs/architecture/)**: Flysystem's internal architecture +* **[Flysystem API](https://flysystem.thephpleague.com/v2/docs/usage/filesystem-api/)**: How to interact with your Flysystem instance +* **[Upgrade to V2](https://flysystem.thephpleague.com/v2/docs/advanced/upgrade-to-2.0.0/)**: How to upgrade your Flysystem V1 instance to V2 + +### Commonly-Used Adapters + +* **[AsyncAws S3](https://flysystem.thephpleague.com/v2/docs/adapter/async-aws-s3/)** +* **[AWS S3](https://flysystem.thephpleague.com/v2/docs/adapter/aws-s3-v3/)** +* **[Local](https://flysystem.thephpleague.com/v2/docs/adapter/local/)** +* **[Memory](https://flysystem.thephpleague.com/v2/docs/adapter/in-memory/)** + +### Third party Adapters + +* **[Gitlab](https://github.com/RoyVoetman/flysystem-gitlab-storage)** +* **[Google Drive (using regular paths)](https://github.com/masbug/flysystem-google-drive-ext)** + +You can always [create an adapter](https://flysystem.thephpleague.com/v2/docs/advanced/creating-an-adapter/) yourself. + +## Security + +If you discover any security related issues, please email info@frankdejonge.nl instead of using the issue tracker. + +## Enjoy + +Oh, and if you've come down this far, you might as well follow me on [twitter](https://twitter.com/frankdejonge). diff --git a/vendor/league/flysystem/src/Config.php b/vendor/league/flysystem/src/Config.php index 639f43d..77c3b5a 100644 --- a/vendor/league/flysystem/src/Config.php +++ b/vendor/league/flysystem/src/Config.php @@ -1,107 +1,43 @@ settings = $settings; + $this->options = $options; } /** - * Get a setting. + * @param mixed $default * - * @param string $key - * @param mixed $default - * - * @return mixed config setting or default when not found + * @return mixed */ - public function get($key, $default = null) + public function get(string $property, $default = null) { - if ( ! array_key_exists($key, $this->settings)) { - return $this->getDefault($key, $default); - } - - return $this->settings[$key]; + return $this->options[$property] ?? $default; } - /** - * Check if an item exists by key. - * - * @param string $key - * - * @return bool - */ - public function has($key) + public function extend(array $options): Config { - if (array_key_exists($key, $this->settings)) { - return true; - } - - return $this->fallback instanceof Config - ? $this->fallback->has($key) - : false; + return new Config(array_merge($this->options, $options)); } - /** - * 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) + public function withDefaults(array $defaults): Config { - 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; + return new Config($this->options + $defaults); } } diff --git a/vendor/league/flysystem/src/CorruptedPathDetected.php b/vendor/league/flysystem/src/CorruptedPathDetected.php index 81a27e5..70631cc 100644 --- a/vendor/league/flysystem/src/CorruptedPathDetected.php +++ b/vendor/league/flysystem/src/CorruptedPathDetected.php @@ -2,15 +2,11 @@ namespace League\Flysystem; -use LogicException; +use RuntimeException; -class CorruptedPathDetected extends LogicException implements FilesystemException +final class CorruptedPathDetected extends RuntimeException implements FilesystemException { - /** - * @param string $path - * @return CorruptedPathDetected - */ - public static function forPath($path) + public static function forPath(string $path): CorruptedPathDetected { return new CorruptedPathDetected("Corrupted path detected: " . $path); } diff --git a/vendor/league/flysystem/src/DirectoryAttributes.php b/vendor/league/flysystem/src/DirectoryAttributes.php new file mode 100644 index 0000000..94e6218 --- /dev/null +++ b/vendor/league/flysystem/src/DirectoryAttributes.php @@ -0,0 +1,110 @@ +path = $path; + $this->visibility = $visibility; + $this->lastModified = $lastModified; + $this->extraMetadata = $extraMetadata; + } + + public function path(): string + { + return $this->path; + } + + public function type(): string + { + return StorageAttributes::TYPE_DIRECTORY; + } + + public function visibility(): ?string + { + return $this->visibility; + } + + public function lastModified(): ?int + { + return $this->lastModified; + } + + public function extraMetadata(): array + { + return $this->extraMetadata; + } + + public function isFile(): bool + { + return false; + } + + public function isDir(): bool + { + return true; + } + + public function withPath(string $path): StorageAttributes + { + $clone = clone $this; + $clone->path = $path; + + return $clone; + } + + public static function fromArray(array $attributes): StorageAttributes + { + return new DirectoryAttributes( + $attributes[StorageAttributes::ATTRIBUTE_PATH], + $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? [] + ); + } + + /** + * @inheritDoc + */ + public function jsonSerialize(): array + { + return [ + StorageAttributes::ATTRIBUTE_TYPE => $this->type, + StorageAttributes::ATTRIBUTE_PATH => $this->path, + StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility, + StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified, + StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata, + ]; + } +} diff --git a/vendor/league/flysystem/src/DirectoryListing.php b/vendor/league/flysystem/src/DirectoryListing.php new file mode 100644 index 0000000..0f429a8 --- /dev/null +++ b/vendor/league/flysystem/src/DirectoryListing.php @@ -0,0 +1,84 @@ + + */ + private $listing; + + /** + * @param iterable $listing + */ + public function __construct(iterable $listing) + { + $this->listing = $listing; + } + + public function filter(callable $filter): DirectoryListing + { + $generator = (static function (iterable $listing) use ($filter): Generator { + foreach ($listing as $item) { + if ($filter($item)) { + yield $item; + } + } + })($this->listing); + + return new DirectoryListing($generator); + } + + public function map(callable $mapper): DirectoryListing + { + $generator = (static function (iterable $listing) use ($mapper): Generator { + foreach ($listing as $item) { + yield $mapper($item); + } + })($this->listing); + + return new DirectoryListing($generator); + } + + public function sortByPath(): DirectoryListing + { + $listing = $this->toArray(); + + usort($listing, function (StorageAttributes $a, StorageAttributes $b) { + return $a->path() <=> $b->path(); + }); + + return new DirectoryListing($listing); + } + + /** + * @return Traversable + */ + public function getIterator(): Traversable + { + return $this->listing instanceof Traversable + ? $this->listing + : new ArrayIterator($this->listing); + } + + /** + * @return T[] + */ + public function toArray(): array + { + return $this->listing instanceof Traversable + ? iterator_to_array($this->listing, false) + : (array) $this->listing; + } +} diff --git a/vendor/league/flysystem/src/FileAttributes.php b/vendor/league/flysystem/src/FileAttributes.php new file mode 100644 index 0000000..2efd9c4 --- /dev/null +++ b/vendor/league/flysystem/src/FileAttributes.php @@ -0,0 +1,139 @@ +path = $path; + $this->fileSize = $fileSize; + $this->visibility = $visibility; + $this->lastModified = $lastModified; + $this->mimeType = $mimeType; + $this->extraMetadata = $extraMetadata; + } + + public function type(): string + { + return $this->type; + } + + public function path(): string + { + return $this->path; + } + + public function fileSize(): ?int + { + return $this->fileSize; + } + + public function visibility(): ?string + { + return $this->visibility; + } + + public function lastModified(): ?int + { + return $this->lastModified; + } + + public function mimeType(): ?string + { + return $this->mimeType; + } + + public function extraMetadata(): array + { + return $this->extraMetadata; + } + + public function isFile(): bool + { + return true; + } + + public function isDir(): bool + { + return false; + } + + public function withPath(string $path): StorageAttributes + { + $clone = clone $this; + $clone->path = $path; + + return $clone; + } + + public static function fromArray(array $attributes): StorageAttributes + { + return new FileAttributes( + $attributes[StorageAttributes::ATTRIBUTE_PATH], + $attributes[StorageAttributes::ATTRIBUTE_FILE_SIZE] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_VISIBILITY] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_LAST_MODIFIED] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_MIME_TYPE] ?? null, + $attributes[StorageAttributes::ATTRIBUTE_EXTRA_METADATA] ?? [] + ); + } + + public function jsonSerialize(): array + { + return [ + StorageAttributes::ATTRIBUTE_TYPE => self::TYPE_FILE, + StorageAttributes::ATTRIBUTE_PATH => $this->path, + StorageAttributes::ATTRIBUTE_FILE_SIZE => $this->fileSize, + StorageAttributes::ATTRIBUTE_VISIBILITY => $this->visibility, + StorageAttributes::ATTRIBUTE_LAST_MODIFIED => $this->lastModified, + StorageAttributes::ATTRIBUTE_MIME_TYPE => $this->mimeType, + StorageAttributes::ATTRIBUTE_EXTRA_METADATA => $this->extraMetadata, + ]; + } +} diff --git a/vendor/league/flysystem/src/Filesystem.php b/vendor/league/flysystem/src/Filesystem.php index c4eaf27..f66574d 100644 --- a/vendor/league/flysystem/src/Filesystem.php +++ b/vendor/league/flysystem/src/Filesystem.php @@ -1,409 +1,163 @@ adapter = $adapter; - $this->setConfig($config); + $this->config = new Config($config); + $this->pathNormalizer = $pathNormalizer ?: new WhitespacePathNormalizer(); + } + + public function fileExists(string $location): bool + { + return $this->adapter->fileExists($this->pathNormalizer->normalizePath($location)); + } + + public function write(string $location, string $contents, array $config = []): void + { + $this->adapter->write( + $this->pathNormalizer->normalizePath($location), + $contents, + $this->config->extend($config) + ); + } + + public function writeStream(string $location, $contents, array $config = []): void + { + /* @var resource $contents */ + $this->assertIsResource($contents); + $this->rewindStream($contents); + $this->adapter->writeStream( + $this->pathNormalizer->normalizePath($location), + $contents, + $this->config->extend($config) + ); + } + + public function read(string $location): string + { + return $this->adapter->read($this->pathNormalizer->normalizePath($location)); + } + + public function readStream(string $location) + { + return $this->adapter->readStream($this->pathNormalizer->normalizePath($location)); + } + + public function delete(string $location): void + { + $this->adapter->delete($this->pathNormalizer->normalizePath($location)); + } + + public function deleteDirectory(string $location): void + { + $this->adapter->deleteDirectory($this->pathNormalizer->normalizePath($location)); + } + + public function createDirectory(string $location, array $config = []): void + { + $this->adapter->createDirectory( + $this->pathNormalizer->normalizePath($location), + $this->config->extend($config) + ); + } + + public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing + { + $path = $this->pathNormalizer->normalizePath($location); + + return new DirectoryListing($this->adapter->listContents($path, $deep)); + } + + public function move(string $source, string $destination, array $config = []): void + { + $this->adapter->move( + $this->pathNormalizer->normalizePath($source), + $this->pathNormalizer->normalizePath($destination), + $this->config->extend($config) + ); + } + + public function copy(string $source, string $destination, array $config = []): void + { + $this->adapter->copy( + $this->pathNormalizer->normalizePath($source), + $this->pathNormalizer->normalizePath($destination), + $this->config->extend($config) + ); + } + + public function lastModified(string $path): int + { + return $this->adapter->lastModified($this->pathNormalizer->normalizePath($path))->lastModified(); + } + + public function fileSize(string $path): int + { + return $this->adapter->fileSize($this->pathNormalizer->normalizePath($path))->fileSize(); + } + + public function mimeType(string $path): string + { + return $this->adapter->mimeType($this->pathNormalizer->normalizePath($path))->mimeType(); + } + + public function setVisibility(string $path, string $visibility): void + { + $this->adapter->setVisibility($this->pathNormalizer->normalizePath($path), $visibility); + } + + public function visibility(string $path): string + { + return $this->adapter->visibility($this->pathNormalizer->normalizePath($path))->visibility(); } /** - * Get the Adapter. - * - * @return AdapterInterface adapter + * @param mixed $contents */ - public function getAdapter() + private function assertIsResource($contents): void { - 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); + if (is_resource($contents) === false) { + throw new InvalidStreamProvided( + "Invalid stream provided, expected stream resource, received " . gettype($contents) + ); + } elseif ($type = get_resource_type($contents) !== 'stream') { + throw new InvalidStreamProvided( + "Invalid stream provided, expected stream resource, received resource of type " . $type + ); } } /** - * Assert a file is absent. - * - * @param string $path path to file - * - * @throws FileExistsException - * - * @return void + * @param resource $resource */ - public function assertAbsent($path) + private function rewindStream($resource): void { - if ($this->config->get('disable_asserts', false) === false && $this->has($path)) { - throw new FileExistsException($path); + if (ftell($resource) !== 0 && stream_get_meta_data($resource)['seekable']) { + rewind($resource); } } } diff --git a/vendor/league/flysystem/src/FilesystemAdapter.php b/vendor/league/flysystem/src/FilesystemAdapter.php new file mode 100644 index 0000000..6dcb51e --- /dev/null +++ b/vendor/league/flysystem/src/FilesystemAdapter.php @@ -0,0 +1,108 @@ + + * + * @throws FilesystemException + */ + public function listContents(string $path, bool $deep): iterable; + + /** + * @throws UnableToMoveFile + * @throws FilesystemException + */ + public function move(string $source, string $destination, Config $config): void; + + /** + * @throws UnableToCopyFile + * @throws FilesystemException + */ + public function copy(string $source, string $destination, Config $config): void; +} diff --git a/vendor/league/flysystem/src/FilesystemException.php b/vendor/league/flysystem/src/FilesystemException.php index 3121e53..f9d6018 100644 --- a/vendor/league/flysystem/src/FilesystemException.php +++ b/vendor/league/flysystem/src/FilesystemException.php @@ -1,7 +1,11 @@ + * + * @throws FilesystemException + */ + public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing; + + /** + * @throws UnableToRetrieveMetadata + * @throws FilesystemException + */ + public function lastModified(string $path): int; + + /** + * @throws UnableToRetrieveMetadata + * @throws FilesystemException + */ + public function fileSize(string $path): int; + + /** + * @throws UnableToRetrieveMetadata + * @throws FilesystemException + */ + public function mimeType(string $path): string; + + /** + * @throws UnableToRetrieveMetadata + * @throws FilesystemException + */ + public function visibility(string $path): string; +} diff --git a/vendor/league/flysystem/src/FilesystemWriter.php b/vendor/league/flysystem/src/FilesystemWriter.php new file mode 100644 index 0000000..a24bb0f --- /dev/null +++ b/vendor/league/flysystem/src/FilesystemWriter.php @@ -0,0 +1,58 @@ +prefixer = new PathPrefixer($location, DIRECTORY_SEPARATOR); + $this->writeFlags = $writeFlags; + $this->linkHandling = $linkHandling; + $this->visibility = $visibility ?: new PortableVisibilityConverter(); + $this->ensureDirectoryExists($location, $this->visibility->defaultForDirectories()); + $this->mimeTypeDetector = $mimeTypeDetector ?: new FinfoMimeTypeDetector(); + } + + public function write(string $path, string $contents, Config $config): void + { + $this->writeToFile($path, $contents, $config); + } + + public function writeStream(string $path, $contents, Config $config): void + { + $this->writeToFile($path, $contents, $config); + } + + /** + * @param resource|string $contents + */ + private function writeToFile(string $path, $contents, Config $config): void + { + $prefixedLocation = $this->prefixer->prefixPath($path); + $this->ensureDirectoryExists( + dirname($prefixedLocation), + $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) + ); + error_clear_last(); + + if (@file_put_contents($prefixedLocation, $contents, $this->writeFlags) === false) { + throw UnableToWriteFile::atLocation($path, error_get_last()['message'] ?? ''); + } + + if ($visibility = $config->get(Config::OPTION_VISIBILITY)) { + $this->setVisibility($path, (string) $visibility); + } + } + + public function delete(string $path): void + { + $location = $this->prefixer->prefixPath($path); + + if ( ! file_exists($location)) { + return; + } + + error_clear_last(); + + if ( ! @unlink($location)) { + throw UnableToDeleteFile::atLocation($location, error_get_last()['message'] ?? ''); + } + } + + public function deleteDirectory(string $prefix): void + { + $location = $this->prefixer->prefixPath($prefix); + + if ( ! is_dir($location)) { + return; + } + + $contents = $this->listDirectoryRecursively($location, RecursiveIteratorIterator::CHILD_FIRST); + + /** @var SplFileInfo $file */ + foreach ($contents as $file) { + if ( ! $this->deleteFileInfoObject($file)) { + throw UnableToDeleteDirectory::atLocation($prefix, "Unable to delete file at " . $file->getPathname()); + } + } + + unset($contents); + + if ( ! @rmdir($location)) { + throw UnableToDeleteDirectory::atLocation($prefix, error_get_last()['message'] ?? ''); + } + } + + private function listDirectoryRecursively( + string $path, + int $mode = RecursiveIteratorIterator::SELF_FIRST + ): Generator { + yield from new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), + $mode + ); + } + + protected function deleteFileInfoObject(SplFileInfo $file): bool + { + switch ($file->getType()) { + case 'dir': + return @rmdir((string) $file->getRealPath()); + case 'link': + return @unlink((string) $file->getPathname()); + default: + return @unlink((string) $file->getRealPath()); + } + } + + public function listContents(string $path, bool $deep): iterable + { + $location = $this->prefixer->prefixPath($path); + + if ( ! is_dir($location)) { + return; + } + + /** @var SplFileInfo[] $iterator */ + $iterator = $deep ? $this->listDirectoryRecursively($location) : $this->listDirectory($location); + + foreach ($iterator as $fileInfo) { + if ($fileInfo->isLink()) { + if ($this->linkHandling & self::SKIP_LINKS) { + continue; + } + throw SymbolicLinkEncountered::atLocation($fileInfo->getPathname()); + } + + $path = $this->prefixer->stripPrefix($fileInfo->getPathname()); + $lastModified = $fileInfo->getMTime(); + $isDirectory = $fileInfo->isDir(); + $permissions = octdec(substr(sprintf('%o', $fileInfo->getPerms()), -4)); + $visibility = $isDirectory ? $this->visibility->inverseForDirectory($permissions) : $this->visibility->inverseForFile($permissions); + + yield $isDirectory ? new DirectoryAttributes($path, $visibility, $lastModified) : new FileAttributes( + str_replace('\\', '/', $path), + $fileInfo->getSize(), + $visibility, + $lastModified + ); + } + } + + public function move(string $source, string $destination, Config $config): void + { + $sourcePath = $this->prefixer->prefixPath($source); + $destinationPath = $this->prefixer->prefixPath($destination); + $this->ensureDirectoryExists( + dirname($destinationPath), + $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) + ); + + if ( ! @rename($sourcePath, $destinationPath)) { + throw UnableToMoveFile::fromLocationTo($sourcePath, $destinationPath); + } + } + + public function copy(string $source, string $destination, Config $config): void + { + $sourcePath = $this->prefixer->prefixPath($source); + $destinationPath = $this->prefixer->prefixPath($destination); + $this->ensureDirectoryExists( + dirname($destinationPath), + $this->resolveDirectoryVisibility($config->get(Config::OPTION_DIRECTORY_VISIBILITY)) + ); + + if ( ! @copy($sourcePath, $destinationPath)) { + throw UnableToCopyFile::fromLocationTo($sourcePath, $destinationPath); + } + } + + public function read(string $path): string + { + $location = $this->prefixer->prefixPath($path); + error_clear_last(); + $contents = @file_get_contents($location); + + if ($contents === false) { + throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? ''); + } + + return $contents; + } + + public function readStream(string $path) + { + $location = $this->prefixer->prefixPath($path); + error_clear_last(); + $contents = @fopen($location, 'rb'); + + if ($contents === false) { + throw UnableToReadFile::fromLocation($path, error_get_last()['message'] ?? ''); + } + + return $contents; + } + + protected function ensureDirectoryExists(string $dirname, int $visibility): void + { + if (is_dir($dirname)) { + return; + } + + error_clear_last(); + + if ( ! @mkdir($dirname, $visibility, true)) { + $mkdirError = error_get_last(); + } + + clearstatcache(true, $dirname); + + if ( ! is_dir($dirname)) { + $errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : ''; + + throw UnableToCreateDirectory::atLocation($dirname, $errorMessage); + } + } + + public function fileExists(string $location): bool + { + $location = $this->prefixer->prefixPath($location); + + return is_file($location); + } + + public function createDirectory(string $path, Config $config): void + { + $location = $this->prefixer->prefixPath($path); + $visibility = $config->get(Config::OPTION_VISIBILITY, $config->get(Config::OPTION_DIRECTORY_VISIBILITY)); + $permissions = $this->resolveDirectoryVisibility($visibility); + + if (is_dir($location)) { + $this->setPermissions($location, $permissions); + + return; + } + + error_clear_last(); + + if ( ! @mkdir($location, $permissions, true)) { + throw UnableToCreateDirectory::atLocation($path, error_get_last()['message'] ?? ''); + } + } + + public function setVisibility(string $path, string $visibility): void + { + $path = $this->prefixer->prefixPath($path); + $visibility = is_dir($path) ? $this->visibility->forDirectory($visibility) : $this->visibility->forFile( + $visibility + ); + + $this->setPermissions($path, $visibility); + } + + public function visibility(string $path): FileAttributes + { + $location = $this->prefixer->prefixPath($path); + clearstatcache(false, $location); + error_clear_last(); + $fileperms = @fileperms($location); + + if ($fileperms === false) { + throw UnableToRetrieveMetadata::visibility($path, error_get_last()['message'] ?? ''); + } + + $permissions = $fileperms & 0777; + $visibility = $this->visibility->inverseForFile($permissions); + + return new FileAttributes($path, null, $visibility); + } + + private function resolveDirectoryVisibility(?string $visibility): int + { + return $visibility === null ? $this->visibility->defaultForDirectories() : $this->visibility->forDirectory( + $visibility + ); + } + + public function mimeType(string $path): FileAttributes + { + $location = $this->prefixer->prefixPath($path); + error_clear_last(); + $mimeType = $this->mimeTypeDetector->detectMimeTypeFromFile($location); + + if ($mimeType === null) { + throw UnableToRetrieveMetadata::mimeType($path, error_get_last()['message'] ?? ''); + } + + return new FileAttributes($path, null, null, null, $mimeType); + } + + public function lastModified(string $path): FileAttributes + { + $location = $this->prefixer->prefixPath($path); + error_clear_last(); + $lastModified = @filemtime($location); + + if ($lastModified === false) { + throw UnableToRetrieveMetadata::lastModified($path, error_get_last()['message'] ?? ''); + } + + return new FileAttributes($path, null, null, $lastModified); + } + + public function fileSize(string $path): FileAttributes + { + $location = $this->prefixer->prefixPath($path); + error_clear_last(); + + if (is_file($location) && ($fileSize = @filesize($location)) !== false) { + return new FileAttributes($path, $fileSize); + } + + throw UnableToRetrieveMetadata::fileSize($path, error_get_last()['message'] ?? ''); + } + + private function listDirectory(string $location): Generator + { + $iterator = new DirectoryIterator($location); + + foreach ($iterator as $item) { + if ($item->isDot()) { + continue; + } + + yield $item; + } + } + + private function setPermissions(string $location, int $visibility): void + { + error_clear_last(); + if ( ! @chmod($location, $visibility)) { + $extraMessage = error_get_last()['message'] ?? ''; + throw UnableToSetVisibility::atLocation($this->prefixer->stripPrefix($location), $extraMessage); + } + } +} diff --git a/vendor/league/flysystem/src/MountManager.php b/vendor/league/flysystem/src/MountManager.php index 620f540..b5a7773 100644 --- a/vendor/league/flysystem/src/MountManager.php +++ b/vendor/league/flysystem/src/MountManager.php @@ -1,648 +1,334 @@ */ - protected $filesystems = []; + private $filesystems = []; /** - * Constructor. + * MountManager constructor. * - * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,] - * - * @throws InvalidArgumentException + * @param array $filesystems */ public function __construct(array $filesystems = []) { $this->mountFilesystems($filesystems); } - /** - * Mount filesystems. - * - * @param FilesystemInterface[] $filesystems [:prefix => Filesystem,] - * - * @throws InvalidArgumentException - * - * @return $this - */ - public function mountFilesystems(array $filesystems) + public function fileExists(string $location): bool { - 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); + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); try { - return $this->invokePlugin($method, $arguments, $filesystem); - } catch (PluginNotFoundException $e) { - // Let it pass, it's ok, don't panic. + return $filesystem->fileExists($path); + } catch (UnableToCheckFileExistence $exception) { + throw UnableToCheckFileExistence::forLocation($location, $exception); + } + } + + public function read(string $location): string + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->read($path); + } catch (UnableToReadFile $exception) { + throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception); + } + } + + public function readStream(string $location) + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->readStream($path); + } catch (UnableToReadFile $exception) { + throw UnableToReadFile::fromLocation($location, $exception->reason(), $exception); + } + } + + public function listContents(string $location, bool $deep = self::LIST_SHALLOW): DirectoryListing + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path, $mountIdentifier] = $this->determineFilesystemAndPath($location); + + return + $filesystem + ->listContents($path, $deep) + ->map( + function (StorageAttributes $attributes) use ($mountIdentifier) { + return $attributes->withPath(sprintf('%s://%s', $mountIdentifier, $attributes->path())); + } + ); + } + + public function lastModified(string $location): int + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->lastModified($path); + } catch (UnableToRetrieveMetadata $exception) { + throw UnableToRetrieveMetadata::lastModified($location, $exception->reason(), $exception); + } + } + + public function fileSize(string $location): int + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->fileSize($path); + } catch (UnableToRetrieveMetadata $exception) { + throw UnableToRetrieveMetadata::fileSize($location, $exception->reason(), $exception); + } + } + + public function mimeType(string $location): string + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->mimeType($path); + } catch (UnableToRetrieveMetadata $exception) { + throw UnableToRetrieveMetadata::mimeType($location, $exception->reason(), $exception); + } + } + + public function visibility(string $location): string + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + return $filesystem->visibility($path); + } catch (UnableToRetrieveMetadata $exception) { + throw UnableToRetrieveMetadata::visibility($location, $exception->reason(), $exception); + } + } + + public function write(string $location, string $contents, array $config = []): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + $filesystem->write($path, $contents, $config); + } catch (UnableToWriteFile $exception) { + throw UnableToWriteFile::atLocation($location, $exception->reason(), $exception); + } + } + + public function writeStream(string $location, $contents, array $config = []): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + $filesystem->writeStream($path, $contents, $config); + } + + public function setVisibility(string $path, string $visibility): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($path); + $filesystem->setVisibility($path, $visibility); + } + + public function delete(string $location): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + $filesystem->delete($path); + } catch (UnableToDeleteFile $exception) { + throw UnableToDeleteFile::atLocation($location, '', $exception); + } + } + + public function deleteDirectory(string $location): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + $filesystem->deleteDirectory($path); + } catch (UnableToDeleteDirectory $exception) { + throw UnableToDeleteDirectory::atLocation($location, '', $exception); + } + } + + public function createDirectory(string $location, array $config = []): void + { + /** @var FilesystemOperator $filesystem */ + [$filesystem, $path] = $this->determineFilesystemAndPath($location); + + try { + $filesystem->createDirectory($path, $config); + } catch (UnableToCreateDirectory $exception) { + throw UnableToCreateDirectory::dueToFailure($location, $exception); + } + } + + public function move(string $source, string $destination, array $config = []): void + { + /** @var FilesystemOperator $sourceFilesystem */ + /* @var FilesystemOperator $destinationFilesystem */ + [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source); + [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination); + + $sourceFilesystem === $destinationFilesystem ? $this->moveInTheSameFilesystem( + $sourceFilesystem, + $sourcePath, + $destinationPath, + $source, + $destination + ) : $this->moveAcrossFilesystems($source, $destination); + } + + public function copy(string $source, string $destination, array $config = []): void + { + /** @var FilesystemOperator $sourceFilesystem */ + /* @var FilesystemOperator $destinationFilesystem */ + [$sourceFilesystem, $sourcePath] = $this->determineFilesystemAndPath($source); + [$destinationFilesystem, $destinationPath] = $this->determineFilesystemAndPath($destination); + + $sourceFilesystem === $destinationFilesystem ? $this->copyInSameFilesystem( + $sourceFilesystem, + $sourcePath, + $destinationPath, + $source, + $destination + ) : $this->copyAcrossFilesystem( + $config['visibility'] ?? null, + $sourceFilesystem, + $sourcePath, + $destinationFilesystem, + $destinationPath, + $source, + $destination + ); + } + + private function mountFilesystems(array $filesystems): void + { + foreach ($filesystems as $key => $filesystem) { + $this->guardAgainstInvalidMount($key, $filesystem); + /* @var string $key */ + /* @var FilesystemOperator $filesystem */ + $this->mountFilesystem($key, $filesystem); + } + } + + /** + * @param mixed $key + * @param mixed $filesystem + */ + private function guardAgainstInvalidMount($key, $filesystem): void + { + if ( ! is_string($key)) { + throw UnableToMountFilesystem::becauseTheKeyIsNotValid($key); } - $callback = [$filesystem, $method]; + if ( ! $filesystem instanceof FilesystemOperator) { + throw UnableToMountFilesystem::becauseTheFilesystemWasNotValid($filesystem); + } + } - return call_user_func_array($callback, $arguments); + private function mountFilesystem(string $key, FilesystemOperator $filesystem): void + { + $this->filesystems[$key] = $filesystem; } /** * @param string $path * - * @throws InvalidArgumentException - * - * @return string[] [:prefix, :path] + * @return array{0:FilesystemOperator, 1:string} */ - protected function getPrefixAndPath($path) + private function determineFilesystemAndPath(string $path): array { if (strpos($path, '://') < 1) { - throw new InvalidArgumentException('No prefix detected in path: ' . $path); + throw UnableToResolveFilesystemMount::becauseTheSeparatorIsMissing($path); } - return explode('://', $path, 2); + /** @var string $mountIdentifier */ + /** @var string $mountPath */ + [$mountIdentifier, $mountPath] = explode('://', $path, 2); + + if ( ! array_key_exists($mountIdentifier, $this->filesystems)) { + throw UnableToResolveFilesystemMount::becauseTheMountWasNotRegistered($mountIdentifier); + } + + return [$this->filesystems[$mountIdentifier], $mountPath, $mountIdentifier]; } - /** - * 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); + private function copyInSameFilesystem( + FilesystemOperator $sourceFilesystem, + string $sourcePath, + string $destinationPath, + string $source, + string $destination + ): void { + try { + $sourceFilesystem->copy($sourcePath, $destinationPath); + } catch (UnableToCopyFile $exception) { + throw UnableToCopyFile::fromLocationTo($source, $destination, $exception); + } } - /** - * 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); + private function copyAcrossFilesystem( + ?string $visibility, + FilesystemOperator $sourceFilesystem, + string $sourcePath, + FilesystemOperator $destinationFilesystem, + string $destinationPath, + string $source, + string $destination + ): void { + try { + $visibility = $visibility ?? $sourceFilesystem->visibility($sourcePath); + $stream = $sourceFilesystem->readStream($sourcePath); + $destinationFilesystem->writeStream($destinationPath, $stream, compact('visibility')); + } catch (UnableToRetrieveMetadata | UnableToReadFile | UnableToWriteFile $exception) { + throw UnableToCopyFile::fromLocationTo($source, $destination, $exception); + } } - /** - * 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); + private function moveInTheSameFilesystem( + FilesystemOperator $sourceFilesystem, + string $sourcePath, + string $destinationPath, + string $source, + string $destination + ): void { + try { + $sourceFilesystem->move($sourcePath, $destinationPath); + } catch (UnableToMoveFile $exception) { + throw UnableToMoveFile::fromLocationTo($source, $destination, $exception); + } } - /** - * 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) + private function moveAcrossFilesystems(string $source, string $destination): void { - 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); + try { + $this->copy($source, $destination); + $this->delete($source); + } catch (UnableToCopyFile | UnableToDeleteFile $exception) { + throw UnableToMoveFile::fromLocationTo($source, $destination, $exception); + } } } diff --git a/vendor/league/flysystem/src/PathNormalizer.php b/vendor/league/flysystem/src/PathNormalizer.php new file mode 100644 index 0000000..54da201 --- /dev/null +++ b/vendor/league/flysystem/src/PathNormalizer.php @@ -0,0 +1,10 @@ +prefix = rtrim($prefix, '\\/'); + + if ($this->prefix !== '' || $prefix === $separator) { + $this->prefix .= $separator; + } + + $this->separator = $separator; + } + + public function prefixPath(string $path): string + { + return $this->prefix . ltrim($path, '\\/'); + } + + public function stripPrefix(string $path): string + { + /* @var string */ + return substr($path, strlen($this->prefix)); + } + + public function stripDirectoryPrefix(string $path): string + { + return rtrim($this->stripPrefix($path), '\\/'); + } + + public function prefixDirectoryPath(string $path): string + { + $prefixedPath = $this->prefixPath(rtrim($path, '\\/')); + + if ((substr($prefixedPath, -1) === $this->separator) || $prefixedPath === '') { + return $prefixedPath; + } + + return $prefixedPath . $this->separator; + } +} diff --git a/vendor/league/flysystem/src/PathTraversalDetected.php b/vendor/league/flysystem/src/PathTraversalDetected.php new file mode 100644 index 0000000..d149997 --- /dev/null +++ b/vendor/league/flysystem/src/PathTraversalDetected.php @@ -0,0 +1,28 @@ +path; + } + + public static function forPath(string $path): PathTraversalDetected + { + $e = new PathTraversalDetected("Path traversal detected: {$path}"); + $e->path = $path; + + return $e; + } +} diff --git a/vendor/league/flysystem/src/PortableVisibilityGuard.php b/vendor/league/flysystem/src/PortableVisibilityGuard.php new file mode 100644 index 0000000..6e2498b --- /dev/null +++ b/vendor/league/flysystem/src/PortableVisibilityGuard.php @@ -0,0 +1,19 @@ +formatPropertyName((string) $offset); + + return isset($this->{$property}); + } + + /** + * @param mixed $offset + * + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + $property = $this->formatPropertyName((string) $offset); + + return $this->{$property}; + } + + /** + * @param mixed $offset + * @param mixed $value + */ + #[\ReturnTypeWillChange] + public function offsetSet($offset, $value): void + { + throw new RuntimeException('Properties can not be manipulated'); + } + + /** + * @param mixed $offset + */ + #[\ReturnTypeWillChange] + public function offsetUnset($offset): void + { + throw new RuntimeException('Properties can not be manipulated'); + } +} diff --git a/vendor/league/flysystem/src/StorageAttributes.php b/vendor/league/flysystem/src/StorageAttributes.php new file mode 100644 index 0000000..6be6235 --- /dev/null +++ b/vendor/league/flysystem/src/StorageAttributes.php @@ -0,0 +1,40 @@ +location; + } + + public static function atLocation(string $pathName): SymbolicLinkEncountered + { + $e = new static("Unsupported symbolic link encountered at location $pathName"); + $e->location = $pathName; + + return $e; + } +} diff --git a/vendor/league/flysystem/src/UnableToCheckFileExistence.php b/vendor/league/flysystem/src/UnableToCheckFileExistence.php new file mode 100644 index 0000000..d78e4ee --- /dev/null +++ b/vendor/league/flysystem/src/UnableToCheckFileExistence.php @@ -0,0 +1,21 @@ +source; + } + + public function destination(): string + { + return $this->destination; + } + + public static function fromLocationTo( + string $sourcePath, + string $destinationPath, + Throwable $previous = null + ): UnableToCopyFile { + $e = new static("Unable to copy file from $sourcePath to $destinationPath", 0 , $previous); + $e->source = $sourcePath; + $e->destination = $destinationPath; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_COPY; + } +} diff --git a/vendor/league/flysystem/src/UnableToCreateDirectory.php b/vendor/league/flysystem/src/UnableToCreateDirectory.php new file mode 100644 index 0000000..8298f9f --- /dev/null +++ b/vendor/league/flysystem/src/UnableToCreateDirectory.php @@ -0,0 +1,44 @@ +location = $dirname; + + return $e; + } + + public static function dueToFailure(string $dirname, Throwable $previous): UnableToCreateDirectory + { + $message = "Unable to create a directory at {$dirname}"; + $e = new static($message, 0, $previous); + $e->location = $dirname; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_CREATE_DIRECTORY; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnableToDeleteDirectory.php b/vendor/league/flysystem/src/UnableToDeleteDirectory.php new file mode 100644 index 0000000..eeeab24 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToDeleteDirectory.php @@ -0,0 +1,48 @@ +location = $location; + $e->reason = $reason; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_DELETE_DIRECTORY; + } + + public function reason(): string + { + return $this->reason; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnableToDeleteFile.php b/vendor/league/flysystem/src/UnableToDeleteFile.php new file mode 100644 index 0000000..18f7215 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToDeleteFile.php @@ -0,0 +1,45 @@ +location = $location; + $e->reason = $reason; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_DELETE; + } + + public function reason(): string + { + return $this->reason; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnableToMountFilesystem.php b/vendor/league/flysystem/src/UnableToMountFilesystem.php new file mode 100644 index 0000000..bd41bc9 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToMountFilesystem.php @@ -0,0 +1,32 @@ +source; + } + + public function destination(): string + { + return $this->destination; + } + + public static function fromLocationTo( + string $sourcePath, + string $destinationPath, + Throwable $previous = null + ): UnableToMoveFile { + $e = new static("Unable to move file from $sourcePath to $destinationPath", 0, $previous); + $e->source = $sourcePath; + $e->destination = $destinationPath; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_MOVE; + } +} diff --git a/vendor/league/flysystem/src/UnableToReadFile.php b/vendor/league/flysystem/src/UnableToReadFile.php new file mode 100644 index 0000000..766b563 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToReadFile.php @@ -0,0 +1,45 @@ +location = $location; + $e->reason = $reason; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_READ; + } + + public function reason(): string + { + return $this->reason; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php b/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php new file mode 100644 index 0000000..91a9ee3 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToResolveFilesystemMount.php @@ -0,0 +1,20 @@ +reason = $reason; + $e->location = $location; + $e->metadataType = $type; + + return $e; + } + + public function reason(): string + { + return $this->reason; + } + + public function location(): string + { + return $this->location; + } + + public function metadataType(): string + { + return $this->metadataType; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_RETRIEVE_METADATA; + } +} diff --git a/vendor/league/flysystem/src/UnableToSetVisibility.php b/vendor/league/flysystem/src/UnableToSetVisibility.php new file mode 100644 index 0000000..5862d0e --- /dev/null +++ b/vendor/league/flysystem/src/UnableToSetVisibility.php @@ -0,0 +1,49 @@ +reason; + } + + public static function atLocation(string $filename, string $extraMessage = '', Throwable $previous = null): self + { + $message = "Unable to set visibility for file {$filename}. $extraMessage"; + $e = new static(rtrim($message), 0, $previous); + $e->reason = $extraMessage; + $e->location = $filename; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_SET_VISIBILITY; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnableToWriteFile.php b/vendor/league/flysystem/src/UnableToWriteFile.php new file mode 100644 index 0000000..5de7866 --- /dev/null +++ b/vendor/league/flysystem/src/UnableToWriteFile.php @@ -0,0 +1,45 @@ +location = $location; + $e->reason = $reason; + + return $e; + } + + public function operation(): string + { + return FilesystemOperationFailed::OPERATION_WRITE; + } + + public function reason(): string + { + return $this->reason; + } + + public function location(): string + { + return $this->location; + } +} diff --git a/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php b/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php new file mode 100644 index 0000000..5cc1eb2 --- /dev/null +++ b/vendor/league/flysystem/src/UnixVisibility/PortableVisibilityConverter.php @@ -0,0 +1,109 @@ +filePublic = $filePublic; + $this->filePrivate = $filePrivate; + $this->directoryPublic = $directoryPublic; + $this->directoryPrivate = $directoryPrivate; + $this->defaultForDirectories = $defaultForDirectories; + } + + public function forFile(string $visibility): int + { + PortableVisibilityGuard::guardAgainstInvalidInput($visibility); + + return $visibility === Visibility::PUBLIC + ? $this->filePublic + : $this->filePrivate; + } + + public function forDirectory(string $visibility): int + { + PortableVisibilityGuard::guardAgainstInvalidInput($visibility); + + return $visibility === Visibility::PUBLIC + ? $this->directoryPublic + : $this->directoryPrivate; + } + + public function inverseForFile(int $visibility): string + { + if ($visibility === $this->filePublic) { + return Visibility::PUBLIC; + } elseif ($visibility === $this->filePrivate) { + return Visibility::PRIVATE; + } + + return Visibility::PUBLIC; // default + } + + public function inverseForDirectory(int $visibility): string + { + if ($visibility === $this->directoryPublic) { + return Visibility::PUBLIC; + } elseif ($visibility === $this->directoryPrivate) { + return Visibility::PRIVATE; + } + + return Visibility::PUBLIC; // default + } + + public function defaultForDirectories(): int + { + return $this->defaultForDirectories === Visibility::PUBLIC ? $this->directoryPublic : $this->directoryPrivate; + } + + /** + * @param array $permissionMap + */ + public static function fromArray(array $permissionMap, string $defaultForDirectories = Visibility::PRIVATE): PortableVisibilityConverter + { + return new PortableVisibilityConverter( + $permissionMap['file']['public'] ?? 0644, + $permissionMap['file']['private'] ?? 0600, + $permissionMap['dir']['public'] ?? 0755, + $permissionMap['dir']['private'] ?? 0700, + $defaultForDirectories + ); + } +} diff --git a/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php b/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php new file mode 100644 index 0000000..64af86a --- /dev/null +++ b/vendor/league/flysystem/src/UnixVisibility/VisibilityConverter.php @@ -0,0 +1,14 @@ +location; + } + + public static function atLocation(string $location): UnreadableFileEncountered + { + $e = new static("Unreadable file encountered at location {$location}."); + $e->location = $location; + + return $e; + } +} diff --git a/vendor/league/flysystem/src/Visibility.php b/vendor/league/flysystem/src/Visibility.php new file mode 100644 index 0000000..071ca00 --- /dev/null +++ b/vendor/league/flysystem/src/Visibility.php @@ -0,0 +1,11 @@ +rejectFunkyWhiteSpace($path); + + return $this->normalizeRelativePath($path); + } + + private function rejectFunkyWhiteSpace(string $path): void + { + if (preg_match('#\p{C}+#u', $path)) { + throw CorruptedPathDetected::forPath($path); + } + } + + private function normalizeRelativePath(string $path): string + { + $parts = []; + + foreach (explode('/', $path) as $part) { + switch ($part) { + case '': + case '.': + break; + + case '..': + if (empty($parts)) { + throw PathTraversalDetected::forPath($path); + } + array_pop($parts); + break; + + default: + $parts[] = $part; + break; + } + } + + return implode('/', $parts); + } +} diff --git a/vendor/services.php b/vendor/services.php index da324c2..998fcb3 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'taoser\\addons\\Service', diff --git a/vendor/topthink/think-filesystem/.gitignore b/vendor/topthink/think-filesystem/.gitignore new file mode 100644 index 0000000..25ad74d --- /dev/null +++ b/vendor/topthink/think-filesystem/.gitignore @@ -0,0 +1,3 @@ +composer.lock +/.idea +/vendor diff --git a/vendor/topthink/think-filesystem/README.md b/vendor/topthink/think-filesystem/README.md new file mode 100644 index 0000000..90977dd --- /dev/null +++ b/vendor/topthink/think-filesystem/README.md @@ -0,0 +1,5 @@ +# think-filesystem for ThinkPHP6.1 + +## 安装 + +> composer require topthink/think-filesystem diff --git a/vendor/topthink/think-filesystem/composer.json b/vendor/topthink/think-filesystem/composer.json new file mode 100644 index 0000000..d8a99be --- /dev/null +++ b/vendor/topthink/think-filesystem/composer.json @@ -0,0 +1,33 @@ +{ + "name": "topthink/think-filesystem", + "description": "The ThinkPHP6.1 Filesystem Package", + "type": "library", + "license": "Apache-2.0", + "authors": [ + { + "name": "yunwuxin", + "email": "448901948@qq.com" + } + ], + "autoload": { + "psr-4": { + "think\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "think\\tests\\": "tests/" + } + }, + "require": { + "topthink/framework": "^6.1", + "league/flysystem": "^2.0" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6", + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^8.0" + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/vendor/topthink/think-filesystem/phpunit.xml.dist b/vendor/topthink/think-filesystem/phpunit.xml.dist new file mode 100644 index 0000000..e20a133 --- /dev/null +++ b/vendor/topthink/think-filesystem/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests + + + + + ./src/think + + + diff --git a/vendor/topthink/think-filesystem/src/Filesystem.php b/vendor/topthink/think-filesystem/src/Filesystem.php new file mode 100644 index 0000000..0aee929 --- /dev/null +++ b/vendor/topthink/think-filesystem/src/Filesystem.php @@ -0,0 +1,89 @@ + +// +---------------------------------------------------------------------- +declare (strict_types = 1); + +namespace think; + +use InvalidArgumentException; +use think\filesystem\Driver; +use think\filesystem\driver\Local; +use think\helper\Arr; + +/** + * Class Filesystem + * @package think + * @mixin Driver + * @mixin Local + */ +class Filesystem extends Manager +{ + protected $namespace = '\\think\\filesystem\\driver\\'; + + /** + * @param null|string $name + * @return Driver + */ + public function disk(string $name = null): Driver + { + return $this->driver($name); + } + + protected function resolveType(string $name) + { + return $this->getDiskConfig($name, 'type', 'local'); + } + + protected function resolveConfig(string $name) + { + return $this->getDiskConfig($name); + } + + /** + * 获取缓存配置 + * @access public + * @param null|string $name 名称 + * @param mixed $default 默认值 + * @return mixed + */ + public function getConfig(string $name = null, $default = null) + { + if (!is_null($name)) { + return $this->app->config->get('filesystem.' . $name, $default); + } + + return $this->app->config->get('filesystem'); + } + + /** + * 获取磁盘配置 + * @param string $disk + * @param null $name + * @param null $default + * @return array + */ + public function getDiskConfig($disk, $name = null, $default = null) + { + if ($config = $this->getConfig("disks.{$disk}")) { + return Arr::get($config, $name, $default); + } + + throw new InvalidArgumentException("Disk [$disk] not found."); + } + + /** + * 默认驱动 + * @return string|null + */ + public function getDefaultDriver() + { + return $this->getConfig('default'); + } +} diff --git a/vendor/topthink/think-filesystem/src/facade/Filesystem.php b/vendor/topthink/think-filesystem/src/facade/Filesystem.php new file mode 100644 index 0000000..0e32c2c --- /dev/null +++ b/vendor/topthink/think-filesystem/src/facade/Filesystem.php @@ -0,0 +1,33 @@ + +// +---------------------------------------------------------------------- +declare (strict_types = 1); + +namespace think\facade; + +use think\Facade; +use think\filesystem\Driver; + +/** + * Class Filesystem + * @package think\facade + * @mixin \think\Filesystem + * @method static Driver disk(string $name = null) , null|string + * @method static mixed getConfig(null|string $name = null, mixed $default = null) 获取缓存配置 + * @method static array getDiskConfig(string $disk, null $name = null, null $default = null) 获取磁盘配置 + * @method static string|null getDefaultDriver() 默认驱动 + */ +class Filesystem extends Facade +{ + protected static function getFacadeClass() + { + return \think\Filesystem::class; + } +} diff --git a/vendor/topthink/think-filesystem/src/filesystem/Driver.php b/vendor/topthink/think-filesystem/src/filesystem/Driver.php new file mode 100644 index 0000000..dfa19bd --- /dev/null +++ b/vendor/topthink/think-filesystem/src/filesystem/Driver.php @@ -0,0 +1,130 @@ + +// +---------------------------------------------------------------------- +declare (strict_types = 1); + +namespace think\filesystem; + +use League\Flysystem\Filesystem; +use League\Flysystem\FilesystemAdapter; +use League\Flysystem\UnableToSetVisibility; +use League\Flysystem\UnableToWriteFile; +use RuntimeException; +use think\Cache; +use think\File; + +/** + * Class Driver + * @package think\filesystem + * @mixin Filesystem + */ +abstract class Driver +{ + + /** @var Cache */ + protected $cache; + + /** @var Filesystem */ + protected $filesystem; + + /** + * 配置参数 + * @var array + */ + protected $config = []; + + public function __construct(Cache $cache, array $config) + { + $this->cache = $cache; + $this->config = array_merge($this->config, $config); + + $adapter = $this->createAdapter(); + $this->filesystem = $this->createFilesystem($adapter); + } + + abstract protected function createAdapter(): FilesystemAdapter; + + protected function createFilesystem(FilesystemAdapter $adapter): Filesystem + { + $config = array_intersect_key($this->config, array_flip(['visibility', 'disable_asserts', 'url'])); + + return new Filesystem($adapter, count($config) > 0 ? $config : null); + } + + /** + * 获取文件完整路径 + * @param string $path + * @return string + */ + public function path(string $path): string + { + return $path; + } + + protected function concatPathToUrl($url, $path) + { + return rtrim($url, '/') . '/' . ltrim($path, '/'); + } + + public function url(string $path): string + { + throw new RuntimeException('This driver does not support retrieving URLs.'); + } + + /** + * 保存文件 + * @param string $path 路径 + * @param File $file 文件 + * @param null|string|\Closure $rule 文件名规则 + * @param array $options 参数 + * @return bool|string + */ + public function putFile(string $path, File $file, $rule = null, array $options = []) + { + return $this->putFileAs($path, $file, $file->hashName($rule), $options); + } + + /** + * 指定文件名保存文件 + * @param string $path 路径 + * @param File $file 文件 + * @param string $name 文件名 + * @param array $options 参数 + * @return bool|string + */ + public function putFileAs(string $path, File $file, string $name, array $options = []) + { + $stream = fopen($file->getRealPath(), 'r'); + $path = trim($path . '/' . $name, '/'); + + $result = $this->put($path, $stream, $options); + + if (is_resource($stream)) { + fclose($stream); + } + + return $result ? $path : false; + } + + protected function put(string $path, $contents, array $options = []) + { + try { + $this->writeStream($path, $contents, $options); + } catch (UnableToWriteFile|UnableToSetVisibility $e) { + return false; + } + return true; + } + + public function __call($method, $parameters) + { + return $this->filesystem->$method(...$parameters); + } +} diff --git a/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php new file mode 100644 index 0000000..3b1b64d --- /dev/null +++ b/vendor/topthink/think-filesystem/src/filesystem/driver/Local.php @@ -0,0 +1,98 @@ + +// +---------------------------------------------------------------------- +declare (strict_types = 1); + +namespace think\filesystem\driver; + +use League\Flysystem\FilesystemAdapter; +use League\Flysystem\Local\LocalFilesystemAdapter; +use League\Flysystem\PathNormalizer; +use League\Flysystem\PathPrefixer; +use League\Flysystem\UnixVisibility\PortableVisibilityConverter; +use League\Flysystem\Visibility; +use League\Flysystem\WhitespacePathNormalizer; +use think\filesystem\Driver; + +class Local extends Driver +{ + /** + * 配置参数 + * @var array + */ + protected $config = [ + 'root' => '', + ]; + + /** + * @var PathPrefixer + */ + protected $prefixer; + + /** + * @var PathNormalizer + */ + protected $normalizer; + + protected function createAdapter(): FilesystemAdapter + { + $visibility = PortableVisibilityConverter::fromArray( + $this->config['permissions'] ?? [], + $this->config['visibility'] ?? Visibility::PRIVATE + ); + + $links = ($this->config['links'] ?? null) === 'skip' + ? LocalFilesystemAdapter::SKIP_LINKS + : LocalFilesystemAdapter::DISALLOW_LINKS; + + return new LocalFilesystemAdapter( + $this->config['root'], + $visibility, + $this->config['lock'] ?? LOCK_EX, + $links + ); + } + + protected function prefixer() + { + if (!$this->prefixer) { + $this->prefixer = new PathPrefixer($this->config['root'], DIRECTORY_SEPARATOR); + } + return $this->prefixer; + } + + protected function normalizer() + { + if (!$this->normalizer) { + $this->normalizer = new WhitespacePathNormalizer(); + } + return $this->normalizer; + } + + /** + * 获取文件访问地址 + * @param string $path 文件路径 + * @return string + */ + public function url(string $path): string + { + $path = $this->normalizer()->normalizePath($path); + + if (isset($this->config['url'])) { + return $this->concatPathToUrl($this->config['url'], $path); + } + return parent::url($path); + } + + public function path(string $path): string + { + return $this->prefixer()->prefixPath($path); + } +} diff --git a/vendor/topthink/think-filesystem/tests/FilesystemTest.php b/vendor/topthink/think-filesystem/tests/FilesystemTest.php new file mode 100644 index 0000000..cc9d94e --- /dev/null +++ b/vendor/topthink/think-filesystem/tests/FilesystemTest.php @@ -0,0 +1,66 @@ +app = m::mock(App::class)->makePartial(); + Container::setInstance($this->app); + $this->app->shouldReceive('make')->with(App::class)->andReturn($this->app); + $this->config = m::mock(Config::class); + $this->config->shouldReceive('get')->with('filesystem.default', null)->andReturn('local'); + $this->app->shouldReceive('get')->with('config')->andReturn($this->config); + $this->filesystem = new Filesystem($this->app); + + $this->root = vfsStream::setup('rootDir'); + } + + protected function tearDown(): void + { + m::close(); + } + + public function testDisk() + { + $this->config->shouldReceive('get')->with('filesystem.disks.local', null)->andReturn([ + 'type' => 'local', + 'root' => $this->root->url(), + ]); + + $this->config->shouldReceive('get')->with('filesystem.disks.foo', null)->andReturn([ + 'type' => 'local', + 'root' => $this->root->url(), + ]); + + $this->assertInstanceOf(Local::class, $this->filesystem->disk()); + + $this->assertInstanceOf(Local::class, $this->filesystem->disk('foo')); + } + +} + diff --git a/vendor/topthink/think-filesystem/tests/bootstrap.php b/vendor/topthink/think-filesystem/tests/bootstrap.php new file mode 100644 index 0000000..a4abe2d --- /dev/null +++ b/vendor/topthink/think-filesystem/tests/bootstrap.php @@ -0,0 +1,2 @@ +