国庆版

This commit is contained in:
taoser 2022-11-18 10:31:44 +08:00
parent ac251681e2
commit e81de0d307
146 changed files with 19723 additions and 742 deletions

View File

@ -5,6 +5,7 @@ namespace app;
use think\App;
use think\exception\ValidateException;
use think\response\Json;
use think\Validate;
use think\Response;
use think\exception\HttpResponseException;
@ -410,7 +411,7 @@ abstract class BaseController
/**
* 标题调用百度关键词词条
*
* @return void
* @return Json
*/
public function getBdiduSearchWordList($words)
{

View File

@ -18,6 +18,6 @@ class Request extends \think\Request
//protected $filter = ['trim','htmlspecialchars'];
//protected $filter = ['trim','strip_tags'];
//protected $filter = ['htmlspecialchars'];
//protected $filter = ['trim'];
protected $filter = ['trim'];
}

View File

@ -2,14 +2,16 @@
namespace app\admin\controller;
use app\common\controller\AdminController;
use app\common\lib\SqlFile;
use think\facade\View;
use think\facade\Db;
use think\facade\Request;
use think\facade\Config;
use app\admin\model\Addons as AddonsModel;
use taoler\com\Files;
use taoler\com\Api;
use app\common\lib\Zip;
use think\response\Json;
use app\admin\model\AuthRule;
class Addons extends AdminController
{
@ -20,8 +22,12 @@ class Addons extends AdminController
{
return View::fetch();
}
public function addonsList()
/**
* 插件列表
* @return Json
*/
public function addonsList() :Json
{
$type = input('type');
@ -59,24 +65,21 @@ class Addons extends AdminController
//在线
case 'onlineAddons':
$url = $this->getSystem()['api_url'].'/v1/addons';
$addons = Api::urlGet($url,[]);
$addons = Api::urlGet($url);
if( $addons->code !== -1){
$res['code'] = 0;
$res['msg'] = '';
$res['data'] = $addons->data;
$res['col'] = [
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'title','title'=> '插件', 'width'=> 200],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'price','title'=> '价格(元)'],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'vers','title'=> '版本选择','exportTemplet' => "function(d, obj){console.log(obj) var td = obj.td(this.field); return td.find('select').val();}"],
['field' => 'ctime','title'=> '时间', 'width'=> 150],
['title' => '操作', 'width'=> 300, 'align'=>'center', 'toolbar'=> '#addons-tool']
['field' => 'price','title'=> '价格(元)','width'=> 80],
['field' => 'downloads','title'=> '下载', 'width'=> 70],
['field' => 'version','title'=> '版本', 'width'=> 70],
['field' => 'status','title'=> '状态', 'width'=> 70],
['title' => '操作', 'width'=> 180, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
} else {
$res = ['code'=>-1,'msg'=>'未获取到服务器信息'];
@ -112,9 +115,11 @@ class Addons extends AdminController
/**
* 编辑版本
*
* @param int $id
* @return \think\Response
* @param $id
* @return string|Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function edit($id)
{
@ -135,11 +140,8 @@ class Addons extends AdminController
}
/**
* 上传版本的zip资源
*
* @param
* @param int $id
* @return \think\Response
* 上传插件文件zip
* @return Json
*/
public function uploadZip()
{
@ -148,88 +150,113 @@ class Addons extends AdminController
try {
validate(['file'=>'filesize:2048|fileExt:zip,rar,7z'])
->check(array($file));
$savename = \think\facade\Filesystem::disk('public')->putFile('addons',$file);
$saveName = \think\facade\Filesystem::disk('public')->putFile('addons',$file);
} catch (\think\exception\ValidateException $e) {
echo $e->getMessage();
return json(['code' => -1,'msg' => $e->getMessage()]);
}
$upload = Config::get('filesystem.disks.public.url');
if($savename){
$name_path =str_replace('\\',"/",$upload.'/'.$savename);
$res = ['code'=>0,'msg'=>'插件上传成功','src'=>$name_path];
} else {
$res = ['code'=>-1,'msg'=>'上传错误'];
}
if($saveName){
$name_path =str_replace('\\',"/",$upload.'/'.$saveName);
$res = ['code'=>0,'msg'=>'插件上传成功','src'=>$name_path];
} else {
$res = ['code'=>-1,'msg'=>'上传错误'];
}
return json($res);
}
//安装插件
public function install()
{
$data = Request::param();
$data = Request::param();
$url = $this->getSystem()['api_url'].'/v1/getaddons';
$addons = Api::urlPost($url,['name'=>$data['name'],'version'=>$data['version']]);
if( $addons->code == -1) {
return json(['code'=>$addons->code,'msg'=>$addons->msg]);
}
//是否安装?
$addInstalledVersion = get_addons_info($data['name']);
if(!empty($addInstalledVersion)){
$verRes = version_compare($data['version'],$addInstalledVersion['version'],'>');
if(!$verRes){
return json(['code'=>-1,'msg'=>'不能降级,请选择正确版本']);
}
//$tpl_ver_res = version_compare($addInstalledVersion['template_version'], config('taoler.template_version'),'<');
}
$addons = Api::urlPost($url,['name'=>$data['name'],'version'=>$data['version']]);
if( $addons->code == -1) {
return json(['code'=>$addons->code,'msg'=>$addons->msg]);
}
//是否安装?
$addInstalledVersion = get_addons_info($data['name']);
// if(!empty($addInstalledVersion)){
// $verRes = version_compare($data['version'],$addInstalledVersion['version'],'>');
// if(!$verRes){
// return json(['code'=>-1,'msg'=>'不能降级,请选择正确版本']);
// }
// //$tpl_ver_res = version_compare($addInstalledVersion['template_version'], config('taoler.template_version'),'<');
// }
$file_url = $addons->addons_src;
//判断远程文件是否可用存在
$header = get_headers($file_url, true);
if(!isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'))){
return json(['code'=>-1,'msg'=>'获取远程文件失败']);
$file_url = $addons->addons_src;
//判断远程文件是否可用存在
$header = get_headers($file_url, true);
if(!isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'))){
return json(['code'=>-1,'msg'=>'获取远程文件失败']);
}
//把远程文件放入本地
//拼接路径
$addons_dir = Files::getDirPath('../runtime/addons/');
Files::mkdirs($addons_dir);
$package_file = $addons_dir . $data['name'] .'.zip'; //升级的压缩包文件
$cpfile = copy($file_url,$package_file);
if(!$cpfile) return json(['code'=>-1,'msg'=>'下载升级文件失败']);
$uzip = new Zip();
$zipDir = strstr($package_file, '.zip',true); //返回文件名后缀前的字符串
$zipPath = Files::getDirPath($zipDir); //转换为带/的路径 压缩文件解压到的路径
$unzip_res = $uzip->unzip($package_file,$zipPath,true);
if(!$unzip_res) return json(['code'=>-1,'msg'=>'解压失败']);
//升级插件
//升级前的写入文件权限检查
$allUpdateFiles = Files::getAllFile($zipPath);
if (empty($allUpdateFiles)) return json(['code' => -1, 'msg' => '无可更新文件。']);
$checkString = '';
foreach ($allUpdateFiles as $updateFile) {
$coverFile = ltrim(str_replace($zipPath, '', $updateFile), DIRECTORY_SEPARATOR);
$dirPath = dirname('../'.$coverFile);
if (file_exists('../'.$coverFile)) {
if (!is_writable('../'.$coverFile)) $checkString .= $coverFile . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
} else {
if (!is_dir($dirPath)) @mkdir($dirPath, 0777, true);
if (!is_writable($dirPath)) $checkString .= $dirPath . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
}
}
if (!empty($checkString)) return json(['code' => -1, 'msg' => $checkString]);
$addonsPath = '../';
$cpRes = Files::copyDirs($zipPath,$addonsPath);
$cpData = $cpRes->getData();
//更新失败
if($cpData['code'] == -1) return json(['code'=>-1,'msg'=>$cpData['msg']]);
//添加数据库
$sqlInstallFile = root_path().'addons/'.$data['name'].'/install.sql';
if(file_exists($sqlInstallFile)) {
SqlFile::dbExecute($sqlInstallFile);
}
//安装菜单
$menuFile = root_path().'addons/'.$data['name'].'/menu.php';
if(file_exists($menuFile)) {
include_once $menuFile;
$menu = Config::get('menu');
if(!empty($menu)){
if(isset($menu['is_nav']) && $menu['is_nav']==1){
$pid = 0;
}else{
$pid = AuthRule::where('name','addons')->value('id');
}
$menu_arr[] = $menu['menu'];
$this->addAddonMenu($menu_arr, (int)$pid,1);
}
}
//把远程文件放入本地
//拼接路径
$addons_dir = Files::getDirPath('../runtime/addons/');
Files::mkdirs($addons_dir);
$package_file = $addons_dir . $data['name'] .'.zip'; //升级的压缩包文件
$cpfile = copy($file_url,$package_file);
if(!$cpfile) return json(['code'=>-1,'msg'=>'下载升级文件失败']);
$uzip = new Zip();
$zipDir = strstr($package_file, '.zip',true); //返回文件名后缀前的字符串
$zipPath = Files::getDirPath($zipDir); //转换为带/的路径 压缩文件解压到的路径
$unzip_res = $uzip->unzip($package_file,$zipPath,true);
if(!$unzip_res) return json(['code'=>-1,'msg'=>'解压失败']);
//升级插件
//升级前的写入文件权限检查
$allUpdateFiles = Files::getAllFile($zipPath);
if (empty($allUpdateFiles)) return json(['code' => -1, 'msg' => '无可更新文件。']);
$checkString = '';
foreach ($allUpdateFiles as $updateFile) {
$coverFile = ltrim(str_replace($zipPath, '', $updateFile), DIRECTORY_SEPARATOR);
$dirPath = dirname('../'.$coverFile);
if (file_exists('../'.$coverFile)) {
if (!is_writable('../'.$coverFile)) $checkString .= $coverFile . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
} else {
if (!is_dir($dirPath)) @mkdir($dirPath, 0777, true);
if (!is_writable($dirPath)) $checkString .= $dirPath . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
}
}
if (!empty($checkString)) return json(['code' => -1, 'msg' => $checkString]);
$addonsPath = '../';
$cpRes = Files::copyDirs($zipPath,$addonsPath);
$cpData = $cpRes->getData();
//更新失败
if($cpData['code'] == -1) return json(['code'=>-1,'msg'=>$cpData['msg']]);
Files::delDirAndFile('../runtime/addons/');
return json(['code'=>0,'msg'=>'插件安装成功!']);
@ -244,6 +271,23 @@ class Addons extends AdminController
$addonsPath = '../addons/'.$name;
$staticPath = 'addons/'.$name;
//卸载菜单
$menuFile = root_path().'addons/'.$name.'/menu.php';
if(file_exists($menuFile)) {
include_once $menuFile;
$menu = Config::get('menu');
if(!empty($menu)){
$menu_arr[] = $menu['menu'];
$this->delAddonMenu($menu_arr);
}
}
//卸载插件数据库
$sqlUninstallFile = root_path().'addons/'.$name.'/uninstall.sql';
if(file_exists($sqlUninstallFile)) {
SqlFile::dbExecute($sqlUninstallFile);
}
if (is_dir($staticPath)) {
Files::delDir($staticPath);
}
@ -253,6 +297,7 @@ class Addons extends AdminController
} else {
return json(['code'=>-1,'msg'=>'卸载失败']);
}
return json(['code'=>0,'msg'=>'卸载成功']);
}
//启用插件
@ -317,4 +362,52 @@ class Addons extends AdminController
return View::fetch();
}
public function addAddonMenu(array $menu,int $pid = 0, int $type = 1)
{
foreach ($menu as $v){
$hasChild = isset($v['sublist']) && $v['sublist'] ? true : false;
try {
$v['pid'] = $pid;
$v['name'] = trim($v['name'],'/');
$v['type'] = $type;
$menu = AuthRule::withTrashed()->where('name',$v['name'])->find();
if($menu){
$menu->restore();
} else {
$menu = AuthRule::create($v);
}
if ($hasChild) {
$this->addAddonMenu($v['sublist'], $menu->id,$type);
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
//循环删除菜单
public function delAddonMenu(array $menu,string $module = 'addon')
{
foreach ($menu as $k=>$v){
$hasChild = isset($v['sublist']) && $v['sublist'] ? true : false;
try {
$v['name'] = trim($v['name'],'/');
$menu_rule = AuthRule::withTrashed()->where('name',$v['name'])->find();
if($menu_rule){
$menu_rule->delete(true);
if ($hasChild) {
$this->delAddonMenu($v['sublist']);
}
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
}

View File

@ -2,6 +2,7 @@
namespace app\admin\controller;
use app\common\controller\AdminController;
use think\App;
use think\facade\Request;
use think\facade\Db;
use think\facade\View;
@ -9,27 +10,20 @@ use app\admin\model\AuthRule as AuthRuleModel;
class AuthRule extends AdminController
{
//
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new AuthRuleModel();
}
/**
* 菜单列表
*/
public function index()
{
if(Request::isAjax()){
$rule = new AuthRuleModel();
$auth_rules = $rule->authRuleTree();
$count = count($auth_rules);
$res = [];
if($auth_rules){
$res = ['code'=>0,'msg'=>'ok','count'=>$count];
foreach($auth_rules as $k => $v){
//$data = $v->getData();
$data = ['id'=>$v['id'],'pid'=>$v['pid'],'title'=>$v['title'],'url'=>$v['name'],'icon'=>$v['icon'],'status'=>$v['status'],'isMenu'=>$v['ishidden'],'sort'=>$v['sort'],'ctime'=>$v['create_time']];
$res['data'][] = $data;
}
}
return json($res);
return $this->model->getAuthRuleTree();
}
return View::fetch();
@ -88,24 +82,19 @@ class AuthRule extends AdminController
{
if(Request::isAjax()){
$data = Request::param();
$plevel = Db::name('auth_rule')->field('level')->find($data['pid']);
//层级level
$plevel = Db::name('auth_rule')->field('level')->find($data['pid']);
if($plevel){
$data['level'] = $plevel['level']+1;
} else {
$data['level'] = 0;
}
$data['create_time'] = time();
$list = Db::name('auth_rule')->save($data);
if($list){
return json(['code'=>0,'msg'=>'添加权限成功']);
}else{
return json(['code'=>-1,'msg'=>'添加权限失败']);
}
return $this->model->saveRule($data);
}
$rule = new AuthRuleModel();
$auth_rules = $rule->authRuleTree();
$auth_rules = $this->model->getAuthRuleTree();
View::assign('AuthRule',$auth_rules);
return View::fetch();
}
@ -116,33 +105,27 @@ class AuthRule extends AdminController
$rule = new AuthRuleModel();
if(Request::isAjax()){
$data = Request::param(['id','pid','title','name','icon','sort','ishidden']);
$ruId = $rule->find($data['pid']); //查询出上级ID
$data = Request::param(['id','pid','title','name','icon','sort','ismenu']);
//层级level
$ruId = $rule->find($data['pid']); //查询出上级ID
if($ruId){
$plevel = $ruId->level; //上级level等级
$data['level'] = $plevel+1;
} else {
$data['level'] = 0;
}
$zi = $rule->where('pid',$data['id'])->select();//查询出下级
$zi = $this->model->where('pid',$data['id'])->select();//查询出下级
if(!empty($zi)){
$zi->update(['level'=>$data['level']+1]);
}
if($zi){
$zi->update(['level'=>$data['level']+1]);
}
$save = AuthRuleModel::update($data);
if($save){
$res = ['code'=>0,'msg'=>'修改成功'];
} else {
$res = ['code'=>-1,'msg'=>'修改失败'];
}
return json($res);
$rule = $this->model->find($data['id']);
return $rule->saveRule($data);
}
$auth_rules = $rule->authRuleTree();
$rules = $rule->find(input('id'));
$auth_rules = $this->model->getAuthRuleTree();
$rules = $this->model->find(input('id'));
View::assign(['AuthRule'=>$auth_rules,'rules'=>$rules]);
return View::fetch();
}
@ -174,7 +157,7 @@ class AuthRule extends AdminController
$data = Request::param();
$rules = Db::name('auth_rule')->save($data);
if($rules){
if($data['ishidden'] == 1){
if($data['ismenu'] == 1){
return json(['code'=>0,'msg'=>'设置菜单显示','icon'=>6]);
} else {
return json(['code'=>0,'msg'=>'取消菜单显示','icon'=>5]);

View File

@ -12,6 +12,7 @@ use think\facade\Db;
use think\facade\Cache;
use taoler\com\Files;
use app\common\lib\Msgres;
use think\response\Json;
class Forum extends AdminController
{
@ -103,7 +104,7 @@ class Forum extends AdminController
if(Request::isAjax()){
$arr = explode(",",$id);
foreach($arr as $v){
$article =Article::find($v);
$article = Article::find($v);
$result = $article->together(['comments'])->delete();
}
@ -118,7 +119,7 @@ class Forum extends AdminController
/**
* 置顶、加精、评论开关,审核等状态管理
*
* @return void
* @return Json
*/
public function check()
{
@ -137,18 +138,9 @@ class Forum extends AdminController
//帖子分类
public function tags()
{
$cate = new Cate();
if(Request::isAjax()){
$list = Cate::select();
if($list){
$res['code'] = 0;
$res['msg'] = '';
$res['count']= count($list);
$res['data'] = [];
foreach($list as $k=>$v){
$res['data'][] = ['sort'=>$v['sort'],'id' => $v['id'],'pid'=>$v['pid'],'tags'=>$v['catename'],'ename'=>$v['ename'],'detpl'=>$v['detpl'],'icon'=>$v['icon'],'is_hot'=>$v['is_hot'],'desc'=>$v['desc']];
}
}
return json($res);
return $cate->getList();
}
//详情模板
$sys = $this->getSystem();
@ -482,20 +474,19 @@ class Forum extends AdminController
/**
* 调用百度关键词
*
* @return void
* @return json
*/
public function getKeywords()
{
$data = Request::only(['tags','flag']);
$data = Request::only(['flag','keywords','content']);
return $this->setKeywords($data);
}
/**
* 标题调用百度关键词词条
*
* @return void
*/
/**
* 标题调用百度关键词词条
* @return Json
*/
public function getWordList()
{
$title = input('title');
@ -507,7 +498,8 @@ class Forum extends AdminController
* 内容中是否有图片视频音频插入
*
* @param [type] $content
* @return boolean
* @return array
*
*/
public function hasIva($content)
{

View File

@ -44,7 +44,7 @@ class Slider extends AdminController
}
if(count($datas)) {
$list = ['code'=>0,'msg'=>'获取数据成功'];
$list = ['code'=>0, 'count'=> count($datas), 'msg'=>'获取数据成功'];
foreach($datas as $k=>$v) {
$list['data'][] = [
'id'=>$v['id'],

View File

@ -168,9 +168,7 @@ class Upgrade extends AdminController
$package_file = $upload_dir.'taoler_'.$version_num.'.zip'; //升级的压缩包文件
$cpfile = copy($file_url,$package_file);
if(!$cpfile)
{
if(!$cpfile) {
return json(['code'=>-1,'msg'=>'下载升级文件失败']);
}
//记录下日志
@ -236,15 +234,12 @@ class Upgrade extends AdminController
private function execute_update(string $package_file)
{
//解压 zip文件有密码的话需要解密
//$uzip = new ZipFile();
$zip = new Zip;
$zipDir = strstr($package_file, '.zip',true); //返回文件名后缀前的字符串
$zipPath = Files::getDirPath($zipDir); //转换为带/的路径 压缩文件解压到的路径
//$unzip_res = $uzip->unzip($package_file,$zipPath,true);
$unzip_res = $zip->unzip($package_file,$zipPath);
if(!$unzip_res)
{
if(!$unzip_res) {
return json(['code'=>-1,'msg'=>'解压失败']);
}
//解压成功,得到文件夹
@ -253,8 +248,7 @@ class Upgrade extends AdminController
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'50%','msg'=>'升级文件解压成功!']);
//升级PHP
if(is_dir($zipPath))
{
if(is_dir($zipPath)) {
//升级前的写入文件权限检查
$allUpdateFiles = Files::getAllFile($zipPath);
@ -276,8 +270,7 @@ class Upgrade extends AdminController
$cpRes = Files::copyDirs($zipPath,$this->root_dir);
$cpData = $cpRes->getData();
//更新失败
if($cpData['code'] == -1)
{
if($cpData['code'] == -1) {
//数据库回滚
/*
if(file_exists($this->upload_dir.'/'.$package_file.'/mysql/mysql_rockback.sql'))
@ -297,13 +290,8 @@ class Upgrade extends AdminController
//升级sql操作
$upSql = $zipPath.'runtime/update.sql';
if(file_exists($upSql))
{
$sqlRes = $this->db_update($upSql);
$upDate = $sqlRes->getData();
if($upDate['code'] == -1){
return json(['code'=>-1,'msg'=>$upDate['msg']]);
}
if(file_exists($upSql)) {
SqlFile::dbExecute($upSql);
//删除sql语句
unlink($upSql);
}
@ -317,7 +305,7 @@ class Upgrade extends AdminController
}
/**
* 处理升级包上传
* 手动处理升级包上传
*/
public function uploadZip()
{
@ -373,36 +361,4 @@ class Upgrade extends AdminController
}
/**
* 数据库操作
*/
public function database_operation($file)
{
$mysqli = new \mysqli('localhost','root','root','test');
if($mysqli->connect_errno)
{
return json(['code'=>0,'msg'=>'Connect failed:'.$mysqli->connect_error]);
}
$sql = file_get_contents($file);
$a = $mysqli->multi_query($sql);
return ['code'=>1,'msg'=>'数据库操作OK'];
}
/**
* 执行数据库操作
*/
public function db_update($file)
{
$sqlf = new SqlFile();
$sql_array = $sqlf->load_sql_file($file);
foreach($sql_array as $v){
$sqlRes = Db::execute($v);
if ($sqlRes === false) {
return json(['code'=>-1,'msg'=>'数据库升级失败']);
}
}
return json(['code'=>0,'msg'=>'数据库升级成功']);
}
}

View File

@ -16,29 +16,36 @@ class AuthRule extends Model
{
$query->where('id', $value );
}
/**
* 权限树
*/
public function authRuleTree()
/**
* 获取权限列表
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getAuthRuleTree()
{
$authRules = $this->order('sort asc')->select();
//return $this->sort($authRules);
return $authRules;
}
/**
* idpid,菜单排序
* @var $data 数据
* @var $pid 父级id
*/
public function sort($data,$pid=0)
{
static $arr = array();
foreach($data as $k=> $v){
if($v['pid']==$pid){
$arr[] = $v;
$this->sort($data,$v['id']);
}
}
return $arr;
}
$authRules = $this->field('id,pid,title,name,icon,status,ismenu,sort,create_time')->select()->toArray();
//数组排序
$cmf_arr = array_column($authRules, 'sort');
array_multisort($cmf_arr, SORT_ASC, $authRules);
if(count($authRules)) {
return json(['code'=>0,'msg'=>'ok','data'=>$authRules]);
} else {
return json(['code'=>0,'msg'=>'no data','data'=>'']);
}
}
public function saveRule($data)
{
$res = $this->save($data);
if($res){
return json(['code'=>0,'msg'=>'添加权限成功']);
}else{
return json(['code'=>-1,'msg'=>'添加权限失败']);
}
}
}

View File

@ -38,9 +38,9 @@
<div class="layui-form-item">
<label class="layui-form-label">类型</label>
<div class="layui-input-block">
<input type="radio" name="ishidden" lay-skin="primary" title="目录" value="-1">
<input type="radio" name="ishidden" lay-skin="primary" title="菜单" value="1" checked>
<input type="radio" name="ishidden" lay-skin="primary" title="按钮" value="0">
<input type="radio" name="ismenu" lay-skin="primary" title="目录" value="0">
<input type="radio" name="ismenu" lay-skin="primary" title="菜单" value="1" checked>
<input type="radio" name="ismenu" lay-skin="primary" title="按钮" value="2">
</div>
</div>
<div class="layui-form-item layui-hide">

View File

@ -39,9 +39,9 @@
<div class="layui-form-item">
<label class="layui-form-label">类型</label>
<div class="layui-input-block">
<input type="radio" name="ishidden" lay-skin="primary" title="目录" value="-1" {if condition="$rules.ishidden == -1"} checked {/if}>
<input type="radio" name="ishidden" lay-skin="primary" title="菜单" value="1" {if condition="$rules.ishidden == 1"} checked {/if}>
<input type="radio" name="ishidden" lay-skin="primary" title="按钮" value="0" {if condition="$rules.ishidden == 0"} checked {/if}>
<input type="radio" name="ismenu" lay-skin="primary" title="目录" value="0" {if condition="$rules.ismenu == 0"} checked {/if}>
<input type="radio" name="ismenu" lay-skin="primary" title="菜单" value="1" {if condition="$rules.ismenu == 1"} checked {/if}>
<input type="radio" name="ismenu" lay-skin="primary" title="按钮" value="2" {if condition="$rules.ismenu == 2"} checked {/if}>
</div>
</div>
<div class="layui-form-item layui-hide">

View File

@ -51,8 +51,8 @@
defaultToolbar: ['filter', 'print', 'exports'],
cols: [
[
{type: 'numbers'},
{type: 'checkbox'},
{field: 'id', title: 'ID',width: 40},
{field: 'title', title: '菜单名称', minWidth: 165},
{field: 'url', title: '菜单地址', rowspan: 2},
{
@ -60,10 +60,10 @@
templet: '<p><i class="layui-icon {{d.icon}}"></i></p>'
},
{field: 'authority', title: '权限标识'},
{field: 'isMenu', title: '类型', templet: type, align: 'center', width: 60},
//{title: '类型', templet: '<p>{{d.isMenu ? "菜单" : "按钮"}}</p>', align: 'center', width: 60},
{field: 'ismenu', title: '类型', templet: type, align: 'center', width: 60},
// {title: '类型', templet: '<p>{{d.ismenu ? "菜单" : "按钮"}}</p>', align: 'center', width: 60},
{field: 'sort', title: '排序', align: 'center', width: 60},
{field: 'ctime',title: '创建时间'},
{field: 'create_time',title: '创建时间'},
{align: 'center', toolbar: '#tbBar', title: '操作', width: 120}
]
],
@ -72,7 +72,7 @@
//自定义“状态”列
function type(data) {
var isMenu = data.isMenu;
var isMenu = data.ismenu;
var btns = "";
if (isMenu == -1) {
return "目录";
@ -149,7 +149,7 @@
$.ajax({
type:"post",
url:"{:url('AuthRule/edit')}",
data:{"id":field.id,"pid":field.pid,"title":field.title,"name":field.name,"icon":field.icon,"sort":field.sort,"ishidden":field.ishidden},
data: field,
daType:"json",
success:function (res){
if (res.code == 0) {
@ -207,7 +207,7 @@
$.ajax({
type:"post",
url:"{:url('AuthRule/add')}",
data:{"pid":field.pid,"title":field.title,"name":field.name,"icon":field.icon,"sort":field.sort,"ishidden":field.ishidden},
data: field,
daType:"json",
success:function (data){
if (data.code == 0) {

View File

@ -109,6 +109,9 @@ layui.config({
upload = layui.upload;
var editor = layui.editor;
//获取百度标签标志tag或者word;
var flag = 'word';
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
var taonystatus = "{:hook('taonystatus')}";
// 编辑器插件启用状态
@ -160,15 +163,15 @@ layui.config({
if (conf !== "1") {
$("#L_title").on("blur", function () {
var title = $(this).val();
var flag = "on";
var content = $("#L_content").val();
$.ajax({
type: "post",
url: "{:url('Forum/getKeywords')}",
data: { keywords: keywords, flag: flag },
data: { keywords: title, content:content, flag: flag },
daType: "json",
success: function (data) {
if (data.code == 0) {
$("input[name='tags']").val(data.data);
$("input[name='keywords']").val(data.data.join(','));
}
},
});

View File

@ -95,7 +95,7 @@ overflow: visible;
[
{type: 'numbers'},
{type: 'checkbox'}
,{field: 'tags', title: '分类名', minWidth: 200}
,{field: 'catename', title: '分类名', minWidth: 200}
,{field: 'ename', title: 'EN别名', width: 100}
,{field: 'detpl',title: '模板', align: 'center',width: 100,templet: '#inputSel'}
,{title: '图标', align: 'center',width: 50,templet: '<p><i class="layui-icon {{d.icon}}"></i></p>'}
@ -136,25 +136,25 @@ overflow: visible;
type: 2
,title: '编辑分类'
,content: forumTagsForm + '?id='+ data.id
,area: ['400px', '450px']
,area: ['400px', '500px']
,btn: ['确定', '取消']
,yes: function(index, layero){
//获取iframe元素的值
var othis = layero.find('iframe').contents().find("#layuiadmin-app-form-tags")
,pid = othis.find('input[name="pid"]').val()
,sort = othis.find('input[name="sort"]').val()
,tags = othis.find('input[name="tags"]').val()
,catename = othis.find('input[name="catename"]').val()
,ename = othis.find('input[name="ename"]').val()
,detpl = othis.find('select[name="detpl"]').val()
,icon = othis.find('input[name="icon"]').val()
,desc = othis.find('input[name="desc"]').val();
if(!tags.replace(/\s/g, '')) return;
if(!catename.replace(/\s/g, '')) return;
$.ajax({
type:"post",
url:forumTagsForm,
data:{"id":data.id,"pid":pid,"sort":sort,"catename":tags,"ename":ename,"detpl":detpl,"icon":icon,"desc":desc},
data:{"id":data.id,"pid":pid,"sort":sort,"catename":catename,"ename":ename,"detpl":detpl,"icon":icon,"desc":desc},
daType:"json",
success:function (data){
if(data.code == 0){layer.msg(data.msg,{icon:6,time:2000},function(){
@ -180,7 +180,7 @@ overflow: visible;
var othis = layero.find('iframe').contents().find("#layuiadmin-app-form-tags").click();
othis.find('input[name="pid"]').val(data.pid)
,othis.find('input[name="sort"]').val(data.sort)
,othis.find('input[name="tags"]').val(data.tags)
,othis.find('input[name="catename"]').val(data.catename)
,othis.find('input[name="ename"]').val(data.ename)
,othis.find('input[name="icon"]').val(data.icon)
,othis.find('input[name="desc"]').val(data.desc);
@ -201,20 +201,20 @@ overflow: visible;
,btn: ['确定', '取消']
,yes: function(index, layero){
var othis = layero.find('iframe').contents().find("#layuiadmin-app-form-tags")
,pid = othis.find('input[name="pid"]').val()
,sort = othis.find('input[name="sort"]').val()
,tags = othis.find('input[name="tags"]').val()
,ename = othis.find('input[name="ename"]').val()
,detpl = othis.find('select[name="detpl"]').val()
,icon = othis.find('input[name="icon"]').val()
,desc = othis.find('input[name="desc"]').val();
,pid = othis.find('input[name="pid"]').val()
,sort = othis.find('input[name="sort"]').val()
,catename = othis.find('input[name="catename"]').val()
,ename = othis.find('input[name="ename"]').val()
,detpl = othis.find('select[name="detpl"]').val()
,icon = othis.find('input[name="icon"]').val()
,desc = othis.find('input[name="desc"]').val();
if(!tags.replace(/\s/g, '')) return;
if(!catename.replace(/\s/g, '')) return;
$.ajax({
type:"post",
url:"{:url('Forum/tagsform')}",
data:{pid:pid,"sort":sort,"catename":tags,"ename":ename,"detpl":detpl,"icon":icon,"desc":desc},
data:{pid:pid,"sort":sort,"catename":catename,"ename":ename,"detpl":detpl,"icon":icon,"desc":desc},
daType:"json",
success:function (data){
if (data.code == 0) {

View File

@ -12,7 +12,7 @@
<div class="layui-form-item">
<label class="layui-form-label">分类名</label>
<div class="layui-input-inline">
<input type="text" name="tags" lay-verify="required" placeholder="分类名*" autocomplete="off" class="layui-input">
<input type="text" name="catename" lay-verify="required" placeholder="分类名*" autocomplete="off" class="layui-input">
</div>
<label class="layui-form-label">EN别名</label>
<div class="layui-input-inline">

View File

@ -74,7 +74,7 @@
,{field: 'slid_href', title: 'URL', minWidth: 250}
,{field: 'slid_color', title: '颜色', width: 80}
,{field: 'slid_start', title: '开始', width: 150, sort: true}
,{field: 'slid_over', title: '结束', width: 150, sort: true}
,{field: 'slid_over', title: '结束','escape':false, width: 150, sort: true}
,{field: 'slid_status', title: '状态', width: 80}
,{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}
]]

View File

@ -7,6 +7,8 @@ use think\facade\Db;
use think\facade\Session;
use taoser\think\Auth;
define('DS', DIRECTORY_SEPARATOR);
// 应用公共文件
function mailto($to,$title,$content)
{
@ -210,21 +212,24 @@ function array_child_append($parent, $pid, $child, $child_key_name)
return $parent;
}
//菜单递归
function getTree($data)
//菜单无限极分类
function getTree($data, $pId='0')
{
$tree = [];
foreach ($data as $array) {
if(isset($data[$array['pid']])) {
$data[$array['pid']]['children'][] = &$data[$array['id']];
//$tree = $data;
} else {
$tree[] = &$data[$array['id']];
}
}
return $tree;
// 递归
$tree = [];
foreach ($data as $k => $v) {
if ($v['pid'] == $pId) {
$child = getTree($data, $v['id']);
if(!empty($child)) {
$v['children'] = $child;
}
$tree[] = $v;
}
}
// 排序
$cmf_arr = array_column($tree, 'sort');
array_multisort($cmf_arr, SORT_ASC, $tree);
return $tree;
}
//按钮权限检查
@ -299,4 +304,5 @@ function find_spider(){
}
}
return false;
}
}

View File

@ -45,8 +45,7 @@ class AdminController extends \app\BaseController
$admin_id = $this->aid;
$auth = new Auth();
$auth_rule_list = Db::name('auth_rule')->where('delete_time',0)->where(['status'=> 1,'ishidden'=>1])->order(['sort' => 'asc'])->select();
//var_export($auth_rule_list);
$auth_rule_list = Db::name('auth_rule')->where(['delete_time'=> 0,'status'=> 1,'ismenu'=>1])->select();
foreach ($auth_rule_list as $value) {
if ($auth->check($value['name'], $admin_id) || $admin_id == 1) {
@ -64,7 +63,7 @@ class AdminController extends \app\BaseController
}
}
$menu = !empty($menu) ? array2tree($menu) : [];
$menu = !empty($menu) ? getTree($menu) : [];
View::assign('menu', $menu);
}
@ -75,13 +74,13 @@ class AdminController extends \app\BaseController
protected function getMenus($type)
{
$menu = [];
$auth_rule_list = Db::name('auth_rule')->where(['delete_time'=> 0, 'status'=> 1,'type'=> $type])->order(['sort' => 'ASC', 'id' => 'ASC'])->select();
$auth_rule_list = Db::name('auth_rule')->where(['delete_time'=> 0, 'status'=> 1,'type'=> $type])->select();
//var_export($auth_rule_list);
foreach ($auth_rule_list as $value) {
$menu[] = $value;
}
$menus = !empty($menu) ? array2tree($menu) : [];
$menus = !empty($menu) ? getTree($menu) : [];
//$menu2 = getTree($menu);
return $menus;
//return View::assign('menus', $menus);

View File

@ -67,12 +67,8 @@ class BaseController extends BaseCtrl
protected function showNav()
{
//1.查询分类表获取所有分类
$cateList = Db::name('cate')->where(['status'=>1,'delete_time'=>0])->order(['id' => 'ASC','sort' => 'ASC'])->cache('catename',3600)->select()->toArray();
$cateList = array2tree($cateList);
// $cateList = getTree($cateList);
return $cateList;
$cateList = Db::name('cate')->where(['status'=>1,'delete_time'=>0])->cache('catename',3600)->select()->toArray();
return getTree($cateList);
}
// 显示子导航subnav
@ -86,7 +82,7 @@ class BaseController extends BaseCtrl
$subCateList = $this->showNav();
} else { // 点击分类,获取子分类信息
$parentId = $pCate['id'];
$subCate = Db::name('cate')->field('id,ename,catename,is_hot,pid')->where(['pid'=>$parentId,'status'=>1,'delete_time'=>0])->order(['id' => 'ASC','sort' => 'ASC'])->select()->toArray();
$subCate = Db::name('cate')->field('id,ename,catename,is_hot,pid')->where(['pid'=>$parentId,'status'=>1,'delete_time'=>0])->select()->toArray();
if(!empty($subCate)) { // 有子分类
$subCateList = array2tree($subCate);
} else { //无子分类

View File

@ -13,21 +13,22 @@ declare (strict_types = 1);
namespace app\common\lib;
use think\facade\Lang;
use think\facade\Db;
class SqlFile
{
protected static $path = null;
/**
* 加载sql文件为分号分割的数组
* <br />支持存储过程和函数提取,自动过滤注释
* <br />例如: var_export(load_sql_file('mysql_routing_example/fn_cdr_parse_accountcode.sql'));
* @param string $path 文件路径
* @return boolean|array
* @since 1.0 <2015-5-27> SoChishun Added.
* @return array
*/
public function load_sql_file($path, $fn_splitor = ';;') {
if (!file_exists($path)) {
return false;
}
public static function loadSqlFile(string $path, $fn_splitor = ';;') : array
{
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$aout = [];
$str = '';
@ -72,4 +73,26 @@ class SqlFile
}
return $aout;
}
/**
* @param $sqlFile
* @return bool|void
* @throws \Exception
*/
public static function dbExecute($sqlFile)
{
if (file_exists($sqlFile)) {
$sqlArr = self::loadSqlFile($sqlFile);
if(!empty($sqlArr)) {
foreach($sqlArr as $v){
try {
Db::execute($v);
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
}
return true;
}
}
}

View File

@ -70,7 +70,7 @@ class Uploads
* @param string $rule 文件命名规则默认md5,uniqid,date,sha1为空则取文件上传名称或者自定义如a.jpg文件名
* @return \think\response\Json
*/
public function put(string $fileName, string $dirName, int $fileSize, string $fileType, string $rule = null)
public function put(string $fileName, string $dirName, int $fileSize, string $fileType, string $rule = '')
{
if(stripos($fileName,'http') !== false) {
$file = $fileName;
@ -90,7 +90,7 @@ class Uploads
} catch (ValidateException $e) {
return json(['status'=>-1,'msg'=>$e->getMessage()]);
}
// 解析存储位置
// 解析存储位置 SYS_开头为系统位置
$isSys = stripos($dirName, 'SYS_');
if($isSys !== false) {
$disk = 'sys';
@ -107,9 +107,9 @@ class Uploads
if(stripos($rule, '.') == false) {
$rule = $file->getOriginalName();
}
$savename = \think\facade\Filesystem::disk($disk)->putFileAs($dirName, $file, $rule);
$savename = Filesystem::disk($disk)->putFileAs($dirName, $file, $rule);
} else {
$savename = \think\facade\Filesystem::disk($disk)->putFile($dirName, $file, $rule);
$savename = Filesystem::disk($disk)->putFile($dirName, $file, $rule);
}
if($savename){

View File

@ -10,8 +10,111 @@
*/
namespace app\common\lib;
use think\Exception;
class Zip
{
/**
* 保持目录结构的压缩方法
* @param string $zipFile 压缩输出文件 相对或者绝对路径
* @param array|string $folderPaths 要压缩的目录 相对或者绝对路径
* @return void
*/
public static function dirZip(string $zipFile, $folderPaths)
{
//1. $folderPaths 路径为数组
// 初始化zip对象
$zip = new \ZipArchive();
//打开压缩文件
$zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
if(is_array($folderPaths)) {
foreach($folderPaths as $folderPath) {
if(self::getDirSize($folderPath) == 0) {
continue;
};
// 被压缩文件绝对路径
$rootPath = realpath($folderPath);
// Create recursive directory iterator
//获取所有文件数组SplFileInfo[] $files
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($rootPath),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
//要跳过所有子目录 Skip directories (they would be added automatically)
if (!$file->isDir()) {
// 真实文件路径
$filePath = $file->getRealPath();
// zip文件的相对路径
$relativePath = str_replace('\\','/',str_replace(root_path(), '', $filePath));
//添加文件到压缩包
$zip->addFile($filePath, $relativePath);
}
}
}
} else {
// 2. $folderPaths 路径为string
if(self::getDirSize($folderPaths) == 0) {
throw new \Exception("Directory name must not be empty.");
};
// 被压缩文件绝对路径
$rootPath = realpath($folderPaths);
// Create recursive directory iterator
//获取所有文件数组SplFileInfo[] $files
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($rootPath),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
//要跳过所有子目录 Skip directories (they would be added automatically)
if (!$file->isDir()) {
// 要压缩的文件路径
$filePath = $file->getRealPath();
// zip目录内文件的相对路径
$relativePath = str_replace('\\','/',str_replace(root_path(), '', $filePath));
//添加文件到压缩包
$zip->addFile($filePath, $relativePath);
}
}
}
$zip->close();
}
/**
* 把目录内所有文件进行压缩输出
* @param string $zipFile 压缩文件保存路径 相对路径或者绝对路径
* @param string $folderPath 要压缩的目录 相对路径或者绝对路径
* @return void
*/
public static function zipDir(string $zipFile, string $folderPath)
{
// 初始化zip对象
$zip = new \ZipArchive();
$zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
$rootPath = realpath($folderPath);
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($rootPath),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file) {
if (!$file->isDir()) {
// 要压缩的文件路径
$filePath = $file->getRealPath();
// zip目录内文件的相对路径
$relativePath = substr($filePath, strlen($rootPath) + 1);
// 添加 文件 到 压缩包
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
}
/**
* 压缩文件
* @param array $files 待压缩文件 array('d:/test/1.txt''d:/test/2.jpg');【文件地址为绝对路径】
@ -49,9 +152,7 @@ class Zip
if (empty($path) || empty($filePath)) {
return false;
}
$zip = new \ZipArchive();
if ($zip->open($filePath) === true) {
$zip->extractTo($path);
$zip->close();
@ -60,5 +161,30 @@ class Zip
return false;
}
}
/**
* 获取文件夹大小
* @param $dir 根文件夹路径
* @return bool|int
*/
public static function getDirSize($dir)
{
if(!is_dir($dir)){
return false;
}
$handle = opendir($dir);
$sizeResult = 0;
while (false !== ($FolderOrFile = readdir($handle))) {
if ($FolderOrFile != "." && $FolderOrFile != "..") {
if (is_dir("$dir/$FolderOrFile")) {
$sizeResult += self::getDirSize("$dir/$FolderOrFile");
} else {
$sizeResult += filesize("$dir/$FolderOrFile");
}
}
}
closedir($handle);
return $sizeResult;
}
}
?>

View File

@ -111,7 +111,8 @@ class Article extends Model
{
$artTop = Cache::get('arttop');
if (!$artTop) {
$artTop = $this::field('id,title,title_color,cate_id,user_id,create_time,is_top,pv,jie,upzip,has_img,has_video,has_audio')->where(['is_top' => 1, 'status' => 1])->with([
$artTop = $this::field('id,title,title_color,cate_id,user_id,create_time,is_top,pv,jie,upzip,has_img,has_video,has_audio')->where(['is_top' => 1, 'status' => 1])
->with([
'cate' => function ($query) {
$query->where('delete_time', 0)->field('id,catename,ename');
},

View File

@ -30,14 +30,14 @@ class Cate extends Model
public function getCateInfo(string $ename)
{
//
return $this::field('ename,catename,detpl,desc')->where('ename',$ename)->cache('cate_'.$ename,600)->find();
return $this->field('ename,catename,detpl,desc')->where('ename',$ename)->cache('cate_'.$ename,600)->find();
}
// 删除类别
public function del($id)
{
$cates = $this::field('id,pid')->with('article')->find($id);
$sonCate = $this::field('id,pid')->where('pid',$cates['id'])->find();
$cates = $this->field('id,pid')->with('article')->find($id);
$sonCate = $this->field('id,pid')->where('pid',$cates['id'])->find();
if(empty($sonCate)) {
$res = $cates->together(['article'])->delete();
if($res){
@ -48,9 +48,21 @@ class Cate extends Model
} else {
return '存在子分类,无法删除';
}
}
// 分类表
public function getList()
{
$data = $this->field('sort,id,pid,catename,ename,detpl,icon,is_hot,desc')->where(['status'=>1])->select()->toArray();
// 排序
$cmf_arr = array_column($data, 'sort');
array_multisort($cmf_arr, SORT_ASC, $data);
if(count($data)) {
return json(['code'=>0,'msg'=>'ok','data'=>$data]);
} else {
return json(['code'=>-1,'msg'=>'no data','data'=>'']);
}
}
}

View File

@ -80,13 +80,13 @@ class Comment extends Model
* @param integer $id
* @return void
*/
public function getUserCommentList(int $id) {
$userCommList = $this::field('id,user_id,create_time,delete_time,article_id,content')
->with(['article' => function(\think\model\Relation $query){
$query->withField('id,title,cate_id,delete_time')->where(['status' => 1]);
public function getUserCommentList1(int $id) {
$userCommList = $this::field('id,user_id,create_time,article_id,content')
->with(['article' => function($query){
$query->withField('id,title,create_time')->where(['delete_time'=>0,'status' => 1]);
}])
->where(['user_id' => $id,'status' => 1])
//->append(['url'])
->append(['url'])
->order(['create_time' => 'desc'])
//->cache(3600)
->select()
@ -95,12 +95,39 @@ class Comment extends Model
return $userCommList;
}
/**
* 获取用户评论列表
*
* @param integer $id
* @return void
*/
public function getUserCommentList(int $id) {
$userCommList = Article::field('Article.id,title,Article.create_time')->hasWhere('comments',['status'=>1,'delete_time'=>0])
->with(['comments' => function($query) use($id){
$query->withField('id,content')->where(['user_id'=>$id,'delete_time'=>0,'status' => 1]);
}])
->append(['url'])
->order(['create_time' => 'desc'])
//->cache(3600)
->select()
->toArray();
return $userCommList;
}
// 获取url
public function getUrlAttr($value,$data)
{
// dump($data);
if(config('taoler.url_rewrite.article_as') == '<ename>/') {
$cate = Cate::field('id,ename')->find($data['article']['cate_id']);
return (string) url('detail',['id' => $data['id'],'ename'=>$cate->ename]);
$article = Article::field('id,cate_id')->with(['cate' => function($query){
$query->withField('id,ename')->where(['status' => 1]);
}])->find($data['article_id']);
return (string) url('detail',['id' => $data['article_id'],'ename'=>$article->cate->ename]);
} else {
return (string) url('detail',['id' => $data['id']]);
}

View File

@ -207,21 +207,22 @@ class User extends BaseController
}
$article = new Article();
// $commont = new Comment();
$arts = $article->getUserArtList((int) $id);
// $reys = $commont->getUserCommentList((int) $id);
// dump($reys);
//用户回答
// $commont = new Comment();
// $reys = $commont->getUserCommentList((int) $id);
$reys = Db::name('comment')
->alias('c')
->join('article a','c.article_id = a.id')
->field('a.id,a.title,c.content,c.create_time,c.delete_time,c.status')
->join('cate t','a.cate_id = t.id')
->field('a.id,a.title,t.ename,c.content,c.create_time,c.delete_time,c.status')
->where(['a.delete_time'=>0,'c.delete_time'=>0,'c.status'=>1])
->where('c.user_id',$id)
->order(['c.create_time'=>'desc'])
->cache(3600)->select();
View::assign(['u'=>$u,'arts'=>$arts,'reys'=>$reys,'jspage'=>'']);
return View::fetch();
}

View File

@ -1,12 +1,5 @@
<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// 检测环境是否支持可写
//define('IS_WRITE', true);
@ -241,7 +234,7 @@ function strReplace($find,$replace,$array){
foreach ($array as $key => $val) {
if (is_array($val)) $array[$key]=$this->strReplace($find,$replace,$array[$key]);
if (is_array($val)) $array[$key] = $this->strReplace($find,$replace,$array[$key]);
}

View File

@ -162,12 +162,12 @@ CREATE TABLE `tao_auth_rule` (
`title` char(20) NOT NULL DEFAULT '' COMMENT '权限标题',
`etitle` varchar(100) NOT NULL DEFAULT '' COMMENT '英文权限标题',
`type` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '类型',
`status` enum('1','0') NOT NULL DEFAULT '1' COMMENT '菜单1启用,0禁用',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1启用,0禁用',
`pid` smallint(5) NOT NULL DEFAULT '0' COMMENT '父级ID',
`level` tinyint(1) NOT NULL DEFAULT '1' COMMENT '菜单层级',
`icon` varchar(50) NOT NULL DEFAULT '' COMMENT '图标',
`ishidden` enum('1','0','-1') NOT NULL DEFAULT '1' COMMENT '0隐藏,1显示-1其它',
`sort` tinyint(4) NOT NULL DEFAULT '50' COMMENT '排序',
`ismenu` tinyint(1) NOT NULL DEFAULT 1 COMMENT '0目录,1菜单2按钮',
`sort` int(10) NOT NULL DEFAULT '50' COMMENT '排序',
`condition` char(100) NOT NULL DEFAULT '',
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',

View File

@ -36,7 +36,8 @@
"yansongda/pay": "~3.1.0",
"guzzlehttp/guzzle": "7.0",
"php-di/php-di": "^6.4",
"workerman/phpsocket.io": "^1.1"
"workerman/phpsocket.io": "^1.1",
"jaeger/querylist": "^4.2"
},
"require-dev": {
"symfony/var-dumper": "^4.2",

1061
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改
'appname' => 'TaoLer',
// 版本配置
'version' => '1.9.29',
'version' => '2.0.0',
// 加盐
'salt' => 'taoler',
// 数据库备份目录

View File

@ -10,6 +10,7 @@
*/
namespace taoler\com;
use think\Response;
class Api
{
@ -50,7 +51,6 @@ class Api
curl_close($ch);
if($httpCode == '200'){
return json_decode($data);
//return $data;
} else {
//$status ='{"code":-1,"msg":"远程服务器失败"}'; //字符串
return json_decode('{"code":-1,"msg":"远程服务器失败,稍后重试"}'); //转换为对象

View File

@ -3,6 +3,7 @@
namespace taoler\com;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
class Files
{
/**
@ -12,7 +13,8 @@ class Files
*/
public static function getDirPath($path)
{
return substr($path,-1) == '/' ? $path : $path.'/';
//去掉path最右侧的/号,再重新组装带/路径
return rtrim($path,'/') . '/';
}
/**
@ -118,27 +120,22 @@ class Files
public static function delDirAndFile(string $dirPath, $nowDir=false )
{
if(!is_dir($dirPath)) return 'dir not exist';
if ( $handle = opendir($dirPath) ) {
while ( false !== ( $item = readdir( $handle ) ) ) {
if ( $item != '.' && $item != '..' ) {
if ( $handle = opendir($dirPath) ) {
while ( false !== ( $item = readdir( $handle ) ) ) {
if ( $item != '.' && $item != '..' ) {
$path = $dirPath.$item;
if (is_dir($path)) {
self::delDirAndFile($path.'/');
if (is_dir($path)) {
self::delDirAndFile($path.'/');
rmdir($path.'/');
} else {
unlink($path);
}
}
}
} else {
unlink($path);
}
}
}
closedir( $handle );
//删除当前文件夹
if($nowDir == true){
if(rmdir($dirPath)){
return true;
} else {
return false;
}
if(!rmdir($dirPath)) return false;
}
} else {
return false;

View File

@ -13,7 +13,7 @@ var forms = table.render({
,{field: 'poster', title: '账号',width: 80}
,{field: 'avatar', title: '头像', width: 60, templet: '#avatarTpl'}
,{field: 'title', title: '标题', minWidth: 180,templet: '<div><a href="{{- d.url }}" target="_blank">{{- d.title }}</a></div>'}
,{field: 'content', title: '内容', templet: '<div>{{= d.content }}</div>', minWidth: 200}
,{field: 'content', title: '内容', 'escape':false, minWidth: 200}
,{field: 'posttime', title: '时间',width: 120, sort: true}
,{field: 'top', title: '置顶', templet: '#buttonTpl', width: 80, align: 'center'}
,{field: 'hot', title: '加精', templet: '#buttonHot', width: 80, align: 'center'}

View File

@ -995,7 +995,7 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
util.fixbar({
bar1: '&#xe642;'
,bgcolor: '#009688'
,css: {right: 10, bottom: 100}
,css: {right: 10, bottom: 50}
,click: function(type){
//添加文章
if(type === 'bar1'){

View File

@ -1,25 +1,2 @@
ALTER TABLE `tao_push_jscode` ADD `type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1push2taglink' AFTER `jscode`;
DROP TABLE IF EXISTS `tao_tag`;
CREATE TABLE `tao_tag` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'tag自增id',
`name` varchar(20) NOT NULL COMMENT '名称',
`ename` varchar(20) NOT NULL COMMENT '英文名',
`create_time` int NOT NULL COMMENT '创建时间',
`update_time` int NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ename` (`ename`) USING BTREE COMMENT 'ename查询tag索引'
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='文章tag表';
DROP TABLE IF EXISTS `tao_taglist`;
CREATE TABLE `tao_taglist` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '标签列表id',
`tag_id` int NOT NULL COMMENT '标签id',
`article_id` int NOT NULL COMMENT '文章id',
`create_time` int NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `tag_id` (`tag_id`) USING BTREE COMMENT 'tagID索引',
KEY `article_id` (`article_id`) USING BTREE COMMENT '文章ID查询索引'
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='tag详细列表';
ALTER TABLE `tao_article` CHANGE `tags` `keywords` varchar(255) DEFAULT NULL COMMENT '关键词';
ALTER TABLE `tao_auth_rule` CHANGE `sort` `sort` int NOT NULL DEFAULT 50 COMMENT '排序';
ALTER TABLE `tao_auth_rule` CHANGE `ishidden` `ismenu` enum('1','2','3','0','-1') NOT NULL DEFAULT '1' COMMENT '1菜单,2按钮3目录';

View File

@ -0,0 +1,559 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\Adapter\Common\Exception\CacheException;
use Cache\Adapter\Common\Exception\CachePoolException;
use Cache\Adapter\Common\Exception\InvalidArgumentException;
use Psr\Cache\CacheItemInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Psr\SimpleCache\CacheInterface;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
abstract class AbstractCachePool implements PhpCachePool, LoggerAwareInterface, CacheInterface
{
const SEPARATOR_TAG = '!';
/**
* @type LoggerInterface
*/
private $logger;
/**
* @type PhpCacheItem[] deferred
*/
protected $deferred = [];
/**
* @param PhpCacheItem $item
* @param int|null $ttl seconds from now
*
* @return bool true if saved
*/
abstract protected function storeItemInCache(PhpCacheItem $item, $ttl);
/**
* Fetch an object from the cache implementation.
*
* If it is a cache miss, it MUST return [false, null, [], null]
*
* @param string $key
*
* @return array with [isHit, value, tags[], expirationTimestamp]
*/
abstract protected function fetchObjectFromCache($key);
/**
* Clear all objects from cache.
*
* @return bool false if error
*/
abstract protected function clearAllObjectsFromCache();
/**
* Remove one object from cache.
*
* @param string $key
*
* @return bool
*/
abstract protected function clearOneObjectFromCache($key);
/**
* Get an array with all the values in the list named $name.
*
* @param string $name
*
* @return array
*/
abstract protected function getList($name);
/**
* Remove the list.
*
* @param string $name
*
* @return bool
*/
abstract protected function removeList($name);
/**
* Add a item key on a list named $name.
*
* @param string $name
* @param string $key
*/
abstract protected function appendListItem($name, $key);
/**
* Remove an item from the list.
*
* @param string $name
* @param string $key
*/
abstract protected function removeListItem($name, $key);
/**
* Make sure to commit before we destruct.
*/
public function __destruct()
{
$this->commit();
}
/**
* {@inheritdoc}
*/
public function getItem($key)
{
$this->validateKey($key);
if (isset($this->deferred[$key])) {
/** @type CacheItem $item */
$item = clone $this->deferred[$key];
$item->moveTagsToPrevious();
return $item;
}
$func = function () use ($key) {
try {
return $this->fetchObjectFromCache($key);
} catch (\Exception $e) {
$this->handleException($e, __FUNCTION__);
}
};
return new CacheItem($key, $func);
}
/**
* {@inheritdoc}
*/
public function getItems(array $keys = [])
{
$items = [];
foreach ($keys as $key) {
$items[$key] = $this->getItem($key);
}
return $items;
}
/**
* {@inheritdoc}
*/
public function hasItem($key)
{
try {
return $this->getItem($key)->isHit();
} catch (\Exception $e) {
$this->handleException($e, __FUNCTION__);
}
}
/**
* {@inheritdoc}
*/
public function clear()
{
// Clear the deferred items
$this->deferred = [];
try {
return $this->clearAllObjectsFromCache();
} catch (\Exception $e) {
$this->handleException($e, __FUNCTION__);
}
}
/**
* {@inheritdoc}
*/
public function deleteItem($key)
{
try {
return $this->deleteItems([$key]);
} catch (\Exception $e) {
$this->handleException($e, __FUNCTION__);
}
}
/**
* {@inheritdoc}
*/
public function deleteItems(array $keys)
{
$deleted = true;
foreach ($keys as $key) {
$this->validateKey($key);
// Delete form deferred
unset($this->deferred[$key]);
// We have to commit here to be able to remove deferred hierarchy items
$this->commit();
$this->preRemoveItem($key);
if (!$this->clearOneObjectFromCache($key)) {
$deleted = false;
}
}
return $deleted;
}
/**
* {@inheritdoc}
*/
public function save(CacheItemInterface $item)
{
if (!$item instanceof PhpCacheItem) {
$e = new InvalidArgumentException('Cache items are not transferable between pools. Item MUST implement PhpCacheItem.');
$this->handleException($e, __FUNCTION__);
}
$this->removeTagEntries($item);
$this->saveTags($item);
$timeToLive = null;
if (null !== $timestamp = $item->getExpirationTimestamp()) {
$timeToLive = $timestamp - time();
if ($timeToLive < 0) {
return $this->deleteItem($item->getKey());
}
}
try {
return $this->storeItemInCache($item, $timeToLive);
} catch (\Exception $e) {
$this->handleException($e, __FUNCTION__);
}
}
/**
* {@inheritdoc}
*/
public function saveDeferred(CacheItemInterface $item)
{
$this->deferred[$item->getKey()] = $item;
return true;
}
/**
* {@inheritdoc}
*/
public function commit()
{
$saved = true;
foreach ($this->deferred as $item) {
if (!$this->save($item)) {
$saved = false;
}
}
$this->deferred = [];
return $saved;
}
/**
* @param string $key
*
* @throws InvalidArgumentException
*/
protected function validateKey($key)
{
if (!is_string($key)) {
$e = new InvalidArgumentException(sprintf(
'Cache key must be string, "%s" given',
gettype($key)
));
$this->handleException($e, __FUNCTION__);
}
if (!isset($key[0])) {
$e = new InvalidArgumentException('Cache key cannot be an empty string');
$this->handleException($e, __FUNCTION__);
}
if (preg_match('|[\{\}\(\)/\\\@\:]|', $key)) {
$e = new InvalidArgumentException(sprintf(
'Invalid key: "%s". The key contains one or more characters reserved for future extension: {}()/\@:',
$key
));
$this->handleException($e, __FUNCTION__);
}
}
/**
* @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
/**
* Logs with an arbitrary level if the logger exists.
*
* @param mixed $level
* @param string $message
* @param array $context
*/
protected function log($level, $message, array $context = [])
{
if ($this->logger !== null) {
$this->logger->log($level, $message, $context);
}
}
/**
* Log exception and rethrow it.
*
* @param \Exception $e
* @param string $function
*
* @throws CachePoolException
*/
private function handleException(\Exception $e, $function)
{
$level = 'alert';
if ($e instanceof InvalidArgumentException) {
$level = 'warning';
}
$this->log($level, $e->getMessage(), ['exception' => $e]);
if (!$e instanceof CacheException) {
$e = new CachePoolException(sprintf('Exception thrown when executing "%s". ', $function), 0, $e);
}
throw $e;
}
/**
* @param array $tags
*
* @return bool
*/
public function invalidateTags(array $tags)
{
$itemIds = [];
foreach ($tags as $tag) {
$itemIds = array_merge($itemIds, $this->getList($this->getTagKey($tag)));
}
// Remove all items with the tag
$success = $this->deleteItems($itemIds);
if ($success) {
// Remove the tag list
foreach ($tags as $tag) {
$this->removeList($this->getTagKey($tag));
$l = $this->getList($this->getTagKey($tag));
}
}
return $success;
}
public function invalidateTag($tag)
{
return $this->invalidateTags([$tag]);
}
/**
* @param PhpCacheItem $item
*/
protected function saveTags(PhpCacheItem $item)
{
$tags = $item->getTags();
foreach ($tags as $tag) {
$this->appendListItem($this->getTagKey($tag), $item->getKey());
}
}
/**
* Removes the key form all tag lists. When an item with tags is removed
* we MUST remove the tags. If we fail to remove the tags a new item with
* the same key will automatically get the previous tags.
*
* @param string $key
*
* @return $this
*/
protected function preRemoveItem($key)
{
$item = $this->getItem($key);
$this->removeTagEntries($item);
return $this;
}
/**
* @param PhpCacheItem $item
*/
private function removeTagEntries(PhpCacheItem $item)
{
$tags = $item->getPreviousTags();
foreach ($tags as $tag) {
$this->removeListItem($this->getTagKey($tag), $item->getKey());
}
}
/**
* @param string $tag
*
* @return string
*/
protected function getTagKey($tag)
{
return 'tag'.self::SEPARATOR_TAG.$tag;
}
/**
* {@inheritdoc}
*/
public function get($key, $default = null)
{
$item = $this->getItem($key);
if (!$item->isHit()) {
return $default;
}
return $item->get();
}
/**
* {@inheritdoc}
*/
public function set($key, $value, $ttl = null)
{
$item = $this->getItem($key);
$item->set($value);
$item->expiresAfter($ttl);
return $this->save($item);
}
/**
* {@inheritdoc}
*/
public function delete($key)
{
return $this->deleteItem($key);
}
/**
* {@inheritdoc}
*/
public function getMultiple($keys, $default = null)
{
if (!is_array($keys)) {
if (!$keys instanceof \Traversable) {
throw new InvalidArgumentException('$keys is neither an array nor Traversable');
}
// Since we need to throw an exception if *any* key is invalid, it doesn't
// make sense to wrap iterators or something like that.
$keys = iterator_to_array($keys, false);
}
$items = $this->getItems($keys);
return $this->generateValues($default, $items);
}
/**
* @param $default
* @param $items
*
* @return \Generator
*/
private function generateValues($default, $items)
{
foreach ($items as $key => $item) {
/** @type $item CacheItemInterface */
if (!$item->isHit()) {
yield $key => $default;
} else {
yield $key => $item->get();
}
}
}
/**
* {@inheritdoc}
*/
public function setMultiple($values, $ttl = null)
{
if (!is_array($values)) {
if (!$values instanceof \Traversable) {
throw new InvalidArgumentException('$values is neither an array nor Traversable');
}
}
$keys = [];
$arrayValues = [];
foreach ($values as $key => $value) {
if (is_int($key)) {
$key = (string) $key;
}
$this->validateKey($key);
$keys[] = $key;
$arrayValues[$key] = $value;
}
$items = $this->getItems($keys);
$itemSuccess = true;
foreach ($items as $key => $item) {
$item->set($arrayValues[$key]);
try {
$item->expiresAfter($ttl);
} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
}
$itemSuccess = $itemSuccess && $this->saveDeferred($item);
}
return $itemSuccess && $this->commit();
}
/**
* {@inheritdoc}
*/
public function deleteMultiple($keys)
{
if (!is_array($keys)) {
if (!$keys instanceof \Traversable) {
throw new InvalidArgumentException('$keys is neither an array nor Traversable');
}
// Since we need to throw an exception if *any* key is invalid, it doesn't
// make sense to wrap iterators or something like that.
$keys = iterator_to_array($keys, false);
}
return $this->deleteItems($keys);
}
/**
* {@inheritdoc}
*/
public function has($key)
{
return $this->hasItem($key);
}
}

View File

@ -0,0 +1,269 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\Adapter\Common\Exception\InvalidArgumentException;
use Cache\TagInterop\TaggableCacheItemInterface;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class CacheItem implements PhpCacheItem
{
/**
* @type array
*/
private $prevTags = [];
/**
* @type array
*/
private $tags = [];
/**
* @type \Closure
*/
private $callable;
/**
* @type string
*/
private $key;
/**
* @type mixed
*/
private $value;
/**
* The expiration timestamp is the source of truth. This is the UTC timestamp
* when the cache item expire. A value of zero means it never expires. A nullvalue
* means that no expiration is set.
*
* @type int|null
*/
private $expirationTimestamp = null;
/**
* @type bool
*/
private $hasValue = false;
/**
* @param string $key
* @param \Closure|bool $callable or boolean hasValue
*/
public function __construct($key, $callable = null, $value = null)
{
$this->key = $key;
if ($callable === true) {
$this->hasValue = true;
$this->value = $value;
} elseif ($callable !== false) {
// This must be a callable or null
$this->callable = $callable;
}
}
/**
* {@inheritdoc}
*/
public function getKey()
{
return $this->key;
}
/**
* {@inheritdoc}
*/
public function set($value)
{
$this->value = $value;
$this->hasValue = true;
$this->callable = null;
return $this;
}
/**
* {@inheritdoc}
*/
public function get()
{
if (!$this->isHit()) {
return;
}
return $this->value;
}
/**
* {@inheritdoc}
*/
public function isHit()
{
$this->initialize();
if (!$this->hasValue) {
return false;
}
if ($this->expirationTimestamp !== null) {
return $this->expirationTimestamp > time();
}
return true;
}
/**
* {@inheritdoc}
*/
public function getExpirationTimestamp()
{
return $this->expirationTimestamp;
}
/**
* {@inheritdoc}
*/
public function expiresAt($expiration)
{
if ($expiration instanceof \DateTimeInterface) {
$this->expirationTimestamp = $expiration->getTimestamp();
} elseif (is_int($expiration) || null === $expiration) {
$this->expirationTimestamp = $expiration;
} else {
throw new InvalidArgumentException('Cache item ttl/expiresAt must be of type integer or \DateTimeInterface.');
}
return $this;
}
/**
* {@inheritdoc}
*/
public function expiresAfter($time)
{
if ($time === null) {
$this->expirationTimestamp = null;
} elseif ($time instanceof \DateInterval) {
$date = new \DateTime();
$date->add($time);
$this->expirationTimestamp = $date->getTimestamp();
} elseif (is_int($time)) {
$this->expirationTimestamp = time() + $time;
} else {
throw new InvalidArgumentException('Cache item ttl/expiresAfter must be of type integer or \DateInterval.');
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getPreviousTags()
{
$this->initialize();
return $this->prevTags;
}
/**
* {@inheritdoc}
*/
public function getTags()
{
return $this->tags;
}
/**
* {@inheritdoc}
*/
public function setTags(array $tags)
{
$this->tags = [];
$this->tag($tags);
return $this;
}
/**
* Adds a tag to a cache item.
*
* @param string|string[] $tags A tag or array of tags
*
* @throws InvalidArgumentException When $tag is not valid.
*
* @return TaggableCacheItemInterface
*/
private function tag($tags)
{
$this->initialize();
if (!is_array($tags)) {
$tags = [$tags];
}
foreach ($tags as $tag) {
if (!is_string($tag)) {
throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', is_object($tag) ? get_class($tag) : gettype($tag)));
}
if (isset($this->tags[$tag])) {
continue;
}
if (!isset($tag[0])) {
throw new InvalidArgumentException('Cache tag length must be greater than zero');
}
if (isset($tag[strcspn($tag, '{}()/\@:')])) {
throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:', $tag));
}
$this->tags[$tag] = $tag;
}
return $this;
}
/**
* If callable is not null, execute it an populate this object with values.
*/
private function initialize()
{
if ($this->callable !== null) {
// $func will be $adapter->fetchObjectFromCache();
$func = $this->callable;
$result = $func();
$this->hasValue = $result[0];
$this->value = $result[1];
$this->prevTags = isset($result[2]) ? $result[2] : [];
$this->expirationTimestamp = null;
if (isset($result[3]) && is_int($result[3])) {
$this->expirationTimestamp = $result[3];
}
$this->callable = null;
}
}
/**
* @internal This function should never be used and considered private.
*
* Move tags from $tags to $prevTags
*/
public function moveTagsToPrevious()
{
$this->prevTags = $this->tags;
$this->tags = [];
}
}

View File

@ -0,0 +1,73 @@
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## 1.3.0
* Support for PHP 8.1
* Drop support for PHP < 7.4
* Allow psr/cache: ^1.0 || ^2.0
## 1.2.0
### Added
* Support for PHP 8
## 1.1.0
### Added
- Support for storing binary data
### Fixed
- Issue with one character variables
### Changed
- Tests are now extending `PHPUnit\Framework\TestCase`
## 1.0.0
* No changes since 0.4.0.
## 0.4.0
### Added
* `AbstractCachePool` has 4 new abstract methods: `getList`, `removeList`, `appendListItem` and `removeListItem`.
* `AbstractCachePool::invalidateTags` and `AbstractCachePool::invalidateTags`
* Added interfaces for our items and pools `PhpCachePool` and `PhpCacheItem`
* Trait to help adapters to support tags. `TagSupportWithArray`.
### Changed
* First parameter to `AbstractCachePool::storeItemInCache` must be a `PhpCacheItem`.
* Return value from `AbstractCachePool::fetchObjectFromCache` must be a an array with 4 values. Added expiration timestamp.
* `HasExpirationDateInterface` is replaced by `HasExpirationTimestampInterface`
* We do not work with `\DateTime` internally anymore. We work with timestamps.
## 0.3.3
### Fixed
* Bugfix when you fetch data from the cache storage that was saved as "non-tagging item" but fetch as a tagging item.
## 0.3.2
### Added
* Cache pools do implement `LoggerAwareInterface`
## 0.3.0
### Changed
* The `AbstractCachePool` does not longer implement `TaggablePoolInterface`. However, the `CacheItem` does still implement `TaggableItemInterface`.
* `CacheItem::getKeyFromTaggedKey` has been removed
* The `CacheItem`'s second parameter is a callable that must return an array with 3 elements; [`hasValue`, `value`, `tags`].
## 0.2.0
* No changelog before this version

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
use Psr\Cache\CacheException as CacheExceptionInterface;
/**
* A base exception. All exceptions in this organization will extend this exception.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
abstract class CacheException extends \RuntimeException implements CacheExceptionInterface
{
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
/**
* If an exception is caused by a pool or by the cache storage.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class CachePoolException extends CacheException
{
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common\Exception;
use Psr\Cache\InvalidArgumentException as CacheInvalidArgumentException;
use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInvalidArgumentException;
class InvalidArgumentException extends CacheException implements CacheInvalidArgumentException, SimpleCacheInvalidArgumentException
{
}

View File

@ -0,0 +1,26 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface HasExpirationTimestampInterface
{
/**
* The timestamp when the object expires.
*
* @return int|null
*/
public function getExpirationTimestamp();
}

View File

@ -0,0 +1,68 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* This trait provides common routines for safely encoding binary and non-UTF8 data in
* JSON. This is needed for components that use JSON natively (currently, the MongoDB
* adapter and EncryptedCachePool).
*
* @author Stephen Clouse <stephen.clouse@noaa.gov>
*/
trait JsonBinaryArmoring
{
private static $ESCAPE_JSON_CHARACTERS = [
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
"\x08", "\x09", "\x0A", "\x0B", "\x0C", "\x0D", "\x0E", "\x0F",
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
"\x18", "\x19", "\x1A", "\x1B", "\x1C", "\x1D", "\x1E", "\x1F",
];
private static $ENCODED_JSON_CHARACTERS = [
'\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007',
'\u0008', '\u0009', '\u000A', '\u000B', '\u000C', '\u000D', '\u000E', '\u000F',
'\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016', '\u0017',
'\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F',
];
/**
* Armor a value going into a JSON document.
*
* @param string $value
*
* @return string
*/
protected static function jsonArmor($value)
{
return str_replace(
static::$ESCAPE_JSON_CHARACTERS,
static::$ENCODED_JSON_CHARACTERS,
utf8_encode($value)
);
}
/**
* De-armor a value from a JSON document.
*
* @param string $value
*
* @return string
*/
protected static function jsonDeArmor($value)
{
return utf8_decode(str_replace(
static::$ENCODED_JSON_CHARACTERS,
static::$ESCAPE_JSON_CHARACTERS,
$value
));
}
}

22
vendor/cache/adapter-common/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\TagInterop\TaggableCacheItemInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface PhpCacheItem extends HasExpirationTimestampInterface, TaggableCacheItemInterface
{
/**
* Get the current tags. These are not the same tags as getPrevious tags. This
* is the tags that has been added to the item after the item was fetched from
* the cache storage.
*
* WARNING: This is generally not the function you want to use. Please see
* `getPreviousTags`.
*
* @return array
*/
public function getTags();
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
use Cache\TagInterop\TaggableCacheItemPoolInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface PhpCachePool extends TaggableCacheItemPoolInterface
{
/**
* {@inheritdoc}
*
* @return PhpCacheItem
*/
public function getItem($key);
/**
* {@inheritdoc}
*
* @return array|\Traversable|PhpCacheItem[]
*/
public function getItems(array $keys = []);
}

15
vendor/cache/adapter-common/README.md vendored Normal file
View File

@ -0,0 +1,15 @@
# Common PSR-6 Cache pool
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/adapter-common/v/stable)](https://packagist.org/packages/cache/adapter-common)
[![codecov.io](https://codecov.io/github/php-cache/adapter-common/coverage.svg?branch=master)](https://codecov.io/github/php-cache/adapter-common?branch=master)
[![Total Downloads](https://poser.pugx.org/cache/adapter-common/downloads)](https://packagist.org/packages/cache/adapter-common)
[![Monthly Downloads](https://poser.pugx.org/cache/adapter-common/d/monthly.png)](https://packagist.org/packages/cache/adapter-common)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This repository contains shared classes and interfaces used by the PHP Cache organisation. To read about
features like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com).
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).

View File

@ -0,0 +1,88 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Common;
/**
* This trait could be used by adapters that do not have a native support for lists.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
trait TagSupportWithArray
{
/**
* Get a value from the storage.
*
* @param string $name
*
* @return mixed
*/
abstract public function getDirectValue($name);
/**
* Set a value to the storage.
*
* @param string $name
* @param mixed $value
*/
abstract public function setDirectValue($name, $value);
/**
* {@inheritdoc}
*/
protected function appendListItem($name, $value)
{
$data = $this->getDirectValue($name);
if (!is_array($data)) {
$data = [];
}
$data[] = $value;
$this->setDirectValue($name, $data);
}
/**
* {@inheritdoc}
*/
protected function getList($name)
{
$data = $this->getDirectValue($name);
if (!is_array($data)) {
$data = [];
}
return $data;
}
/**
* {@inheritdoc}
*/
protected function removeList($name)
{
$this->setDirectValue($name, []);
return true;
}
/**
* {@inheritdoc}
*/
protected function removeListItem($name, $key)
{
$data = $this->getList($name);
foreach ($data as $i => $value) {
if ($key === $value) {
unset($data[$i]);
}
}
return $this->setDirectValue($name, $data);
}
}

View File

@ -0,0 +1,55 @@
{
"name": "cache/adapter-common",
"description": "Common classes for PSR-6 adapters",
"license": "MIT",
"type": "library",
"keywords": [
"cache",
"psr-6",
"tag"
],
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"homepage": "http://www.php-cache.com/en/latest/",
"require": {
"php": ">=7.4",
"cache/tag-interop": "^1.0",
"psr/cache": "^1.0 || ^2.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"cache/integration-tests": "^0.17",
"phpunit/phpunit": "^7.5.20 || ^9.5.10"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Cache\\Adapter\\Common\\": ""
}
},
"autoload-dev": {
"psr-4": {
"Cache\\Adapter\\Common\\Tests\\": "Tests/"
},
"exclude-from-classmap": [
"/Tests/"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}

View File

@ -0,0 +1,64 @@
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## UNRELEASED
## 1.2.0
* Support for PHP 8.1
* Drop support for PHP < 7.4
* Allow psr/cache: ^1.0 || ^2.0
## 1.1.0
### Added
* Support for PHP 8
### Changed
* Use `League\Flysystem\FilesystemInterface` instead of concrete `League\Flysystem\Filesystem` class
## 1.0.0
* No changes since 0.4.0
## 0.4.0
### Added
* Support for the new `TaggableCacheItemPoolInterface`.
* Support for PSR-16 SimpleCache
### Changed
* The behavior of `CacheItem::getTags()` has changed. It will not return the tags stored in the cache storage.
### Removed
* `CacheItem::getExpirationDate()`. Use `CacheItem::getExpirationTimestamp()`
* `CacheItem::getTags()`. Use `CacheItem::getPreviousTags()`
* `CacheItem::addTag()`. Use `CacheItem::setTags()`
## 0.3.3
### Fixed
* Race condition in `fetchObjectFromCache`.
## 0.3.2
### Changed
* Using `Filesystem::update` instead of `Filesystem::delete` and `Filesystem::write`.
## 0.3.1
### Added
* Add ability to change cache path in FilesystemCachePool
## 0.3.0
* No changelog before this version

View File

@ -0,0 +1,213 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\Adapter\Filesystem;
use Cache\Adapter\Common\AbstractCachePool;
use Cache\Adapter\Common\Exception\InvalidArgumentException;
use Cache\Adapter\Common\PhpCacheItem;
use League\Flysystem\FileExistsException;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\FilesystemInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class FilesystemCachePool extends AbstractCachePool
{
/**
* @type FilesystemInterface
*/
private $filesystem;
/**
* The folder should not begin nor end with a slash. Example: path/to/cache.
*
* @type string
*/
private $folder;
/**
* @param FilesystemInterface $filesystem
* @param string $folder
*/
public function __construct(FilesystemInterface $filesystem, $folder = 'cache')
{
$this->folder = $folder;
$this->filesystem = $filesystem;
$this->filesystem->createDir($this->folder);
}
/**
* @param string $folder
*/
public function setFolder($folder)
{
$this->folder = $folder;
}
/**
* {@inheritdoc}
*/
protected function fetchObjectFromCache($key)
{
$empty = [false, null, [], null];
$file = $this->getFilePath($key);
try {
$data = @unserialize($this->filesystem->read($file));
if ($data === false) {
return $empty;
}
} catch (FileNotFoundException $e) {
return $empty;
}
// Determine expirationTimestamp from data, remove items if expired
$expirationTimestamp = $data[2] ?: null;
if ($expirationTimestamp !== null && time() > $expirationTimestamp) {
foreach ($data[1] as $tag) {
$this->removeListItem($this->getTagKey($tag), $key);
}
$this->forceClear($key);
return $empty;
}
return [true, $data[0], $data[1], $expirationTimestamp];
}
/**
* {@inheritdoc}
*/
protected function clearAllObjectsFromCache()
{
$this->filesystem->deleteDir($this->folder);
$this->filesystem->createDir($this->folder);
return true;
}
/**
* {@inheritdoc}
*/
protected function clearOneObjectFromCache($key)
{
return $this->forceClear($key);
}
/**
* {@inheritdoc}
*/
protected function storeItemInCache(PhpCacheItem $item, $ttl)
{
$data = serialize(
[
$item->get(),
$item->getTags(),
$item->getExpirationTimestamp(),
]
);
$file = $this->getFilePath($item->getKey());
if ($this->filesystem->has($file)) {
// Update file if it exists
return $this->filesystem->update($file, $data);
}
try {
return $this->filesystem->write($file, $data);
} catch (FileExistsException $e) {
// To handle issues when/if race conditions occurs, we try to update here.
return $this->filesystem->update($file, $data);
}
}
/**
* @param string $key
*
* @throws InvalidArgumentException
*
* @return string
*/
private function getFilePath($key)
{
if (!preg_match('|^[a-zA-Z0-9_\.! ]+$|', $key)) {
throw new InvalidArgumentException(sprintf('Invalid key "%s". Valid filenames must match [a-zA-Z0-9_\.! ].', $key));
}
return sprintf('%s/%s', $this->folder, $key);
}
/**
* {@inheritdoc}
*/
protected function getList($name)
{
$file = $this->getFilePath($name);
if (!$this->filesystem->has($file)) {
$this->filesystem->write($file, serialize([]));
}
return unserialize($this->filesystem->read($file));
}
/**
* {@inheritdoc}
*/
protected function removeList($name)
{
$file = $this->getFilePath($name);
$this->filesystem->delete($file);
}
/**
* {@inheritdoc}
*/
protected function appendListItem($name, $key)
{
$list = $this->getList($name);
$list[] = $key;
return $this->filesystem->update($this->getFilePath($name), serialize($list));
}
/**
* {@inheritdoc}
*/
protected function removeListItem($name, $key)
{
$list = $this->getList($name);
foreach ($list as $i => $item) {
if ($item === $key) {
unset($list[$i]);
}
}
return $this->filesystem->update($this->getFilePath($name), serialize($list));
}
/**
* @param $key
*
* @return bool
*/
private function forceClear($key)
{
try {
return $this->filesystem->delete($this->getFilePath($key));
} catch (FileNotFoundException $e) {
return true;
}
}
}

22
vendor/cache/filesystem-adapter/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.

View File

@ -0,0 +1,45 @@
# Filesystem PSR-6 Cache pool
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/filesystem-adapter/v/stable)](https://packagist.org/packages/cache/filesystem-adapter)
[![codecov.io](https://codecov.io/github/php-cache/filesystem-adapter/coverage.svg?branch=master)](https://codecov.io/github/php-cache/filesystem-adapter?branch=master)
[![Total Downloads](https://poser.pugx.org/cache/filesystem-adapter/downloads)](https://packagist.org/packages/cache/filesystem-adapter)
[![Monthly Downloads](https://poser.pugx.org/cache/filesystem-adapter/d/monthly.png)](https://packagist.org/packages/cache/filesystem-adapter)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This is a PSR-6 cache implementation using Filesystem. It is a part of the PHP Cache organisation. To read about
features like tagging and hierarchy support please read the shared documentation at [www.php-cache.com](http://www.php-cache.com).
This implementation is using the excellent [Flysystem](http://flysystem.thephpleague.com/).
### Install
```bash
composer require cache/filesystem-adapter
```
### Use
To create an instance of `FilesystemCachePool` you need to configure a `Filesystem` and its adapter.
```php
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use Cache\Adapter\Filesystem\FilesystemCachePool;
$filesystemAdapter = new Local(__DIR__.'/');
$filesystem = new Filesystem($filesystemAdapter);
$pool = new FilesystemCachePool($filesystem);
```
You can change the folder the cache pool will write to through the `setFolder` setter:
```php
$pool = new FilesystemCachePool($filesystem);
$pool->setFolder('path/to/cache');
```
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).

View File

@ -0,0 +1,55 @@
{
"name": "cache/filesystem-adapter",
"description": "A PSR-6 cache implementation using filesystem. This implementation supports tags",
"license": "MIT",
"type": "library",
"keywords": [
"cache",
"psr-6",
"filesystem",
"tag"
],
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"homepage": "http://www.php-cache.com/en/latest/",
"require": {
"php": ">=7.4",
"cache/adapter-common": "^1.0",
"league/flysystem": "^1.0",
"psr/cache": "^1.0 || ^2.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"cache/integration-tests": "^0.17",
"phpunit/phpunit": "^7.5.20 || ^9.5.10"
},
"provide": {
"psr/cache-implementation": "^1.0",
"psr/simple-cache-implementation": "^1.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Cache\\Adapter\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}

View File

@ -0,0 +1,5 @@
This is a READ ONLY repository.
Please make your pull request to https://github.com/php-cache/cache
Thank you for contributing.

2
vendor/cache/tag-interop/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
composer.lock
vendor

22
vendor/cache/tag-interop/.travis.yml vendored Normal file
View File

@ -0,0 +1,22 @@
language: php
sudo: false
matrix:
include:
- php: 7.1
cache:
directories:
- "$HOME/.composer/cache"
install:
- composer update --prefer-dist --prefer-stable
script:
- ./vendor/bin/phpunit --coverage-clover=coverage.xml
after_success:
- pip install --user codecov && codecov
notifications:
email: false

18
vendor/cache/tag-interop/Changelog.md vendored Normal file
View File

@ -0,0 +1,18 @@
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## 1.1.0
* Support PHP 8.1
* Support for psr/cache v2
## 1.0.1
* Support PHP 8
## 1.0.0
* First release

22
vendor/cache/tag-interop/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Aaron Scherer, Tobias Nyholm
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.

25
vendor/cache/tag-interop/README.md vendored Normal file
View File

@ -0,0 +1,25 @@
# Tag support for PSR-6 Cache
[![Gitter](https://badges.gitter.im/php-cache/cache.svg)](https://gitter.im/php-cache/cache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Latest Stable Version](https://poser.pugx.org/cache/tag-interop/v/stable)](https://packagist.org/packages/cache/tag-interop)
[![Total Downloads](https://poser.pugx.org/cache/tag-interop/downloads)](https://packagist.org/packages/cache/tag-interop)
[![Monthly Downloads](https://poser.pugx.org/cache/tag-interop/d/monthly.png)](https://packagist.org/packages/cache/tag-interop)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This repository holds two interfaces for tagging. These interfaces will make their
way into PHP Fig. Representatives from Symfony, PHP-cache and Drupal has worked
together to agree on these interfaces.
### Install
```bash
composer require cache/tag-interop
```
### Use
Read the [documentation on usage](http://www.php-cache.com/).
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/php-cache/cache) or
report any issues you find on the [issue tracker](http://issues.php-cache.com).

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\TagInterop;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
/**
* An item that supports tags. This interface is a soon-to-be-PSR.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
interface TaggableCacheItemInterface extends CacheItemInterface
{
/**
* Get all existing tags. These are the tags the item has when the item is
* returned from the pool.
*
* @return array
*/
public function getPreviousTags();
/**
* Overwrite all tags with a new set of tags.
*
* @param string[] $tags An array of tags
*
* @throws InvalidArgumentException When a tag is not valid.
*
* @return TaggableCacheItemInterface
*/
public function setTags(array $tags);
}

View File

@ -0,0 +1,60 @@
<?php
/*
* This file is part of php-cache organization.
*
* (c) 2015 Aaron Scherer <aequasi@gmail.com>, Tobias Nyholm <tobias.nyholm@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Cache\TagInterop;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
/**
* Interface for invalidating cached items using tags. This interface is a soon-to-be-PSR.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
interface TaggableCacheItemPoolInterface extends CacheItemPoolInterface
{
/**
* Invalidates cached items using a tag.
*
* @param string $tag The tag to invalidate
*
* @throws InvalidArgumentException When $tags is not valid
*
* @return bool True on success
*/
public function invalidateTag($tag);
/**
* Invalidates cached items using tags.
*
* @param string[] $tags An array of tags to invalidate
*
* @throws InvalidArgumentException When $tags is not valid
*
* @return bool True on success
*/
public function invalidateTags(array $tags);
/**
* {@inheritdoc}
*
* @return TaggableCacheItemInterface
*/
public function getItem($key);
/**
* {@inheritdoc}
*
* @return array|\Traversable|TaggableCacheItemInterface[]
*/
public function getItems(array $keys = []);
}

39
vendor/cache/tag-interop/composer.json vendored Normal file
View File

@ -0,0 +1,39 @@
{
"name": "cache/tag-interop",
"description": "Framework interoperable interfaces for tags",
"license": "MIT",
"type": "library",
"keywords": [
"cache",
"psr6",
"tag",
"psr"
],
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
},
{
"name": "Nicolas Grekas ",
"email": "p@tchwork.com",
"homepage": "https://github.com/nicolas-grekas"
}
],
"homepage": "https://www.php-cache.com/en/latest/",
"require": {
"php": "^5.5 || ^7.0 || ^8.0",
"psr/cache": "^1.0 || ^2.0"
},
"autoload": {
"psr-4": {
"Cache\\TagInterop\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
}
}

View File

@ -7,9 +7,22 @@ $baseDir = dirname($vendorDir);
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Callback' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'CallbackBody' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'CallbackParam' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'CallbackParameterToReference' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'CallbackReturnReference' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'CallbackReturnValue' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'DOMDocumentWrapper' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'DOMEvent' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'ICallbackNamed' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'phpQuery' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryEvents' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryObject' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryPlugins' => $vendorDir . '/jaeger/phpquery-single/phpQuery.php',
);

View File

@ -14,10 +14,12 @@ return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
'6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => $vendorDir . '/taoser/think-addons/src/helper.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
'8c783b3a3de2f6d9177022b5ccdcc841' => $vendorDir . '/yansongda/pay/src/Functions.php',

View File

@ -22,10 +22,12 @@ return array(
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'),
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
'Tightenco\\Collect\\' => array($vendorDir . '/tightenco/collect/src/Collect'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
'QL\\' => array($vendorDir . '/jaeger/querylist/src'),
'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'),
@ -41,6 +43,7 @@ return array(
'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
'Jaeger\\' => array($vendorDir . '/jaeger/g-http/src'),
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
@ -50,5 +53,8 @@ return array(
'DI\\' => array($vendorDir . '/php-di/php-di/src'),
'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'),
'Channel\\' => array($vendorDir . '/workerman/channel/src'),
'Cache\\TagInterop\\' => array($vendorDir . '/cache/tag-interop'),
'Cache\\Adapter\\Filesystem\\' => array($vendorDir . '/cache/filesystem-adapter'),
'Cache\\Adapter\\Common\\' => array($vendorDir . '/cache/adapter-common'),
'BaconQrCode\\' => array($vendorDir . '/bacon/bacon-qr-code/src'),
);

View File

@ -15,10 +15,12 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
'6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php',
'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => __DIR__ . '/..' . '/taoser/think-addons/src/helper.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
'8c783b3a3de2f6d9177022b5ccdcc841' => __DIR__ . '/..' . '/yansongda/pay/src/Functions.php',
@ -63,6 +65,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
'Workerman\\' => 10,
),
'T' =>
array (
'Tightenco\\Collect\\' => 18,
),
'S' =>
array (
'Symfony\\Polyfill\\Php80\\' => 23,
@ -70,6 +76,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Component\\VarDumper\\' => 28,
),
'Q' =>
array (
'QL\\' => 3,
),
'P' =>
array (
'Psr\\SimpleCache\\' => 16,
@ -91,6 +101,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'League\\Flysystem\\' => 17,
'Laravel\\SerializableClosure\\' => 28,
),
'J' =>
array (
'Jaeger\\' => 7,
),
'I' =>
array (
'Invoker\\' => 8,
@ -117,6 +131,9 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'C' =>
array (
'Channel\\' => 8,
'Cache\\TagInterop\\' => 17,
'Cache\\Adapter\\Filesystem\\' => 25,
'Cache\\Adapter\\Common\\' => 21,
),
'B' =>
array (
@ -193,6 +210,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/workerman/workerman',
),
'Tightenco\\Collect\\' =>
array (
0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
@ -209,6 +230,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/symfony/var-dumper',
),
'QL\\' =>
array (
0 => __DIR__ . '/..' . '/jaeger/querylist/src',
),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
@ -269,6 +294,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/laravel/serializable-closure/src',
),
'Jaeger\\' =>
array (
0 => __DIR__ . '/..' . '/jaeger/g-http/src',
),
'Invoker\\' =>
array (
0 => __DIR__ . '/..' . '/php-di/invoker/src',
@ -305,6 +334,18 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/workerman/channel/src',
),
'Cache\\TagInterop\\' =>
array (
0 => __DIR__ . '/..' . '/cache/tag-interop',
),
'Cache\\Adapter\\Filesystem\\' =>
array (
0 => __DIR__ . '/..' . '/cache/filesystem-adapter',
),
'Cache\\Adapter\\Common\\' =>
array (
0 => __DIR__ . '/..' . '/cache/adapter-common',
),
'BaconQrCode\\' =>
array (
0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src',
@ -317,11 +358,24 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Callback' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'CallbackBody' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'CallbackParam' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'CallbackParameterToReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'CallbackReturnReference' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'CallbackReturnValue' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'DOMDocumentWrapper' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'DOMEvent' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'ICallbackNamed' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'phpQuery' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryEvents' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryObject' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
'phpQueryPlugins' => __DIR__ . '/..' . '/jaeger/phpquery-single/phpQuery.php',
);
public static function getInitializer(ClassLoader $loader)

View File

@ -57,6 +57,210 @@
},
"install-path": "../bacon/bacon-qr-code"
},
{
"name": "cache/adapter-common",
"version": "1.3.0",
"version_normalized": "1.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-cache/adapter-common.git",
"reference": "8788309be72aa7be69b88cdc0687549c74a7d479"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-cache/adapter-common/zipball/8788309be72aa7be69b88cdc0687549c74a7d479",
"reference": "8788309be72aa7be69b88cdc0687549c74a7d479",
"shasum": ""
},
"require": {
"cache/tag-interop": "^1.0",
"php": ">=7.4",
"psr/cache": "^1.0 || ^2.0",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"cache/integration-tests": "^0.17",
"phpunit/phpunit": "^7.5.20 || ^9.5.10"
},
"time": "2022-01-15T15:47:19+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Cache\\Adapter\\Common\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"description": "Common classes for PSR-6 adapters",
"homepage": "http://www.php-cache.com/en/latest/",
"keywords": [
"cache",
"psr-6",
"tag"
],
"support": {
"source": "https://github.com/php-cache/adapter-common/tree/1.3.0"
},
"install-path": "../cache/adapter-common"
},
{
"name": "cache/filesystem-adapter",
"version": "1.2.0",
"version_normalized": "1.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-cache/filesystem-adapter.git",
"reference": "f1faaae40aaa696ef899cef6f6888aedb90b419b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-cache/filesystem-adapter/zipball/f1faaae40aaa696ef899cef6f6888aedb90b419b",
"reference": "f1faaae40aaa696ef899cef6f6888aedb90b419b",
"shasum": ""
},
"require": {
"cache/adapter-common": "^1.0",
"league/flysystem": "^1.0",
"php": ">=7.4",
"psr/cache": "^1.0 || ^2.0",
"psr/simple-cache": "^1.0"
},
"provide": {
"psr/cache-implementation": "^1.0",
"psr/simple-cache-implementation": "^1.0"
},
"require-dev": {
"cache/integration-tests": "^0.17",
"phpunit/phpunit": "^7.5.20 || ^9.5.10"
},
"time": "2022-01-15T15:47:19+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Cache\\Adapter\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Aaron Scherer",
"email": "aequasi@gmail.com",
"homepage": "https://github.com/aequasi"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
}
],
"description": "A PSR-6 cache implementation using filesystem. This implementation supports tags",
"homepage": "http://www.php-cache.com/en/latest/",
"keywords": [
"cache",
"filesystem",
"psr-6",
"tag"
],
"support": {
"source": "https://github.com/php-cache/filesystem-adapter/tree/1.2.0"
},
"install-path": "../cache/filesystem-adapter"
},
{
"name": "cache/tag-interop",
"version": "1.1.0",
"version_normalized": "1.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-cache/tag-interop.git",
"reference": "b062b1d735357da50edf8387f7a8696f3027d328"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-cache/tag-interop/zipball/b062b1d735357da50edf8387f7a8696f3027d328",
"reference": "b062b1d735357da50edf8387f7a8696f3027d328",
"shasum": ""
},
"require": {
"php": "^5.5 || ^7.0 || ^8.0",
"psr/cache": "^1.0 || ^2.0"
},
"time": "2021-12-31T10:03:23+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Cache\\TagInterop\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/nyholm"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com",
"homepage": "https://github.com/nicolas-grekas"
}
],
"description": "Framework interoperable interfaces for tags",
"homepage": "https://www.php-cache.com/en/latest/",
"keywords": [
"cache",
"psr",
"psr6",
"tag"
],
"support": {
"issues": "https://github.com/php-cache/tag-interop/issues",
"source": "https://github.com/php-cache/tag-interop/tree/1.1.0"
},
"install-path": "../cache/tag-interop"
},
{
"name": "dasprid/enum",
"version": "1.0.3",
@ -536,6 +740,163 @@
],
"install-path": "../guzzlehttp/psr7"
},
{
"name": "jaeger/g-http",
"version": "V1.7.2",
"version_normalized": "1.7.2.0",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/GHttp.git",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/GHttp/zipball/82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"shasum": ""
},
"require": {
"cache/filesystem-adapter": "^1",
"guzzlehttp/guzzle": "^6.0 | ^7.0"
},
"time": "2021-08-08T04:59:44+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Jaeger\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaeger",
"email": "JaegerCode@gmail.com"
}
],
"description": "Simple Http client base on GuzzleHttp",
"support": {
"issues": "https://github.com/jae-jae/GHttp/issues",
"source": "https://github.com/jae-jae/GHttp/tree/V1.7.2"
},
"install-path": "../jaeger/g-http"
},
{
"name": "jaeger/phpquery-single",
"version": "1.1.1",
"version_normalized": "1.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/phpQuery-single.git",
"reference": "39a650ade692a6b480c22220dce0c198d6a946fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/phpQuery-single/zipball/39a650ade692a6b480c22220dce0c198d6a946fb",
"reference": "39a650ade692a6b480c22220dce0c198d6a946fb",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2022-03-26T15:01:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"phpQuery.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tobiasz Cudnik",
"email": "tobiasz.cudnik@gmail.com",
"homepage": "https://github.com/TobiaszCudnik",
"role": "Developer"
},
{
"name": "Jaeger",
"role": "Packager"
}
],
"description": "phpQuery单文件版本是Querylist的依赖(http://querylist.cc/)phpQuery项目主页:http://code.google.com/p/phpquery/",
"homepage": "http://code.google.com/p/phpquery/",
"support": {
"issues": "https://github.com/jae-jae/phpQuery-single/issues",
"source": "https://github.com/jae-jae/phpQuery-single/tree/1.1.1"
},
"install-path": "../jaeger/phpquery-single"
},
{
"name": "jaeger/querylist",
"version": "V4.2.8",
"version_normalized": "4.2.8.0",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/QueryList.git",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/QueryList/zipball/39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"shasum": ""
},
"require": {
"ext-dom": "*",
"jaeger/g-http": "^1.1",
"jaeger/phpquery-single": "^1",
"php": ">=7.1",
"tightenco/collect": ">5.0"
},
"require-dev": {
"phpunit/phpunit": "^8.5",
"symfony/var-dumper": "^3.3"
},
"time": "2021-07-05T06:07:58+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"QL\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaeger",
"email": "JaegerCode@gmail.com"
}
],
"description": "Simple, elegant, extensible PHP Web Scraper (crawler/spider),Use the css3 dom selector,Based on phpQuery! 简洁、优雅、可扩展的PHP采集工具(爬虫)基于phpQuery。",
"homepage": "http://querylist.cc",
"keywords": [
"QueryList",
"phpQuery",
"spider"
],
"support": {
"issues": "https://github.com/jae-jae/QueryList/issues",
"source": "https://github.com/jae-jae/QueryList/tree/V4.2.8"
},
"funding": [
{
"url": "https://opencollective.com/querylist",
"type": "open_collective"
}
],
"install-path": "../jaeger/querylist"
},
{
"name": "laravel/serializable-closure",
"version": "v1.2.2",
@ -2159,6 +2520,63 @@
},
"install-path": "../taoser/think-setarr"
},
{
"name": "tightenco/collect",
"version": "v8.83.23",
"version_normalized": "8.83.23.0",
"source": {
"type": "git",
"url": "https://github.com/tighten/collect.git",
"reference": "a4423c6ace6b54ba4f86c0ac9de588c57bc94d79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tighten/collect/zipball/a4423c6ace6b54ba4f86c0ac9de588c57bc94d79",
"reference": "a4423c6ace6b54ba4f86c0ac9de588c57bc94d79",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0",
"symfony/var-dumper": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"nesbot/carbon": "^2.23.0",
"phpunit/phpunit": "^8.3"
},
"time": "2022-08-22T17:50:04+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"src/Collect/Support/helpers.php",
"src/Collect/Support/alias.php"
],
"psr-4": {
"Tightenco\\Collect\\": "src/Collect"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
}
],
"description": "Collect - Illuminate Collections as a separate package.",
"keywords": [
"collection",
"laravel"
],
"support": {
"issues": "https://github.com/tighten/collect/issues",
"source": "https://github.com/tighten/collect/tree/v8.83.23"
},
"install-path": "../tightenco/collect"
},
{
"name": "topthink/framework",
"version": "v6.0.13",
@ -3075,10 +3493,6 @@
],
"dev": true,
"dev-package-names": [
"symfony/polyfill-mbstring",
"symfony/polyfill-php72",
"symfony/polyfill-php80",
"symfony/var-dumper",
"topthink/think-trace"
]
}

View File

@ -3,7 +3,7 @@
'name' => 'taoser/taoler',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '2f7a73366c80586c404f620fc440626d4c033930',
'reference' => '846581c3abfa893a57d4ce930c2fa684dfd688af',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -19,6 +19,33 @@
'aliases' => array(),
'dev_requirement' => false,
),
'cache/adapter-common' => array(
'pretty_version' => '1.3.0',
'version' => '1.3.0.0',
'reference' => '8788309be72aa7be69b88cdc0687549c74a7d479',
'type' => 'library',
'install_path' => __DIR__ . '/../cache/adapter-common',
'aliases' => array(),
'dev_requirement' => false,
),
'cache/filesystem-adapter' => array(
'pretty_version' => '1.2.0',
'version' => '1.2.0.0',
'reference' => 'f1faaae40aaa696ef899cef6f6888aedb90b419b',
'type' => 'library',
'install_path' => __DIR__ . '/../cache/filesystem-adapter',
'aliases' => array(),
'dev_requirement' => false,
),
'cache/tag-interop' => array(
'pretty_version' => '1.1.0',
'version' => '1.1.0.0',
'reference' => 'b062b1d735357da50edf8387f7a8696f3027d328',
'type' => 'library',
'install_path' => __DIR__ . '/../cache/tag-interop',
'aliases' => array(),
'dev_requirement' => false,
),
'dasprid/enum' => array(
'pretty_version' => '1.0.3',
'version' => '1.0.3.0',
@ -73,6 +100,33 @@
'aliases' => array(),
'dev_requirement' => false,
),
'jaeger/g-http' => array(
'pretty_version' => 'V1.7.2',
'version' => '1.7.2.0',
'reference' => '82585ddd5e2c6651e37ab1d8166efcdbb6b293d4',
'type' => 'library',
'install_path' => __DIR__ . '/../jaeger/g-http',
'aliases' => array(),
'dev_requirement' => false,
),
'jaeger/phpquery-single' => array(
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'reference' => '39a650ade692a6b480c22220dce0c198d6a946fb',
'type' => 'library',
'install_path' => __DIR__ . '/../jaeger/phpquery-single',
'aliases' => array(),
'dev_requirement' => false,
),
'jaeger/querylist' => array(
'pretty_version' => 'V4.2.8',
'version' => '4.2.8.0',
'reference' => '39dc0ca9c668bec7a793e20472ccd7d26ef89ea4',
'type' => 'library',
'install_path' => __DIR__ . '/../jaeger/querylist',
'aliases' => array(),
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v1.2.2',
'version' => '1.2.2.0',
@ -172,6 +226,12 @@
'aliases' => array(),
'dev_requirement' => false,
),
'psr/cache-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '^1.0',
),
),
'psr/container' => array(
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
@ -244,6 +304,12 @@
'aliases' => array(),
'dev_requirement' => false,
),
'psr/simple-cache-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '^1.0',
),
),
'ralouphie/getallheaders' => array(
'pretty_version' => '3.0.3',
'version' => '3.0.3.0',
@ -260,7 +326,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'dev_requirement' => true,
'dev_requirement' => false,
),
'symfony/polyfill-php72' => array(
'pretty_version' => 'v1.26.0',
@ -269,7 +335,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
'aliases' => array(),
'dev_requirement' => true,
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.26.0',
@ -278,7 +344,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'dev_requirement' => true,
'dev_requirement' => false,
),
'symfony/var-dumper' => array(
'pretty_version' => 'v4.4.44',
@ -287,12 +353,12 @@
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-dumper',
'aliases' => array(),
'dev_requirement' => true,
'dev_requirement' => false,
),
'taoser/taoler' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '2f7a73366c80586c404f620fc440626d4c033930',
'reference' => '846581c3abfa893a57d4ce930c2fa684dfd688af',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -325,6 +391,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'tightenco/collect' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => 'a4423c6ace6b54ba4f86c0ac9de588c57bc94d79',
'type' => 'library',
'install_path' => __DIR__ . '/../tightenco/collect',
'aliases' => array(),
'dev_requirement' => false,
),
'topthink/framework' => array(
'pretty_version' => 'v6.0.13',
'version' => '6.0.13.0',

3
vendor/jaeger/g-http/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea
/vendor/
composer.lock

158
vendor/jaeger/g-http/README.md vendored Normal file
View File

@ -0,0 +1,158 @@
# GHttp
基于GuzzleHttp的简单版Http客户端。 Simple Http client base on GuzzleHttp
## 安装
```
composer require jaeger/g-http
```
## 用法
#### 1. get / getJson
```php
use Jaeger\GHttp;
$rt = GHttp::get('https://www.baidu.com/s?wd=QueryList');
$rt = GHttp::get('https://www.baidu.com/s','wd=QueryList&wd2=teststr');
//or
$rt = GHttp::get('https://www.baidu.com/s',[
'wd' => 'QueryList',
'wd2' => 'teststr'
]);
//opt
$rt = GHttp::get('https://www.baidu.com/s',[
'wd' => 'QueryList'
],[
'headers' => [
'referer' => 'https://baidu.com',
'User-Agent' => 'Mozilla/5.0 (Windows NTChrome/58.0.3029.110 Safari/537.36',
'Cookie' => 'cookie xxx'
]
]);
$rt = GHttp::getJson('https://xxxx.com/json');
```
#### 2.post / postRaw / postJson
```php
$rt = GHttp::post('https://www.posttestserver.com/post.php',[
'name' => 'QueryList',
'password' => 'ql'
]);
$rt = GHttp::post('https://www.posttestserver.com/post.php','name=QueryList&password=ql');
$rt = GHttp::postRaw('http://httpbin.org/post','raw data');
$rt = GHttp::postRaw('http://httpbin.org/post',['aa' => 11,'bb' => 22]);
$rt = GHttp::postJson('http://httpbin.org/post',['aa' => 11,'bb' => 22]);
$rt = GHttp::postJson('http://httpbin.org/post','aa=11&bb=22');
```
#### 3.download
```php
GHttp::download('http://sw.bos.baidu.com/setup.exe','./path/to/xx.exe');
```
### 4. concurrent requests
```php
use Jaeger\GHttp;
$urls = [
'http://httpbin.org/get?name=php',
'http://httpbin.org/get?name=go',
'http://httpbin.org/get?name=c#',
'http://httpbin.org/get?name=java'
];
GHttp::multiRequest($urls)->withHeaders([
'X-Powered-By' => 'Jaeger'
])->withOptions([
'timeout' => 10
])->concurrency(2)->success(function($response,$index){
print_r((String)$response->getBody());
print_r($index);
})->error(function($reason,$index){
print_r($reason);
})->get();
```
```php
use Jaeger\GHttp;
use GuzzleHttp\Psr7\Request;
$requests = [
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'php'
])),
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'go'
])),
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'c#'
]))
];
GHttp::multiRequest($requests)->success(function($response,$index){
print_r((String)$response->getBody());
print_r($index);
})->post();
```
### 5. Request with cache
Base on PHP-Cache: http://www.php-cache.com
- Use filesystem cache
```php
use Jaeger\GHttp;
$rt = GHttp::get('http://httpbin.org/get',[
'wd' => 'QueryList'
],[
'cache' => __DIR__,
'cache_ttl' => 120 //seconds
]);
```
- Use predis cache
Install predis adapter:
```
composer require cache/predis-adapter
```
Usage:
```php
use Jaeger\GHttp;
use Cache\Adapter\Predis\PredisCachePool;
$client = new \Predis\Client('tcp:/127.0.0.1:6379');
$pool = new PredisCachePool($client);
$rt = GHttp::get('http://httpbin.org/get',[
'wd' => 'QueryList'
],[
'cache' => $pool,
'cache_ttl' => 120 //seconds
]);
```

20
vendor/jaeger/g-http/composer.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"name": "jaeger/g-http",
"description": "Simple Http client base on GuzzleHttp",
"license": "MIT",
"authors": [
{
"name": "Jaeger",
"email": "JaegerCode@gmail.com"
}
],
"require": {
"cache/filesystem-adapter": "^1",
"guzzlehttp/guzzle": "^6.0 | ^7.0"
},
"autoload":{
"psr-4":{
"Jaeger\\":"src"
}
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/10
* Time: 下午4:04
*/
require __DIR__.'/../vendor/autoload.php';
use Jaeger\GHttp;
$urls = [
'http://httpbin.org/get?name=php',
'http://httpbin.org/get?name=go',
'http://httpbin.org/get?name=c#',
'http://httpbin.org/get?name=java'
];
GHttp::multiRequest($urls)->withHeaders([
'X-Powered-By' => 'Jaeger'
])->withOptions([
'timeout' => 10
])->concurrency(2)->success(function($response,$index){
print_r((String)$response->getBody());
print_r($index);
})->error(function($reason,$index){
print_r($reason);
})->get();

View File

@ -0,0 +1,37 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/10
* Time: 下午6:51
*/
require __DIR__.'/../vendor/autoload.php';
use Jaeger\GHttp;
use GuzzleHttp\Psr7\Request;
$requests = [
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'php'
])),
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'go'
])),
new Request('POST','http://httpbin.org/post',[
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'g-http'
],http_build_query([
'name' => 'c#'
]))
];
GHttp::multiRequest($requests)->success(function($response,$index){
print_r((String)$response->getBody());
print_r($index);
})->post();

View File

@ -0,0 +1,33 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/11
* Time: 下午6:48
*/
require __DIR__.'/../vendor/autoload.php';
use Jaeger\GHttp;
use Cache\Adapter\Predis\PredisCachePool;
$rt = GHttp::get('http://httpbin.org/get',[
'wd' => 'QueryList'
],[
'cache' => __DIR__,
'cache_ttl' => 120
]);
print_r($rt);
$client = new \Predis\Client('tcp:/127.0.0.1:6379');
$pool = new PredisCachePool($client);
$rt = GHttp::get('http://httpbin.org/get',[
'wd' => 'QueryList'
],[
'cache' => $pool,
'cache_ttl' => 120
]);
print_r($rt);

View File

@ -0,0 +1,22 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/11
* Time: 下午6:48
*/
require __DIR__.'/../vendor/autoload.php';
use Jaeger\GHttp;
$rt = GHttp::get('http://httpbin.org/get',[
'wd' => 'QueryList'
],[
'headers' => [
'referer' => 'https://baidu.com',
'User-Agent' => 'Mozilla/5.0 (Windows NTChrome/58.0.3029.110 Safari/537.36',
'Cookie' => 'cookie xxx'
],
]);
print_r($rt);

65
vendor/jaeger/g-http/src/Cache.php vendored Normal file
View File

@ -0,0 +1,65 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/11
* Time: 下午6:39
*/
namespace Jaeger;
use Cache\Adapter\Common\AbstractCachePool;
use Cache\Adapter\Filesystem\FilesystemCachePool;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
class Cache extends GHttp
{
public static function remember($name, $arguments)
{
$cachePool = null;
$cacheConfig = self::initCacheConfig($arguments);
if (empty($cacheConfig['cache'])) {
return self::$name(...$arguments);
}
if (is_string($cacheConfig['cache'])) {
$filesystemAdapter = new Local($cacheConfig['cache']);
$filesystem = new Filesystem($filesystemAdapter);
$cachePool = new FilesystemCachePool($filesystem);
}else if ($cacheConfig['cache'] instanceof AbstractCachePool) {
$cachePool = $cacheConfig['cache'];
}
$cacheKey = self::getCacheKey($name,$arguments);
$data = $cachePool->get($cacheKey);
if(empty($data)) {
$data = self::$name(...$arguments);
if(!empty($data)) {
$cachePool->set($cacheKey,$data,$cacheConfig['cache_ttl']);
}
}
return $data;
}
protected static function initCacheConfig($arguments)
{
$cacheConfig = [
'cache' => null,
'cache_ttl' => null
];
if(!empty($arguments[2])) {
$cacheConfig = array_merge([
'cache' => null,
'cache_ttl' => null
],$arguments[2]);
}
return $cacheConfig;
}
protected static function getCacheKey($name, $arguments)
{
return md5($name.'_'.json_encode($arguments));
}
}

164
vendor/jaeger/g-http/src/GHttp.php vendored Normal file
View File

@ -0,0 +1,164 @@
<?php
/**
* 基于GuzzleHttp的简单版Http客户端。 Simple Http client base on GuzzleHttp
*
* @Author: Jaeger <JaegerCode@gmail.com>
*
* @Version V1.0
*/
namespace Jaeger;
use GuzzleHttp\Client;
/**
* Class GHttp
* @package Jaeger
*
* @method static string get($url,$args = null,$otherArgs = [])
* @method static mixed getJson($url, $args = null, $otherArgs = [])
* @method static string post($url,$args = null,$otherArgs = [])
* @method static string postRaw($url, $raw = null, $otherArgs = [])
* @method static string postJson($url, $args = null, $otherArgs = [])
*/
class GHttp
{
private static $client = null;
public static function __callStatic($name, $arguments)
{
$protectedName = '_'.$name;
if(method_exists(self::class,$protectedName)){
return Cache::remember($protectedName, $arguments);
}
throw new MethodNotFoundException('Call undefined method '.self::class.':'.$name.'()');
}
public static function getClient(array $config = [])
{
if(self::$client == null){
self::$client = new Client($config);
}
return self::$client;
}
/**
* @param $url
* @param array $args
* @param array $otherArgs
* @return string
*/
protected static function _get($url,$args = null,$otherArgs = [])
{
is_string($args) && parse_str($args,$args);
$args = array_merge([
'verify' => false,
'query' => $args,
'headers' => [
'referer' => $url,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
]
],$otherArgs);
$client = self::getClient();
$response = $client->request('GET', $url,$args);
return (string)$response->getBody();
}
protected static function _getJson($url, $args = null, $otherArgs = [])
{
$data = self::get($url, $args , $otherArgs);
return json_decode($data,JSON_UNESCAPED_UNICODE);
}
/**
* @param $url
* @param array $args
* @param array $otherArgs
* @return string
*/
protected static function _post($url,$args = null,$otherArgs = [])
{
is_string($args) && parse_str($args,$args);
$args = array_merge([
'verify' => false,
'form_params' => $args,
'headers' => [
'referer' => $url,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
]
],$otherArgs);
$client = self::getClient();
$response = $client->request('Post', $url,$args);
return (string)$response->getBody();
}
/**
* @param $url
* @param null $raw
* @param array $otherArgs
* @return string
*/
protected static function _postRaw($url, $raw = null, $otherArgs = [])
{
is_array($raw) && $raw = json_encode($raw);
$args = array_merge([
'verify' => false,
'body' => $raw,
'headers' => [
'referer' => $url,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
]
],$otherArgs);
$client = self::getClient();
$response = $client->request('Post', $url,$args);
return (string)$response->getBody();
}
/**
* @param $url
* @param null $args
* @param array $otherArgs
* @return string
*/
protected static function _postJson($url, $args = null, $otherArgs = [])
{
is_string($args) && parse_str($args,$args);
$args = array_merge([
'verify' => false,
'json' => $args,
'headers' => [
'referer' => $url,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
]
],$otherArgs);
$client = self::getClient();
$response = $client->request('Post', $url,$args);
return (string)$response->getBody();
}
/**
* @param $url
* @param $filePath
* @param null $args
* @param array $otherArgs
* @return string
*/
public static function download($url,$filePath,$args = null,$otherArgs = [])
{
$otherArgs = array_merge($otherArgs,[
'sink' => $filePath,
]);
return self::get($url,$args,$otherArgs);
}
/**
* @param $urls
* @return MultiRequest
*/
public static function multiRequest($urls)
{
$client = self::getClient();
return MultiRequest::newRequest($client)->urls($urls);
}
}

View File

@ -0,0 +1,19 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/12
* Time: 上午10:56
*/
namespace Jaeger;
use Exception;
use Throwable;
class MethodNotFoundException extends Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@ -0,0 +1,113 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 18/12/10
* Time: 下午6:04
*/
namespace Jaeger;
use GuzzleHttp\Client;
use Closure;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
class MultiRequest
{
protected $client;
protected $headers = [];
protected $options = [];
protected $successCallback;
protected $errorCallback;
protected $urls = [];
protected $method;
protected $concurrency = 5;
public function __construct(Client $client)
{
$this->client = $client;
$this->headers = [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
];
}
public static function newRequest(Client $client)
{
$request = new self($client);
return $request;
}
public function withHeaders($headers)
{
$this->headers = array_merge($this->headers,$headers);
return $this;
}
public function withOptions($options)
{
$this->options = $options;
return $this;
}
public function concurrency($concurrency)
{
$this->concurrency = $concurrency;
return $this;
}
public function success(Closure $success)
{
$this->successCallback = $success;
return $this;
}
public function error(Closure $error)
{
$this->errorCallback = $error;
return $this;
}
public function urls(array $urls)
{
$this->urls = $urls;
return $this;
}
public function get()
{
$this->method = 'GET';
$this->send();
}
public function post()
{
$this->method = 'POST';
$this->send();
}
protected function send()
{
$client = $this->client;
$requests = function ($urls) use($client){
foreach ($urls as $url) {
if (is_string($url)) {
yield new Request($this->method,$url,$this->headers);
} else {
yield $url;
}
}
};
$pool = new Pool($client, $requests($this->urls), [
'concurrency' => $this->concurrency,
'fulfilled' => $this->successCallback,
'rejected' => $this->errorCallback,
'options' => $this->options
]);
$promise = $pool->promise();
$promise->wait();
}
}

36
vendor/jaeger/phpquery-single/README.md vendored Normal file
View File

@ -0,0 +1,36 @@
# phpQuery-single
phpQuery onefile composer.Continuous maintenance,Welcome PR.
`QueryList` base on phpQuery: https://github.com/jae-jae/QueryList
phpQuery单文件版本,持续维护欢迎PR.
> phpQuery项目主页:http://code.google.com/p/phpquery/
`QueryList`是基于phpQuery的采集工具: https://github.com/jae-jae/QueryList
## Composer Installation
Packagist: https://packagist.org/packages/jaeger/phpquery-single
```
composer require jaeger/phpquery-single
```
## Usage
```php
$html = <<<STR
<div id="one">
<div class="two">
<a href="http://querylist.cc">QueryList官网</a>
<img src="http://querylist.cc/1.jpg" alt="这是图片">
<img src="http://querylist.cc/2.jpg" alt="这是图片2">
</div>
<span>其它的<b>一些</b>文本</span>
</div>
STR;
$doc = phpQuery::newDocumentHTML($html);
$src = $doc->find('.two img:eq(0)')->attr('src');
echo $src;
// http://querylist.cc/1.jpg
```

View File

@ -0,0 +1,24 @@
{
"name": "jaeger/phpquery-single",
"description": "phpQuery单文件版本是Querylist的依赖(http://querylist.cc/)phpQuery项目主页:http://code.google.com/p/phpquery/",
"homepage": "http://code.google.com/p/phpquery/",
"license": "MIT",
"require": {
"PHP":">=5.3.0"
},
"authors": [
{
"name": "Tobiasz Cudnik"
,"email": "tobiasz.cudnik@gmail.com"
,"homepage": "https://github.com/TobiaszCudnik"
,"role": "Developer"
}
,{
"name": "Jaeger",
"role": "Packager"
}
],
"autoload":{
"classmap":["phpQuery.php"]
}
}

6086
vendor/jaeger/phpquery-single/phpQuery.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: querylist # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

5
vendor/jaeger/querylist/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/vendor/
.idea/
composer.lock
.DS_Store
*.cache

309
vendor/jaeger/querylist/README-ZH.md vendored Normal file
View File

@ -0,0 +1,309 @@
<p align="center">
<img width="150" src="logo.png" alt="QueryList">
<br>
<br>
</p>
# QueryList 简介
`QueryList`是一套简洁、优雅、可扩展的PHP采集工具(爬虫)基于phpQuery。
## 特性
- 拥有与jQuery完全相同的CSS3 DOM选择器
- 拥有与jQuery完全相同的DOM操作API
- 拥有通用的列表采集方案
- 拥有强大的HTTP请求套件轻松实现如模拟登陆、伪造浏览器、HTTP代理等意复杂的网络请求
- 拥有乱码解决方案
- 拥有强大的内容过滤功能可使用jQuey选择器来过滤内容
- 拥有高度的模块化设计,扩展性强
- 拥有富有表现力的API
- 拥有高质量文档
- 拥有丰富的插件
- 拥有专业的问答社区和交流群
通过插件可以轻松实现诸如:
- 多线程采集
- 采集JavaScript动态渲染的页面 (PhantomJS/headless WebKit)
- 图片本地化
- 模拟浏览器行为提交Form表单
- 网络爬虫
- .....
## 环境要求
- PHP >= 7.1
> 如果你的PHP版本还停留在PHP5或者不会使用Composer,你可以选择使用QueryList3,QueryList3支持php5.3以及手动安装。
QueryList3 文档:http://v3.querylist.cc
## 安装
通过Composer安装:
```
composer require jaeger/querylist
```
## 使用
#### 元素操作
- 采集「昵图网」所有图片地址
```php
QueryList::get('http://www.nipic.com')->find('img')->attrs('src');
```
- 采集百度搜索结果
```php
$ql = QueryList::get('http://www.baidu.com/s?wd=QueryList');
$ql->find('title')->text(); // 获取网站标题
$ql->find('meta[name=keywords]')->content; // 获取网站头部关键词
$ql->find('h3>a')->texts(); //获取搜索结果标题列表
$ql->find('h3>a')->attrs('href'); //获取搜索结果链接列表
$ql->find('img')->src; //获取第一张图片的链接地址
$ql->find('img:eq(1)')->src; //获取第二张图片的链接地址
$ql->find('img')->eq(2)->src; //获取第三张图片的链接地址
// 遍历所有图片
$ql->find('img')->map(function($img){
echo $img->alt; //打印图片的alt属性
});
```
- 更多用法
```php
$ql->find('#head')->append('<div>追加内容</div>')->find('div')->htmls();
$ql->find('.two')->children('img')->attrs('alt'); //获取class为two元素下的所有img孩子节点
//遍历class为two元素下的所有孩子节点
$data = $ql->find('.two')->children()->map(function ($item){
//用is判断节点类型
if($item->is('a')){
return $item->text();
}elseif($item->is('img'))
{
return $item->alt;
}
});
$ql->find('a')->attr('href', 'newVal')->removeClass('className')->html('newHtml')->...
$ql->find('div > p')->add('div > ul')->filter(':has(a)')->find('p:first')->nextAll()->andSelf()->...
$ql->find('div.old')->replaceWith( $ql->find('div.new')->clone())->appendTo('.trash')->prepend('Deleted')->...
```
#### 列表采集
采集百度搜索结果列表的标题和链接:
```php
$data = QueryList::get('http://www.baidu.com/s?wd=QueryList')
// 设置采集规则
->rules([
'title'=>array('h3','text'),
'link'=>array('h3>a','href')
])
->query()->getData();
print_r($data->all());
```
采集结果:
```
Array
(
[0] => Array
(
[title] => QueryList|基于phpQuery的无比强大的PHP采集工具
[link] => http://www.baidu.com/link?url=GU_YbDT2IHk4ns1tjG2I8_vjmH0SCJEAPuuZN
)
[1] => Array
(
[title] => PHP 用QueryList抓取网页内容 - wb145230 - 博客园
[link] => http://www.baidu.com/link?url=zn0DXBnrvIF2ibRVW34KcRVFG1_bCdZvqvwIhUqiXaS
)
[2] => Array
(
[title] => 介绍- QueryList指导文档
[link] => http://www.baidu.com/link?url=pSypvMovqS4v2sWeQo5fDBJ4EoYhXYi0Lxx
)
//...
)
```
#### 编码转换
```php
// 输出编码:UTF-8,输入编码:GB2312
QueryList::get('https://top.etao.com')->encoding('UTF-8','GB2312')->find('a')->texts();
// 输出编码:UTF-8,输入编码:自动识别
QueryList::get('https://top.etao.com')->encoding('UTF-8')->find('a')->texts();
```
#### HTTP网络操作GuzzleHttp
- 携带cookie登录新浪微博
```php
//采集新浪微博需要登录才能访问的页面
$ql = QueryList::get('http://weibo.com','param1=testvalue & params2=somevalue',[
'headers' => [
//填写从浏览器获取到的cookie
'Cookie' => 'SINAGLOBAL=546064; wb_cmtLike_2112031=1; wvr=6;....'
]
]);
//echo $ql->getHtml();
echo $ql->find('title')->text();
//输出: 我的首页 微博-随时随地发现新鲜事
```
- 使用Http代理
```php
$urlParams = ['param1' => 'testvalue','params2' => 'somevalue'];
$opts = [
// 设置http代理
'proxy' => 'http://222.141.11.17:8118',
//设置超时时间,单位:秒
'timeout' => 30,
// 伪造http头
'headers' => [
'Referer' => 'https://querylist.cc/',
'User-Agent' => 'testing/1.0',
'Accept' => 'application/json',
'X-Foo' => ['Bar', 'Baz'],
'Cookie' => 'abc=111;xxx=222'
]
];
$ql->get('http://httpbin.org/get',$urlParams,$opts);
// echo $ql->getHtml();
```
- 模拟登录
```php
// 用post登录
$ql = QueryList::post('http://xxxx.com/login',[
'username' => 'admin',
'password' => '123456'
])->get('http://xxx.com/admin');
//采集需要登录才能访问的页面
$ql->get('http://xxx.com/admin/page');
//echo $ql->getHtml();
```
#### Form表单操作
模拟登陆GitHub
```php
// 获取QueryList实例
$ql = QueryList::getInstance();
//获取到登录表单
$form = $ql->get('https://github.com/login')->find('form');
//填写GitHub用户名和密码
$form->find('input[name=login]')->val('your github username or email');
$form->find('input[name=password]')->val('your github password');
//序列化表单数据
$fromData = $form->serializeArray();
$postData = [];
foreach ($fromData as $item) {
$postData[$item['name']] = $item['value'];
}
//提交登录表单
$actionUrl = 'https://github.com'.$form->attr('action');
$ql->post($actionUrl,$postData);
//判断登录是否成功
// echo $ql->getHtml();
$userName = $ql->find('.header-nav-current-user>.css-truncate-target')->text();
if($userName)
{
echo '登录成功!欢迎你:'.$userName;
}else{
echo '登录失败!';
}
```
#### Bind功能扩展
自定义扩展一个`myHttp`方法:
```php
$ql = QueryList::getInstance();
//绑定一个myHttp方法到QueryList对象
$ql->bind('myHttp',function ($url){
// $this 为当前的QueryList对象
$html = file_get_contents($url);
$this->setHtml($html);
return $this;
});
//然后就可以通过注册的名字来调用
$data = $ql->myHttp('https://toutiao.io')->find('h3 a')->texts();
print_r($data->all());
```
或者把实现体封装到class然后这样绑定:
```php
$ql->bind('myHttp',function ($url){
return new MyHttp($this,$url);
});
```
#### 插件使用
- 使用PhantomJS插件采集JavaScript动态渲染的页面:
```php
// 安装时设置PhantomJS二进制文件路径
$ql = QueryList::use(PhantomJs::class,'/usr/local/bin/phantomjs');
// 采集今日头条手机版
$data = $ql->browser('https://m.toutiao.com')->find('p')->texts();
print_r($data->all());
// 使用HTTP代理
$ql->browser('https://m.toutiao.com',false,[
'--proxy' => '192.168.1.42:8080',
'--proxy-type' => 'http'
])
```
- 使用CURL多线程插件,多线程采集GitHub排行榜:
```php
$ql = QueryList::use(CurlMulti::class);
$ql->curlMulti([
'https://github.com/trending/php',
'https://github.com/trending/go',
//.....more urls
])
// 每个任务成功完成调用此回调
->success(function (QueryList $ql,CurlMulti $curl,$r){
echo "Current url:{$r['info']['url']} \r\n";
$data = $ql->find('h3 a')->texts();
print_r($data->all());
})
// 每个任务失败回调
->error(function ($errorInfo,CurlMulti $curl){
echo "Current url:{$errorInfo['info']['url']} \r\n";
print_r($errorInfo['error']);
})
->start([
// 最大并发数
'maxThread' => 10,
// 错误重试次数
'maxTry' => 3,
]);
```
## 插件
- [jae-jae/QueryList-PhantomJS](https://github.com/jae-jae/QueryList-PhantomJS): 使用PhantomJS采集JavaScript动态渲染的页面
- [jae-jae/QueryList-CurlMulti](https://github.com/jae-jae/QueryList-CurlMulti) : Curl多线程采集
- [jae-jae/QueryList-AbsoluteUrl](https://github.com/jae-jae/QueryList-AbsoluteUrl) : 转换URL相对路径到绝对路径
- [jae-jae/QueryList-Rule-Google](https://github.com/jae-jae/QueryList-Rule-Google) : 谷歌搜索引擎
- [jae-jae/QueryList-Rule-Baidu](https://github.com/jae-jae/QueryList-Rule-Baidu) : 百度搜索引擎
查看更多的QueryList插件和基于QueryList的产品:[QueryList社区力量](https://github.com/jae-jae/QueryList-Community)
## 贡献
欢迎为QueryList贡献代码。关于贡献插件可以查看:[QueryList插件贡献说明](https://github.com/jae-jae/QueryList-Community/blob/master/CONTRIBUTING.md)
## 寻求帮助?
- QueryList主页: [http://querylist.cc](http://querylist.cc/)
- QueryList文档: [http://doc.querylist.cc](http://doc.querylist.cc/)
- QueryList问答:[http://wenda.querylist.cc](http://wenda.querylist.cc/)
- QueryList交流QQ群:123266961 <a target="_blank" href="http://shang.qq.com/wpa/qunwpa?idkey=a1b248ae30b3f711bdab4f799df839300dc7fed54331177035efa0513da027f6"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="cafeEX" title="cafeEX"></a>
- GitHub:https://github.com/jae-jae/QueryList
- Git@OSC:http://git.oschina.net/jae/QueryList
## Author
Jaeger <JaegerCode@gmail.com>
## Lisence
QueryList is licensed under the license of MIT. See the LICENSE for more details.

304
vendor/jaeger/querylist/README.md vendored Normal file
View File

@ -0,0 +1,304 @@
<p align="center">
<img width="150" src="logo.png" alt="QueryList">
<br>
<br>
</p>
# QueryList
`QueryList` is a simple, elegant, extensible PHP Web Scraper (crawler/spider) ,based on phpQuery.
[API Documentation](https://github.com/jae-jae/QueryList/wiki)
[中文文档](README-ZH.md)
## Features
- Have the same CSS3 DOM selector as jQuery
- Have the same DOM manipulation API as jQuery
- Have a generic list crawling program
- Have a strong HTTP request suite, easy to achieve such as: simulated landing, forged browser, HTTP proxy and other complex network requests
- Have a messy code solution
- Have powerful content filtering, you can use the jQuey selector to filter content
- Has a high degree of modular design, scalability and strong
- Have an expressive API
- Has a wealth of plug-ins
Through plug-ins you can easily implement things like:
- Multithreaded crawl
- Crawl JavaScript dynamic rendering page (PhantomJS/headless WebKit)
- Image downloads to local
- Simulate browser behavior such as submitting Form forms
- Web crawler
- .....
## Requirements
- PHP >= 7.1
## Installation
By Composer installation:
```
composer require jaeger/querylist
```
## Usage
#### DOM Traversal and Manipulation
- Crawl「GitHub」all picture links
```php
QueryList::get('https://github.com')->find('img')->attrs('src');
```
- Crawl Google search results
```php
$ql = QueryList::get('https://www.google.co.jp/search?q=QueryList');
$ql->find('title')->text(); //The page title
$ql->find('meta[name=keywords]')->content; //The page keywords
$ql->find('h3>a')->texts(); //Get a list of search results titles
$ql->find('h3>a')->attrs('href'); //Get a list of search results links
$ql->find('img')->src; //Gets the link address of the first image
$ql->find('img:eq(1)')->src; //Gets the link address of the second image
$ql->find('img')->eq(2)->src; //Gets the link address of the third image
// Loop all the images
$ql->find('img')->map(function($img){
echo $img->alt; //Print the alt attribute of the image
});
```
- More usage
```php
$ql->find('#head')->append('<div>Append content</div>')->find('div')->htmls();
$ql->find('.two')->children('img')->attrs('alt'); // Get the class is the "two" element under all img child nodes
// Loop class is the "two" element under all child nodes
$data = $ql->find('.two')->children()->map(function ($item){
// Use "is" to determine the node type
if($item->is('a')){
return $item->text();
}elseif($item->is('img'))
{
return $item->alt;
}
});
$ql->find('a')->attr('href', 'newVal')->removeClass('className')->html('newHtml')->...
$ql->find('div > p')->add('div > ul')->filter(':has(a)')->find('p:first')->nextAll()->andSelf()->...
$ql->find('div.old')->replaceWith( $ql->find('div.new')->clone())->appendTo('.trash')->prepend('Deleted')->...
```
#### List crawl
Crawl the title and link of the Google search results list:
```php
$data = QueryList::get('https://www.google.co.jp/search?q=QueryList')
// Set the crawl rules
->rules([
'title'=>array('h3','text'),
'link'=>array('h3>a','href')
])
->query()->getData();
print_r($data->all());
```
Results:
```
Array
(
[0] => Array
(
[title] => Angular - QueryList
[link] => https://angular.io/api/core/QueryList
)
[1] => Array
(
[title] => QueryList | @angular/core - Angularリファレンス - Web Creative Park
[link] => http://www.webcreativepark.net/angular/querylist/
)
[2] => Array
(
[title] => QueryListにQueryを追加したり、追加されたことを感知する | TIPS ...
[link] => http://www.webcreativepark.net/angular/querylist_query_add_subscribe/
)
//...
)
```
#### Encode convert
```php
// Out charset :UTF-8
// In charset :GB2312
QueryList::get('https://top.etao.com')->encoding('UTF-8','GB2312')->find('a')->texts();
// Out charset:UTF-8
// In charset:Automatic Identification
QueryList::get('https://top.etao.com')->encoding('UTF-8')->find('a')->texts();
```
#### HTTP Client (GuzzleHttp)
- Carry cookie login GitHub
```php
//Crawl GitHub content
$ql = QueryList::get('https://github.com','param1=testvalue & params2=somevalue',[
'headers' => [
// Fill in the cookie from the browser
'Cookie' => 'SINAGLOBAL=546064; wb_cmtLike_2112031=1; wvr=6;....'
]
]);
//echo $ql->getHtml();
$userName = $ql->find('.header-nav-current-user>.css-truncate-target')->text();
echo $userName;
```
- Use the Http proxy
```php
$urlParams = ['param1' => 'testvalue','params2' => 'somevalue'];
$opts = [
// Set the http proxy
'proxy' => 'http://222.141.11.17:8118',
//Set the timeout time in seconds
'timeout' => 30,
// Fake HTTP headers
'headers' => [
'Referer' => 'https://querylist.cc/',
'User-Agent' => 'testing/1.0',
'Accept' => 'application/json',
'X-Foo' => ['Bar', 'Baz'],
'Cookie' => 'abc=111;xxx=222'
]
];
$ql->get('http://httpbin.org/get',$urlParams,$opts);
// echo $ql->getHtml();
```
- Analog login
```php
// Post login
$ql = QueryList::post('http://xxxx.com/login',[
'username' => 'admin',
'password' => '123456'
])->get('http://xxx.com/admin');
// Crawl pages that need to be logged in to access
$ql->get('http://xxx.com/admin/page');
//echo $ql->getHtml();
```
#### Submit forms
Login GitHub
```php
// Get the QueryList instance
$ql = QueryList::getInstance();
// Get the login form
$form = $ql->get('https://github.com/login')->find('form');
// Fill in the GitHub username and password
$form->find('input[name=login]')->val('your github username or email');
$form->find('input[name=password]')->val('your github password');
// Serialize the form data
$fromData = $form->serializeArray();
$postData = [];
foreach ($fromData as $item) {
$postData[$item['name']] = $item['value'];
}
// Submit the login form
$actionUrl = 'https://github.com'.$form->attr('action');
$ql->post($actionUrl,$postData);
// To determine whether the login is successful
// echo $ql->getHtml();
$userName = $ql->find('.header-nav-current-user>.css-truncate-target')->text();
if($userName)
{
echo 'Login successful ! Welcome:'.$userName;
}else{
echo 'Login failed !';
}
```
#### Bind function extension
Customize the extension of a `myHttp` method:
```php
$ql = QueryList::getInstance();
//Bind a `myHttp` method to the QueryList object
$ql->bind('myHttp',function ($url){
// $this is the current QueryList object
$html = file_get_contents($url);
$this->setHtml($html);
return $this;
});
// And then you can call by the name of the binding
$data = $ql->myHttp('https://toutiao.io')->find('h3 a')->texts();
print_r($data->all());
```
Or package to class, and then bind:
```php
$ql->bind('myHttp',function ($url){
return new MyHttp($this,$url);
});
```
#### Plugin used
- Use the PhantomJS plugin to crawl JavaScript dynamically rendered pages:
```php
// Set the PhantomJS binary file path during installation
$ql = QueryList::use(PhantomJs::class,'/usr/local/bin/phantomjs');
// Crawl「500px」all picture links
$data = $ql->browser('https://500px.com/editors')->find('img')->attrs('src');
print_r($data->all());
// Use the HTTP proxy
$ql->browser('https://500px.com/editors',false,[
'--proxy' => '192.168.1.42:8080',
'--proxy-type' => 'http'
])
```
- Using the CURL multithreading plug-in, multi-threaded crawling GitHub trending :
```php
$ql = QueryList::use(CurlMulti::class);
$ql->curlMulti([
'https://github.com/trending/php',
'https://github.com/trending/go',
//.....more urls
])
// Called if task is success
->success(function (QueryList $ql,CurlMulti $curl,$r){
echo "Current url:{$r['info']['url']} \r\n";
$data = $ql->find('h3 a')->texts();
print_r($data->all());
})
// Task fail callback
->error(function ($errorInfo,CurlMulti $curl){
echo "Current url:{$errorInfo['info']['url']} \r\n";
print_r($errorInfo['error']);
})
->start([
// Maximum number of threads
'maxThread' => 10,
// Number of error retries
'maxTry' => 3,
]);
```
## Plugins
- [jae-jae/QueryList-PhantomJS](https://github.com/jae-jae/QueryList-PhantomJS):Use PhantomJS to crawl Javascript dynamically rendered page.
- [jae-jae/QueryList-CurlMulti](https://github.com/jae-jae/QueryList-CurlMulti) : Curl multi threading.
- [jae-jae/QueryList-AbsoluteUrl](https://github.com/jae-jae/QueryList-AbsoluteUrl) : Converting relative urls to absolute.
- [jae-jae/QueryList-Rule-Google](https://github.com/jae-jae/QueryList-Rule-Google) : Google searcher.
- [jae-jae/QueryList-Rule-Baidu](https://github.com/jae-jae/QueryList-Rule-Baidu) : Baidu searcher.
View more QueryList plugins and QueryList-based products: [QueryList Community](https://github.com/jae-jae/QueryList-Community)
## Contributing
Welcome to contribute code for the QueryList。About Contributing Plugins can be viewed:[QueryList Plugin Contributing Guide](https://github.com/jae-jae/QueryList-Community/blob/master/CONTRIBUTING.md)
## Author
Jaeger <JaegerCode@gmail.com>
If this library is useful for you, say thanks [buying me a beer :beer:](https://www.paypal.me/jaepay)!
## Lisence
QueryList is licensed under the license of MIT. See the LICENSE for more details.

40
vendor/jaeger/querylist/composer.json vendored Normal file
View File

@ -0,0 +1,40 @@
{
"name": "jaeger/querylist",
"description": "Simple, elegant, extensible PHP Web Scraper (crawler/spider),Use the css3 dom selector,Based on phpQuery! 简洁、优雅、可扩展的PHP采集工具(爬虫)基于phpQuery。",
"keywords":["QueryList","phpQuery","spider"],
"homepage": "http://querylist.cc",
"require": {
"PHP":">=7.1",
"jaeger/phpquery-single": "^1",
"jaeger/g-http": "^1.1",
"ext-dom": "*",
"tightenco/collect": ">5.0"
},
"suggest":{
},
"license": "MIT",
"authors": [
{
"name": "Jaeger",
"email": "JaegerCode@gmail.com"
}
],
"autoload":{
"psr-4":{
"QL\\":"src"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"require-dev": {
"symfony/var-dumper": "^3.3",
"phpunit/phpunit": "^8.5"
},
"scripts": {
"test": "./vendor/bin/phpunit"
}
}

BIN
vendor/jaeger/querylist/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

19
vendor/jaeger/querylist/phpunit.xml vendored Normal file
View File

@ -0,0 +1,19 @@
<phpunit
bootstrap="vendor/autoload.php"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite name="querylist">
<directory>./tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

94
vendor/jaeger/querylist/src/Config.php vendored Normal file
View File

@ -0,0 +1,94 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/22
*/
namespace QL;
use Closure;
use Tightenco\Collect\Support\Collection;
class Config
{
protected static $instance = null;
protected $plugins;
protected $binds;
/**
* Config constructor.
*/
public function __construct()
{
$this->plugins = new Collection();
$this->binds = new Collection();
}
/**
* Get the Config instance
*
* @return null|Config
*/
public static function getInstance()
{
self::$instance || self::$instance = new self();
return self::$instance;
}
/**
* Global installation plugin
*
* @param $plugins
* @param array ...$opt
* @return $this
*/
public function use($plugins,...$opt)
{
if(is_string($plugins)){
$this->plugins->push([$plugins,$opt]);
}else{
$this->plugins = $this->plugins->merge($plugins);
}
return $this;
}
/**
* Global binding custom method
*
* @param string $name
* @param Closure $provider
* @return $this
*/
public function bind(string $name, Closure $provider)
{
$this->binds[$name] = $provider;
return $this;
}
public function bootstrap(QueryList $queryList)
{
$this->installPlugins($queryList);
$this->installBind($queryList);
}
protected function installPlugins(QueryList $queryList)
{
$this->plugins->each(function($plugin) use($queryList){
if(is_string($plugin)){
$queryList->use($plugin);
}else{
$queryList->use($plugin[0],...$plugin[1]);
}
});
}
protected function installBind(QueryList $queryList)
{
$this->binds->each(function ($provider,$name) use($queryList){
$queryList->bind($name,$provider);
});
}
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/22
*/
namespace QL\Contracts;
use QL\QueryList;
interface PluginContract
{
public static function install(QueryList $queryList,...$opt);
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/20
*/
namespace QL\Contracts;
use QL\Kernel;
interface ServiceProviderContract
{
public function register(Kernel $kernel);
}

30
vendor/jaeger/querylist/src/Dom/Dom.php vendored Normal file
View File

@ -0,0 +1,30 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/19
*/
namespace QL\Dom;
use phpQueryObject;
class Dom
{
protected $document;
/**
* Dom constructor.
*/
public function __construct(phpQueryObject $document)
{
$this->document = $document;
}
public function find($selector)
{
$elements = $this->document->find($selector);
return new Elements($elements);
}
}

View File

@ -0,0 +1,260 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/19
*/
namespace QL\Dom;
use phpDocumentor\Reflection\Types\Null_;
use phpQueryObject;
use Tightenco\Collect\Support\Collection;
/**
* Class Elements
* @package QL\Dom
*
* @method Elements toReference(&$var)
* @method Elements documentFragment($state = null)
* @method Elements toRoot()
* @method Elements getDocumentIDRef(&$documentID)
* @method Elements getDocument()
* @method \DOMDocument getDOMDocument()
* @method Elements getDocumentID()
* @method Elements unloadDocument()
* @method bool isHTML()
* @method bool isXHTML()
* @method bool isXML()
* @method string serialize()
* @method array serializeArray($submit = null)
* @method \DOMElement|\DOMElement[] get($index = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method string|array getString($index = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method string|array getStrings($index = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method Elements newInstance($newStack = null)
* @method Elements find($selectors, $context = null, $noHistory = false)
* @method Elements|bool is($selector, $nodes = null)
* @method Elements filterCallback($callback, $_skipHistory = false)
* @method Elements filter($selectors, $_skipHistory = false)
* @method Elements load($url, $data = null, $callback = null)
* @method Elements trigger($type, $data = [])
* @method Elements triggerHandler($type, $data = [])
* @method Elements bind($type, $data, $callback = null)
* @method Elements unbind($type = null, $callback = null)
* @method Elements change($callback = null)
* @method Elements submit($callback = null)
* @method Elements click($callback = null)
* @method Elements wrapAllOld($wrapper)
* @method Elements wrapAll($wrapper)
* @method Elements wrapAllPHP($codeBefore, $codeAfter)
* @method Elements wrap($wrapper)
* @method Elements wrapPHP($codeBefore, $codeAfter)
* @method Elements wrapInner($wrapper)
* @method Elements wrapInnerPHP($codeBefore, $codeAfter)
* @method Elements contents()
* @method Elements contentsUnwrap()
* @method Elements switchWith($markup)
* @method Elements eq($num)
* @method Elements size()
* @method Elements length()
* @method int count()
* @method Elements end($level = 1)
* @method Elements _clone()
* @method Elements replaceWithPHP($code)
* @method Elements replaceWith($content)
* @method Elements replaceAll($selector)
* @method Elements remove($selector = null)
* @method Elements|string markup($markup = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method string markupOuter($callback1 = null, $callback2 = null, $callback3 = null)
* @method Elements|string html($html = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method Elements|string xml($xml = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method string htmlOuter($callback1 = null, $callback2 = null, $callback3 = null)
* @method string xmlOuter($callback1 = null, $callback2 = null, $callback3 = null)
* @method Elements php($code)
* @method string markupPHP($code)
* @method string markupOuterPHP()
* @method Elements children($selector)
* @method Elements ancestors($selector)
* @method Elements append($content)
* @method Elements appendPHP($content)
* @method Elements appendTo($seletor)
* @method Elements prepend($content)
* @method Elements prependPHP($content)
* @method Elements prependTo($seletor)
* @method Elements before($content)
* @method Elements beforePHP($content)
* @method Elements insertBefore($seletor)
* @method Elements after($content)
* @method Elements afterPHP($content)
* @method Elements insertAfter($seletor)
* @method Elements insert($target, $type)
* @method int index($subject)
* @method Elements slice($start, $end = null)
* @method Elements reverse()
* @method Elements|string text($text = null, $callback1 = null, $callback2 = null, $callback3 = null)
* @method Elements plugin($class, $file = null)
* @method Elements _next($selector = null)
* @method Elements _prev($selector = null)
* @method Elements prev($selector = null)
* @method Elements prevAll($selector = null)
* @method Elements nextAll($selector = null)
* @method Elements siblings($selector = null)
* @method Elements not($selector = null)
* @method Elements add($selector = null)
* @method Elements parent($selector = null)
* @method Elements parents($selector = null)
* @method Elements stack($nodeTypes = null)
* @method Elements|string attr($attr = null, $value = null)
* @method Elements attrPHP($attr, $code)
* @method Elements removeAttr($attr)
* @method Elements|string val($val = null)
* @method Elements andSelf()
* @method Elements addClass($className)
* @method Elements addClassPHP($className)
* @method bool hasClass($className)
* @method Elements removeClass($className)
* @method Elements toggleClass($className)
* @method Elements _empty()
* @method Elements callback($callback, $param1 = null, $param2 = null, $param3 = null)
* @method string data($key, $value = null)
* @method Elements removeData($key)
* @method void rewind()
* @method Elements current()
* @method int key()
* @method Elements next($cssSelector = null)
* @method bool valid()
* @method bool offsetExists($offset)
* @method Elements offsetGet($offset)
* @method void offsetSet($offset, $value)
* @method string whois($oneNode)
* @method Elements dump()
* @method Elements dumpWhois()
* @method Elements dumpLength()
* @method Elements dumpTree($html, $title)
* @method dumpDie()
*/
class Elements
{
/**
* @var phpQueryObject
*/
protected $elements;
/**
* Elements constructor.
* @param $elements
*/
public function __construct(phpQueryObject $elements)
{
$this->elements = $elements;
}
public function __get($name)
{
return property_exists($this->elements, $name) ? $this->elements->$name : $this->elements->attr($name);
}
public function __call($name, $arguments)
{
$obj = call_user_func_array([$this->elements, $name], $arguments);
if ($obj instanceof phpQueryObject) {
$obj = new self($obj);
} else if (is_string($obj)) {
$obj = trim($obj);
}
return $obj;
}
/**
* Iterating elements
*
* @param callable $callback
*
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->elements as $key => $element) {
$break = $callback(new self(pq($element)), $key);
if ($break === false) {
break;
}
}
return $this;
}
/**
* Iterating elements
*
* @param $callback
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
*/
public function map($callback)
{
$collection = new Collection();
$this->elements->each(function ($dom) use (& $collection, $callback) {
$collection->push($callback(new self(pq($dom))));
});
return $collection;
}
/**
* Gets the attributes of all the elements
*
* @param string $attr HTML attribute name
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
*/
public function attrs($attr)
{
return $this->map(function ($item) use ($attr) {
return $item->attr($attr);
});
}
/**
* Gets the text of all the elements
*
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
*/
public function texts()
{
return $this->map(function ($item) {
return trim($item->text());
});
}
/**
* Gets the html of all the elements
*
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
*/
public function htmls()
{
return $this->map(function ($item) {
return trim($item->html());
});
}
/**
* Gets the htmlOuter of all the elements
*
* @return \Illuminate\Support\Collection|\Tightenco\Collect\Support\Collection
*/
public function htmlOuters()
{
return $this->map(function ($item) {
return trim($item->htmlOuter());
});
}
/**
* @return phpQueryObject
*/
public function getElements(): phpQueryObject
{
return $this->elements;
}
}

View File

@ -0,0 +1,322 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/21
*/
namespace QL\Dom;
use Tightenco\Collect\Support\Collection;
use phpQuery;
use phpQueryObject;
use QL\QueryList;
use Closure;
class Query
{
protected $html;
/**
* @var \phpQueryObject
*/
protected $document;
protected $rules;
protected $range = null;
protected $ql;
/**
* @var Collection
*/
protected $data;
public function __construct(QueryList $ql)
{
$this->ql = $ql;
}
/**
* @param bool $rel
* @return String
*/
public function getHtml($rel = true)
{
return $rel ? $this->document->htmlOuter() : $this->html;
}
/**
* @param $html
* @param null $charset
* @return QueryList
*/
public function setHtml($html, $charset = null)
{
$this->html = value($html);
$this->destroyDocument();
$this->document = phpQuery::newDocumentHTML($this->html, $charset);
return $this->ql;
}
/**
* Get crawl results
*
* @param Closure|null $callback
* @return Collection|static
*/
public function getData(Closure $callback = null)
{
return $this->handleData($this->data, $callback);
}
/**
* @param Collection $data
*/
public function setData(Collection $data)
{
$this->data = $data;
}
/**
* Searches for all elements that match the specified expression.
*
* @param $selector A string containing a selector expression to match elements against.
* @return Elements
*/
public function find($selector)
{
return (new Dom($this->document))->find($selector);
}
/**
* Set crawl rule
*
* $rules = [
* 'rule_name1' => ['selector','HTML attribute | text | html','Tag filter list','callback'],
* 'rule_name2' => ['selector','HTML attribute | text | html','Tag filter list','callback'],
* // ...
* ]
*
* @param array $rules
* @return QueryList
*/
public function rules(array $rules)
{
$this->rules = $rules;
return $this->ql;
}
/**
* Set the slice area for crawl list
*
* @param $selector
* @return QueryList
*/
public function range($selector)
{
$this->range = $selector;
return $this->ql;
}
/**
* Remove HTML head,try to solve the garbled
*
* @return QueryList
*/
public function removeHead()
{
$html = preg_replace('/(<head>|<head\s+.+?>).+<\/head>/is', '<head></head>', $this->html);
$this->setHtml($html);
return $this->ql;
}
/**
* Execute the query rule
*
* @param Closure|null $callback
* @return QueryList
*/
public function query(Closure $callback = null)
{
$this->data = $this->getList();
$this->data = $this->handleData($this->data, $callback);
return $this->ql;
}
public function handleData(Collection $data, $callback)
{
if (is_callable($callback)) {
if (empty($this->range)) {
$data = new Collection($callback($data->all(), null));
} else {
$data = $data->map($callback);
}
}
return $data;
}
protected function getList()
{
$data = [];
if (empty($this->range)) {
foreach ($this->rules as $key => $reg_value) {
$rule = $this->parseRule($reg_value);
$contentElements = $this->document->find($rule['selector']);
$data[$key] = $this->extractContent($contentElements, $key, $rule);
}
} else {
$rangeElements = $this->document->find($this->range);
$i = 0;
foreach ($rangeElements as $element) {
foreach ($this->rules as $key => $reg_value) {
$rule = $this->parseRule($reg_value);
$contentElements = pq($element)->find($rule['selector']);
$data[$i][$key] = $this->extractContent($contentElements, $key, $rule);
}
$i++;
}
}
return new Collection($data);
}
protected function extractContent(phpQueryObject $pqObj, $ruleName, $rule)
{
switch ($rule['attr']) {
case 'text':
$content = $this->allowTags($pqObj->html(), $rule['filter_tags']);
break;
case 'texts':
$content = (new Elements($pqObj))->map(function (Elements $element) use ($rule) {
return $this->allowTags($element->html(), $rule['filter_tags']);
})->all();
break;
case 'html':
$content = $this->stripTags($pqObj->html(), $rule['filter_tags']);
break;
case 'htmls':
$content = (new Elements($pqObj))->map(function (Elements $element) use ($rule) {
return $this->stripTags($element->html(), $rule['filter_tags']);
})->all();
break;
case 'htmlOuter':
$content = $this->stripTags($pqObj->htmlOuter(), $rule['filter_tags']);
break;
case 'htmlOuters':
$content = (new Elements($pqObj))->map(function (Elements $element) use ($rule) {
return $this->stripTags($element->htmlOuter(), $rule['filter_tags']);
})->all();
break;
default:
if(preg_match('/attr\((.+)\)/', $rule['attr'], $arr)) {
$content = $pqObj->attr($arr[1]);
} elseif (preg_match('/attrs\((.+)\)/', $rule['attr'], $arr)) {
$content = (new Elements($pqObj))->attrs($arr[1])->all();
} else {
$content = $pqObj->attr($rule['attr']);
}
break;
}
if (is_callable($rule['handle_callback'])) {
$content = call_user_func($rule['handle_callback'], $content, $ruleName);
}
return $content;
}
protected function parseRule($rule)
{
$result = [];
$result['selector'] = $rule[0];
$result['attr'] = $rule[1];
$result['filter_tags'] = $rule[2] ?? '';
$result['handle_callback'] = $rule[3] ?? null;
return $result;
}
/**
* 去除特定的html标签
* @param string $html
* @param string $tags_str 多个标签名之间用空格隔开
* @return string
*/
protected function stripTags($html, $tags_str)
{
$tagsArr = $this->tag($tags_str);
$html = $this->removeTags($html, $tagsArr[1]);
$p = array();
foreach ($tagsArr[0] as $tag) {
$p[] = "/(<(?:\/" . $tag . "|" . $tag . ")[^>]*>)/i";
}
$html = preg_replace($p, "", trim($html));
return $html;
}
/**
* 保留特定的html标签
* @param string $html
* @param string $tags_str 多个标签名之间用空格隔开
* @return string
*/
protected function allowTags($html, $tags_str)
{
$tagsArr = $this->tag($tags_str);
$html = $this->removeTags($html, $tagsArr[1]);
$allow = '';
foreach ($tagsArr[0] as $tag) {
$allow .= "<$tag> ";
}
return strip_tags(trim($html), $allow);
}
protected function tag($tags_str)
{
$tagArr = preg_split("/\s+/", $tags_str, -1, PREG_SPLIT_NO_EMPTY);
$tags = array(array(), array());
foreach ($tagArr as $tag) {
if (preg_match('/-(.+)/', $tag, $arr)) {
array_push($tags[1], $arr[1]);
} else {
array_push($tags[0], $tag);
}
}
return $tags;
}
/**
* 移除特定的html标签
* @param string $html
* @param array $tags 标签数组
* @return string
*/
protected function removeTags($html, $tags)
{
$tag_str = '';
if (count($tags)) {
foreach ($tags as $tag) {
$tag_str .= $tag_str ? ',' . $tag : $tag;
}
// phpQuery::$defaultCharset = $this->inputEncoding?$this->inputEncoding:$this->htmlEncoding;
$doc = phpQuery::newDocumentHTML($html);
pq($doc)->find($tag_str)->remove();
$html = pq($doc)->htmlOuter();
$doc->unloadDocument();
}
return $html;
}
protected function destroyDocument()
{
if ($this->document instanceof phpQueryObject) {
$this->document->unloadDocument();
}
}
public function __destruct()
{
$this->destroyDocument();
}
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/21
*/
namespace QL\Exceptions;
use Exception;
class ServiceNotFoundException extends Exception
{
}

74
vendor/jaeger/querylist/src/Kernel.php vendored Normal file
View File

@ -0,0 +1,74 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/21
*/
namespace QL;
use QL\Contracts\ServiceProviderContract;
use QL\Exceptions\ServiceNotFoundException;
use QL\Providers\EncodeServiceProvider;
use Closure;
use QL\Providers\HttpServiceProvider;
use QL\Providers\PluginServiceProvider;
use QL\Providers\SystemServiceProvider;
use Tightenco\Collect\Support\Collection;
class Kernel
{
protected $providers = [
SystemServiceProvider::class,
HttpServiceProvider::class,
EncodeServiceProvider::class,
PluginServiceProvider::class
];
protected $binds;
protected $ql;
/**
* Kernel constructor.
* @param $ql
*/
public function __construct(QueryList $ql)
{
$this->ql = $ql;
$this->binds = new Collection();
}
public function bootstrap()
{
//注册服务提供者
$this->registerProviders();
return $this;
}
public function registerProviders()
{
foreach ($this->providers as $provider) {
$this->register(new $provider());
}
}
public function bind(string $name,Closure $provider)
{
$this->binds[$name] = $provider;
}
public function getService(string $name)
{
if(!$this->binds->offsetExists($name)){
throw new ServiceNotFoundException("Service: {$name} not found!");
}
return $this->binds[$name];
}
private function register(ServiceProviderContract $instance)
{
$instance->register($this);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/20
*/
namespace QL\Providers;
use QL\Contracts\ServiceProviderContract;
use QL\Kernel;
use QL\Services\EncodeService;
class EncodeServiceProvider implements ServiceProviderContract
{
public function register(Kernel $kernel)
{
$kernel->bind('encoding',function (string $outputEncoding,string $inputEncoding = null){
return EncodeService::convert($this,$outputEncoding,$inputEncoding);
});
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Created by PhpStorm.
* User: Jaeger <JaegerCode@gmail.com>
* Date: 2017/9/22
*/
namespace QL\Providers;
use QL\Contracts\ServiceProviderContract;
use QL\Kernel;
use QL\Services\HttpService;
use QL\Services\MultiRequestService;
class HttpServiceProvider implements ServiceProviderContract
{
public function register(Kernel $kernel)
{
$kernel->bind('get',function (...$args){
return HttpService::get($this,...$args);
});
$kernel->bind('post',function (...$args){
return HttpService::post($this,...$args);
});
$kernel->bind('postJson',function (...$args){
return HttpService::postJson($this,...$args);
});
$kernel->bind('multiGet',function (...$args){
return new MultiRequestService($this,'get',...$args);
});
$kernel->bind('multiPost',function (...$args){
return new MultiRequestService($this,'post',...$args);
});
}
}

Some files were not shown because too many files have changed in this diff Show More