Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

1
vendor/5ini99/think-addons/.gitignore vendored Executable file
View File

@ -0,0 +1 @@


32
vendor/5ini99/think-addons/LICENSE.txt vendored Executable file
View File

@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

190
vendor/5ini99/think-addons/README.md vendored Executable file
View File

@ -0,0 +1,190 @@
# think-addons
The ThinkPHP5 Addons Package
## 安装
> composer require 5ini99/think-addons
## 配置
### 公共配置
```
'addons'=>[
// 可以定义多个钩子
'testhook'=>'test' // 键为钩子名称,用于在业务中自定义钩子处理,值为实现该钩子的插件,
// 多个插件可以用数组也可以用逗号分割
]
```
## 创建插件
> 创建的插件可以在view视图中使用也可以在php业务中使用
安装完成后访问系统时会在项目根目录生成名为`addons`的目录,在该目录中创建需要的插件。
下面写一个例子:
### 创建test插件
> 在addons目录中创建test目录
### 创建钩子实现类
> 在test目录中创建Test.php类文件。注意类文件首字母需大写
```
<?php
namespace addons\test; // 注意命名空间规范
use think\addons\Addons;
/**
* 插件测试
* @author byron sampson
*/
class Test extends Addons // 需继承think\addons\Addons类
{
// 该插件的基础信息
public $info = [
'name' => 'test', // 插件标识
'title' => '插件测试', // 插件名称
'description' => 'thinkph5插件测试', // 插件简介
'status' => 0, // 状态
'author' => 'byron sampson',
'version' => '0.1'
];
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
/**
* 实现的testhook钩子方法
* @return mixed
*/
public function testhook($param)
{
// 调用钩子时候的参数信息
print_r($param);
// 当前插件的配置信息配置信息存在当前目录的config.php文件中见下方
print_r($this->getConfig());
// 可以返回模板,模板文件默认读取的为插件目录中的文件。模板名不能为空!
return $this->fetch('info');
}
}
```
### 创建插件配置文件
> 在test目录中创建config.php类文件插件配置文件可以省略。
```
<?php
return [
'display' => [
'title' => '是否显示:',
'type' => 'radio',
'options' => [
'1' => '显示',
'0' => '不显示'
],
'value' => '1'
]
];
```
### 创建钩子模板文件
> 在test目录中创建info.html模板文件钩子在使用fetch方法时对应的模板文件。
```
<h1>hello tpl</h1>
如果插件中需要有链接或提交数据的业务可以在插件中创建controller业务文件
要访问插件中的controller时使用addon_url生成url链接。
如下:
<a href="{:addon_url('test://Action/link')}">link test</a>
格式为:
test为插件名Action为controller中的类名link为controller中的方法
```
### 创建插件的controller文件
> 在test目录中创建controller目录在controller目录中创建Action.php文件
> controller类的用法与tp5中的controller一致
```
<?php
namespace addons\test\controller;
class Action
{
public function link()
{
echo 'hello link';
}
}
```
> 如果需要使用view模板则需要继承`\think\addons\Controller`类
> 模板文件所在位置为插件目录的view中规则与模块中的view规则一致
```
<?php
namespace addons\test\controller;
use think\addons\Controller;
class Action extends Controller
{
public function link()
{
return $this->fetch();
}
}
```
## 使用钩子
> 创建好插件后就可以在正常业务中使用该插件中的钩子了
> 使用钩子的时候第二个参数可以省略
### 模板中使用钩子
```
<div>{:hook('testhook', ['id'=>1])}</div>
```
### php业务中使用
> 只要是thinkphp5正常流程中的任意位置均可以使用
```
hook('testhook', ['id'=>1])
```
## 插件目录结构
### 最终生成的目录结构为
```
tp5
- addons
-- test
--- controller
---- Action.php
--- view
---- action
----- link.html
--- config.php
--- info.html
--- Test.php
- application
- thinkphp
- extend
- vendor
- public
```

28
vendor/5ini99/think-addons/composer.json vendored Executable file
View File

@ -0,0 +1,28 @@
{
"name": "5ini99/think-addons",
"description": "addons package for thinkphp5",
"homepage": "https://github.com/5ini99/think-addons",
"license": "Apache-2.0",
"minimum-stability": "stable",
"version": "1.2.0",
"authors": [
{
"name": "xiaobo.sun",
"email": "xiaobo.sun@qq.com"
}
],
"support": {
"issues": "https://github.com/5ini99/think-addons/issues"
},
"require": {
"php": ">=5.4.0"
},
"autoload": {
"psr-4": {
"think\\addons\\": "src/"
},
"files": [
"src/helper.php"
]
}
}

202
vendor/5ini99/think-addons/src/Addons.php vendored Executable file
View File

@ -0,0 +1,202 @@
<?php
namespace think\addons;
use think\Config;
use think\View;
use think\Db;
/**
* 插件基类
* Class Addons
* @author Byron Sampson <xiaobo.sun@qq.com>
* @package think\addons
*/
abstract class Addons{
/**
* 视图实例对象
* @var view
* @access protected
*/
protected $view = null;
// 当前错误信息
protected $error;
/**
* $info = [
* 'name' => 'Test',
* 'title' => '测试插件',
* 'description' => '用于WSTMart的插件扩展演示',
* 'status' => 1,
* 'author' => 'WSTMart',
* 'version' => '1.0.1'
* ]
*/
public $info = [];
public $addons_path = '';
public $config_file = '';
/**
* 架构函数
* @access public
*/
public function __construct()
{
// 获取当前插件目录
$this->addons_path = ADDON_PATH . $this->getName() . DS;
// 读取当前插件配置信息
if (is_file($this->addons_path . 'config.php')) {
$this->config_file = $this->addons_path . 'config.php';
}
// 初始化视图模型
$config = ['view_path' => $this->addons_path];
$config = array_merge(Config::get('template'), $config);
$this->view = new View($config, Config::get('view_replace_str'));
// 控制器初始化
if (method_exists($this, '_initialize')) {
$this->_initialize();
}
}
/**
* 获取插件的配置数组
* @param string $name 可选模块名
* @return array|mixed|null
*/
final public function getConfig($name = '')
{
static $_config = array();
if (empty($name)) {
$name = $this->getName();
}
if (isset($_config[$name])) {
return $_config[$name];
}
$map['name'] = $name;
$map['status'] = 1;
$config = [];
if (is_file($this->config_file)) {
$temp_arr = include $this->config_file;
foreach ($temp_arr as $key => $value) {
if ($value['type'] == 'group') {
foreach ($value['options'] as $gkey => $gvalue) {
foreach ($gvalue['options'] as $ikey => $ivalue) {
$config[$ikey] = $ivalue['value'];
}
}
} else {
$config[$key] = $temp_arr[$key]['value'];
}
}
unset($temp_arr);
}
$_config[$name] = $config;
return $config;
}
/**
* 获取当前模块名
* @return string
*/
final public function getName(){
$data = explode('\\', get_class($this));
return strtolower(array_pop($data));
}
/**
* 检查配置信息是否完整
* @return bool
*/
final public function checkInfo(){
$info_check_keys = ['name', 'title', 'description', 'status', 'author', 'version'];
foreach ($info_check_keys as $value) {
if (!array_key_exists($value, $this->info)) {
return false;
}
}
return true;
}
/**
* 加载模板和页面输出 可以返回输出内容
* @access public
* @param string $template 模板文件名或者内容
* @param array $vars 模板输出变量
* @param array $replace 替换内容
* @param array $config 模板参数
* @return mixed
* @throws \Exception
*/
public function fetch($template = '', $vars = [], $replace = [], $config = []){
if (!is_file($template)) {
$template = '/' . $template;
}
// 关闭模板布局
$this->view->engine->layout(false);
echo $this->view->fetch($template, $vars, $replace, $config);
}
/**
* 渲染内容输出
* @access public
* @param string $content 内容
* @param array $vars 模板输出变量
* @param array $replace 替换内容
* @param array $config 模板参数
* @return mixed
*/
public function display($content, $vars = [], $replace = [], $config = []){
// 关闭模板布局
$this->view->engine->layout(false);
echo $this->view->display($content, $vars, $replace, $config);
}
/**
* 渲染内容输出
* @access public
* @param string $content 内容
* @param array $vars 模板输出变量
* @return mixed
*/
public function show($content, $vars = []){
// 关闭模板布局
$this->view->engine->layout(false);
echo $this->view->fetch($content, $vars, [], [], true);
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return void
*/
public function assign($name, $value = ''){
$this->view->assign($name, $value);
}
/**
* 获取当前错误信息
* @return mixed
*/
public function getError(){
return $this->error;
}
//必须实现安装
abstract public function install();
//必须卸载插件方法
abstract public function uninstall();
abstract public function enable();
abstract public function disable();
abstract public function saveConfig();
}

View File

@ -0,0 +1,41 @@
<?php
namespace think\addons;
use think\Hook;
use think\Request;
/**
* 插件执行默认控制器
* Class AddonsController
* @package think\addons
*/
class AddonsController extends Controller
{
/**
* 插件执行
*/
public function execute()
{
if (!empty($this->addon) && !empty($this->controller) && !empty($this->action)) {
// 获取类的命名空间
$class = get_addon_class($this->addon, 'controller', $this->controller);
if (class_exists($class)) {
$model = new $class();
if ($model === false) {
abort(500, lang('addon init fail'));
}
// 调用操作
if (!method_exists($model, $this->action)) {
abort(500, lang('Controller Class Method Not Exists'));
}
// 监听addons_init
Hook::listen('addons_init', $this);
return call_user_func_array([$model, $this->action], [Request::instance()]);
} else {
abort(500, lang('Controller Class Not Exists'));
}
}
abort(500, lang('addon cannot name or action'));
}
}

88
vendor/5ini99/think-addons/src/BaseModel.php vendored Executable file
View File

@ -0,0 +1,88 @@
<?php
namespace think\addons;
use think\Db;
/**
* 插件基类服务器
* Class Model
* @package think\addons
*/
class BaseModel extends \think\Model{
/**
* 获取插件配置内容
*/
public function getConf($addonsName){
$data = cache('ADDONS_'.$addonsName);
if(!$data){
$rs = Db::name('addons')->where('name',$addonsName)->field('config')->find();
$data = json_decode($rs['config'],true);
cache('ADDONS_'.$addonsName,$data,31622400);
}
return $data;
}
public function getAddonStatus($addonsName){
$rs = Db::name('addons')->where('name',$addonsName)->field('status')->find();
return (int)$rs["status"];
}
/**
* 获取空模型
*/
public function getEModel($tables){
$rs = Db::query('show columns FROM `'.config('database.prefix').$tables."`");
$obj = [];
if($rs){
foreach($rs as $key => $v) {
$obj[$v['Field']] = $v['Default'];
if($v['Key'] == 'PRI')$obj[$v['Field']] = 0;
}
}
return $obj;
}
/**
* 绑定勾子
* @param 插件名 $addonName
* @param 勾子数组 $hooks
*/
public function bindHoods($addonName,$hooks){
$list = Db::name('hooks')->where("name","in",$hooks)->field(["hookId","name","addons"])->select();
for($i=0,$k=count($list);$i<$k;$i++){
$hook = $list[$i];
$objs = explode(",",$hook["addons"]);
$objs = array_filter($objs);
if(!in_array($addonName,$objs)){
$addons = $addonName;
if(!empty($objs)){
$objs[] = $addonName;
$addons = implode(",",$objs);
}
Db::name('hooks')->where(["hookId"=>$hook["hookId"]])->update(["addons"=>$addons]);
}
}
}
/**
* 解绑勾子
* @param 插件名 $addonName
* @param 勾子数组 $hooks
*/
public function unbindHoods($addonName,$hooks){
$list = Db::name('hooks')->where("name","in",$hooks)->field(["hookId","name","addons"])->select();
for($i=0,$k=count($list);$i<$k;$i++){
$hook = $list[$i];
$objs = explode(",",$hook["addons"]);
$temps = array();
for($m=0,$n=count($objs);$m<$n;$m++){
if($objs[$m]!=$addonName){
$temps[] = $objs[$m];
}
}
$addons = implode(",",$temps);
Db::name('hooks')->where(["hookId"=>$hook["hookId"]])->update(["addons"=>$addons]);
}
}
}

270
vendor/5ini99/think-addons/src/Controller.php vendored Executable file
View File

@ -0,0 +1,270 @@
<?php
namespace think\addons;
use think\Request;
use think\Config;
use think\Loader;
/**
* 插件基类控制器
* Class Controller
* @package think\addons
*/
class Controller extends \think\Controller
{
// 当前插件操作
protected $addon = null;
protected $controller = null;
protected $action = null;
// 当前template
protected $template;
// 模板配置信息
protected $config = [
'type' => 'Think',
'view_path' => '',
'view_suffix' => 'html',
'strip_space' => true,
'view_depr' => DS,
'tpl_begin' => '{',
'tpl_end' => '}',
'taglib_begin' => '{',
'taglib_end' => '}',
];
/**
* 架构函数
* @param Request $request Request对象
* @access public
*/
public function __construct(Request $request = null)
{
WSTConf('CONF.seoMallSwitch');
if(WSTConf('CONF.seoMallSwitch')==0){
$this->redirect('home/switchs/index');
exit;
}
// 生成request对象
$this->request = is_null($request) ? Request::instance() : $request;
// 初始化配置信息
$this->config = Config::get('template') ?: $this->config;
// 处理路由参数
$route = $this->request->param('route', '');
$param = explode('-', $route);
// 是否自动转换控制器和操作名
$convert = \think\Config::get('url_convert');
if('wechat/weixinpays/toaddonpay' != $this->request->path()){
// 格式化路由的插件位置
$this->action = $convert ? strtolower(array_pop($param)) : array_pop($param);
$this->controller = $convert ? strtolower(array_pop($param)) : array_pop($param);
$this->addon = $convert ? strtolower(array_pop($param)) : array_pop($param);
$base = new \think\addons\BaseModel();
$status = $base->getAddonStatus(ucfirst($this->addon));
if(isset($status) && $status!=1){
$request = request();
$module = WSTVisitModule();
header("Location:".url($module.'/error/message'));
exit();
}
}
// 生成view_path
$view_path = $this->config['view_path'] ?: 'view';
// 重置配置
Config::set('template.view_path', ADDON_PATH . $this->addon . DS . $view_path . DS);
$this->checkPrivileges();
parent::__construct($request);
$this->assign("v",WSTConf('CONF.wstVersion')."_".WSTConf('CONF.wsthomeStyleId'));
$this->initLayout();
}
/**
* 定义模板
*/
public function initLayout(){
$wsthomeStyle = WSTConf('CONF.wsthomeStyle')?WSTConf('CONF.wsthomeStyle'):'default';
$wstmobileStyle = WSTConf('CONF.wstmobileStyle')?WSTConf('CONF.wstmobileStyle'):'default';
$wstwechatStyle = WSTConf('CONF.wstwechatStyle')?WSTConf('CONF.wstwechatStyle'):'default';
$this->assign('LAYOUT_HOME_BASE','home@'.$wsthomeStyle.'/base');
$this->assign('LAYOUT_HOME_TOP','home@'.$wsthomeStyle.'/top');
$this->assign('LAYOUT_HOME_HEADER','home@'.$wsthomeStyle.'/header');
$this->assign('LAYOUT_HOME_SHOP_APPLY','home@'.$wsthomeStyle.'/shop_apply');
$this->assign('LAYOUT_HOME_RIGHT_CART','home@'.$wsthomeStyle.'/right_cart');
$this->assign('LAYOUT_HOME_FOOTER','home@'.$wsthomeStyle.'/footer');
$this->assign('LAYOUT_HOME_SHOP_BASE','home@'.$wsthomeStyle.'/shops/base');
$this->assign('LAYOUT_HOME_SHOP_HEADER','home@'.$wsthomeStyle.'/shops/header');
$this->assign('LAYOUT_HOME_USER_BASE','home@'.$wsthomeStyle.'/users/base');
$this->assign('LAYOUT_HOME_USER_HEADER','home@'.$wsthomeStyle.'/users/header');
$this->assign('LAYOUT_ADMIN_BASE','admin@base');
$this->assign('LAYOUT_MOBILE_BASE','mobile@'.$wstmobileStyle.'/base');
$this->assign('LAYOUT_MOBILE_DIALOG','mobile@'.$wstmobileStyle.'/dialog');
$this->assign('LAYOUT_MOBILE_FOOTER','mobile@'.$wstmobileStyle.'/footer');
$this->assign('LAYOUT_WECHAT_BASE','wechat@'.$wstwechatStyle.'/base');
$this->assign('LAYOUT_WECHAT_DIALOG','wechat@'.$wstwechatStyle.'/dialog');
$this->assign('LAYOUT_WECHAT_FOOTER','wechat@'.$wstwechatStyle.'/footer');
}
/**
* @deprecated 建议使用 checkAuth和checkShopAuth区分商家 2017.04.25
*/
public function checkPrivileges(){
$urls = model('home/HomeMenus')->getMenusUrl();
$request = request();
$visit = strtolower($request->path());
if(isset($urls[$visit])){
$menuType = (int)$urls[$visit];
$userType = -1;
if((int)session('WST_USER.userId')>0)$userType = 0;
if((int)session('WST_USER.shopId')>0)$userType = 1;
//未登录不允许访问受保护的资源
if($userType==-1){
if($request->isAjax()){
echo json_encode(['status'=>-999,'msg'=>'对不起,您还没有登录,请先登录']);
}else{
header("Location:".url('home/users/login'));
}
exit();
}
//已登录但不是商家 则不允许访问受保护的商家资源
if($userType==0 && $menuType==1){
if($request->isAjax()){
echo json_encode(['status'=>-999,'msg'=>'对不起,您不是商家,请先申请为商家再访问']);
}else{
header("Location:".url('home/shops/login'));
}
exit();
}
}
}
public function checkAdminAuth(){
$STAFF = session('WST_STAFF');
$request = request();
if(empty($STAFF)){
if($request->isAjax()){
echo json_encode(['status'=>-999,'msg'=>'对不起,您还没有登录,请先登录']);
}else{
header("Location:".url('admin/index/login'));
}
exit();
}else{
$urls = WSTVisitPrivilege();
$privileges = session('WST_STAFF.privileges');
$visit = $request->path();
if(!$privileges || (array_key_exists($visit,$urls) && !$this->checkUserCode($urls[$visit],$privileges))){
if($request->isAjax()){
echo json_encode(['status'=>-998,'msg'=>'对不起,您没有操作权限,请与管理员联系']);
}else{
header("Content-type: text/html; charset=utf-8");
echo "对不起,您没有操作权限,请与管理员联系";
}
exit();
}
}
}
private function checkUserCode($urlCodes,$userCodes){
foreach ($urlCodes as $key => $value) {
if(in_array($key,$userCodes))return true;
}
return false;
}
/**
* @deprecated 建议使用checkAdminAuth将来可能会移除. 2017.04.25
*/
public function checkAdminPrivileges(){
$this->checkAdminAuth();
}
// 登录验证方法--用户
protected function checkAuth(){
$USER = session('WST_USER');
if(empty($USER)){
if(request()->isAjax()){
die('{"status":-999,"msg":"您还未登录"}');
}else{
$module = WSTVisitModule();
$this->redirect($module.'/users/login');
exit;
}
}
}
//登录验证方法--商家
protected function checkShopAuth(){
$USER = session('WST_USER');
if(empty($USER) || $USER['userType']!=1){
if(request()->isAjax()){
die('{"status":-998,"msg":"您还未登录"}');
}else{
$module = WSTVisitModule();
$this->redirect($module.'/shops/login');
exit;
}
}
}
/**
* 重写父类前置方法判断
*/
protected function beforeAction($method, $options = [])
{
// 设置当前访问的controller、action
request()->controller($this->controller);
request()->action($this->action);
if (isset($options['only'])) {
if (is_string($options['only'])) {
$options['only'] = explode(',', $options['only']);
}
if (!in_array($this->request->action(), $options['only'])) {
return;
}
} elseif (isset($options['except'])) {
if (is_string($options['except'])) {
$options['except'] = explode(',', $options['except']);
}
if (in_array($this->request->action(), $options['except'])) {
return;
}
}
call_user_func([$this, $method]);
}
/**
* 加载模板输出
* @access protected
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param array $replace 模板替换
* @param array $config 模板参数
* @return mixed
*/
public function fetch($template = '', $vars = [], $replace = [], $config = []){
$controller = Loader::parseName($this->controller);
if ('think' == strtolower($this->config['type']) && $controller && 0 !== strpos($template, '/')) {
$depr = $this->config['view_depr'];
$template = str_replace(['/', ':'], $depr, $template);
if ('' == $template) {
// 如果模板文件名为空 按照默认规则定位
$template = str_replace('.', DS, $controller) . $depr . $this->action;
} elseif (false === strpos($template, $depr)) {
$template = str_replace('.', DS, $controller) . $depr . $template;
}
}
$replace['__STYLE__'] = str_replace('/index.php','',\think\Request::instance()->root()).'/hyhproject/home/view/'.WSTConf('CONF.wsthomeStyle');
$replace['__ADMIN__'] = str_replace('/index.php','',\think\Request::instance()->root()).'/hyhproject/admin/view';
$replace['__WECHAT__'] = str_replace('/index.php','',\think\Request::instance()->root()).'/hyhproject/wechat/view/'.WSTConf('CONF.wstwechatStyle');;
$replace['__MOBILE__'] = str_replace('/index.php','',\think\Request::instance()->root()).'/hyhproject/mobile/view/default';
return \Think\Controller::fetch($template, $vars, $replace, $config);
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return void
*/
public function assign($name, $value = ''){
$this->view->assign($name, $value);
}
}

207
vendor/5ini99/think-addons/src/helper.php vendored Executable file
View File

@ -0,0 +1,207 @@
<?php
use think\Hook;
use think\Config;
use think\Loader;
use think\Db;
// 插件目录
define('ADDON_PATH', ROOT_PATH . 'addons' . DS);
// 定义路由
\think\Route::any('addon/:route', "\\think\\addons\\AddonsController@execute");
// 如果插件目录不存在则创建
if (!is_dir(ADDON_PATH)) {
@mkdir(ADDON_PATH, 0777, true);
}
// 注册类的根命名空间
\think\Loader::addNamespace('addons', ADDON_PATH);
// 闭包初始化行为
Hook::add('app_begin', function () {
$hooks = cache('hooks');
if(empty($hooks)){
$addons = Db::name('hooks')->where("addons != ''")->column('name,addons');
if(!empty($addons)){
foreach ($addons as $key => $values) {
if($values){
$map['status'] = 1;
$names = explode(',',$values);
$map['name'] = array('IN',$names);
$map['dataFlag'] = 1;
$data = model('common/addons')->where($map)->column('addonId,name');
if($data){
$data = array_intersect($names, $data);
$addons[$key] = array_filter(array_map('get_addon_class', $data));
\think\Hook::add($key, $addons[$key]);
}
}
}
array_filter($addons);
cache('hooks', $addons);
}
}else{
foreach ($hooks as $key => $values) {
if(is_array($hooks[$key])){
\think\Hook::add($key, $hooks[$key]);
}
}
}
get_addon_function();
});
/**
* 处理插件钩子
* @param string $hook 钩子名称
* @param mixed $params 传入参数
* @return void
*/
function hook($hook, $params = []){
\think\Hook::listen($hook, $params);
}
/**
* 加载插件函数
*/
function get_addon_function(){
$addonsrs = cache('WST_ADDONS');
if(!$addonsrs){
$addonsrs = model('common/addons')->where('status =1 and dataFlag = 1')->column('addonId,name');
cache('WST_ADDONS',$addonsrs);
}
if(!empty($addonsrs)){
$adds = [];
foreach ($addonsrs as $key => $value) {
$name = strtolower($value);
$adds[$name] = ['addonId'=>$key,'name'=>$name];
if(is_file(ROOT_PATH.'addons'.DS.$name.DS.'common'.DS.'function.php')){
include_once(ROOT_PATH.'addons'.DS.$name.DS.'common'.DS.'function.php');
}
}
WSTConf('WST_ADDONS',$adds);
}
}
/**
* 获取插件类的类名
* @param $name 插件名
* @param string $type 返回命名空间类型
* @param string $class 当前类名
* @return string
*/
function get_addon_class($name, $type = 'hook', $class = null){
$name = \think\Loader::parseName($name);
// 处理多级控制器情况
if (!is_null($class) && strpos($class, '.')) {
$class = explode('.', $class);
foreach ($class as $key => $cls) {
$class[$key] = \think\Loader::parseName($cls, 1);
}
$class = implode('\\', $class);
} else {
$class = \think\Loader::parseName(is_null($class) ? $name : $class, 1);
}
switch ($type) {
case 'controller':
$namespace = "\\addons\\" . $name . "\\controller\\" . $class;
break;
default:
$namespace = "\\addons\\" . $name . "\\" . $class;
}
return class_exists($namespace) ? $namespace : '';
}
/**
* 获取插件类的配置文件数组
* @param string $name 插件名
* @return array
*/
function get_addon_config($name){
$class = get_addon_class($name);
if (class_exists($class)) {
$addon = new $class();
return $addon->getConfig();
} else {
return [];
}
}
/**
* 插件显示内容里生成访问插件的url
* @param $url
* @param array $param
* @return bool|string
* @param bool|string $suffix 生成的URL后缀
* @param bool|string $domain 域名
*/
function addon_url($url, $param = [], $suffix = true, $domain = false){
$url = parse_url($url);
$case = config('url_convert');
$addons = $case ? Loader::parseName($url['scheme']) : $url['scheme'];
$controller = $case ? Loader::parseName($url['host']) : $url['host'];
$action = trim($case ? strtolower($url['path']) : $url['path'], '/');
/* 解析URL带的参数 */
if (isset($url['query'])) {
parse_str($url['query'], $query);
$param = array_merge($query, $param);
}
// 生成插件链接新规则
$actions = "{$addons}-{$controller}-{$action}";
return url("/addon/{$actions}", $param, $suffix, $domain);
}
/**
* 安装插件执行sql
*/
function installSql($name){
$sqlfile = WSTRootPath()."/addons/".$name."/install.sql";
if(file_exists($sqlfile)){
$sql = file_get_contents($sqlfile);
excuteSql($sql,config('database')["prefix"]);
}
}
/**
* 卸载插件执行sql
*/
function uninstallSql($name){
$sqlfile = WSTRootPath()."/addons/".$name."/uninstall.sql";
if(file_exists($sqlfile)){
$sql = file_get_contents($sqlfile);
excuteSql($sql,config('database')["prefix"]);
}
}
/**
* 执行sql
* @param string $db_prefix
*/
function excuteSql($sql,$db_prefix=''){
if(!isset($sql) || empty($sql)) return;
$sql = str_replace("\r", "\n", str_replace(' `wst_', ' `'.$db_prefix, $sql));
$ret = array();
$num = 0;
foreach(explode(";\n", trim($sql)) as $query) {
$ret[$num] = '';
$queries = explode("\n", trim($query));
foreach($queries as $query) {
$ret[$num] .= (isset($query[0]) && $query[0] == '#') || (isset($query[1]) && isset($query[1]) && $query[0].$query[1] == '--') ? '' : $query;
}
$num++;
}
unset($sql);
foreach($ret as $query){
$query = trim($query);
if($query) {
if(strtoupper(substr($query, 0, 12)) == 'CREATE TABLE'){
$type = strtoupper(preg_replace("/^\s*CREATE TABLE\s+.+\s+\(.+?\).*(ENGINE|TYPE)\s*=\s*([a-z]+?).*$/isU", "\\2", $query));
$query = preg_replace("/^\s*(CREATE TABLE\s+.+\s+\(.+?\)).*$/isU", "\\1", $query)." ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
Db::execute($query);
}
}
}