升级核心框架
This commit is contained in:
parent
cd50418e62
commit
83ca563d1c
@ -107,7 +107,8 @@ class Article extends Model
|
||||
'user' => function ($query) {
|
||||
$query->field('id,name,nickname,user_img,area_id,vip');
|
||||
}
|
||||
])->withCount(['comments'])->order('create_time', 'desc')->limit($num)->select();
|
||||
])->withCount(['comments'])->order('create_time', 'desc')->limit($num)->select()->toArray();
|
||||
|
||||
Cache::tag('tagArtDetail')->set('arttop', $artTop, 60);
|
||||
}
|
||||
return $artTop;
|
||||
@ -133,7 +134,7 @@ class Article extends Model
|
||||
'user' => function($query){
|
||||
$query->field('id,name,nickname,user_img,area_id,vip');
|
||||
} ])
|
||||
->withCount(['comments'])->where(['status'=>1,'is_top'=>0])->order('create_time','desc')->limit($num)->select();
|
||||
->withCount(['comments'])->where(['status'=>1,'is_top'=>0])->order('create_time','desc')->limit($num)->select()->toArray();
|
||||
Cache::tag('tagArt')->set('artlist',$artList,60);
|
||||
}
|
||||
return $artList;
|
||||
@ -167,7 +168,7 @@ class Article extends Model
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getArtDetail(int $id)
|
||||
public function getArtDetail(int $id, int $page)
|
||||
{
|
||||
$article = Cache::get('article_'.$id);
|
||||
if(!$article){
|
||||
@ -179,8 +180,8 @@ class Article extends Model
|
||||
'user' => function($query){
|
||||
$query->field('id,name,nickname,user_img,area_id,vip');
|
||||
}
|
||||
])->find($id);
|
||||
Cache::tag('tagArtDetail')->set('article_'.$id,$article,3600);
|
||||
])->withCount(['comments'])->find($id)->toArray();
|
||||
Cache::tag('tagArtDetail')->set('article_'.$id, $article, 3600);
|
||||
}
|
||||
return $article;
|
||||
}
|
||||
@ -225,7 +226,7 @@ class Article extends Model
|
||||
'list_rows' => 15,
|
||||
'page' => $page,
|
||||
'path' =>$url.'[PAGE]'.$suffix
|
||||
]);
|
||||
])->toArray();
|
||||
break;
|
||||
|
||||
case 'hot':
|
||||
@ -241,7 +242,7 @@ class Article extends Model
|
||||
'list_rows' => 15,
|
||||
'page' => $page,
|
||||
'path' =>$url.'[PAGE]'.$suffix
|
||||
]);
|
||||
])->toArray();
|
||||
break;
|
||||
|
||||
case 'top':
|
||||
@ -257,7 +258,7 @@ class Article extends Model
|
||||
'list_rows' => 15,
|
||||
'page' => $page,
|
||||
'path' =>$url.'[PAGE]'.$suffix
|
||||
]);
|
||||
])->toArray();
|
||||
break;
|
||||
|
||||
case 'wait':
|
||||
@ -273,7 +274,7 @@ class Article extends Model
|
||||
'list_rows' => 15,
|
||||
'page' => $page,
|
||||
'path' =>$url.'[PAGE]'.$suffix
|
||||
]);
|
||||
])->toArray();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -289,7 +290,7 @@ class Article extends Model
|
||||
'list_rows' => 15,
|
||||
'page' => $page,
|
||||
'path' =>$url.'[PAGE]'.$suffix
|
||||
]);
|
||||
])->toArray();
|
||||
break;
|
||||
}
|
||||
Cache::tag('tagArtDetail')->set('arts'.$ename.$type.$page,$artList,600);
|
||||
|
@ -29,9 +29,9 @@ class Comment extends Model
|
||||
}
|
||||
|
||||
//获取评论
|
||||
public function getComment($id)
|
||||
public function getComment($id, $page)
|
||||
{
|
||||
$comments = $this::where(['article_id'=>$id,'status'=>1])->order(['cai'=>'asc','create_time'=>'asc'])->paginate(10);
|
||||
$comments = $this::with(['user'])->where(['article_id'=>$id,'status'=>1])->order(['cai'=>'asc','create_time'=>'asc'])->paginate(['list_rows'=>10, 'page'=>$page]);
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Slider extends Model
|
||||
{
|
||||
$sliders = Cache::get('slider'.$type);
|
||||
if(!$sliders){
|
||||
$sliders = $this::where(['slid_status'=>1,'delete_time'=>0,'slid_type'=>$type])->whereTime('slid_over','>=',time())->select();
|
||||
$sliders = $this::where(['slid_status'=>1,'delete_time'=>0,'slid_type'=>$type])->whereTime('slid_over','>=',time())->select()->toArray();
|
||||
Cache::set('slider'.$type,$sliders,3600);
|
||||
}
|
||||
return $sliders;
|
||||
|
@ -29,27 +29,35 @@ class Article extends BaseController
|
||||
// 抛出 HTTP 异常
|
||||
throw new \think\exception\HttpException(404, '请求异常');
|
||||
}
|
||||
$page = Request::param('page') ? Request::param('page') : 1;
|
||||
|
||||
//获取分类ID
|
||||
$ename = Request::param('ename');
|
||||
$type = Request::param('type') ?? 'all';
|
||||
$tpl = Db::name('cate')->where('ename',$ename)->value('detpl');
|
||||
//分页伪静态
|
||||
$str = Request::baseUrl(); //不带参数在url
|
||||
//$str = Request::baseUrl(); //不带参数在url
|
||||
$path = Request::pathinfo();
|
||||
$str = '/'.app('http')->getName().'/'.$path;
|
||||
//halt($str);
|
||||
|
||||
$patterns = "/\d+/"; //数字正则
|
||||
preg_match($patterns,$str,$arr); //正则查询页码出现在位置
|
||||
$p = preg_match($patterns,$str,$arr); //正则查询页码出现在位置
|
||||
|
||||
//检测route配置中是否设置了伪静态后缀
|
||||
$suffix = Config::get('route.url_html_suffix') ? '.'.Config::get('route.url_html_suffix') : '/';
|
||||
if(Config::get('route.url_html_suffix')){
|
||||
|
||||
//伪静态有后缀
|
||||
if(isset($arr[0])){
|
||||
$page = $arr[0];
|
||||
$url = strstr($str,$arr[0],true);
|
||||
} else {
|
||||
$page = 1;
|
||||
$url = strstr($str,'.html',true).'/';
|
||||
$url = strstr($str,'.html',true);
|
||||
}
|
||||
} else {
|
||||
|
||||
//伪静态后缀false
|
||||
if(isset($arr[0])){
|
||||
$page = $arr[0];
|
||||
@ -59,10 +67,12 @@ class Article extends BaseController
|
||||
$url = $str.'/';
|
||||
}
|
||||
}
|
||||
|
||||
//分类列表
|
||||
$article = new ArticleModel();
|
||||
$artList = $article->getCateList($ename,$type,$page,$url,$suffix);
|
||||
$count = $artList->total();
|
||||
|
||||
//$count = $artList->total();
|
||||
|
||||
// 热议文章
|
||||
$artHot = $article->getArtHot(10);
|
||||
@ -74,30 +84,38 @@ class Article extends BaseController
|
||||
//分类钻展赞助
|
||||
$ad_comm = $ad->getSliderList(6);
|
||||
|
||||
View::assign(['type'=>$type,'artList'=>$artList,'artHot'=>$artHot,'ad_cateImg'=>$ad_cateImg,'ad_comm'=>$ad_comm,'jspage'=>'jie','count'=>$count,'page'=>$page,'url'=>$url]);
|
||||
View::assign(['type'=>$type,'artList'=>$artList,'artHot'=>$artHot,'ad_cateImg'=>$ad_cateImg,'ad_comm'=>$ad_comm,'jspage'=>'jie','url'=>$url]);
|
||||
return View::fetch('article/'.$tpl.'/cate');
|
||||
}
|
||||
|
||||
//文章详情页
|
||||
public function detail($id)
|
||||
{
|
||||
$page = input('page') ? input('page') : 1;
|
||||
$article = new ArticleModel();
|
||||
$artDetail = $article->getArtDetail($id);
|
||||
if(is_null($artDetail)){
|
||||
$id = input('id');
|
||||
$artStu = Db::name('article')->field('id')->where(['status'=>1,'delete_time'=>0])->find($id);
|
||||
if(is_null($artStu)){
|
||||
// 抛出 HTTP 异常
|
||||
throw new \think\exception\HttpException(404, '异常消息');
|
||||
}
|
||||
$arId = $artDetail->cate->id;
|
||||
|
||||
//输出内容
|
||||
$page = input('page') ? input('page') : 1;
|
||||
$article = new ArticleModel();
|
||||
$artDetail = $article->getArtDetail($id,$page);
|
||||
$arId = $artDetail['cate_id'];
|
||||
$tpl = Db::name('cate')->where('id',$arId)->value('detpl');
|
||||
$comments = $artDetail->comments()->where('status',1)->order(['cai'=>'asc','create_time'=>'asc'])->paginate(['list_rows'=>10, 'page'=>$page]);
|
||||
//$comment = new \app\common\model\Comment();
|
||||
//$comments = $comment->getComment($id);
|
||||
//dump($comments);
|
||||
$count = $comments->total();
|
||||
$artDetail->inc('pv')->update();
|
||||
$download = $artDetail['upzip'] ? download($artDetail['upzip'],'file') : '';
|
||||
|
||||
//$count = $comments->total();
|
||||
//$artDetail->inc('pv')->update();
|
||||
|
||||
//浏览pv
|
||||
Db::name('article')->where('id',$id)->inc('pv')->update();
|
||||
$pv = Db::name('article')->field('pv')->where('id',$id)->value('pv');
|
||||
$download = $artDetail->upzip ? download($artDetail->upzip,'file') : '';
|
||||
|
||||
//评论
|
||||
$comment = new Comment;
|
||||
$comments = $comment->getComment($id, $page);
|
||||
|
||||
// 热议文章
|
||||
$artHot = $article->getArtHot(10);
|
||||
@ -108,7 +126,7 @@ class Article extends BaseController
|
||||
//分类钻展赞助
|
||||
$ad_comm = $ad->getSliderList(7);
|
||||
|
||||
View::assign(['article'=>$artDetail,'pv'=>$pv,'comments'=>$comments,'artHot'=>$artHot,'ad_art'=>$ad_artImg,'ad_comm'=>$ad_comm,$download,'count'=>$count,'page'=>$page,'jspage'=>'jie']);
|
||||
View::assign(['article'=>$artDetail,'pv'=>$pv,'artHot'=>$artHot,'ad_art'=>$ad_artImg,'ad_comm'=>$ad_comm,$download,'page'=>$page,'comments'=>$comments,'jspage'=>'jie']);
|
||||
return View::fetch('article/'.$tpl.'/detail');
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,10 @@ use think\facade\Route;
|
||||
Route::get('captcha/[:config]','\\think\\captcha\\CaptchaController@index');
|
||||
Route::rule('/', 'index'); // 首页访问路由
|
||||
Route::group(function () {
|
||||
Route::get('jie/:id', 'article/detail');
|
||||
Route::get('column/<ename?>/<type?>/<page?>','article/cate')
|
||||
Route::get('jie/:id', 'article/detail');
|
||||
//Route::get('column/<ename>','article/cate');
|
||||
//Route::get('column/<ename>/<type>','article/cate');
|
||||
Route::get('column/<ename>/[:type]/[:page]','article/cate')
|
||||
->pattern([
|
||||
'ename' => '\w+',
|
||||
'page' => '\d+',
|
||||
|
@ -12,8 +12,9 @@ class Index extends BaseController
|
||||
// 检测是否安装过
|
||||
protected function initialize(){
|
||||
if(file_exists('./install.lock')){
|
||||
echo "<script>alert('已经成功安装了TaoLer社区系统,安装系统已锁定。如需重新安装,请删除根目录下的install.lock文件')</script>";
|
||||
die();
|
||||
//echo "<script>alert('已经成功安装了TaoLer社区系统,安装系统已锁定。如需重新安装,请删除根目录下的install.lock文件')</script>";
|
||||
//die();
|
||||
return response("<script>alert('已经成功安装了TaoLer社区系统,安装系统已锁定。如需重新安装,请删除根目录下的install.lock文件')</script>");
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +145,7 @@ class Index extends BaseController
|
||||
<?php
|
||||
return [
|
||||
// 默认使用的数据库连接配置
|
||||
'default' => 'mysql',
|
||||
'default' => env('database.driver', 'mysql'),
|
||||
// 自定义时间查询规则
|
||||
'time_query_rule' => [],
|
||||
// 自动写入时间戳字段
|
||||
@ -156,43 +157,44 @@ return [
|
||||
// 数据库连接配置信息
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => '{$data['DB_HOST']}',
|
||||
// 数据库名
|
||||
'database' => '{$data['DB_NAME']}',
|
||||
// 用户名
|
||||
'username' => '{$data['DB_USER']}',
|
||||
// 密码
|
||||
'password' => '{$data['DB_PWD']}',
|
||||
// 端口
|
||||
'hostport' => '{$data['DB_PORT']}',
|
||||
// 数据库连接参数
|
||||
'params' => [],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => '{$data['DB_PREFIX']}',
|
||||
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||
'deploy' => 0,
|
||||
// 数据库读写是否分离 主从式有效
|
||||
'rw_separate' => false,
|
||||
// 读写分离后 主服务器数量
|
||||
'master_num' => 1,
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => true,
|
||||
// 开启字段缓存
|
||||
'fields_cache' => false,
|
||||
// 字段缓存路径
|
||||
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||
],
|
||||
// 数据库类型
|
||||
'type' => env('database.type', 'mysql'),
|
||||
// 服务器地址
|
||||
'hostname' => env('database.hostname', '{$data['DB_HOST']}'),
|
||||
// 数据库名
|
||||
'database' => env('database.database', '{$data['DB_NAME']}'),
|
||||
// 用户名
|
||||
'username' => env('database.username', '{$data['DB_USER']}'),
|
||||
// 密码
|
||||
'password' => env('database.password', '{$data['DB_PWD']}'),
|
||||
// 端口
|
||||
'hostport' => env('database.hostport', '{$data['DB_PORT']}'),
|
||||
// 数据库连接参数
|
||||
'params' => [],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => env('database.prefix', '{$data['DB_PREFIX']}'),
|
||||
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||
'deploy' => 0,
|
||||
// 数据库读写是否分离 主从式有效
|
||||
'rw_separate' => false,
|
||||
// 读写分离后 主服务器数量
|
||||
'master_num' => 1,
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => env('app_debug', true),
|
||||
// 开启字段缓存
|
||||
'fields_cache' => false,
|
||||
// 字段缓存路径
|
||||
//'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||
],
|
||||
// 更多的数据库配置信息
|
||||
],
|
||||
];
|
||||
php;
|
||||
|
@ -21,13 +21,12 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>php版本</td>
|
||||
<td>>7.1</td>
|
||||
<td>>7.2.5</td>
|
||||
<td>
|
||||
<?php echo PHP_VERSION ?>
|
||||
</td>
|
||||
<?php $php_version=explode('.', PHP_VERSION); ?>
|
||||
<td class="<?php if(($php_version['0']>=7) && $php_version['1']>1)echo 'yes'; ?>">
|
||||
<?php if (($php_version['0']>=7) && $php_version['1']>1): ?> √
|
||||
<td class="<?php if(version_compare(PHP_VERSION, '7.2.5', '>='))echo 'yes'; ?>">
|
||||
<?php if (version_compare(PHP_VERSION, '7.2.5', '>=')): ?> √
|
||||
<?php else: ?> ×
|
||||
<?php endif ?>
|
||||
</td>
|
||||
|
100
composer.lock
generated
100
composer.lock
generated
@ -531,6 +531,65 @@
|
||||
},
|
||||
"time": "2021-11-05T16:50:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
@ -767,16 +826,16 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/framework",
|
||||
"version": "v6.0.9",
|
||||
"version": "v6.0.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/framework.git",
|
||||
"reference": "0b5fb453f0e533de3af3a1ab6a202510b61be617"
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/0b5fb453f0e533de3af3a1ab6a202510b61be617",
|
||||
"reference": "0b5fb453f0e533de3af3a1ab6a202510b61be617",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -792,12 +851,14 @@
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"php": ">=7.2.5",
|
||||
"psr/container": "~1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/log": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"topthink/think-helper": "^3.1.1",
|
||||
"topthink/think-orm": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/psr7": "^2.1.0",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
@ -832,9 +893,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/framework/issues",
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.9"
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.10"
|
||||
},
|
||||
"time": "2021-07-22T03:24:49+00:00"
|
||||
"time": "2021-12-31T09:14:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-captcha",
|
||||
@ -897,16 +958,16 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-helper",
|
||||
"version": "v3.1.5",
|
||||
"version": "v3.1.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-helper.git",
|
||||
"reference": "f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905"
|
||||
"reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905",
|
||||
"reference": "f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff",
|
||||
"reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -918,6 +979,9 @@
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@ -940,9 +1004,9 @@
|
||||
"description": "The ThinkPHP6 Helper Package",
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-helper/issues",
|
||||
"source": "https://github.com/top-think/think-helper/tree/v3.1.5"
|
||||
"source": "https://github.com/top-think/think-helper/tree/v3.1.6"
|
||||
},
|
||||
"time": "2021-06-21T06:17:31+00:00"
|
||||
"time": "2021-12-15T04:27:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-multi-app",
|
||||
@ -1000,16 +1064,16 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-orm",
|
||||
"version": "v2.0.45",
|
||||
"version": "v2.0.47",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-orm.git",
|
||||
"reference": "3dcf9af447b048103093840833e8c74ab849152f"
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/3dcf9af447b048103093840833e8c74ab849152f",
|
||||
"reference": "3dcf9af447b048103093840833e8c74ab849152f",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -1055,9 +1119,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-orm/issues",
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.45"
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.47"
|
||||
},
|
||||
"time": "2021-11-30T14:31:05+00:00"
|
||||
"time": "2021-12-31T06:12:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-template",
|
||||
|
@ -15,4 +15,6 @@ return [
|
||||
'httponly' => false,
|
||||
// 是否使用 setcookie
|
||||
'setcookie' => true,
|
||||
// samesite 设置,支持 'strict' 'lax'
|
||||
'samesite' => '',
|
||||
];
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
// 默认使用的数据库连接配置
|
||||
'default' => 'mysql',
|
||||
'default' => env('database.driver', 'mysql'),
|
||||
// 自定义时间查询规则
|
||||
'time_query_rule' => [],
|
||||
// 自动写入时间戳字段
|
||||
@ -13,42 +13,43 @@ return [
|
||||
// 数据库连接配置信息
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
// 数据库类型
|
||||
'type' => 'mysql',
|
||||
// 服务器地址
|
||||
'hostname' => '',
|
||||
// 数据库名
|
||||
'database' => '',
|
||||
// 用户名
|
||||
'username' => '',
|
||||
// 密码
|
||||
'password' => '',
|
||||
// 端口
|
||||
'hostport' => '3306',
|
||||
// 数据库连接参数
|
||||
'params' => [],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => 'tao_',
|
||||
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||
'deploy' => 0,
|
||||
// 数据库读写是否分离 主从式有效
|
||||
'rw_separate' => false,
|
||||
// 读写分离后 主服务器数量
|
||||
'master_num' => 1,
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => true,
|
||||
// 开启字段缓存
|
||||
'fields_cache' => false,
|
||||
// 字段缓存路径
|
||||
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||
],
|
||||
// 数据库类型
|
||||
'type' => env('database.type', 'mysql'),
|
||||
// 服务器地址
|
||||
'hostname' => env('database.hostname', ''),
|
||||
// 数据库名
|
||||
'database' => env('database.database', ''),
|
||||
// 用户名
|
||||
'username' => env('database.username', ''),
|
||||
// 密码
|
||||
'password' => env('database.password', ''),
|
||||
// 端口
|
||||
'hostport' => env('database.hostport', ''),
|
||||
// 数据库连接参数
|
||||
'params' => [],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => 'utf8',
|
||||
// 数据库表前缀
|
||||
'prefix' => env('database.prefix', 'tao_'),
|
||||
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||
'deploy' => 0,
|
||||
// 数据库读写是否分离 主从式有效
|
||||
'rw_separate' => false,
|
||||
// 读写分离后 主服务器数量
|
||||
'master_num' => 1,
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => env('app_debug', true),
|
||||
// 开启字段缓存
|
||||
'fields_cache' => false,
|
||||
// 字段缓存路径
|
||||
//'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||
],
|
||||
// 更多的数据库配置信息
|
||||
],
|
||||
];
|
2
vendor/composer/autoload_files.php
vendored
2
vendor/composer/autoload_files.php
vendored
@ -11,8 +11,8 @@ return array(
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'223fa6f9b46fbe5d6b44c5ff847bfceb' => $vendorDir . '/taoser/think-addons/src/helper.php',
|
||||
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'd421242fd42b2ea6cd13f802bcf18a6e' => $baseDir . '/extend/taoler/com/form.php',
|
||||
);
|
||||
|
1
vendor/composer/autoload_psr4.php
vendored
1
vendor/composer/autoload_psr4.php
vendored
@ -22,6 +22,7 @@ return array(
|
||||
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
|
7
vendor/composer/autoload_static.php
vendored
7
vendor/composer/autoload_static.php
vendored
@ -12,9 +12,9 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'223fa6f9b46fbe5d6b44c5ff847bfceb' => __DIR__ . '/..' . '/taoser/think-addons/src/helper.php',
|
||||
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'd421242fd42b2ea6cd13f802bcf18a6e' => __DIR__ . '/../..' . '/extend/taoler/com/form.php',
|
||||
);
|
||||
|
||||
@ -52,6 +52,7 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
'Psr\\SimpleCache\\' => 16,
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
'Psr\\Container\\' => 14,
|
||||
'Psr\\Cache\\' => 10,
|
||||
'PHPMailer\\PHPMailer\\' => 20,
|
||||
@ -136,6 +137,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
|
109
vendor/composer/installed.json
vendored
109
vendor/composer/installed.json
vendored
@ -542,6 +542,68 @@
|
||||
},
|
||||
"install-path": "../psr/container"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"version_normalized": "1.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
||||
},
|
||||
"install-path": "../psr/http-message"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
@ -1147,17 +1209,17 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/framework",
|
||||
"version": "v6.0.9",
|
||||
"version_normalized": "6.0.9.0",
|
||||
"version": "v6.0.10",
|
||||
"version_normalized": "6.0.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/framework.git",
|
||||
"reference": "0b5fb453f0e533de3af3a1ab6a202510b61be617"
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/0b5fb453f0e533de3af3a1ab6a202510b61be617",
|
||||
"reference": "0b5fb453f0e533de3af3a1ab6a202510b61be617",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"reference": "d9cadb6971ae92ff85ba5f2be77a40b0ad5718fb",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -1173,17 +1235,19 @@
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"php": ">=7.2.5",
|
||||
"psr/container": "~1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/log": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"topthink/think-helper": "^3.1.1",
|
||||
"topthink/think-orm": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/psr7": "^2.1.0",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"time": "2021-07-22T03:24:49+00:00",
|
||||
"time": "2021-12-31T09:14:28+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1215,7 +1279,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/framework/issues",
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.9"
|
||||
"source": "https://github.com/top-think/framework/tree/v6.0.10"
|
||||
},
|
||||
"install-path": "../topthink/framework"
|
||||
},
|
||||
@ -1279,17 +1343,17 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-helper",
|
||||
"version": "v3.1.5",
|
||||
"version_normalized": "3.1.5.0",
|
||||
"version": "v3.1.6",
|
||||
"version_normalized": "3.1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-helper.git",
|
||||
"reference": "f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905"
|
||||
"reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905",
|
||||
"reference": "f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/769acbe50a4274327162f9c68ec2e89a38eb2aff",
|
||||
"reference": "769acbe50a4274327162f9c68ec2e89a38eb2aff",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -1301,7 +1365,10 @@
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"time": "2021-06-21T06:17:31+00:00",
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"time": "2021-12-15T04:27:55+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1325,7 +1392,7 @@
|
||||
"description": "The ThinkPHP6 Helper Package",
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-helper/issues",
|
||||
"source": "https://github.com/top-think/think-helper/tree/v3.1.5"
|
||||
"source": "https://github.com/top-think/think-helper/tree/v3.1.6"
|
||||
},
|
||||
"install-path": "../topthink/think-helper"
|
||||
},
|
||||
@ -1384,17 +1451,17 @@
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-orm",
|
||||
"version": "v2.0.45",
|
||||
"version_normalized": "2.0.45.0",
|
||||
"version": "v2.0.47",
|
||||
"version_normalized": "2.0.47.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-orm.git",
|
||||
"reference": "3dcf9af447b048103093840833e8c74ab849152f"
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/3dcf9af447b048103093840833e8c74ab849152f",
|
||||
"reference": "3dcf9af447b048103093840833e8c74ab849152f",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"reference": "e69151fba9dd21f86e392a0ae208825904d6d49a",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -1414,7 +1481,7 @@
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7|^8|^9.5"
|
||||
},
|
||||
"time": "2021-11-30T14:31:05+00:00",
|
||||
"time": "2021-12-31T06:12:13+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -1442,7 +1509,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/top-think/think-orm/issues",
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.45"
|
||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.47"
|
||||
},
|
||||
"install-path": "../topthink/think-orm"
|
||||
},
|
||||
|
31
vendor/composer/installed.php
vendored
31
vendor/composer/installed.php
vendored
@ -5,7 +5,7 @@
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '13037f7440f2dcce2cd78297df9d6a675744ecad',
|
||||
'reference' => 'f35436abc461b29e7056f63f10302c84aeb2bfbc',
|
||||
'name' => 'taoser/taoler',
|
||||
'dev' => true,
|
||||
),
|
||||
@ -82,6 +82,15 @@
|
||||
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '1.1.4',
|
||||
'version' => '1.1.4.0',
|
||||
@ -142,7 +151,7 @@
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'reference' => '13037f7440f2dcce2cd78297df9d6a675744ecad',
|
||||
'reference' => 'f35436abc461b29e7056f63f10302c84aeb2bfbc',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'taoser/think-addons' => array(
|
||||
@ -164,12 +173,12 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/framework' => array(
|
||||
'pretty_version' => 'v6.0.9',
|
||||
'version' => '6.0.9.0',
|
||||
'pretty_version' => 'v6.0.10',
|
||||
'version' => '6.0.10.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/framework',
|
||||
'aliases' => array(),
|
||||
'reference' => '0b5fb453f0e533de3af3a1ab6a202510b61be617',
|
||||
'reference' => 'd9cadb6971ae92ff85ba5f2be77a40b0ad5718fb',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-captcha' => array(
|
||||
@ -182,12 +191,12 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-helper' => array(
|
||||
'pretty_version' => 'v3.1.5',
|
||||
'version' => '3.1.5.0',
|
||||
'pretty_version' => 'v3.1.6',
|
||||
'version' => '3.1.6.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-helper',
|
||||
'aliases' => array(),
|
||||
'reference' => 'f98e3ad44acd27ae85a4d923b1bdfd16c6d8d905',
|
||||
'reference' => '769acbe50a4274327162f9c68ec2e89a38eb2aff',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-multi-app' => array(
|
||||
@ -200,12 +209,12 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-orm' => array(
|
||||
'pretty_version' => 'v2.0.45',
|
||||
'version' => '2.0.45.0',
|
||||
'pretty_version' => 'v2.0.47',
|
||||
'version' => '2.0.47.0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../topthink/think-orm',
|
||||
'aliases' => array(),
|
||||
'reference' => '3dcf9af447b048103093840833e8c74ab849152f',
|
||||
'reference' => 'e69151fba9dd21f86e392a0ae208825904d6d49a',
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'topthink/think-template' => array(
|
||||
|
36
vendor/psr/http-message/CHANGELOG.md
vendored
Normal file
36
vendor/psr/http-message/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file, in reverse chronological order by release.
|
||||
|
||||
## 1.0.1 - 2016-08-06
|
||||
|
||||
### Added
|
||||
|
||||
- Nothing.
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Nothing.
|
||||
|
||||
### Removed
|
||||
|
||||
- Nothing.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Updated all `@return self` annotation references in interfaces to use
|
||||
`@return static`, which more closelly follows the semantics of the
|
||||
specification.
|
||||
- Updated the `MessageInterface::getHeaders()` return annotation to use the
|
||||
value `string[][]`, indicating the format is a nested array of strings.
|
||||
- Updated the `@link` annotation for `RequestInterface::withRequestTarget()`
|
||||
to point to the correct section of RFC 7230.
|
||||
- Updated the `ServerRequestInterface::withUploadedFiles()` parameter annotation
|
||||
to add the parameter name (`$uploadedFiles`).
|
||||
- Updated a `@throws` annotation for the `UploadedFileInterface::moveTo()`
|
||||
method to correctly reference the method parameter (it was referencing an
|
||||
incorrect parameter name previously).
|
||||
|
||||
## 1.0.0 - 2016-05-18
|
||||
|
||||
Initial stable release; reflects accepted PSR-7 specification.
|
19
vendor/psr/http-message/LICENSE
vendored
Normal file
19
vendor/psr/http-message/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2014 PHP Framework Interoperability Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
13
vendor/psr/http-message/README.md
vendored
Normal file
13
vendor/psr/http-message/README.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
PSR Http Message
|
||||
================
|
||||
|
||||
This repository holds all interfaces/classes/traits related to
|
||||
[PSR-7](http://www.php-fig.org/psr/psr-7/).
|
||||
|
||||
Note that this is not a HTTP message implementation of its own. It is merely an
|
||||
interface that describes a HTTP message. See the specification for more details.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
We'll certainly need some stuff in here.
|
26
vendor/psr/http-message/composer.json
vendored
Normal file
26
vendor/psr/http-message/composer.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"description": "Common interface for HTTP messages",
|
||||
"keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
187
vendor/psr/http-message/src/MessageInterface.php
vendored
Normal file
187
vendor/psr/http-message/src/MessageInterface.php
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* HTTP messages consist of requests from a client to a server and responses
|
||||
* from a server to a client. This interface defines the methods common to
|
||||
* each.
|
||||
*
|
||||
* Messages are considered immutable; all methods that might change state MUST
|
||||
* be implemented such that they retain the internal state of the current
|
||||
* message and return an instance that contains the changed state.
|
||||
*
|
||||
* @link http://www.ietf.org/rfc/rfc7230.txt
|
||||
* @link http://www.ietf.org/rfc/rfc7231.txt
|
||||
*/
|
||||
interface MessageInterface
|
||||
{
|
||||
/**
|
||||
* Retrieves the HTTP protocol version as a string.
|
||||
*
|
||||
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
|
||||
*
|
||||
* @return string HTTP protocol version.
|
||||
*/
|
||||
public function getProtocolVersion();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified HTTP protocol version.
|
||||
*
|
||||
* The version string MUST contain only the HTTP version number (e.g.,
|
||||
* "1.1", "1.0").
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new protocol version.
|
||||
*
|
||||
* @param string $version HTTP protocol version
|
||||
* @return static
|
||||
*/
|
||||
public function withProtocolVersion($version);
|
||||
|
||||
/**
|
||||
* Retrieves all message header values.
|
||||
*
|
||||
* The keys represent the header name as it will be sent over the wire, and
|
||||
* each value is an array of strings associated with the header.
|
||||
*
|
||||
* // Represent the headers as a string
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* echo $name . ": " . implode(", ", $values);
|
||||
* }
|
||||
*
|
||||
* // Emit headers iteratively:
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* foreach ($values as $value) {
|
||||
* header(sprintf('%s: %s', $name, $value), false);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* While header names are not case-sensitive, getHeaders() will preserve the
|
||||
* exact case in which headers were originally specified.
|
||||
*
|
||||
* @return string[][] Returns an associative array of the message's headers. Each
|
||||
* key MUST be a header name, and each value MUST be an array of strings
|
||||
* for that header.
|
||||
*/
|
||||
public function getHeaders();
|
||||
|
||||
/**
|
||||
* Checks if a header exists by the given case-insensitive name.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return bool Returns true if any header names match the given header
|
||||
* name using a case-insensitive string comparison. Returns false if
|
||||
* no matching header name is found in the message.
|
||||
*/
|
||||
public function hasHeader($name);
|
||||
|
||||
/**
|
||||
* Retrieves a message header value by the given case-insensitive name.
|
||||
*
|
||||
* This method returns an array of all the header values of the given
|
||||
* case-insensitive header name.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return an
|
||||
* empty array.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string[] An array of string values as provided for the given
|
||||
* header. If the header does not appear in the message, this method MUST
|
||||
* return an empty array.
|
||||
*/
|
||||
public function getHeader($name);
|
||||
|
||||
/**
|
||||
* Retrieves a comma-separated string of the values for a single header.
|
||||
*
|
||||
* This method returns all of the header values of the given
|
||||
* case-insensitive header name as a string concatenated together using
|
||||
* a comma.
|
||||
*
|
||||
* NOTE: Not all header values may be appropriately represented using
|
||||
* comma concatenation. For such headers, use getHeader() instead
|
||||
* and supply your own delimiter when concatenating.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return
|
||||
* an empty string.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string A string of values as provided for the given header
|
||||
* concatenated together using a comma. If the header does not appear in
|
||||
* the message, this method MUST return an empty string.
|
||||
*/
|
||||
public function getHeaderLine($name);
|
||||
|
||||
/**
|
||||
* Return an instance with the provided value replacing the specified header.
|
||||
*
|
||||
* While header names are case-insensitive, the casing of the header will
|
||||
* be preserved by this function, and returned from getHeaders().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new and/or updated header and value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withHeader($name, $value);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified header appended with the given value.
|
||||
*
|
||||
* Existing values for the specified header will be maintained. The new
|
||||
* value(s) will be appended to the existing list. If the header did not
|
||||
* exist previously, it will be added.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new header and/or value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to add.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withAddedHeader($name, $value);
|
||||
|
||||
/**
|
||||
* Return an instance without the specified header.
|
||||
*
|
||||
* Header resolution MUST be done without case-sensitivity.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the named header.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to remove.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutHeader($name);
|
||||
|
||||
/**
|
||||
* Gets the body of the message.
|
||||
*
|
||||
* @return StreamInterface Returns the body as a stream.
|
||||
*/
|
||||
public function getBody();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified message body.
|
||||
*
|
||||
* The body MUST be a StreamInterface object.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return a new instance that has the
|
||||
* new body stream.
|
||||
*
|
||||
* @param StreamInterface $body Body.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException When the body is not valid.
|
||||
*/
|
||||
public function withBody(StreamInterface $body);
|
||||
}
|
129
vendor/psr/http-message/src/RequestInterface.php
vendored
Normal file
129
vendor/psr/http-message/src/RequestInterface.php
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Representation of an outgoing, client-side request.
|
||||
*
|
||||
* Per the HTTP specification, this interface includes properties for
|
||||
* each of the following:
|
||||
*
|
||||
* - Protocol version
|
||||
* - HTTP method
|
||||
* - URI
|
||||
* - Headers
|
||||
* - Message body
|
||||
*
|
||||
* During construction, implementations MUST attempt to set the Host header from
|
||||
* a provided URI if no Host header is provided.
|
||||
*
|
||||
* Requests are considered immutable; all methods that might change state MUST
|
||||
* be implemented such that they retain the internal state of the current
|
||||
* message and return an instance that contains the changed state.
|
||||
*/
|
||||
interface RequestInterface extends MessageInterface
|
||||
{
|
||||
/**
|
||||
* Retrieves the message's request target.
|
||||
*
|
||||
* Retrieves the message's request-target either as it will appear (for
|
||||
* clients), as it appeared at request (for servers), or as it was
|
||||
* specified for the instance (see withRequestTarget()).
|
||||
*
|
||||
* In most cases, this will be the origin-form of the composed URI,
|
||||
* unless a value was provided to the concrete implementation (see
|
||||
* withRequestTarget() below).
|
||||
*
|
||||
* If no URI is available, and no request-target has been specifically
|
||||
* provided, this method MUST return the string "/".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestTarget();
|
||||
|
||||
/**
|
||||
* Return an instance with the specific request-target.
|
||||
*
|
||||
* If the request needs a non-origin-form request-target — e.g., for
|
||||
* specifying an absolute-form, authority-form, or asterisk-form —
|
||||
* this method may be used to create an instance with the specified
|
||||
* request-target, verbatim.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* changed request target.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
|
||||
* request-target forms allowed in request messages)
|
||||
* @param mixed $requestTarget
|
||||
* @return static
|
||||
*/
|
||||
public function withRequestTarget($requestTarget);
|
||||
|
||||
/**
|
||||
* Retrieves the HTTP method of the request.
|
||||
*
|
||||
* @return string Returns the request method.
|
||||
*/
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* Return an instance with the provided HTTP method.
|
||||
*
|
||||
* While HTTP method names are typically all uppercase characters, HTTP
|
||||
* method names are case-sensitive and thus implementations SHOULD NOT
|
||||
* modify the given string.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* changed request method.
|
||||
*
|
||||
* @param string $method Case-sensitive method.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid HTTP methods.
|
||||
*/
|
||||
public function withMethod($method);
|
||||
|
||||
/**
|
||||
* Retrieves the URI instance.
|
||||
*
|
||||
* This method MUST return a UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
* @return UriInterface Returns a UriInterface instance
|
||||
* representing the URI of the request.
|
||||
*/
|
||||
public function getUri();
|
||||
|
||||
/**
|
||||
* Returns an instance with the provided URI.
|
||||
*
|
||||
* This method MUST update the Host header of the returned request by
|
||||
* default if the URI contains a host component. If the URI does not
|
||||
* contain a host component, any pre-existing Host header MUST be carried
|
||||
* over to the returned request.
|
||||
*
|
||||
* You can opt-in to preserving the original state of the Host header by
|
||||
* setting `$preserveHost` to `true`. When `$preserveHost` is set to
|
||||
* `true`, this method interacts with the Host header in the following ways:
|
||||
*
|
||||
* - If the Host header is missing or empty, and the new URI contains
|
||||
* a host component, this method MUST update the Host header in the returned
|
||||
* request.
|
||||
* - If the Host header is missing or empty, and the new URI does not contain a
|
||||
* host component, this method MUST NOT update the Host header in the returned
|
||||
* request.
|
||||
* - If a Host header is present and non-empty, this method MUST NOT update
|
||||
* the Host header in the returned request.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new UriInterface instance.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-4.3
|
||||
* @param UriInterface $uri New request URI to use.
|
||||
* @param bool $preserveHost Preserve the original state of the Host header.
|
||||
* @return static
|
||||
*/
|
||||
public function withUri(UriInterface $uri, $preserveHost = false);
|
||||
}
|
68
vendor/psr/http-message/src/ResponseInterface.php
vendored
Normal file
68
vendor/psr/http-message/src/ResponseInterface.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Representation of an outgoing, server-side response.
|
||||
*
|
||||
* Per the HTTP specification, this interface includes properties for
|
||||
* each of the following:
|
||||
*
|
||||
* - Protocol version
|
||||
* - Status code and reason phrase
|
||||
* - Headers
|
||||
* - Message body
|
||||
*
|
||||
* Responses are considered immutable; all methods that might change state MUST
|
||||
* be implemented such that they retain the internal state of the current
|
||||
* message and return an instance that contains the changed state.
|
||||
*/
|
||||
interface ResponseInterface extends MessageInterface
|
||||
{
|
||||
/**
|
||||
* Gets the response status code.
|
||||
*
|
||||
* The status code is a 3-digit integer result code of the server's attempt
|
||||
* to understand and satisfy the request.
|
||||
*
|
||||
* @return int Status code.
|
||||
*/
|
||||
public function getStatusCode();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified status code and, optionally, reason phrase.
|
||||
*
|
||||
* If no reason phrase is specified, implementations MAY choose to default
|
||||
* to the RFC 7231 or IANA recommended reason phrase for the response's
|
||||
* status code.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated status and reason phrase.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @param int $code The 3-digit integer result code to set.
|
||||
* @param string $reasonPhrase The reason phrase to use with the
|
||||
* provided status code; if none is provided, implementations MAY
|
||||
* use the defaults as suggested in the HTTP specification.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException For invalid status code arguments.
|
||||
*/
|
||||
public function withStatus($code, $reasonPhrase = '');
|
||||
|
||||
/**
|
||||
* Gets the response reason phrase associated with the status code.
|
||||
*
|
||||
* Because a reason phrase is not a required element in a response
|
||||
* status line, the reason phrase value MAY be null. Implementations MAY
|
||||
* choose to return the default RFC 7231 recommended reason phrase (or those
|
||||
* listed in the IANA HTTP Status Code Registry) for the response's
|
||||
* status code.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @return string Reason phrase; must return an empty string if none present.
|
||||
*/
|
||||
public function getReasonPhrase();
|
||||
}
|
261
vendor/psr/http-message/src/ServerRequestInterface.php
vendored
Normal file
261
vendor/psr/http-message/src/ServerRequestInterface.php
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Representation of an incoming, server-side HTTP request.
|
||||
*
|
||||
* Per the HTTP specification, this interface includes properties for
|
||||
* each of the following:
|
||||
*
|
||||
* - Protocol version
|
||||
* - HTTP method
|
||||
* - URI
|
||||
* - Headers
|
||||
* - Message body
|
||||
*
|
||||
* Additionally, it encapsulates all data as it has arrived to the
|
||||
* application from the CGI and/or PHP environment, including:
|
||||
*
|
||||
* - The values represented in $_SERVER.
|
||||
* - Any cookies provided (generally via $_COOKIE)
|
||||
* - Query string arguments (generally via $_GET, or as parsed via parse_str())
|
||||
* - Upload files, if any (as represented by $_FILES)
|
||||
* - Deserialized body parameters (generally from $_POST)
|
||||
*
|
||||
* $_SERVER values MUST be treated as immutable, as they represent application
|
||||
* state at the time of request; as such, no methods are provided to allow
|
||||
* modification of those values. The other values provide such methods, as they
|
||||
* can be restored from $_SERVER or the request body, and may need treatment
|
||||
* during the application (e.g., body parameters may be deserialized based on
|
||||
* content type).
|
||||
*
|
||||
* Additionally, this interface recognizes the utility of introspecting a
|
||||
* request to derive and match additional parameters (e.g., via URI path
|
||||
* matching, decrypting cookie values, deserializing non-form-encoded body
|
||||
* content, matching authorization headers to users, etc). These parameters
|
||||
* are stored in an "attributes" property.
|
||||
*
|
||||
* Requests are considered immutable; all methods that might change state MUST
|
||||
* be implemented such that they retain the internal state of the current
|
||||
* message and return an instance that contains the changed state.
|
||||
*/
|
||||
interface ServerRequestInterface extends RequestInterface
|
||||
{
|
||||
/**
|
||||
* Retrieve server parameters.
|
||||
*
|
||||
* Retrieves data related to the incoming request environment,
|
||||
* typically derived from PHP's $_SERVER superglobal. The data IS NOT
|
||||
* REQUIRED to originate from $_SERVER.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getServerParams();
|
||||
|
||||
/**
|
||||
* Retrieve cookies.
|
||||
*
|
||||
* Retrieves cookies sent by the client to the server.
|
||||
*
|
||||
* The data MUST be compatible with the structure of the $_COOKIE
|
||||
* superglobal.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCookieParams();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified cookies.
|
||||
*
|
||||
* The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
|
||||
* be compatible with the structure of $_COOKIE. Typically, this data will
|
||||
* be injected at instantiation.
|
||||
*
|
||||
* This method MUST NOT update the related Cookie header of the request
|
||||
* instance, nor related values in the server params.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated cookie values.
|
||||
*
|
||||
* @param array $cookies Array of key/value pairs representing cookies.
|
||||
* @return static
|
||||
*/
|
||||
public function withCookieParams(array $cookies);
|
||||
|
||||
/**
|
||||
* Retrieve query string arguments.
|
||||
*
|
||||
* Retrieves the deserialized query string arguments, if any.
|
||||
*
|
||||
* Note: the query params might not be in sync with the URI or server
|
||||
* params. If you need to ensure you are only getting the original
|
||||
* values, you may need to parse the query string from `getUri()->getQuery()`
|
||||
* or from the `QUERY_STRING` server param.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueryParams();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified query string arguments.
|
||||
*
|
||||
* These values SHOULD remain immutable over the course of the incoming
|
||||
* request. They MAY be injected during instantiation, such as from PHP's
|
||||
* $_GET superglobal, or MAY be derived from some other value such as the
|
||||
* URI. In cases where the arguments are parsed from the URI, the data
|
||||
* MUST be compatible with what PHP's parse_str() would return for
|
||||
* purposes of how duplicate query parameters are handled, and how nested
|
||||
* sets are handled.
|
||||
*
|
||||
* Setting query string arguments MUST NOT change the URI stored by the
|
||||
* request, nor the values in the server params.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated query string arguments.
|
||||
*
|
||||
* @param array $query Array of query string arguments, typically from
|
||||
* $_GET.
|
||||
* @return static
|
||||
*/
|
||||
public function withQueryParams(array $query);
|
||||
|
||||
/**
|
||||
* Retrieve normalized file upload data.
|
||||
*
|
||||
* This method returns upload metadata in a normalized tree, with each leaf
|
||||
* an instance of Psr\Http\Message\UploadedFileInterface.
|
||||
*
|
||||
* These values MAY be prepared from $_FILES or the message body during
|
||||
* instantiation, or MAY be injected via withUploadedFiles().
|
||||
*
|
||||
* @return array An array tree of UploadedFileInterface instances; an empty
|
||||
* array MUST be returned if no data is present.
|
||||
*/
|
||||
public function getUploadedFiles();
|
||||
|
||||
/**
|
||||
* Create a new instance with the specified uploaded files.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated body parameters.
|
||||
*
|
||||
* @param array $uploadedFiles An array tree of UploadedFileInterface instances.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException if an invalid structure is provided.
|
||||
*/
|
||||
public function withUploadedFiles(array $uploadedFiles);
|
||||
|
||||
/**
|
||||
* Retrieve any parameters provided in the request body.
|
||||
*
|
||||
* If the request Content-Type is either application/x-www-form-urlencoded
|
||||
* or multipart/form-data, and the request method is POST, this method MUST
|
||||
* return the contents of $_POST.
|
||||
*
|
||||
* Otherwise, this method may return any results of deserializing
|
||||
* the request body content; as parsing returns structured content, the
|
||||
* potential types MUST be arrays or objects only. A null value indicates
|
||||
* the absence of body content.
|
||||
*
|
||||
* @return null|array|object The deserialized body parameters, if any.
|
||||
* These will typically be an array or object.
|
||||
*/
|
||||
public function getParsedBody();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified body parameters.
|
||||
*
|
||||
* These MAY be injected during instantiation.
|
||||
*
|
||||
* If the request Content-Type is either application/x-www-form-urlencoded
|
||||
* or multipart/form-data, and the request method is POST, use this method
|
||||
* ONLY to inject the contents of $_POST.
|
||||
*
|
||||
* The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
|
||||
* deserializing the request body content. Deserialization/parsing returns
|
||||
* structured data, and, as such, this method ONLY accepts arrays or objects,
|
||||
* or a null value if nothing was available to parse.
|
||||
*
|
||||
* As an example, if content negotiation determines that the request data
|
||||
* is a JSON payload, this method could be used to create a request
|
||||
* instance with the deserialized parameters.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated body parameters.
|
||||
*
|
||||
* @param null|array|object $data The deserialized body data. This will
|
||||
* typically be in an array or object.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException if an unsupported argument type is
|
||||
* provided.
|
||||
*/
|
||||
public function withParsedBody($data);
|
||||
|
||||
/**
|
||||
* Retrieve attributes derived from the request.
|
||||
*
|
||||
* The request "attributes" may be used to allow injection of any
|
||||
* parameters derived from the request: e.g., the results of path
|
||||
* match operations; the results of decrypting cookies; the results of
|
||||
* deserializing non-form-encoded message bodies; etc. Attributes
|
||||
* will be application and request specific, and CAN be mutable.
|
||||
*
|
||||
* @return array Attributes derived from the request.
|
||||
*/
|
||||
public function getAttributes();
|
||||
|
||||
/**
|
||||
* Retrieve a single derived request attribute.
|
||||
*
|
||||
* Retrieves a single derived request attribute as described in
|
||||
* getAttributes(). If the attribute has not been previously set, returns
|
||||
* the default value as provided.
|
||||
*
|
||||
* This method obviates the need for a hasAttribute() method, as it allows
|
||||
* specifying a default value to return if the attribute is not found.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $default Default value to return if the attribute does not exist.
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($name, $default = null);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified derived request attribute.
|
||||
*
|
||||
* This method allows setting a single derived request attribute as
|
||||
* described in getAttributes().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated attribute.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $value The value of the attribute.
|
||||
* @return static
|
||||
*/
|
||||
public function withAttribute($name, $value);
|
||||
|
||||
/**
|
||||
* Return an instance that removes the specified derived request attribute.
|
||||
*
|
||||
* This method allows removing a single derived request attribute as
|
||||
* described in getAttributes().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the attribute.
|
||||
*
|
||||
* @see getAttributes()
|
||||
* @param string $name The attribute name.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutAttribute($name);
|
||||
}
|
158
vendor/psr/http-message/src/StreamInterface.php
vendored
Normal file
158
vendor/psr/http-message/src/StreamInterface.php
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Describes a data stream.
|
||||
*
|
||||
* Typically, an instance will wrap a PHP stream; this interface provides
|
||||
* a wrapper around the most common operations, including serialization of
|
||||
* the entire stream to a string.
|
||||
*/
|
||||
interface StreamInterface
|
||||
{
|
||||
/**
|
||||
* Reads all data from the stream into a string, from the beginning to end.
|
||||
*
|
||||
* This method MUST attempt to seek to the beginning of the stream before
|
||||
* reading data and read the stream until the end is reached.
|
||||
*
|
||||
* Warning: This could attempt to load a large amount of data into memory.
|
||||
*
|
||||
* This method MUST NOT raise an exception in order to conform with PHP's
|
||||
* string casting operations.
|
||||
*
|
||||
* @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Closes the stream and any underlying resources.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Separates any underlying resources from the stream.
|
||||
*
|
||||
* After the stream has been detached, the stream is in an unusable state.
|
||||
*
|
||||
* @return resource|null Underlying PHP stream, if any
|
||||
*/
|
||||
public function detach();
|
||||
|
||||
/**
|
||||
* Get the size of the stream if known.
|
||||
*
|
||||
* @return int|null Returns the size in bytes if known, or null if unknown.
|
||||
*/
|
||||
public function getSize();
|
||||
|
||||
/**
|
||||
* Returns the current position of the file read/write pointer
|
||||
*
|
||||
* @return int Position of the file pointer
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public function tell();
|
||||
|
||||
/**
|
||||
* Returns true if the stream is at the end of the stream.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function eof();
|
||||
|
||||
/**
|
||||
* Returns whether or not the stream is seekable.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSeekable();
|
||||
|
||||
/**
|
||||
* Seek to a position in the stream.
|
||||
*
|
||||
* @link http://www.php.net/manual/en/function.fseek.php
|
||||
* @param int $offset Stream offset
|
||||
* @param int $whence Specifies how the cursor position will be calculated
|
||||
* based on the seek offset. Valid values are identical to the built-in
|
||||
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
|
||||
* offset bytes SEEK_CUR: Set position to current location plus offset
|
||||
* SEEK_END: Set position to end-of-stream plus offset.
|
||||
* @throws \RuntimeException on failure.
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET);
|
||||
|
||||
/**
|
||||
* Seek to the beginning of the stream.
|
||||
*
|
||||
* If the stream is not seekable, this method will raise an exception;
|
||||
* otherwise, it will perform a seek(0).
|
||||
*
|
||||
* @see seek()
|
||||
* @link http://www.php.net/manual/en/function.fseek.php
|
||||
* @throws \RuntimeException on failure.
|
||||
*/
|
||||
public function rewind();
|
||||
|
||||
/**
|
||||
* Returns whether or not the stream is writable.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isWritable();
|
||||
|
||||
/**
|
||||
* Write data to the stream.
|
||||
*
|
||||
* @param string $string The string that is to be written.
|
||||
* @return int Returns the number of bytes written to the stream.
|
||||
* @throws \RuntimeException on failure.
|
||||
*/
|
||||
public function write($string);
|
||||
|
||||
/**
|
||||
* Returns whether or not the stream is readable.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isReadable();
|
||||
|
||||
/**
|
||||
* Read data from the stream.
|
||||
*
|
||||
* @param int $length Read up to $length bytes from the object and return
|
||||
* them. Fewer than $length bytes may be returned if underlying stream
|
||||
* call returns fewer bytes.
|
||||
* @return string Returns the data read from the stream, or an empty string
|
||||
* if no bytes are available.
|
||||
* @throws \RuntimeException if an error occurs.
|
||||
*/
|
||||
public function read($length);
|
||||
|
||||
/**
|
||||
* Returns the remaining contents in a string
|
||||
*
|
||||
* @return string
|
||||
* @throws \RuntimeException if unable to read or an error occurs while
|
||||
* reading.
|
||||
*/
|
||||
public function getContents();
|
||||
|
||||
/**
|
||||
* Get stream metadata as an associative array or retrieve a specific key.
|
||||
*
|
||||
* The keys returned are identical to the keys returned from PHP's
|
||||
* stream_get_meta_data() function.
|
||||
*
|
||||
* @link http://php.net/manual/en/function.stream-get-meta-data.php
|
||||
* @param string $key Specific metadata to retrieve.
|
||||
* @return array|mixed|null Returns an associative array if no key is
|
||||
* provided. Returns a specific key value if a key is provided and the
|
||||
* value is found, or null if the key is not found.
|
||||
*/
|
||||
public function getMetadata($key = null);
|
||||
}
|
123
vendor/psr/http-message/src/UploadedFileInterface.php
vendored
Normal file
123
vendor/psr/http-message/src/UploadedFileInterface.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Value object representing a file uploaded through an HTTP request.
|
||||
*
|
||||
* Instances of this interface are considered immutable; all methods that
|
||||
* might change state MUST be implemented such that they retain the internal
|
||||
* state of the current instance and return an instance that contains the
|
||||
* changed state.
|
||||
*/
|
||||
interface UploadedFileInterface
|
||||
{
|
||||
/**
|
||||
* Retrieve a stream representing the uploaded file.
|
||||
*
|
||||
* This method MUST return a StreamInterface instance, representing the
|
||||
* uploaded file. The purpose of this method is to allow utilizing native PHP
|
||||
* stream functionality to manipulate the file upload, such as
|
||||
* stream_copy_to_stream() (though the result will need to be decorated in a
|
||||
* native PHP stream wrapper to work with such functions).
|
||||
*
|
||||
* If the moveTo() method has been called previously, this method MUST raise
|
||||
* an exception.
|
||||
*
|
||||
* @return StreamInterface Stream representation of the uploaded file.
|
||||
* @throws \RuntimeException in cases when no stream is available or can be
|
||||
* created.
|
||||
*/
|
||||
public function getStream();
|
||||
|
||||
/**
|
||||
* Move the uploaded file to a new location.
|
||||
*
|
||||
* Use this method as an alternative to move_uploaded_file(). This method is
|
||||
* guaranteed to work in both SAPI and non-SAPI environments.
|
||||
* Implementations must determine which environment they are in, and use the
|
||||
* appropriate method (move_uploaded_file(), rename(), or a stream
|
||||
* operation) to perform the operation.
|
||||
*
|
||||
* $targetPath may be an absolute path, or a relative path. If it is a
|
||||
* relative path, resolution should be the same as used by PHP's rename()
|
||||
* function.
|
||||
*
|
||||
* The original file or stream MUST be removed on completion.
|
||||
*
|
||||
* If this method is called more than once, any subsequent calls MUST raise
|
||||
* an exception.
|
||||
*
|
||||
* When used in an SAPI environment where $_FILES is populated, when writing
|
||||
* files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
|
||||
* used to ensure permissions and upload status are verified correctly.
|
||||
*
|
||||
* If you wish to move to a stream, use getStream(), as SAPI operations
|
||||
* cannot guarantee writing to stream destinations.
|
||||
*
|
||||
* @see http://php.net/is_uploaded_file
|
||||
* @see http://php.net/move_uploaded_file
|
||||
* @param string $targetPath Path to which to move the uploaded file.
|
||||
* @throws \InvalidArgumentException if the $targetPath specified is invalid.
|
||||
* @throws \RuntimeException on any error during the move operation, or on
|
||||
* the second or subsequent call to the method.
|
||||
*/
|
||||
public function moveTo($targetPath);
|
||||
|
||||
/**
|
||||
* Retrieve the file size.
|
||||
*
|
||||
* Implementations SHOULD return the value stored in the "size" key of
|
||||
* the file in the $_FILES array if available, as PHP calculates this based
|
||||
* on the actual size transmitted.
|
||||
*
|
||||
* @return int|null The file size in bytes or null if unknown.
|
||||
*/
|
||||
public function getSize();
|
||||
|
||||
/**
|
||||
* Retrieve the error associated with the uploaded file.
|
||||
*
|
||||
* The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
|
||||
*
|
||||
* If the file was uploaded successfully, this method MUST return
|
||||
* UPLOAD_ERR_OK.
|
||||
*
|
||||
* Implementations SHOULD return the value stored in the "error" key of
|
||||
* the file in the $_FILES array.
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.errors.php
|
||||
* @return int One of PHP's UPLOAD_ERR_XXX constants.
|
||||
*/
|
||||
public function getError();
|
||||
|
||||
/**
|
||||
* Retrieve the filename sent by the client.
|
||||
*
|
||||
* Do not trust the value returned by this method. A client could send
|
||||
* a malicious filename with the intention to corrupt or hack your
|
||||
* application.
|
||||
*
|
||||
* Implementations SHOULD return the value stored in the "name" key of
|
||||
* the file in the $_FILES array.
|
||||
*
|
||||
* @return string|null The filename sent by the client or null if none
|
||||
* was provided.
|
||||
*/
|
||||
public function getClientFilename();
|
||||
|
||||
/**
|
||||
* Retrieve the media type sent by the client.
|
||||
*
|
||||
* Do not trust the value returned by this method. A client could send
|
||||
* a malicious media type with the intention to corrupt or hack your
|
||||
* application.
|
||||
*
|
||||
* Implementations SHOULD return the value stored in the "type" key of
|
||||
* the file in the $_FILES array.
|
||||
*
|
||||
* @return string|null The media type sent by the client or null if none
|
||||
* was provided.
|
||||
*/
|
||||
public function getClientMediaType();
|
||||
}
|
323
vendor/psr/http-message/src/UriInterface.php
vendored
Normal file
323
vendor/psr/http-message/src/UriInterface.php
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
<?php
|
||||
namespace Psr\Http\Message;
|
||||
|
||||
/**
|
||||
* Value object representing a URI.
|
||||
*
|
||||
* This interface is meant to represent URIs according to RFC 3986 and to
|
||||
* provide methods for most common operations. Additional functionality for
|
||||
* working with URIs can be provided on top of the interface or externally.
|
||||
* Its primary use is for HTTP requests, but may also be used in other
|
||||
* contexts.
|
||||
*
|
||||
* Instances of this interface are considered immutable; all methods that
|
||||
* might change state MUST be implemented such that they retain the internal
|
||||
* state of the current instance and return an instance that contains the
|
||||
* changed state.
|
||||
*
|
||||
* Typically the Host header will be also be present in the request message.
|
||||
* For server-side requests, the scheme will typically be discoverable in the
|
||||
* server parameters.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc3986 (the URI specification)
|
||||
*/
|
||||
interface UriInterface
|
||||
{
|
||||
/**
|
||||
* Retrieve the scheme component of the URI.
|
||||
*
|
||||
* If no scheme is present, this method MUST return an empty string.
|
||||
*
|
||||
* The value returned MUST be normalized to lowercase, per RFC 3986
|
||||
* Section 3.1.
|
||||
*
|
||||
* The trailing ":" character is not part of the scheme and MUST NOT be
|
||||
* added.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.1
|
||||
* @return string The URI scheme.
|
||||
*/
|
||||
public function getScheme();
|
||||
|
||||
/**
|
||||
* Retrieve the authority component of the URI.
|
||||
*
|
||||
* If no authority information is present, this method MUST return an empty
|
||||
* string.
|
||||
*
|
||||
* The authority syntax of the URI is:
|
||||
*
|
||||
* <pre>
|
||||
* [user-info@]host[:port]
|
||||
* </pre>
|
||||
*
|
||||
* If the port component is not set or is the standard port for the current
|
||||
* scheme, it SHOULD NOT be included.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.2
|
||||
* @return string The URI authority, in "[user-info@]host[:port]" format.
|
||||
*/
|
||||
public function getAuthority();
|
||||
|
||||
/**
|
||||
* Retrieve the user information component of the URI.
|
||||
*
|
||||
* If no user information is present, this method MUST return an empty
|
||||
* string.
|
||||
*
|
||||
* If a user is present in the URI, this will return that value;
|
||||
* additionally, if the password is also present, it will be appended to the
|
||||
* user value, with a colon (":") separating the values.
|
||||
*
|
||||
* The trailing "@" character is not part of the user information and MUST
|
||||
* NOT be added.
|
||||
*
|
||||
* @return string The URI user information, in "username[:password]" format.
|
||||
*/
|
||||
public function getUserInfo();
|
||||
|
||||
/**
|
||||
* Retrieve the host component of the URI.
|
||||
*
|
||||
* If no host is present, this method MUST return an empty string.
|
||||
*
|
||||
* The value returned MUST be normalized to lowercase, per RFC 3986
|
||||
* Section 3.2.2.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
|
||||
* @return string The URI host.
|
||||
*/
|
||||
public function getHost();
|
||||
|
||||
/**
|
||||
* Retrieve the port component of the URI.
|
||||
*
|
||||
* If a port is present, and it is non-standard for the current scheme,
|
||||
* this method MUST return it as an integer. If the port is the standard port
|
||||
* used with the current scheme, this method SHOULD return null.
|
||||
*
|
||||
* If no port is present, and no scheme is present, this method MUST return
|
||||
* a null value.
|
||||
*
|
||||
* If no port is present, but a scheme is present, this method MAY return
|
||||
* the standard port for that scheme, but SHOULD return null.
|
||||
*
|
||||
* @return null|int The URI port.
|
||||
*/
|
||||
public function getPort();
|
||||
|
||||
/**
|
||||
* Retrieve the path component of the URI.
|
||||
*
|
||||
* The path can either be empty or absolute (starting with a slash) or
|
||||
* rootless (not starting with a slash). Implementations MUST support all
|
||||
* three syntaxes.
|
||||
*
|
||||
* Normally, the empty path "" and absolute path "/" are considered equal as
|
||||
* defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
|
||||
* do this normalization because in contexts with a trimmed base path, e.g.
|
||||
* the front controller, this difference becomes significant. It's the task
|
||||
* of the user to handle both "" and "/".
|
||||
*
|
||||
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986, Sections 2 and 3.3.
|
||||
*
|
||||
* As an example, if the value should include a slash ("/") not intended as
|
||||
* delimiter between path segments, that value MUST be passed in encoded
|
||||
* form (e.g., "%2F") to the instance.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-2
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.3
|
||||
* @return string The URI path.
|
||||
*/
|
||||
public function getPath();
|
||||
|
||||
/**
|
||||
* Retrieve the query string of the URI.
|
||||
*
|
||||
* If no query string is present, this method MUST return an empty string.
|
||||
*
|
||||
* The leading "?" character is not part of the query and MUST NOT be
|
||||
* added.
|
||||
*
|
||||
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986, Sections 2 and 3.4.
|
||||
*
|
||||
* As an example, if a value in a key/value pair of the query string should
|
||||
* include an ampersand ("&") not intended as a delimiter between values,
|
||||
* that value MUST be passed in encoded form (e.g., "%26") to the instance.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-2
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.4
|
||||
* @return string The URI query string.
|
||||
*/
|
||||
public function getQuery();
|
||||
|
||||
/**
|
||||
* Retrieve the fragment component of the URI.
|
||||
*
|
||||
* If no fragment is present, this method MUST return an empty string.
|
||||
*
|
||||
* The leading "#" character is not part of the fragment and MUST NOT be
|
||||
* added.
|
||||
*
|
||||
* The value returned MUST be percent-encoded, but MUST NOT double-encode
|
||||
* any characters. To determine what characters to encode, please refer to
|
||||
* RFC 3986, Sections 2 and 3.5.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-2
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.5
|
||||
* @return string The URI fragment.
|
||||
*/
|
||||
public function getFragment();
|
||||
|
||||
/**
|
||||
* Return an instance with the specified scheme.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified scheme.
|
||||
*
|
||||
* Implementations MUST support the schemes "http" and "https" case
|
||||
* insensitively, and MAY accommodate other schemes if required.
|
||||
*
|
||||
* An empty scheme is equivalent to removing the scheme.
|
||||
*
|
||||
* @param string $scheme The scheme to use with the new instance.
|
||||
* @return static A new instance with the specified scheme.
|
||||
* @throws \InvalidArgumentException for invalid or unsupported schemes.
|
||||
*/
|
||||
public function withScheme($scheme);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified user information.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified user information.
|
||||
*
|
||||
* Password is optional, but the user information MUST include the
|
||||
* user; an empty string for the user is equivalent to removing user
|
||||
* information.
|
||||
*
|
||||
* @param string $user The user name to use for authority.
|
||||
* @param null|string $password The password associated with $user.
|
||||
* @return static A new instance with the specified user information.
|
||||
*/
|
||||
public function withUserInfo($user, $password = null);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified host.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified host.
|
||||
*
|
||||
* An empty host value is equivalent to removing the host.
|
||||
*
|
||||
* @param string $host The hostname to use with the new instance.
|
||||
* @return static A new instance with the specified host.
|
||||
* @throws \InvalidArgumentException for invalid hostnames.
|
||||
*/
|
||||
public function withHost($host);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified port.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified port.
|
||||
*
|
||||
* Implementations MUST raise an exception for ports outside the
|
||||
* established TCP and UDP port ranges.
|
||||
*
|
||||
* A null value provided for the port is equivalent to removing the port
|
||||
* information.
|
||||
*
|
||||
* @param null|int $port The port to use with the new instance; a null value
|
||||
* removes the port information.
|
||||
* @return static A new instance with the specified port.
|
||||
* @throws \InvalidArgumentException for invalid ports.
|
||||
*/
|
||||
public function withPort($port);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified path.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified path.
|
||||
*
|
||||
* The path can either be empty or absolute (starting with a slash) or
|
||||
* rootless (not starting with a slash). Implementations MUST support all
|
||||
* three syntaxes.
|
||||
*
|
||||
* If the path is intended to be domain-relative rather than path relative then
|
||||
* it must begin with a slash ("/"). Paths not starting with a slash ("/")
|
||||
* are assumed to be relative to some base path known to the application or
|
||||
* consumer.
|
||||
*
|
||||
* Users can provide both encoded and decoded path characters.
|
||||
* Implementations ensure the correct encoding as outlined in getPath().
|
||||
*
|
||||
* @param string $path The path to use with the new instance.
|
||||
* @return static A new instance with the specified path.
|
||||
* @throws \InvalidArgumentException for invalid paths.
|
||||
*/
|
||||
public function withPath($path);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified query string.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified query string.
|
||||
*
|
||||
* Users can provide both encoded and decoded query characters.
|
||||
* Implementations ensure the correct encoding as outlined in getQuery().
|
||||
*
|
||||
* An empty query string value is equivalent to removing the query string.
|
||||
*
|
||||
* @param string $query The query string to use with the new instance.
|
||||
* @return static A new instance with the specified query string.
|
||||
* @throws \InvalidArgumentException for invalid query strings.
|
||||
*/
|
||||
public function withQuery($query);
|
||||
|
||||
/**
|
||||
* Return an instance with the specified URI fragment.
|
||||
*
|
||||
* This method MUST retain the state of the current instance, and return
|
||||
* an instance that contains the specified URI fragment.
|
||||
*
|
||||
* Users can provide both encoded and decoded fragment characters.
|
||||
* Implementations ensure the correct encoding as outlined in getFragment().
|
||||
*
|
||||
* An empty fragment value is equivalent to removing the fragment.
|
||||
*
|
||||
* @param string $fragment The fragment to use with the new instance.
|
||||
* @return static A new instance with the specified fragment.
|
||||
*/
|
||||
public function withFragment($fragment);
|
||||
|
||||
/**
|
||||
* Return the string representation as a URI reference.
|
||||
*
|
||||
* Depending on which components of the URI are present, the resulting
|
||||
* string is either a full URI or relative reference according to RFC 3986,
|
||||
* Section 4.1. The method concatenates the various components of the URI,
|
||||
* using the appropriate delimiters:
|
||||
*
|
||||
* - If a scheme is present, it MUST be suffixed by ":".
|
||||
* - If an authority is present, it MUST be prefixed by "//".
|
||||
* - The path can be concatenated without delimiters. But there are two
|
||||
* cases where the path has to be adjusted to make the URI reference
|
||||
* valid as PHP does not allow to throw an exception in __toString():
|
||||
* - If the path is rootless and an authority is present, the path MUST
|
||||
* be prefixed by "/".
|
||||
* - If the path is starting with more than one "/" and no authority is
|
||||
* present, the starting slashes MUST be reduced to one.
|
||||
* - If a query is present, it MUST be prefixed by "?".
|
||||
* - If a fragment is present, it MUST be prefixed by "#".
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc3986#section-4.1
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
2
vendor/services.php
vendored
2
vendor/services.php
vendored
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// This file is automatically generated at:2021-12-30 16:35:53
|
||||
// This file is automatically generated at:2022-01-02 21:09:33
|
||||
declare (strict_types = 1);
|
||||
return array (
|
||||
0 => 'taoser\\addons\\Service',
|
||||
|
2
vendor/topthink/framework/README.md
vendored
2
vendor/topthink/framework/README.md
vendored
@ -35,7 +35,7 @@ ThinkPHP6.0底层架构采用PHP7.1改写和进一步优化。
|
||||
* 统一和精简大量用法
|
||||
|
||||
|
||||
> ThinkPHP6.0的运行环境要求PHP7.1+,兼容PHP8.0。
|
||||
> ThinkPHP6.0的运行环境要求PHP7.2+,兼容PHP8.1
|
||||
|
||||
## 安装
|
||||
|
||||
|
4
vendor/topthink/framework/composer.json
vendored
4
vendor/topthink/framework/composer.json
vendored
@ -27,13 +27,15 @@
|
||||
"psr/log": "~1.0",
|
||||
"psr/container": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"topthink/think-orm": "^2.0",
|
||||
"topthink/think-helper": "^3.1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"guzzlehttp/psr7": "^2.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [],
|
||||
|
2
vendor/topthink/framework/src/helper.php
vendored
2
vendor/topthink/framework/src/helper.php
vendored
@ -149,7 +149,7 @@ if (!function_exists('cookie')) {
|
||||
{
|
||||
if (is_null($value)) {
|
||||
// 删除
|
||||
Cookie::delete($name);
|
||||
Cookie::delete($name, $option ?: []);
|
||||
} elseif ('' === $value) {
|
||||
// 获取
|
||||
return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1)) : Cookie::get($name);
|
||||
|
31
vendor/topthink/framework/src/think/App.php
vendored
31
vendor/topthink/framework/src/think/App.php
vendored
@ -39,7 +39,7 @@ use think\initializer\RegisterService;
|
||||
*/
|
||||
class App extends Container
|
||||
{
|
||||
const VERSION = '6.0.9';
|
||||
const VERSION = '6.0.10LTS';
|
||||
|
||||
/**
|
||||
* 应用调试模式
|
||||
@ -168,7 +168,7 @@ class App extends Container
|
||||
*/
|
||||
public function __construct(string $rootPath = '')
|
||||
{
|
||||
$this->thinkPath = dirname(__DIR__) . DIRECTORY_SEPARATOR;
|
||||
$this->thinkPath = realpath(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
|
||||
$this->rootPath = $rootPath ? rtrim($rootPath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $this->getDefaultRootPath();
|
||||
$this->appPath = $this->rootPath . 'app' . DIRECTORY_SEPARATOR;
|
||||
$this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
|
||||
@ -450,13 +450,8 @@ class App extends Container
|
||||
// 加载全局初始化文件
|
||||
$this->load();
|
||||
|
||||
// 加载框架默认语言包
|
||||
$langSet = $this->lang->defaultLangSet();
|
||||
|
||||
$this->lang->load($this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $langSet . '.php');
|
||||
|
||||
// 加载应用默认语言包
|
||||
$this->loadLangPack($langSet);
|
||||
$this->loadLangPack();
|
||||
|
||||
// 监听AppInit
|
||||
$this->event->trigger(AppInit::class);
|
||||
@ -482,25 +477,13 @@ class App extends Container
|
||||
|
||||
/**
|
||||
* 加载语言包
|
||||
* @param string $langset 语言
|
||||
* @return void
|
||||
*/
|
||||
public function loadLangPack($langset)
|
||||
public function loadLangPack()
|
||||
{
|
||||
if (empty($langset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载系统语言包
|
||||
$files = glob($this->appPath . 'lang' . DIRECTORY_SEPARATOR . $langset . '.*');
|
||||
$this->lang->load($files);
|
||||
|
||||
// 加载扩展(自定义)语言包
|
||||
$list = $this->config->get('lang.extend_list', []);
|
||||
|
||||
if (isset($list[$langset])) {
|
||||
$this->lang->load($list[$langset]);
|
||||
}
|
||||
// 加载默认语言包
|
||||
$langSet = $this->lang->defaultLangSet();
|
||||
$this->lang->switchLangSet($langSet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,7 @@ use ReflectionMethod;
|
||||
use think\exception\ClassNotFoundException;
|
||||
use think\exception\FuncNotFoundException;
|
||||
use think\helper\Str;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* 容器管理类 支持PSR-11
|
||||
@ -520,34 +521,38 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
|
||||
$this->delete($name);
|
||||
}
|
||||
|
||||
public function offsetExists($key)
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($key): bool
|
||||
{
|
||||
return $this->exists($key);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->make($key);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
$this->bind($key, $value);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
$this->delete($key);
|
||||
}
|
||||
|
||||
//Countable
|
||||
public function count()
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->instances);
|
||||
}
|
||||
|
||||
//IteratorAggregate
|
||||
public function getIterator()
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->instances);
|
||||
}
|
||||
|
@ -158,11 +158,13 @@ class Cookie
|
||||
* Cookie删除
|
||||
* @access public
|
||||
* @param string $name cookie名称
|
||||
* @param array $options cookie参数
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $name): void
|
||||
public function delete(string $name, array $options = []): void
|
||||
{
|
||||
$this->setCookie($name, '', time() - 3600, $this->config);
|
||||
$config = array_merge($this->config, array_change_key_case($options));
|
||||
$this->setCookie($name, '', time() - 3600, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
26
vendor/topthink/framework/src/think/Env.php
vendored
26
vendor/topthink/framework/src/think/Env.php
vendored
@ -26,6 +26,17 @@ class Env implements ArrayAccess
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* 数据转换映射
|
||||
* @var array
|
||||
*/
|
||||
protected $convert = [
|
||||
'true' => true,
|
||||
'false' => false,
|
||||
'off' => false,
|
||||
'on' => true,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->data = $_ENV;
|
||||
@ -39,7 +50,7 @@ class Env implements ArrayAccess
|
||||
*/
|
||||
public function load(string $file): void
|
||||
{
|
||||
$env = parse_ini_file($file, true) ?: [];
|
||||
$env = parse_ini_file($file, true, INI_SCANNER_RAW) ?: [];
|
||||
$this->set($env);
|
||||
}
|
||||
|
||||
@ -57,9 +68,14 @@ class Env implements ArrayAccess
|
||||
}
|
||||
|
||||
$name = strtoupper(str_replace('.', '_', $name));
|
||||
|
||||
if (isset($this->data[$name])) {
|
||||
return $this->data[$name];
|
||||
$result = $this->data[$name];
|
||||
|
||||
if (is_string($result) && isset($this->convert[$result])) {
|
||||
return $this->convert[$result];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->getEnv($name, $default);
|
||||
@ -159,21 +175,25 @@ class Env implements ArrayAccess
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $value): void
|
||||
{
|
||||
$this->set($name, $value);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($name): bool
|
||||
{
|
||||
return $this->__isset($name);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
{
|
||||
throw new Exception('not support: unset');
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($name)
|
||||
{
|
||||
return $this->get($name);
|
||||
|
2
vendor/topthink/framework/src/think/File.php
vendored
2
vendor/topthink/framework/src/think/File.php
vendored
@ -176,7 +176,7 @@ class File extends SplFileInfo
|
||||
$this->hashName = call_user_func($rule);
|
||||
break;
|
||||
default:
|
||||
$this->hashName = date('Ymd') . DIRECTORY_SEPARATOR . md5((string) microtime(true));
|
||||
$this->hashName = date('Ymd') . DIRECTORY_SEPARATOR . md5(microtime(true) . $this->getPathname());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
54
vendor/topthink/framework/src/think/Lang.php
vendored
54
vendor/topthink/framework/src/think/Lang.php
vendored
@ -18,6 +18,8 @@ namespace think;
|
||||
*/
|
||||
class Lang
|
||||
{
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 配置参数
|
||||
* @var array
|
||||
@ -62,15 +64,26 @@ class Lang
|
||||
* @access public
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
public function __construct(App $app, array $config = [])
|
||||
{
|
||||
$this->config = array_merge($this->config, array_change_key_case($config));
|
||||
$this->range = $this->config['default_lang'];
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
public static function __make(Config $config)
|
||||
public static function __make(App $app, Config $config)
|
||||
{
|
||||
return new static($config->get('lang'));
|
||||
return new static($app, $config->get('lang'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前语言配置
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig(): array
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,6 +117,35 @@ class Lang
|
||||
return $this->config['default_lang'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换语言
|
||||
* @access public
|
||||
* @param string $langset 语言
|
||||
* @return void
|
||||
*/
|
||||
public function switchLangSet(string $langset)
|
||||
{
|
||||
if (empty($langset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载系统语言包
|
||||
$this->load([
|
||||
$this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',
|
||||
]);
|
||||
|
||||
// 加载系统语言包
|
||||
$files = glob($this->app->getAppPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.*');
|
||||
$this->load($files);
|
||||
|
||||
// 加载扩展(自定义)语言包
|
||||
$list = $this->app->config->get('lang.extend_list', []);
|
||||
|
||||
if (isset($list[$langset])) {
|
||||
$this->load($list[$langset]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载语言定义(不区分大小写)
|
||||
* @access public
|
||||
@ -202,6 +244,10 @@ class Lang
|
||||
{
|
||||
$range = $range ?: $this->range;
|
||||
|
||||
if (!isset($this->lang[$range])) {
|
||||
$this->switchLangSet($range);
|
||||
}
|
||||
|
||||
// 空参数返回所有定义
|
||||
if (is_null($name)) {
|
||||
return $this->lang[$range] ?? [];
|
||||
@ -241,6 +287,7 @@ class Lang
|
||||
|
||||
/**
|
||||
* 自动侦测设置获取语言选择
|
||||
* @deprecated
|
||||
* @access public
|
||||
* @param Request $request
|
||||
* @return string
|
||||
@ -280,6 +327,7 @@ class Lang
|
||||
|
||||
/**
|
||||
* 保存当前语言到Cookie
|
||||
* @deprecated
|
||||
* @access public
|
||||
* @param Cookie $cookie Cookie对象
|
||||
* @return void
|
||||
|
@ -13,6 +13,7 @@ declare (strict_types = 1);
|
||||
namespace think;
|
||||
|
||||
use ArrayAccess;
|
||||
use think\facade\Lang;
|
||||
use think\file\UploadedFile;
|
||||
use think\route\Rule;
|
||||
|
||||
@ -1227,7 +1228,7 @@ class Request implements ArrayAccess
|
||||
7 => 'file write error',
|
||||
];
|
||||
|
||||
$msg = $fileUploadErrors[$error];
|
||||
$msg = Lang::get($fileUploadErrors[$error]);
|
||||
throw new Exception($msg, $error);
|
||||
}
|
||||
|
||||
@ -2150,19 +2151,23 @@ class Request implements ArrayAccess
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($name): bool
|
||||
{
|
||||
return $this->has($name);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($name)
|
||||
{
|
||||
return $this->param($name);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $value)
|
||||
{}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
{}
|
||||
|
||||
|
21
vendor/topthink/framework/src/think/Response.php
vendored
21
vendor/topthink/framework/src/think/Response.php
vendored
@ -130,16 +130,19 @@ abstract class Response
|
||||
// 处理输出数据
|
||||
$data = $this->getContent();
|
||||
|
||||
if (!headers_sent() && !empty($this->header)) {
|
||||
// 发送状态码
|
||||
http_response_code($this->code);
|
||||
// 发送头部信息
|
||||
foreach ($this->header as $name => $val) {
|
||||
header($name . (!is_null($val) ? ':' . $val : ''));
|
||||
if (!headers_sent()) {
|
||||
if (!empty($this->header)) {
|
||||
// 发送状态码
|
||||
http_response_code($this->code);
|
||||
// 发送头部信息
|
||||
foreach ($this->header as $name => $val) {
|
||||
header($name . (!is_null($val) ? ':' . $val : ''));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->cookie) {
|
||||
$this->cookie->save();
|
||||
}
|
||||
}
|
||||
if ($this->cookie) {
|
||||
$this->cookie->save();
|
||||
}
|
||||
|
||||
$this->sendData($data);
|
||||
|
@ -67,7 +67,7 @@ abstract class Make extends Command
|
||||
|
||||
protected function getPathName(string $name): string
|
||||
{
|
||||
$name = str_replace('app\\', '', $name);
|
||||
$name = substr($name, 4);
|
||||
|
||||
return $this->app->getBasePath() . ltrim(str_replace('\\', '/', $name), '/') . '.php';
|
||||
}
|
||||
|
@ -91,14 +91,13 @@ class RouteList extends Command
|
||||
|
||||
foreach ($routeList as $item) {
|
||||
$item['route'] = $item['route'] instanceof \Closure ? '<Closure>' : $item['route'];
|
||||
$row = [$item['rule'], $item['route'], $item['method'], $item['name']];
|
||||
|
||||
if ($this->input->hasOption('more')) {
|
||||
$item = [$item['rule'], $item['route'], $item['method'], $item['name'], $item['domain'], json_encode($item['option']), json_encode($item['pattern'])];
|
||||
} else {
|
||||
$item = [$item['rule'], $item['route'], $item['method'], $item['name']];
|
||||
array_push($row, $item['domain'], json_encode($item['option']), json_encode($item['pattern']));
|
||||
}
|
||||
|
||||
$rows[] = $item;
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
if ($this->input->getOption('sort')) {
|
||||
|
@ -17,6 +17,7 @@ use League\Flysystem\Adapter\AbstractAdapter;
|
||||
use League\Flysystem\Cached\CachedAdapter;
|
||||
use League\Flysystem\Cached\Storage\Memory as MemoryStore;
|
||||
use League\Flysystem\Filesystem;
|
||||
use RuntimeException;
|
||||
use think\Cache;
|
||||
use think\File;
|
||||
|
||||
@ -91,6 +92,16 @@ abstract class Driver
|
||||
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 路径
|
||||
|
@ -41,4 +41,12 @@ class Local extends Driver
|
||||
$permissions
|
||||
);
|
||||
}
|
||||
|
||||
public function url(string $path): string
|
||||
{
|
||||
if (isset($this->config['url'])) {
|
||||
return $this->concatPathToUrl($this->config['url'], $path);
|
||||
}
|
||||
return parent::url($path);
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,9 @@ class File implements LogHandlerInterface
|
||||
|
||||
try {
|
||||
if (count($files) > $this->config['max_files']) {
|
||||
set_error_handler(function ($errno, $errstr, $errfile, $errline) {});
|
||||
unlink($files[0]);
|
||||
restore_error_handler();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
//
|
||||
|
@ -14,6 +14,8 @@ namespace think\middleware;
|
||||
|
||||
use Closure;
|
||||
use think\App;
|
||||
use think\Config;
|
||||
use think\Cookie;
|
||||
use think\Lang;
|
||||
use think\Request;
|
||||
use think\Response;
|
||||
@ -24,13 +26,14 @@ use think\Response;
|
||||
class LoadLangPack
|
||||
{
|
||||
protected $app;
|
||||
|
||||
protected $lang;
|
||||
protected $config;
|
||||
|
||||
public function __construct(App $app, Lang $lang)
|
||||
public function __construct(App $app, Lang $lang, Config $config)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->lang = $lang;
|
||||
$this->app = $app;
|
||||
$this->lang = $lang;
|
||||
$this->config = $lang->getConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,19 +46,71 @@ class LoadLangPack
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
// 自动侦测当前语言
|
||||
$langset = $this->lang->detect($request);
|
||||
$langset = $this->detect($request);
|
||||
|
||||
if ($this->lang->defaultLangSet() != $langset) {
|
||||
// 加载系统语言包
|
||||
$this->lang->load([
|
||||
$this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',
|
||||
]);
|
||||
|
||||
$this->app->LoadLangPack($langset);
|
||||
$this->lang->switchLangSet($langset);
|
||||
}
|
||||
|
||||
$this->lang->saveToCookie($this->app->cookie);
|
||||
$this->saveToCookie($this->app->cookie, $langset);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动侦测设置获取语言选择
|
||||
* @access protected
|
||||
* @param Request $request
|
||||
* @return string
|
||||
*/
|
||||
protected function detect(Request $request): string
|
||||
{
|
||||
// 自动侦测设置获取语言选择
|
||||
$langSet = '';
|
||||
|
||||
if ($request->get($this->config['detect_var'])) {
|
||||
// url中设置了语言变量
|
||||
$langSet = strtolower($request->get($this->config['detect_var']));
|
||||
} elseif ($request->header($this->config['header_var'])) {
|
||||
// Header中设置了语言变量
|
||||
$langSet = strtolower($request->header($this->config['header_var']));
|
||||
} elseif ($request->cookie($this->config['cookie_var'])) {
|
||||
// Cookie中设置了语言变量
|
||||
$langSet = strtolower($request->cookie($this->config['cookie_var']));
|
||||
} elseif ($request->server('HTTP_ACCEPT_LANGUAGE')) {
|
||||
// 自动侦测浏览器语言
|
||||
$match = preg_match('/^([a-z\d\-]+)/i', $request->server('HTTP_ACCEPT_LANGUAGE'), $matches);
|
||||
if ($match) {
|
||||
$langSet = strtolower($matches[1]);
|
||||
if (isset($this->config['accept_language'][$langSet])) {
|
||||
$langSet = $this->config['accept_language'][$langSet];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->config['allow_lang_list']) || in_array($langSet, $this->config['allow_lang_list'])) {
|
||||
// 合法的语言
|
||||
$range = $langSet;
|
||||
$this->lang->setLangSet($range);
|
||||
} else {
|
||||
$range = $this->lang->getLangSet();
|
||||
}
|
||||
|
||||
return $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存当前语言到Cookie
|
||||
* @access protected
|
||||
* @param Cookie $cookie Cookie对象
|
||||
* @param string $langSet 语言
|
||||
* @return void
|
||||
*/
|
||||
protected function saveToCookie(Cookie $cookie, string $langSet)
|
||||
{
|
||||
if ($this->config['use_cookie']) {
|
||||
$cookie->set($this->config['cookie_var'], $langSet);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ declare (strict_types = 1);
|
||||
|
||||
namespace think\route;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use think\App;
|
||||
use think\Container;
|
||||
use think\Request;
|
||||
@ -94,6 +95,12 @@ abstract class Dispatch
|
||||
{
|
||||
if ($data instanceof Response) {
|
||||
$response = $data;
|
||||
} elseif ($data instanceof ResponseInterface) {
|
||||
$response = Response::create($data->getBody()->getContents(), 'html', $data->getStatusCode());
|
||||
|
||||
foreach ($data->getHeaders() as $header => $values) {
|
||||
$response->header([$header => implode(", ", $values)]);
|
||||
}
|
||||
} elseif (!is_null($data)) {
|
||||
// 默认自动识别响应输出类型
|
||||
$type = $this->request->isJson() ? 'json' : 'html';
|
||||
|
@ -320,7 +320,7 @@ class Url
|
||||
}
|
||||
|
||||
if (empty($pattern)) {
|
||||
return [rtrim($url, '?/-'), $domain, $suffix];
|
||||
return [rtrim($url, '?-'), $domain, $suffix];
|
||||
}
|
||||
|
||||
$type = $this->route->config('url_common_param');
|
||||
@ -331,11 +331,11 @@ class Url
|
||||
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key, '<' . $key . '>'], $type ? (string) $vars[$key] : urlencode((string) $vars[$key]), $url);
|
||||
$keys[] = $key;
|
||||
$url = str_replace(['/?', '-?'], ['/', '-'], $url);
|
||||
$result = [rtrim($url, '?/-'), $domain, $suffix];
|
||||
$result = [rtrim($url, '?-'), $domain, $suffix];
|
||||
} elseif (2 == $val) {
|
||||
$url = str_replace(['/[:' . $key . ']', '[:' . $key . ']', '<' . $key . '?>'], '', $url);
|
||||
$url = str_replace(['/?', '-?'], ['/', '-'], $url);
|
||||
$result = [rtrim($url, '?/-'), $domain, $suffix];
|
||||
$result = [rtrim($url, '?-'), $domain, $suffix];
|
||||
} else {
|
||||
$result = null;
|
||||
$keys = [];
|
||||
|
@ -113,6 +113,13 @@ class Controller extends Dispatch
|
||||
});
|
||||
}
|
||||
|
||||
protected function parseActions($actions)
|
||||
{
|
||||
return array_map(function ($item) {
|
||||
return strtolower($item);
|
||||
}, is_string($actions) ? explode(",", $actions) : $actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用反射机制注册控制器中间件
|
||||
* @access public
|
||||
@ -128,30 +135,34 @@ class Controller extends Dispatch
|
||||
$reflectionProperty->setAccessible(true);
|
||||
|
||||
$middlewares = $reflectionProperty->getValue($controller);
|
||||
$action = $this->request->action(true);
|
||||
|
||||
foreach ($middlewares as $key => $val) {
|
||||
if (!is_int($key)) {
|
||||
if (isset($val['only']) && !in_array($this->request->action(true), array_map(function ($item) {
|
||||
return strtolower($item);
|
||||
}, is_string($val['only']) ? explode(",", $val['only']) : $val['only']))) {
|
||||
continue;
|
||||
} elseif (isset($val['except']) && in_array($this->request->action(true), array_map(function ($item) {
|
||||
return strtolower($item);
|
||||
}, is_string($val['except']) ? explode(',', $val['except']) : $val['except']))) {
|
||||
continue;
|
||||
} else {
|
||||
$val = $key;
|
||||
$middleware = $key;
|
||||
$options = $val;
|
||||
} elseif (isset($val['middleware'])) {
|
||||
$middleware = $val['middleware'];
|
||||
$options = $val['options'] ?? [];
|
||||
} else {
|
||||
$middleware = $val;
|
||||
$options = [];
|
||||
}
|
||||
|
||||
if (isset($options['only']) && !in_array($action, $this->parseActions($options['only']))) {
|
||||
continue;
|
||||
} elseif (isset($options['except']) && in_array($action, $this->parseActions($options['except']))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_string($middleware) && strpos($middleware, ':')) {
|
||||
$middleware = explode(':', $middleware);
|
||||
if (count($middleware) > 1) {
|
||||
$middleware = [$middleware[0], array_slice($middleware, 1)];
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($val) && strpos($val, ':')) {
|
||||
$val = explode(':', $val);
|
||||
if (count($val) > 1) {
|
||||
$val = [$val[0], array_slice($val, 1)];
|
||||
}
|
||||
}
|
||||
|
||||
$this->app->middleware->controller($val);
|
||||
$this->app->middleware->controller($middleware);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
vendor/topthink/framework/tests/DispatchTest.php
vendored
Normal file
32
vendor/topthink/framework/tests/DispatchTest.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace think\tests;
|
||||
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Mockery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use think\Request;
|
||||
use think\route\Dispatch;
|
||||
use think\route\Rule;
|
||||
|
||||
class DispatchTest extends TestCase
|
||||
{
|
||||
public function testPsr7Response()
|
||||
{
|
||||
$request = Mockery::mock(Request::class);
|
||||
$rule = Mockery::mock(Rule::class);
|
||||
$dispatch = new class($request, $rule, '') extends Dispatch {
|
||||
public function exec()
|
||||
{
|
||||
return new Response(200, ['framework' => ['tp', 'thinkphp'], 'psr' => 'psr-7'], '123');
|
||||
}
|
||||
};
|
||||
|
||||
$response = $dispatch->run();
|
||||
|
||||
$this->assertInstanceOf(\think\Response::class, $response);
|
||||
$this->assertEquals('123', $response->getContent());
|
||||
$this->assertEquals('tp, thinkphp', $response->getHeader('framework'));
|
||||
$this->assertEquals('psr-7', $response->getHeader('psr'));
|
||||
}
|
||||
}
|
2
vendor/topthink/framework/tests/EnvTest.php
vendored
2
vendor/topthink/framework/tests/EnvTest.php
vendored
@ -21,8 +21,6 @@ class EnvTest extends TestCase
|
||||
|
||||
$this->assertEquals('value1', $env->get('key1'));
|
||||
$this->assertEquals('value2', $env->get('key2'));
|
||||
|
||||
$this->assertSame(['KEY1' => 'value1', 'KEY2' => 'value2'], $env->get());
|
||||
}
|
||||
|
||||
public function testServerEnv()
|
||||
|
@ -194,6 +194,10 @@ class RouteTest extends TestCase
|
||||
$this->createMiddleware()->mockery_getName() . ":params1:params2",
|
||||
$this->createMiddleware(0)->mockery_getName() => ['except' => 'bar'],
|
||||
$this->createMiddleware()->mockery_getName() => ['only' => 'bar'],
|
||||
[
|
||||
'middleware' => [$this->createMiddleware()->mockery_getName(), [new \stdClass()]],
|
||||
'options' => ['only' => 'bar'],
|
||||
],
|
||||
];
|
||||
|
||||
$this->app->shouldReceive('parseClass')->with('controller', 'Foo')->andReturn($controller->mockery_getName());
|
||||
@ -211,7 +215,8 @@ class RouteTest extends TestCase
|
||||
$controller = m::mock(FooClass::class);
|
||||
$controller->shouldReceive('index')->andReturn('bar');
|
||||
|
||||
$this->app->shouldReceive('parseClass')->once()->with('controller', 'Foo')->andReturn($controller->mockery_getName());
|
||||
$this->app->shouldReceive('parseClass')->once()->with('controller', 'Foo')
|
||||
->andReturn($controller->mockery_getName());
|
||||
$this->app->shouldReceive('make')->with($controller->mockery_getName(), [], true)->andReturn($controller);
|
||||
|
||||
$request = $this->makeRequest('foo');
|
||||
|
36
vendor/topthink/think-helper/.github/workflows/ci.yml
vendored
Normal file
36
vendor/topthink/think-helper/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
|
||||
jobs:
|
||||
phpcs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup PHP environment
|
||||
uses: shivammathur/setup-php@v2
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: PHPCSFixer check
|
||||
run: composer check-style
|
||||
phpunit:
|
||||
strategy:
|
||||
matrix:
|
||||
php_version: [7.3, 7.4, 8.0]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup PHP environment
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php_version }}
|
||||
coverage: xdebug
|
||||
- name: Install dependencies
|
||||
run: composer install
|
||||
- name: PHPUnit check
|
||||
run: ./vendor/bin/phpunit --coverage-text
|
36
vendor/topthink/think-helper/.github/workflows/php.yml
vendored
Normal file
36
vendor/topthink/think-helper/.github/workflows/php.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: PHP Composer
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 3.0 ]
|
||||
pull_request:
|
||||
branches: [ 3.0 ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate --strict
|
||||
|
||||
- name: Cache Composer packages
|
||||
id: composer-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: vendor
|
||||
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-php-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
|
||||
# Docs: https://getcomposer.org/doc/articles/scripts.md
|
||||
|
||||
- name: Run test suite
|
||||
run: composer test
|
3
vendor/topthink/think-helper/.gitignore
vendored
3
vendor/topthink/think-helper/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/vendor/
|
||||
/.idea/
|
||||
composer.lock
|
||||
composer.lock
|
||||
.phpunit.result.cache
|
2
vendor/topthink/think-helper/README.md
vendored
2
vendor/topthink/think-helper/README.md
vendored
@ -2,6 +2,8 @@
|
||||
|
||||
基于PHP7.1+
|
||||
|
||||
[![PHP Composer](https://github.com/larvatecn/think-helper/actions/workflows/php.yml/badge.svg)](https://github.com/larvatecn/think-helper/actions/workflows/php.yml)
|
||||
|
||||
> 以下类库都在`\\think\\helper`命名空间下
|
||||
|
||||
## Str
|
||||
|
16
vendor/topthink/think-helper/composer.json
vendored
16
vendor/topthink/think-helper/composer.json
vendored
@ -10,7 +10,10 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
@ -18,5 +21,16 @@
|
||||
"files": [
|
||||
"src/helper.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./vendor/bin/phpunit --colors"
|
||||
},
|
||||
"scripts-descriptions": {
|
||||
"test": "Run all tests."
|
||||
}
|
||||
}
|
||||
|
17
vendor/topthink/think-helper/phpunit.xml.dist
vendored
Normal file
17
vendor/topthink/think-helper/phpunit.xml.dist
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Application Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
17
vendor/topthink/think-helper/src/Collection.php
vendored
17
vendor/topthink/think-helper/src/Collection.php
vendored
@ -20,6 +20,7 @@ use JsonSerializable;
|
||||
use think\contract\Arrayable;
|
||||
use think\contract\Jsonable;
|
||||
use think\helper\Arr;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* 数据集管理类
|
||||
@ -142,7 +143,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
|
||||
public function intersect($items, string $indexKey = null)
|
||||
{
|
||||
if ($this->isEmpty() || is_scalar($this->items[0])) {
|
||||
return new static(array_diff($this->items, $this->convertToArray($items)));
|
||||
return new static(array_intersect($this->items, $this->convertToArray($items)));
|
||||
}
|
||||
|
||||
$intersect = [];
|
||||
@ -579,16 +580,19 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
public function offsetExists($offset)
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset) : bool
|
||||
{
|
||||
return array_key_exists($offset, $this->items);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->items[$offset];
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_null($offset)) {
|
||||
@ -598,24 +602,27 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
|
||||
}
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->items[$offset]);
|
||||
}
|
||||
|
||||
//Countable
|
||||
public function count()
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
//IteratorAggregate
|
||||
public function getIterator()
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
//JsonSerializable
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
@ -627,7 +634,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
|
||||
* @param integer $options json参数
|
||||
* @return string
|
||||
*/
|
||||
public function toJson(int $options = JSON_UNESCAPED_UNICODE) : string
|
||||
public function toJson(int $options = JSON_UNESCAPED_UNICODE): string
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ class Str
|
||||
}
|
||||
|
||||
if (!ctype_lower($value)) {
|
||||
$value = preg_replace('/\s+/u', '', $value);
|
||||
$value = preg_replace('/\s+/u', '', ucwords($value));
|
||||
|
||||
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
|
||||
}
|
||||
|
342
vendor/topthink/think-helper/tests/ArrTest.php
vendored
Normal file
342
vendor/topthink/think-helper/tests/ArrTest.php
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use stdClass;
|
||||
use think\Collection;
|
||||
use think\helper\Arr;
|
||||
|
||||
class ArrTest extends TestCase
|
||||
{
|
||||
public function testAdd()
|
||||
{
|
||||
$array = Arr::add(['name' => 'ThinkPHP'], 'price', 100);
|
||||
$this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array);
|
||||
}
|
||||
|
||||
public function testCrossJoin()
|
||||
{
|
||||
// Single dimension
|
||||
$this->assertSame(
|
||||
[[1, 'a'], [1, 'b'], [1, 'c']],
|
||||
Arr::crossJoin([1], ['a', 'b', 'c'])
|
||||
);
|
||||
// Square matrix
|
||||
$this->assertSame(
|
||||
[[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']],
|
||||
Arr::crossJoin([1, 2], ['a', 'b'])
|
||||
);
|
||||
// Rectangular matrix
|
||||
$this->assertSame(
|
||||
[[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']],
|
||||
Arr::crossJoin([1, 2], ['a', 'b', 'c'])
|
||||
);
|
||||
// 3D matrix
|
||||
$this->assertSame(
|
||||
[
|
||||
[1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'],
|
||||
[1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'],
|
||||
[2, 'a', 'I'], [2, 'a', 'II'], [2, 'a', 'III'],
|
||||
[2, 'b', 'I'], [2, 'b', 'II'], [2, 'b', 'III'],
|
||||
],
|
||||
Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II', 'III'])
|
||||
);
|
||||
// With 1 empty dimension
|
||||
$this->assertSame([], Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III']));
|
||||
$this->assertSame([], Arr::crossJoin([1, 2], [], ['I', 'II', 'III']));
|
||||
$this->assertSame([], Arr::crossJoin([1, 2], ['a', 'b'], []));
|
||||
// With empty arrays
|
||||
$this->assertSame([], Arr::crossJoin([], [], []));
|
||||
$this->assertSame([], Arr::crossJoin([], []));
|
||||
$this->assertSame([], Arr::crossJoin([]));
|
||||
// Not really a proper usage, still, test for preserving BC
|
||||
$this->assertSame([[]], Arr::crossJoin());
|
||||
}
|
||||
|
||||
public function testDivide()
|
||||
{
|
||||
list($keys, $values) = Arr::divide(['name' => 'ThinkPHP']);
|
||||
$this->assertSame(['name'], $keys);
|
||||
$this->assertSame(['ThinkPHP'], $values);
|
||||
}
|
||||
|
||||
public function testDot()
|
||||
{
|
||||
$array = Arr::dot(['foo' => ['bar' => 'baz']]);
|
||||
$this->assertSame(['foo.bar' => 'baz'], $array);
|
||||
$array = Arr::dot([]);
|
||||
$this->assertSame([], $array);
|
||||
$array = Arr::dot(['foo' => []]);
|
||||
$this->assertSame(['foo' => []], $array);
|
||||
$array = Arr::dot(['foo' => ['bar' => []]]);
|
||||
$this->assertSame(['foo.bar' => []], $array);
|
||||
}
|
||||
|
||||
public function testExcept()
|
||||
{
|
||||
$array = ['name' => 'ThinkPHP', 'price' => 100];
|
||||
$array = Arr::except($array, ['price']);
|
||||
$this->assertSame(['name' => 'ThinkPHP'], $array);
|
||||
}
|
||||
|
||||
public function testExists()
|
||||
{
|
||||
$this->assertTrue(Arr::exists([1], 0));
|
||||
$this->assertTrue(Arr::exists([null], 0));
|
||||
$this->assertTrue(Arr::exists(['a' => 1], 'a'));
|
||||
$this->assertTrue(Arr::exists(['a' => null], 'a'));
|
||||
$this->assertFalse(Arr::exists([1], 1));
|
||||
$this->assertFalse(Arr::exists([null], 1));
|
||||
$this->assertFalse(Arr::exists(['a' => 1], 0));
|
||||
}
|
||||
|
||||
public function testFirst()
|
||||
{
|
||||
$array = [100, 200, 300];
|
||||
$value = Arr::first($array, function ($value) {
|
||||
return $value >= 150;
|
||||
});
|
||||
$this->assertSame(200, $value);
|
||||
$this->assertSame(100, Arr::first($array));
|
||||
|
||||
$this->assertSame('default', Arr::first([], null, 'default'));
|
||||
|
||||
$this->assertSame('default', Arr::first([], function () {
|
||||
return false;
|
||||
}, 'default'));
|
||||
}
|
||||
|
||||
public function testLast()
|
||||
{
|
||||
$array = [100, 200, 300];
|
||||
$last = Arr::last($array, function ($value) {
|
||||
return $value < 250;
|
||||
});
|
||||
$this->assertSame(200, $last);
|
||||
$last = Arr::last($array, function ($value, $key) {
|
||||
return $key < 2;
|
||||
});
|
||||
$this->assertSame(200, $last);
|
||||
$this->assertSame(300, Arr::last($array));
|
||||
}
|
||||
|
||||
public function testFlatten()
|
||||
{
|
||||
// Flat arrays are unaffected
|
||||
$array = ['#foo', '#bar', '#baz'];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten(['#foo', '#bar', '#baz']));
|
||||
// Nested arrays are flattened with existing flat items
|
||||
$array = [['#foo', '#bar'], '#baz'];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Flattened array includes "null" items
|
||||
$array = [['#foo', null], '#baz', null];
|
||||
$this->assertSame(['#foo', null, '#baz', null], Arr::flatten($array));
|
||||
// Sets of nested arrays are flattened
|
||||
$array = [['#foo', '#bar'], ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Deeply nested arrays are flattened
|
||||
$array = [['#foo', ['#bar']], ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Nested arrays are flattened alongside arrays
|
||||
$array = [new Collection(['#foo', '#bar']), ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Nested arrays containing plain arrays are flattened
|
||||
$array = [new Collection(['#foo', ['#bar']]), ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Nested arrays containing arrays are flattened
|
||||
$array = [['#foo', new Collection(['#bar'])], ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#baz'], Arr::flatten($array));
|
||||
// Nested arrays containing arrays containing arrays are flattened
|
||||
$array = [['#foo', new Collection(['#bar', ['#zap']])], ['#baz']];
|
||||
$this->assertSame(['#foo', '#bar', '#zap', '#baz'], Arr::flatten($array));
|
||||
}
|
||||
|
||||
public function testFlattenWithDepth()
|
||||
{
|
||||
// No depth flattens recursively
|
||||
$array = [['#foo', ['#bar', ['#baz']]], '#zap'];
|
||||
$this->assertSame(['#foo', '#bar', '#baz', '#zap'], Arr::flatten($array));
|
||||
// Specifying a depth only flattens to that depth
|
||||
$array = [['#foo', ['#bar', ['#baz']]], '#zap'];
|
||||
$this->assertSame(['#foo', ['#bar', ['#baz']], '#zap'], Arr::flatten($array, 1));
|
||||
$array = [['#foo', ['#bar', ['#baz']]], '#zap'];
|
||||
$this->assertSame(['#foo', '#bar', ['#baz'], '#zap'], Arr::flatten($array, 2));
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
$array = ['products.item' => ['price' => 100]];
|
||||
$this->assertSame(['price' => 100], Arr::get($array, 'products.item'));
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
$value = Arr::get($array, 'products.item');
|
||||
$this->assertSame(['price' => 100], $value);
|
||||
// Test null array values
|
||||
$array = ['foo' => null, 'bar' => ['baz' => null]];
|
||||
$this->assertNull(Arr::get($array, 'foo', 'default'));
|
||||
$this->assertNull(Arr::get($array, 'bar.baz', 'default'));
|
||||
// Test null key returns the whole array
|
||||
$array = ['foo', 'bar'];
|
||||
$this->assertSame($array, Arr::get($array, null));
|
||||
// Test $array is empty and key is null
|
||||
$this->assertSame([], Arr::get([], null));
|
||||
$this->assertSame([], Arr::get([], null, 'default'));
|
||||
}
|
||||
|
||||
public function testHas()
|
||||
{
|
||||
$array = ['products.item' => ['price' => 100]];
|
||||
$this->assertTrue(Arr::has($array, 'products.item'));
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
$this->assertTrue(Arr::has($array, 'products.item'));
|
||||
$this->assertTrue(Arr::has($array, 'products.item.price'));
|
||||
$this->assertFalse(Arr::has($array, 'products.foo'));
|
||||
$this->assertFalse(Arr::has($array, 'products.item.foo'));
|
||||
$array = ['foo' => null, 'bar' => ['baz' => null]];
|
||||
$this->assertTrue(Arr::has($array, 'foo'));
|
||||
$this->assertTrue(Arr::has($array, 'bar.baz'));
|
||||
$array = ['foo', 'bar'];
|
||||
$this->assertFalse(Arr::has($array, null));
|
||||
$this->assertFalse(Arr::has([], null));
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
$this->assertTrue(Arr::has($array, ['products.item']));
|
||||
$this->assertTrue(Arr::has($array, ['products.item', 'products.item.price']));
|
||||
$this->assertTrue(Arr::has($array, ['products', 'products']));
|
||||
$this->assertFalse(Arr::has($array, ['foo']));
|
||||
$this->assertFalse(Arr::has($array, []));
|
||||
$this->assertFalse(Arr::has($array, ['products.item', 'products.price']));
|
||||
$this->assertFalse(Arr::has([], [null]));
|
||||
}
|
||||
|
||||
public function testIsAssoc()
|
||||
{
|
||||
$this->assertTrue(Arr::isAssoc(['a' => 'a', 0 => 'b']));
|
||||
$this->assertTrue(Arr::isAssoc([1 => 'a', 0 => 'b']));
|
||||
$this->assertTrue(Arr::isAssoc([1 => 'a', 2 => 'b']));
|
||||
$this->assertFalse(Arr::isAssoc([0 => 'a', 1 => 'b']));
|
||||
$this->assertFalse(Arr::isAssoc(['a', 'b']));
|
||||
}
|
||||
|
||||
public function testOnly()
|
||||
{
|
||||
$array = ['name' => 'ThinkPHP', 'price' => 100, 'orders' => 10];
|
||||
$array = Arr::only($array, ['name', 'price']);
|
||||
$this->assertSame(['name' => 'ThinkPHP', 'price' => 100], $array);
|
||||
}
|
||||
|
||||
public function testPrepend()
|
||||
{
|
||||
$array = Arr::prepend(['one', 'two', 'three', 'four'], 'zero');
|
||||
$this->assertSame(['zero', 'one', 'two', 'three', 'four'], $array);
|
||||
$array = Arr::prepend(['one' => 1, 'two' => 2], 0, 'zero');
|
||||
$this->assertSame(['zero' => 0, 'one' => 1, 'two' => 2], $array);
|
||||
}
|
||||
|
||||
public function testPull()
|
||||
{
|
||||
$array = ['name' => 'ThinkPHP', 'price' => 100];
|
||||
$name = Arr::pull($array, 'name');
|
||||
$this->assertSame('ThinkPHP', $name);
|
||||
$this->assertSame(['price' => 100], $array);
|
||||
// Only works on first level keys
|
||||
$array = ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane'];
|
||||
$name = Arr::pull($array, 'i@example.com');
|
||||
$this->assertSame('Joe', $name);
|
||||
$this->assertSame(['jack@localhost' => 'Jane'], $array);
|
||||
// Does not work for nested keys
|
||||
$array = ['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']];
|
||||
$name = Arr::pull($array, 'emails.i@example.com');
|
||||
$this->assertNull($name);
|
||||
$this->assertSame(['emails' => ['i@example.com' => 'Joe', 'jack@localhost' => 'Jane']], $array);
|
||||
}
|
||||
|
||||
public function testRandom()
|
||||
{
|
||||
$randomValue = Arr::random(['foo', 'bar', 'baz']);
|
||||
$this->assertContains($randomValue, ['foo', 'bar', 'baz']);
|
||||
$randomValues = Arr::random(['foo', 'bar', 'baz'], 1);
|
||||
$this->assertIsArray($randomValues);
|
||||
$this->assertCount(1, $randomValues);
|
||||
$this->assertContains($randomValues[0], ['foo', 'bar', 'baz']);
|
||||
$randomValues = Arr::random(['foo', 'bar', 'baz'], 2);
|
||||
$this->assertIsArray($randomValues);
|
||||
$this->assertCount(2, $randomValues);
|
||||
$this->assertContains($randomValues[0], ['foo', 'bar', 'baz']);
|
||||
$this->assertContains($randomValues[1], ['foo', 'bar', 'baz']);
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::set($array, 'products.item.price', 200);
|
||||
Arr::set($array, 'goods.item.price', 200);
|
||||
$this->assertSame(['products' => ['item' => ['price' => 200]], 'goods' => ['item' => ['price' => 200]]], $array);
|
||||
}
|
||||
|
||||
public function testWhere()
|
||||
{
|
||||
$array = [100, '200', 300, '400', 500];
|
||||
$array = Arr::where($array, function ($value, $key) {
|
||||
return is_string($value);
|
||||
});
|
||||
$this->assertSame([1 => '200', 3 => '400'], $array);
|
||||
}
|
||||
|
||||
public function testWhereKey()
|
||||
{
|
||||
$array = ['10' => 1, 'foo' => 3, 20 => 2];
|
||||
$array = Arr::where($array, function ($value, $key) {
|
||||
return is_numeric($key);
|
||||
});
|
||||
$this->assertSame(['10' => 1, 20 => 2], $array);
|
||||
}
|
||||
|
||||
public function testForget()
|
||||
{
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::forget($array, null);
|
||||
$this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::forget($array, []);
|
||||
$this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::forget($array, 'products.item');
|
||||
$this->assertSame(['products' => []], $array);
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::forget($array, 'products.item.price');
|
||||
$this->assertSame(['products' => ['item' => []]], $array);
|
||||
$array = ['products' => ['item' => ['price' => 100]]];
|
||||
Arr::forget($array, 'products.final.price');
|
||||
$this->assertSame(['products' => ['item' => ['price' => 100]]], $array);
|
||||
$array = ['shop' => ['cart' => [150 => 0]]];
|
||||
Arr::forget($array, 'shop.final.cart');
|
||||
$this->assertSame(['shop' => ['cart' => [150 => 0]]], $array);
|
||||
$array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]];
|
||||
Arr::forget($array, 'products.item.price.taxes');
|
||||
$this->assertSame(['products' => ['item' => ['price' => ['original' => 50]]]], $array);
|
||||
$array = ['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]];
|
||||
Arr::forget($array, 'products.item.final.taxes');
|
||||
$this->assertSame(['products' => ['item' => ['price' => ['original' => 50, 'taxes' => 60]]]], $array);
|
||||
$array = ['products' => ['item' => ['price' => 50], null => 'something']];
|
||||
Arr::forget($array, ['products.amount.all', 'products.item.price']);
|
||||
$this->assertSame(['products' => ['item' => [], null => 'something']], $array);
|
||||
// Only works on first level keys
|
||||
$array = ['i@example.com' => 'Joe', 'i@thinkphp.com' => 'Jane'];
|
||||
Arr::forget($array, 'i@example.com');
|
||||
$this->assertSame(['i@thinkphp.com' => 'Jane'], $array);
|
||||
// Does not work for nested keys
|
||||
$array = ['emails' => ['i@example.com' => ['name' => 'Joe'], 'jack@localhost' => ['name' => 'Jane']]];
|
||||
Arr::forget($array, ['emails.i@example.com', 'emails.jack@localhost']);
|
||||
$this->assertSame(['emails' => ['i@example.com' => ['name' => 'Joe']]], $array);
|
||||
}
|
||||
|
||||
public function testWrap()
|
||||
{
|
||||
$string = 'a';
|
||||
$array = ['a'];
|
||||
$object = new stdClass();
|
||||
$object->value = 'a';
|
||||
$this->assertSame(['a'], Arr::wrap($string));
|
||||
$this->assertSame($array, Arr::wrap($array));
|
||||
$this->assertSame([$object], Arr::wrap($object));
|
||||
}
|
||||
}
|
70
vendor/topthink/think-helper/tests/CollectionTest.php
vendored
Normal file
70
vendor/topthink/think-helper/tests/CollectionTest.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use think\Collection;
|
||||
|
||||
class CollectionTest extends TestCase
|
||||
{
|
||||
public function testMerge()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello']);
|
||||
$this->assertSame(['name' => 'Hello', 'id' => 1], $c->merge(['id' => 1])->all());
|
||||
}
|
||||
|
||||
public function testFirst()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertSame('Hello', $c->first());
|
||||
}
|
||||
|
||||
public function testLast()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertSame(25, $c->last());
|
||||
}
|
||||
|
||||
public function testToArray()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertSame(['name' => 'Hello', 'age' => 25], $c->toArray());
|
||||
}
|
||||
|
||||
public function testToJson()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertSame(json_encode(['name' => 'Hello', 'age' => 25]), $c->toJson());
|
||||
$this->assertSame(json_encode(['name' => 'Hello', 'age' => 25]), (string) $c);
|
||||
$this->assertSame(json_encode(['name' => 'Hello', 'age' => 25]), json_encode($c));
|
||||
}
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$sc = serialize($c);
|
||||
$c = unserialize($sc);
|
||||
|
||||
$this->assertSame(['name' => 'Hello', 'age' => 25], $c->all());
|
||||
}
|
||||
|
||||
public function testGetIterator()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertInstanceOf(\ArrayIterator::class, $c->getIterator());
|
||||
|
||||
$this->assertSame(['name' => 'Hello', 'age' => 25], $c->getIterator()->getArrayCopy());
|
||||
}
|
||||
|
||||
public function testCount()
|
||||
{
|
||||
$c = new Collection(['name' => 'Hello', 'age' => 25]);
|
||||
|
||||
$this->assertCount(2, $c);
|
||||
}
|
||||
}
|
59
vendor/topthink/think-helper/tests/StrTest.php
vendored
Normal file
59
vendor/topthink/think-helper/tests/StrTest.php
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
namespace Tests;
|
||||
|
||||
use think\helper\Str;
|
||||
|
||||
class StrTest extends TestCase
|
||||
{
|
||||
public function testCamel()
|
||||
{
|
||||
$this->assertSame('fooBar', Str::camel('FooBar'));
|
||||
$this->assertSame('fooBar', Str::camel('FooBar'));
|
||||
$this->assertSame('fooBar', Str::camel('foo_bar'));
|
||||
$this->assertSame('fooBar', Str::camel('_foo_bar'));
|
||||
$this->assertSame('fooBar', Str::camel('_foo_bar_'));
|
||||
}
|
||||
|
||||
public function testStudly()
|
||||
{
|
||||
$this->assertSame('FooBar', Str::studly('fooBar'));
|
||||
$this->assertSame('FooBar', Str::studly('_foo_bar'));
|
||||
$this->assertSame('FooBar', Str::studly('_foo_bar_'));
|
||||
$this->assertSame('FooBar', Str::studly('_foo_bar_'));
|
||||
}
|
||||
|
||||
public function testSnake()
|
||||
{
|
||||
$this->assertSame('think_p_h_p_framework', Str::snake('ThinkPHPFramework'));
|
||||
$this->assertSame('think_php_framework', Str::snake('ThinkPhpFramework'));
|
||||
$this->assertSame('think php framework', Str::snake('ThinkPhpFramework', ' '));
|
||||
$this->assertSame('think_php_framework', Str::snake('Think Php Framework'));
|
||||
$this->assertSame('think_php_framework', Str::snake('Think Php Framework '));
|
||||
// ensure cache keys don't overlap
|
||||
$this->assertSame('think__php__framework', Str::snake('ThinkPhpFramework', '__'));
|
||||
$this->assertSame('think_php_framework_', Str::snake('ThinkPhpFramework_', '_'));
|
||||
$this->assertSame('think_php_framework', Str::snake('think php Framework'));
|
||||
$this->assertSame('think_php_frame_work', Str::snake('think php FrameWork'));
|
||||
// prevent breaking changes
|
||||
$this->assertSame('foo-bar', Str::snake('foo-bar'));
|
||||
$this->assertSame('foo-_bar', Str::snake('Foo-Bar'));
|
||||
$this->assertSame('foo__bar', Str::snake('Foo_Bar'));
|
||||
$this->assertSame('żółtałódka', Str::snake('ŻółtaŁódka'));
|
||||
}
|
||||
|
||||
public function testTitle()
|
||||
{
|
||||
$this->assertSame('Welcome Back', Str::title('welcome back'));
|
||||
}
|
||||
|
||||
public function testRandom()
|
||||
{
|
||||
$this->assertIsString(Str::random(10));
|
||||
}
|
||||
|
||||
public function testUpper()
|
||||
{
|
||||
$this->assertSame('USERNAME', Str::upper('username'));
|
||||
$this->assertSame('USERNAME', Str::upper('userNaMe'));
|
||||
}
|
||||
}
|
13
vendor/topthink/think-helper/tests/TestCase.php
vendored
Normal file
13
vendor/topthink/think-helper/tests/TestCase.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase as BaseTestCase;
|
||||
|
||||
/**
|
||||
* Class TestCase
|
||||
* @author Tongle Xu <xutongle@gmail.com>
|
||||
*/
|
||||
class TestCase extends BaseTestCase
|
||||
{
|
||||
}
|
43
vendor/topthink/think-orm/src/Model.php
vendored
43
vendor/topthink/think-orm/src/Model.php
vendored
@ -243,6 +243,29 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
||||
}
|
||||
}
|
||||
|
||||
$this->filter(function ($result, $options) {
|
||||
// 关联查询
|
||||
if (!empty($options['relation'])) {
|
||||
$result->relationQuery($options['relation'], $options['with_relation_attr']);
|
||||
}
|
||||
|
||||
// 预载入查询
|
||||
if (empty($options['is_resultSet']) && !empty($options['with'])) {
|
||||
$result->eagerlyResult($result, $options['with'], $options['with_relation_attr'], false, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// JOIN预载入查询
|
||||
if (empty($options['is_resultSet']) && !empty($options['with_join'])) {
|
||||
$result->eagerlyResult($result, $options['with_join'], $options['with_relation_attr'], true, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// 关联统计
|
||||
if (!empty($options['with_count'])) {
|
||||
foreach ($options['with_count'] as $val) {
|
||||
$result->relationCount($this, (array) $val[0], $val[1], $val[2], false);
|
||||
}
|
||||
}
|
||||
});
|
||||
// 执行初始化操作
|
||||
$this->initialize();
|
||||
}
|
||||
@ -260,11 +283,12 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
||||
/**
|
||||
* 创建新的模型实例
|
||||
* @access public
|
||||
* @param array $data 数据
|
||||
* @param mixed $where 更新条件
|
||||
* @param array $data 数据
|
||||
* @param mixed $where 更新条件
|
||||
* @param array $options 参数
|
||||
* @return Model
|
||||
*/
|
||||
public function newInstance(array $data = [], $where = null): Model
|
||||
public function newInstance(array $data = [], $where = null, array $options = []): Model
|
||||
{
|
||||
$model = new static($data);
|
||||
|
||||
@ -284,6 +308,11 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
||||
|
||||
$model->setUpdateWhere($where);
|
||||
|
||||
// 查询数据处理
|
||||
foreach ($this->filter as $filter) {
|
||||
call_user_func_array($filter, [$model, $options]);
|
||||
}
|
||||
|
||||
$model->trigger('AfterRead');
|
||||
|
||||
return $model;
|
||||
@ -970,21 +999,25 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $value)
|
||||
{
|
||||
$this->setAttr($name, $value);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($name): bool
|
||||
{
|
||||
return $this->__isset($name);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($name)
|
||||
{
|
||||
$this->__unset($name);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($name)
|
||||
{
|
||||
return $this->getAttr($name);
|
||||
@ -1037,10 +1070,6 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
|
||||
return call_user_func_array(static::$macro[static::class][$method]->bindTo($this, static::class), $args);
|
||||
}
|
||||
|
||||
if ('withattr' == strtolower($method)) {
|
||||
return call_user_func_array([$this, 'withAttribute'], $args);
|
||||
}
|
||||
|
||||
return call_user_func_array([$this->db(), $method], $args);
|
||||
}
|
||||
|
||||
|
10
vendor/topthink/think-orm/src/Paginator.php
vendored
10
vendor/topthink/think-orm/src/Paginator.php
vendored
@ -410,7 +410,8 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
* @return Traversable An instance of an object implementing <b>Iterator</b> or
|
||||
* <b>Traversable</b>
|
||||
*/
|
||||
public function getIterator()
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->items->all());
|
||||
}
|
||||
@ -421,7 +422,8 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return $this->items->offsetExists($offset);
|
||||
}
|
||||
@ -432,6 +434,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->items->offsetGet($offset);
|
||||
@ -443,6 +446,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->items->offsetSet($offset, $value);
|
||||
@ -455,6 +459,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
* @return void
|
||||
* @since 5.0.0
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->items->offsetUnset($offset);
|
||||
@ -498,6 +503,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
|
17
vendor/topthink/think-orm/src/db/BaseQuery.php
vendored
17
vendor/topthink/think-orm/src/db/BaseQuery.php
vendored
@ -106,6 +106,12 @@ abstract class BaseQuery
|
||||
$name = Str::snake(substr($method, 5));
|
||||
array_unshift($args, $name);
|
||||
return call_user_func_array([$this, 'where'], $args);
|
||||
} elseif ($this->model && in_array($method, ['hidden', 'visible', 'append'])) {
|
||||
// 调用模型类方法
|
||||
$this->model->filter(function ($model, $options) use ($method, $args) {
|
||||
call_user_func_array([$model, $method], $args);
|
||||
});
|
||||
return $this;
|
||||
} elseif ($this->model && method_exists($this->model, 'scope' . $method)) {
|
||||
// 动态调用命名范围
|
||||
$method = 'scope' . $method;
|
||||
@ -137,7 +143,7 @@ abstract class BaseQuery
|
||||
$query->name($this->name);
|
||||
}
|
||||
|
||||
if (isset($this->options['json'])) {
|
||||
if (!empty($this->options['json'])) {
|
||||
$query->json($this->options['json'], $this->options['json_assoc']);
|
||||
}
|
||||
|
||||
@ -278,7 +284,9 @@ abstract class BaseQuery
|
||||
public function column($field, string $key = ''): array
|
||||
{
|
||||
$result = $this->connection->column($this, $field, $key);
|
||||
$this->resultSet($result, false);
|
||||
if (count($result) != count($result, 1)) {
|
||||
$this->resultSet($result, false);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -867,6 +875,7 @@ abstract class BaseQuery
|
||||
{
|
||||
$this->options['json'] = $json;
|
||||
$this->options['json_assoc'] = $assoc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -1124,7 +1133,7 @@ abstract class BaseQuery
|
||||
* 查找单条记录
|
||||
* @access public
|
||||
* @param mixed $data 查询数据
|
||||
* @return array|Model|null|static
|
||||
* @return array|Model|null|static|mixed
|
||||
* @throws Exception
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DataNotFoundException
|
||||
@ -1178,7 +1187,7 @@ abstract class BaseQuery
|
||||
$this->parseView($options);
|
||||
}
|
||||
|
||||
foreach (['data', 'order', 'join', 'union'] as $name) {
|
||||
foreach (['data', 'order', 'join', 'union', 'filter', 'json'] as $name) {
|
||||
if (!isset($options[$name])) {
|
||||
$options[$name] = [];
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ abstract class PDOConnection extends Connection
|
||||
*/
|
||||
protected function getFieldType(string $type): string
|
||||
{
|
||||
if (0 === strpos($type, 'set') || 0 === strpos($type, 'enum')) {
|
||||
if (0 === stripos($type, 'set') || 0 === stripos($type, 'enum')) {
|
||||
$result = 'string';
|
||||
} elseif (preg_match('/(double|float|decimal|real|numeric)/is', $type)) {
|
||||
$result = 'float';
|
||||
@ -287,11 +287,11 @@ abstract class PDOConnection extends Connection
|
||||
$result = 'int';
|
||||
} elseif (preg_match('/bool/is', $type)) {
|
||||
$result = 'bool';
|
||||
} elseif (0 === strpos($type, 'timestamp')) {
|
||||
} elseif (0 === stripos($type, 'timestamp')) {
|
||||
$result = 'timestamp';
|
||||
} elseif (0 === strpos($type, 'datetime')) {
|
||||
} elseif (0 === stripos($type, 'datetime')) {
|
||||
$result = 'datetime';
|
||||
} elseif (0 === strpos($type, 'date')) {
|
||||
} elseif (0 === stripos($type, 'date')) {
|
||||
$result = 'date';
|
||||
} else {
|
||||
$result = 'string';
|
||||
@ -1273,7 +1273,7 @@ abstract class PDOConnection extends Connection
|
||||
$type = is_array($val) ? $val[1] : PDO::PARAM_STR;
|
||||
|
||||
if (self::PARAM_FLOAT == $type || PDO::PARAM_STR == $type) {
|
||||
$value = '\'' . addslashes($value) . '\'';
|
||||
$value = '\'' . addcslashes($value, "'") . '\'';
|
||||
} elseif (PDO::PARAM_INT == $type && '' === $value) {
|
||||
$value = '0';
|
||||
}
|
||||
|
@ -94,4 +94,16 @@ class Sqlite extends Builder
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置锁机制
|
||||
* @access protected
|
||||
* @param Query $query 查询对象
|
||||
* @param bool|string $lock
|
||||
* @return string
|
||||
*/
|
||||
protected function parseLock(Query $query, $lock = false): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -51,42 +51,6 @@ trait ModelRelationQuery
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要隐藏的输出属性
|
||||
* @access public
|
||||
* @param array $hidden 需要隐藏的字段名
|
||||
* @return $this
|
||||
*/
|
||||
public function hidden(array $hidden)
|
||||
{
|
||||
$this->options['hidden'] = $hidden;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要输出的属性
|
||||
* @access public
|
||||
* @param array $visible 需要输出的属性
|
||||
* @return $this
|
||||
*/
|
||||
public function visible(array $visible)
|
||||
{
|
||||
$this->options['visible'] = $visible;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置需要追加输出的属性
|
||||
* @access public
|
||||
* @param array $append 需要追加的属性
|
||||
* @return $this
|
||||
*/
|
||||
public function append(array $append)
|
||||
{
|
||||
$this->options['append'] = $append;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加查询范围
|
||||
* @access public
|
||||
@ -187,7 +151,9 @@ trait ModelRelationQuery
|
||||
$this->options['with_attr'][$name] = $callback;
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $this->filter(function ($result) {
|
||||
return $this->getResultAttr($result, $this->options['with_attr']);
|
||||
}, 'with_attr');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -418,23 +384,10 @@ trait ModelRelationQuery
|
||||
return $this->model->toCollection();
|
||||
}
|
||||
|
||||
// 检查动态获取器
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
foreach ($this->options['with_attr'] as $name => $val) {
|
||||
if (strpos($name, '.')) {
|
||||
[$relation, $field] = explode('.', $name);
|
||||
|
||||
$withRelationAttr[$relation][$field] = $val;
|
||||
unset($this->options['with_attr'][$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$withRelationAttr = $withRelationAttr ?? [];
|
||||
|
||||
$withRelationAttr = $this->getWithRelationAttr();
|
||||
foreach ($resultSet as $key => &$result) {
|
||||
// 数据转换为模型对象
|
||||
$this->resultToModel($result, $this->options, true, $withRelationAttr);
|
||||
$this->resultToModel($result, $this->options, true);
|
||||
}
|
||||
|
||||
if (!empty($this->options['with'])) {
|
||||
@ -451,74 +404,75 @@ trait ModelRelationQuery
|
||||
return $this->model->toCollection($resultSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查动态获取器
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getWithRelationAttr(): array
|
||||
{
|
||||
if (isset($this->options['with_relation_attr'])) {
|
||||
return $this->options['with_relation_attr'];
|
||||
}
|
||||
|
||||
$withRelationAttr = [];
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
foreach ($this->options['with_attr'] as $name => $val) {
|
||||
if (strpos($name, '.')) {
|
||||
[$relation, $field] = explode('.', $name);
|
||||
|
||||
$withRelationAttr[$relation][$field] = $val;
|
||||
unset($this->options['with_attr'][$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->options['with_relation_attr'] = $withRelationAttr;
|
||||
return $withRelationAttr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据转换为模型对象
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @param array $options 查询参数
|
||||
* @param bool $resultSet 是否为数据集查询
|
||||
* @param array $withRelationAttr 关联字段获取器
|
||||
* @return void
|
||||
*/
|
||||
protected function resultToModel(array &$result, array $options = [], bool $resultSet = false, array $withRelationAttr = []): void
|
||||
protected function resultToModel(array &$result, array $options = [], bool $resultSet = false): void
|
||||
{
|
||||
// 动态获取器
|
||||
if (!empty($options['with_attr']) && empty($withRelationAttr)) {
|
||||
foreach ($options['with_attr'] as $name => $val) {
|
||||
if (strpos($name, '.')) {
|
||||
[$relation, $field] = explode('.', $name);
|
||||
|
||||
$withRelationAttr[$relation][$field] = $val;
|
||||
unset($options['with_attr'][$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$options['with_relation_attr'] = $this->getWithRelationAttr();
|
||||
$options['is_resultSet'] = $resultSet;
|
||||
|
||||
// JSON 数据处理
|
||||
if (!empty($options['json'])) {
|
||||
$this->jsonResult($result, $options['json'], $options['json_assoc'], $withRelationAttr);
|
||||
$this->jsonResult($result, $options['json'], $options['json_assoc'], $options['with_relation_attr']);
|
||||
}
|
||||
|
||||
$result = $this->model
|
||||
->newInstance($result, $resultSet ? null : $this->getModelUpdateCondition($options));
|
||||
|
||||
// 动态获取器
|
||||
if (!empty($options['with_attr'])) {
|
||||
$result->withAttribute($options['with_attr']);
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
$result = call_user_func($filter, $result);
|
||||
}
|
||||
|
||||
// 输出属性控制
|
||||
if (!empty($options['visible'])) {
|
||||
$result->visible($options['visible']);
|
||||
} elseif (!empty($options['hidden'])) {
|
||||
$result->hidden($options['hidden']);
|
||||
}
|
||||
|
||||
if (!empty($options['append'])) {
|
||||
$result->append($options['append']);
|
||||
}
|
||||
|
||||
// 关联查询
|
||||
if (!empty($options['relation'])) {
|
||||
$result->relationQuery($options['relation'], $withRelationAttr);
|
||||
}
|
||||
|
||||
// 预载入查询
|
||||
if (!$resultSet && !empty($options['with'])) {
|
||||
$result->eagerlyResult($result, $options['with'], $withRelationAttr, false, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// JOIN预载入查询
|
||||
if (!$resultSet && !empty($options['with_join'])) {
|
||||
$result->eagerlyResult($result, $options['with_join'], $withRelationAttr, true, $options['with_cache'] ?? false);
|
||||
}
|
||||
|
||||
// 关联统计
|
||||
if (!empty($options['with_count'])) {
|
||||
foreach ($options['with_count'] as $val) {
|
||||
$result->relationCount($this, (array) $val[0], $val[1], $val[2], false);
|
||||
}
|
||||
}
|
||||
$result = $this->model->newInstance($result, $resultSet ? null : $this->getModelUpdateCondition($options), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询软删除数据
|
||||
* @access public
|
||||
* @return Query
|
||||
*/
|
||||
public function withTrashed()
|
||||
{
|
||||
return $this->model ? $this->model->queryWithTrashed() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 只查询软删除数据
|
||||
* @access public
|
||||
* @return Query
|
||||
*/
|
||||
public function onlyTrashed()
|
||||
{
|
||||
return $this->model ? $this->model->queryOnlyTrashed() : $this;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,23 @@ use think\Model;
|
||||
*/
|
||||
trait ResultOperation
|
||||
{
|
||||
/**
|
||||
* 设置数据处理
|
||||
* @access public
|
||||
* @param callable $filter 数据处理Callable
|
||||
* @param string $index 索引(唯一)
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(callable $filter, string $index = null)
|
||||
{
|
||||
if ($index) {
|
||||
$this->options['filter'][$index] = $filter;
|
||||
} else {
|
||||
$this->options['filter'][] = $filter;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否允许返回空数据(或空模型)
|
||||
* @access public
|
||||
@ -62,11 +79,9 @@ trait ResultOperation
|
||||
$this->jsonResult($result, $this->options['json'], true);
|
||||
}
|
||||
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
$this->getResultAttr($result, $this->options['with_attr']);
|
||||
foreach ($this->options['filter'] as $filter) {
|
||||
$result = call_user_func($filter, $result);
|
||||
}
|
||||
|
||||
$this->filterResult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,22 +93,8 @@ trait ResultOperation
|
||||
*/
|
||||
protected function resultSet(array &$resultSet, bool $toCollection = true): void
|
||||
{
|
||||
if (!empty($this->options['json'])) {
|
||||
foreach ($resultSet as &$result) {
|
||||
$this->jsonResult($result, $this->options['json'], true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->options['with_attr'])) {
|
||||
foreach ($resultSet as &$result) {
|
||||
$this->getResultAttr($result, $this->options['with_attr']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->options['visible']) || !empty($this->options['hidden'])) {
|
||||
foreach ($resultSet as &$result) {
|
||||
$this->filterResult($result);
|
||||
}
|
||||
foreach ($resultSet as &$result) {
|
||||
$this->result($result);
|
||||
}
|
||||
|
||||
// 返回Collection对象
|
||||
@ -102,36 +103,14 @@ trait ResultOperation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据的可见和隐藏
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @return void
|
||||
*/
|
||||
protected function filterResult(&$result): void
|
||||
{
|
||||
$array = [];
|
||||
if (!empty($this->options['visible'])) {
|
||||
foreach ($this->options['visible'] as $key) {
|
||||
$array[] = $key;
|
||||
}
|
||||
$result = array_intersect_key($result, array_flip($array));
|
||||
} elseif (!empty($this->options['hidden'])) {
|
||||
foreach ($this->options['hidden'] as $key) {
|
||||
$array[] = $key;
|
||||
}
|
||||
$result = array_diff_key($result, array_flip($array));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用获取器处理数据
|
||||
* @access protected
|
||||
* @param array $result 查询数据
|
||||
* @param array $withAttr 字段获取器
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
protected function getResultAttr(array &$result, array $withAttr = []): void
|
||||
protected function getResultAttr(array $result, array $withAttr = []): array
|
||||
{
|
||||
foreach ($withAttr as $name => $closure) {
|
||||
$name = Str::snake($name);
|
||||
@ -147,6 +126,8 @@ trait ResultOperation
|
||||
$result[$name] = $closure($result[$name] ?? null, $result);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +151,7 @@ trait ResultOperation
|
||||
* 查找单条记录 不存在返回空数据(或者空模型)
|
||||
* @access public
|
||||
* @param mixed $data 数据
|
||||
* @return array|Model|static
|
||||
* @return array|Model|static|mixed
|
||||
*/
|
||||
public function findOrEmpty($data = null)
|
||||
{
|
||||
@ -242,7 +223,7 @@ trait ResultOperation
|
||||
* 查找单条记录 如果不存在则抛出异常
|
||||
* @access public
|
||||
* @param array|string|Query|Closure $data 数据
|
||||
* @return array|Model|static
|
||||
* @return array|Model|static|mixed
|
||||
* @throws ModelNotFoundException
|
||||
* @throws DataNotFoundException
|
||||
*/
|
||||
|
@ -361,9 +361,7 @@ trait WhereQuery
|
||||
$field = $this->options['via'] . '.' . $field;
|
||||
}
|
||||
|
||||
if ($field instanceof Raw) {
|
||||
return $this->whereRaw($field, is_array($op) ? $op : [], $logic);
|
||||
} elseif ($strict) {
|
||||
if ($strict) {
|
||||
// 使用严格模式查询
|
||||
if ('=' == $op) {
|
||||
$where = $this->whereEq($field, $condition);
|
||||
|
@ -157,7 +157,7 @@ class Collection extends BaseCollection
|
||||
public function withAttr($name, $callback = null)
|
||||
{
|
||||
$this->each(function (Model $model) use ($name, $callback) {
|
||||
$model->withAttribute($name, $callback);
|
||||
$model->withAttr($name, $callback);
|
||||
});
|
||||
|
||||
return $this;
|
||||
|
@ -106,6 +106,12 @@ trait Attribute
|
||||
*/
|
||||
private $withAttr = [];
|
||||
|
||||
/**
|
||||
* 数据处理
|
||||
* @var array
|
||||
*/
|
||||
private $filter = [];
|
||||
|
||||
/**
|
||||
* 获取模型对象的主键
|
||||
* @access public
|
||||
@ -177,6 +183,24 @@ trait Attribute
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置模型数据处理
|
||||
* @access public
|
||||
* @param callable $filter 数据处理Callable
|
||||
* @param string $index 索引(唯一)
|
||||
* @return $this
|
||||
*/
|
||||
public function filter(callable $filter, string $index = null)
|
||||
{
|
||||
if ($index) {
|
||||
$this->filter[$index] = $filter;
|
||||
} else {
|
||||
$this->filter[] = $filter;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实际的字段名
|
||||
* @access protected
|
||||
@ -633,11 +657,11 @@ trait Attribute
|
||||
* @param callable $callback 闭包获取器
|
||||
* @return $this
|
||||
*/
|
||||
public function withAttribute($name, callable $callback = null)
|
||||
public function withAttr($name, callable $callback = null)
|
||||
{
|
||||
if (is_array($name)) {
|
||||
foreach ($name as $key => $val) {
|
||||
$this->withAttribute($key, $val);
|
||||
$this->withAttr($key, $val);
|
||||
}
|
||||
} else {
|
||||
$name = $this->getRealFieldName($name);
|
||||
|
@ -330,6 +330,7 @@ trait Conversion
|
||||
}
|
||||
|
||||
// JsonSerializable
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
|
@ -55,6 +55,16 @@ trait SoftDelete
|
||||
return $model->withTrashedData(true)->db();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询软删除数据
|
||||
* @access public
|
||||
* @return Query
|
||||
*/
|
||||
public function queryWithTrashed(): Query
|
||||
{
|
||||
return $this->withTrashedData(true)->db();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含软删除数据
|
||||
* @access protected
|
||||
@ -86,6 +96,23 @@ trait SoftDelete
|
||||
return $model->db();
|
||||
}
|
||||
|
||||
/**
|
||||
* 只查询软删除数据
|
||||
* @access public
|
||||
* @return Query
|
||||
*/
|
||||
public function queryOnlyTrashed(): Query
|
||||
{
|
||||
$field = $this->getDeleteTimeField(true);
|
||||
|
||||
if ($field) {
|
||||
return $this->db()
|
||||
->useSoftDelete($field, $this->getWithTrashedExp());
|
||||
}
|
||||
|
||||
return $this->db();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取软删除数据的查询条件
|
||||
* @access protected
|
||||
@ -152,12 +179,12 @@ trait SoftDelete
|
||||
public static function destroy($data, bool $force = false): bool
|
||||
{
|
||||
// 传入空值(包括空字符串和空数组)的时候不会做任何的数据删除操作,但传入0则是有效的
|
||||
if(empty($data) && $data !== 0){
|
||||
if (empty($data) && 0 !== $data) {
|
||||
return false;
|
||||
}
|
||||
// 仅当强制删除时包含软删除数据
|
||||
$model = (new static());
|
||||
if($force){
|
||||
if ($force) {
|
||||
$model->withTrashedData(true);
|
||||
}
|
||||
$query = $model->db(false);
|
||||
|
@ -19,7 +19,6 @@ use think\db\Raw;
|
||||
use think\Model;
|
||||
use think\model\Pivot;
|
||||
use think\model\Relation;
|
||||
use think\Paginator;
|
||||
|
||||
/**
|
||||
* 多对多关联类
|
||||
@ -120,31 +119,6 @@ class BelongsToMany extends Relation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合成中间表模型
|
||||
* @access protected
|
||||
* @param array|Collection|Paginator $models
|
||||
*/
|
||||
protected function hydratePivot(iterable $models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$pivot = [];
|
||||
|
||||
foreach ($model->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
[$name, $attr] = explode('__', $key, 2);
|
||||
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($model->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$model->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟获取关联数据
|
||||
* @access public
|
||||
@ -158,62 +132,9 @@ class BelongsToMany extends Relation
|
||||
$closure($this->getClosureType($closure));
|
||||
}
|
||||
|
||||
$result = $this->relation($subRelation)
|
||||
return $this->relation($subRelation)
|
||||
->select()
|
||||
->setParent(clone $this->parent);
|
||||
|
||||
$this->hydratePivot($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载select方法
|
||||
* @access public
|
||||
* @param mixed $data
|
||||
* @return Collection
|
||||
*/
|
||||
public function select($data = null): Collection
|
||||
{
|
||||
$this->baseQuery();
|
||||
$result = $this->query->select($data);
|
||||
$this->hydratePivot($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载paginate方法
|
||||
* @access public
|
||||
* @param int|array $listRows
|
||||
* @param int|bool $simple
|
||||
* @return Paginator
|
||||
*/
|
||||
public function paginate($listRows = null, $simple = false): Paginator
|
||||
{
|
||||
$this->baseQuery();
|
||||
$result = $this->query->paginate($listRows, $simple);
|
||||
$this->hydratePivot($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载find方法
|
||||
* @access public
|
||||
* @param mixed $data
|
||||
* @return Model
|
||||
*/
|
||||
public function find($data = null)
|
||||
{
|
||||
$this->baseQuery();
|
||||
$result = $this->query->find($data);
|
||||
|
||||
if ($result && !$result->isEmpty()) {
|
||||
$this->hydratePivot([$result]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -673,6 +594,23 @@ class BelongsToMany extends Relation
|
||||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
|
||||
$this->query->getModel()->filter(function ($result, $options) {
|
||||
$pivot = [];
|
||||
|
||||
foreach ($result->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
[$name, $attr] = explode('__', $key, 2);
|
||||
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($result->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
||||
});
|
||||
|
||||
// 关联查询
|
||||
if (null === $this->parent->getKey()) {
|
||||
$condition = ['pivot.' . $localKey, 'exp', new Raw('=' . $this->parent->getTable() . '.' . $this->parent->getPk())];
|
||||
|
@ -17,7 +17,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="question-list">
|
||||
{volist name="artList" id="art"}
|
||||
{volist name="artList['data']" id="art"}
|
||||
<li>
|
||||
{if ($art.jie == 1)}
|
||||
<div class="que-sta-jie">
|
||||
@ -32,7 +32,7 @@
|
||||
{/if}
|
||||
<div class="que-body">
|
||||
<h2>
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color:'{$art.title_color}';">{$art.title}</a>
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color:{$art.title_color};">{$art.title}</a>
|
||||
</h2>
|
||||
<div class="que-user-info">
|
||||
<a href="{:url('user/home',['id'=>$art.user.id])}" class="que-avatar">
|
||||
@ -94,9 +94,9 @@
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'pages' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
,count: {$count} //数据总数,从服务端得到
|
||||
,limit: 15
|
||||
,curr : {$page}
|
||||
,count: "{$artList['total']}" //数据总数,从服务端得到
|
||||
,limit: "{$artList['per_page']}"
|
||||
,curr : "{$artList['current_page']}"
|
||||
|
||||
//获取起始页
|
||||
,jump: function(obj, first){
|
||||
|
@ -12,7 +12,7 @@
|
||||
<div class="fly-panel detail-box">
|
||||
{//标题}
|
||||
<div class="title layui-clear">
|
||||
<h1 style="color:'{$article.title_color}';">{$article.title}</h1>
|
||||
<h1 style="color:{$article.title_color};">{$article.title}</h1>
|
||||
{if ($article.jie == 0)}
|
||||
<span class="layui-btn layui-btn-xs" style="background-color: #FF5722;">{:lang('no finished')}</span>
|
||||
{else /}
|
||||
@ -30,7 +30,7 @@
|
||||
</a>
|
||||
<span class="user-post-time" data="{$article.create_time}" style="padding-top: 5px;">2019-12-01</span>
|
||||
<span class="user-questions-right">
|
||||
<i class="iconfont" title="{:lang('reply')}"></i>{$comments->count()}<i class="iconfont" title="浏览"></i>{$pv}
|
||||
<i class="iconfont" title="{:lang('reply')}"></i>{$article.comments_count}<i class="iconfont" title="浏览"></i>{$pv}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -88,9 +88,9 @@
|
||||
{/if}
|
||||
{//评论内容}
|
||||
<div class="fly-panel detail-box" id="flyReply">
|
||||
<span style="font-size:18px;">评论 {$comments->count()}</span>
|
||||
<span style="font-size:18px;">评论 {$article.comments_count}</span>
|
||||
<ul class="jieda" id="jieda">
|
||||
{volist name="comments" id="vo" empty= ""}
|
||||
{volist name="comments" id="vo" empty= ""}
|
||||
<li data-id="{$vo.id}" class="jieda-daan">
|
||||
<a name="item-1111111111"></a>
|
||||
<div class="detail-about detail-about-reply">
|
||||
@ -104,7 +104,7 @@
|
||||
{if condition="$article.user.id eq $vo.user.id"}<span>({:lang('poster')})</span>{/if}
|
||||
</div>
|
||||
<div class="detail-hits"><span class="post-time" data="{$vo.create_time}"></span></div>
|
||||
{if $vo.cai == 1}<i class="iconfont icon-caina" title="最佳答案"></i>{/if}
|
||||
{if $vo.cai == 1}<i class="iconfont icon-caina" title="最佳答案"></i>{/if}
|
||||
</div>
|
||||
<div class="detail-body jieda-body photos">{$vo.content}</div>
|
||||
<div class="jieda-reply">
|
||||
@ -112,19 +112,19 @@
|
||||
<i class="iconfont icon-zan"></i><em>{$vo.zan}</em>赞
|
||||
</span>
|
||||
<span type="reply"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
|
||||
{//评论编辑删除采纳权限}
|
||||
{//评论编辑删除采纳权限}
|
||||
<div class="jieda-admin">
|
||||
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
|
||||
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
|
||||
<span type="edit">{:lang('edit')}</span>
|
||||
<span type="del">{:lang('delete')}</span>
|
||||
{/if}
|
||||
{if ($vo.cai == 0) && ((session('user_id') == $article.user_id) OR ($user.auth ?? '')) /}<span class="jieda-accept" type="accept">{:lang('accept')}</span>{/if}
|
||||
{/if}
|
||||
{if ($vo.cai == 0) && ((session('user_id') == $article.user_id) OR ($user.auth ?? '')) /}<span class="jieda-accept" type="accept">{:lang('accept')}</span>{/if}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{/volist}
|
||||
</ul>
|
||||
<div style="text-align: center">{$comments|raw}</div>
|
||||
<div style="text-align: center" id="pages"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -285,7 +285,7 @@ layui.use(['fly', 'face','colorpicker','plyr', 'laypage'], function(){
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'pages' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
,count: {$count} //数据总数,从服务端得到
|
||||
,count: "{$article.comments_count}" //数据总数,从服务端得到
|
||||
,limit: 10
|
||||
,curr : {$page}
|
||||
|
||||
@ -294,8 +294,10 @@ layui.use(['fly', 'face','colorpicker','plyr', 'laypage'], function(){
|
||||
//首次不执行
|
||||
if(!first){
|
||||
var page = obj.curr;
|
||||
var url = "{:url('article/detail',['id'=>$article.id])}"
|
||||
$.post(url,{"page":page},function(){
|
||||
console.log(page);
|
||||
var url = "{:url('article/detail',['id'=>$article.id])}";
|
||||
var id = "{$article.id}";
|
||||
$.post("{:url('article/detail')}",{"page":page,"id":id},function(){
|
||||
window.location.href = url + '?page=' + page + '#flyReply';
|
||||
});
|
||||
}
|
||||
|
@ -12,14 +12,14 @@
|
||||
|
||||
{include file="public/filter" /}
|
||||
<ul class="fly-list">
|
||||
{volist name="artList" id="art"}
|
||||
{volist name="artList['data']" id="art"}
|
||||
<li>
|
||||
<a href="{:url('user/home',['id'=>$art.user.id])}" class="fly-avatar">
|
||||
<a href="{:url('user/home',['id'=>$art.user_id])}" class="fly-avatar">
|
||||
<img src="{$art.user.user_img}" alt="{$art.user.name}">
|
||||
</a>
|
||||
<h2>
|
||||
{if config('taoler.config.cate_show') == 1}<a class="layui-badge">{:cookie('think_lang') == 'en-us' ? $art.cate.ename : $art.cate.catename}</a>{/if}
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color:{$art.title_color};">{$art.title}</a>
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color: {$art['title_color']};">{$art.title}</a>
|
||||
</h2>
|
||||
<div class="fly-list-info">
|
||||
<a href="{:url('user/home',['id'=>$art.user.id])}" link>
|
||||
@ -95,19 +95,20 @@
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'pages' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
,count: {$count} //数据总数,从服务端得到
|
||||
,limit: 15
|
||||
,curr :{$page}
|
||||
,count: "{$artList['total']}" //数据总数,从服务端得到
|
||||
,limit: "{$artList['per_page']}"
|
||||
,curr : "{$artList['current_page']}"
|
||||
//获取起始页
|
||||
,jump: function(obj, first){
|
||||
//obj包含了当前分页的所有参数,比如:
|
||||
//console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
|
||||
//console.log(obj.limit); //得到每页显示的条数
|
||||
//首次不执行
|
||||
if(!first){
|
||||
//do something
|
||||
//window.location.href= url+obj.curr+'&limit='+obj.limit+'#collection'; //跳转
|
||||
window.location.href = '{$url}'+obj.curr+'.html'; //跳转
|
||||
//var page = obj.curr ? obj.curr : 1;
|
||||
window.location.href = '{$url}'+ obj.curr +'.html'; //跳转
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -10,14 +10,14 @@
|
||||
<div class="layui-col-md9">
|
||||
<div class="fly-panel" style="margin-bottom: 0;">
|
||||
<ul class="fly-list">
|
||||
{volist name="artList" id="art"}
|
||||
{volist name="artList['data']" id="art"}
|
||||
<li>
|
||||
<a href="{:url('user/home',['id'=>$art.user.id])}" class="fly-avatar">
|
||||
<img src="{$art.user.user_img}" alt="{$art.user.name}">
|
||||
</a>
|
||||
<h2>
|
||||
{if config('taoler.config.cate_show') == 1}<a class="layui-badge">{:cookie('think_lang') == 'en-us' ? $art.cate.ename : $art.cate.catename}</a>{/if}
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color:'{$art.title_color}';">{$art.title}</a>
|
||||
<a href="{:url('article/detail',['id' => $art.id])}" style="color:{$art.title_color};">{$art.title}</a>
|
||||
</h2>
|
||||
<div class="fly-list-info">
|
||||
<a href="{:url('user/home',['id'=>$art.user.id])}" link>
|
||||
@ -86,9 +86,9 @@
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'pages' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
,count: {$count} //数据总数,从服务端得到
|
||||
,limit: 15
|
||||
,curr : {$page}
|
||||
,count: "{$artList['total']}" //数据总数,从服务端得到
|
||||
,limit: "{$artList['per_page']}"
|
||||
,curr : "{$artList['current_page']}"
|
||||
|
||||
//获取起始页
|
||||
,jump: function(obj, first){
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div class="layui-col-md9 content detail">
|
||||
<div class="fly-panel detail-box">
|
||||
{//标题}
|
||||
<h1 style="color:'{$article.title_color}';">{$article.title}</h1>
|
||||
<h1 style="color:{$article.title_color};">{$article.title}</h1>
|
||||
<div class="detail_qrcode layui-hide-xs" onclick="PhoneDown();" id="mobile"></div>
|
||||
{//图标}
|
||||
<div class="fly-detail-info">
|
||||
@ -20,7 +20,7 @@
|
||||
{if ($article.is_hot == 1)}<span class="layui-badge layui-bg-red">{:lang('hot')}</span>{/if}
|
||||
<span id="LAY_jieAdmin" data-id="{$article['id']}"></span>
|
||||
<span class="fly-list-nums">
|
||||
<a href="#comment"><i class="iconfont" title="{:lang('reply')}"></i>{$comments->count()}</a><i class="iconfont" title="浏览"></i>{$pv}
|
||||
<a href="#comment"><i class="iconfont" title="{:lang('reply')}"></i>{$article.comments_count}</a><i class="iconfont" title="浏览"></i>{$pv}
|
||||
</span>
|
||||
</div>
|
||||
{//作者}
|
||||
@ -75,13 +75,13 @@
|
||||
</div>
|
||||
{//评论}
|
||||
<div class="fly-panel detail-box" id="flyReply">
|
||||
<span style="font-size:18px;">评论 {$comments->count()}</span>
|
||||
<span style="font-size:18px;">评论 {$article.comments_count}</span>
|
||||
<ul class="jieda" id="jieda">
|
||||
{volist name="comments" id="vo" empty= ""}
|
||||
<li data-id="{$vo.id}" class="jieda-daan">
|
||||
<a name="item-1111111111"></a>
|
||||
<div class="detail-about detail-about-reply">
|
||||
<a class="fly-avatar" href="{:url('user/home',['id'=>$vo.user.id])}">
|
||||
<a class="fly-avatar" href="{:url('user/home',['id'=>$vo.user_id])}">
|
||||
<img src="{$vo.user.user_img}" alt=" "><i class="iconfont icon-renzheng" title="认证信息"></i>
|
||||
</a>
|
||||
<div class="fly-detail-user">
|
||||
@ -262,7 +262,7 @@ layui.use(['fly', 'face','colorpicker','plyr', 'laypage'], function(){
|
||||
//执行一个laypage实例
|
||||
laypage.render({
|
||||
elem: 'pages' //注意,这里的 test1 是 ID,不用加 # 号
|
||||
,count: {$count} //数据总数,从服务端得到
|
||||
,count: "{$article.comments_count}" //数据总数,从服务端得到
|
||||
,limit: 10
|
||||
,curr : {$page}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
</ul>
|
||||
<div style="text-align: center">
|
||||
<div class="laypage-main">
|
||||
<a href="{:url('article/cate',['ename'=>'all'])}" class="laypage-next">{:lang('more post')}</a>
|
||||
<a href="{:url('article/cate',['ename'=>'all','page'=>1])}" class="laypage-next">{:lang('more post')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user