插件机制完善

This commit is contained in:
2020-04-04 14:20:01 +08:00
parent 2f4386f196
commit ba37debc0e
13 changed files with 174 additions and 117 deletions

View File

@@ -1,40 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: yangweijie <yangweijiester@gmail.com> <code-tech.diandian.com>
// +----------------------------------------------------------------------
namespace addons\Syslogin;
/**
* 系统环境信息插件
* @author thinkphp
*/
class Syslogin extends Addons{
public $info = array(
'name'=>'Syslogin',
'title'=>'第三方登录',
'description'=>'第三方登录',
'status'=>0,
'author'=>'molong',
'version'=>'0.1'
);
public function loginBottomAddon(){
}
public function install(){
return true;
}
public function uninstall(){
return true;
}
}

View File

@@ -15,6 +15,7 @@ use think\facade\Cache;
use think\Validate;
use app\model\Config;
use think\facade\Route;
use app\model\Hooks;
class Base {
@@ -71,7 +72,11 @@ class Base {
$config = Config::getConfigList($this->request);
Cache::set('system_config_data', $config);
}
config($config, 'config');
$hooks = Hooks::where('status', 1)->column('addons', 'name');
foreach($hooks as $key => $value){
$hooks[$key] = $value ? explode(",", $value) : [];
}
Cache::set('sentcms_hooks', $hooks);
View::assign('config', $config);
// 控制器初始化
$this->initialize();

View File

@@ -56,6 +56,20 @@ class Upload extends Base {
echo $data->output();
}
public function delete(){
$id = $this->request->param('id', 0);
if(!$id){
$data = [
'status' => false
];
}else{
$data = [
'status' => true
];
}
return json($data);
}
protected function save($file, $upload_type){
$data = [];
$savename = Filesystem::disk('public')->putFile($upload_type, $file, 'md5');

View File

@@ -23,7 +23,7 @@ class Addons extends Base {
public function index($refresh = 0) {
$map = [];
if ($refresh) {
AddonsM::refreshAddons();
AddonsM::refreshAddons($this->app->getRootPath() . 'addons' . DIRECTORY_SEPARATOR);
}
$list = AddonsM::where($map)->order('id desc')->paginate($this->request->pageConfig);
@@ -36,33 +36,9 @@ class Addons extends Base {
}
/**
* @title 添加插件
* @title 删除插件
*/
public function add() {
if ($this->request->isPost()) {
$data = $this->addons->create();
if ($data) {
if ($result) {
return $this->success("创建成功!", url('admin/addons/index'));
} else {
return $this->error("创建失败!");
}
} else {
return $this->error($this->addons->getError());
}
} else {
// $hooks = db('Hooks')->field('name,description')->select();
// $this->assign('Hooks', $hooks);
// $hook = db('Hooks')->field(true)->select();
// foreach ($hook as $key => $value) {
// $addons_opt[$value['name']] = $value['name'];
// }
// $addons_opt = array(array('type' => 'select', 'opt' => $addons_opt));
// if (!is_writable(SENT_ADDON_PATH)) {
// return $this->error('您没有创建目录写入权限,无法使用此功能');
// }
return $this->fetch();
}
public function del() {
}
/**

View File

@@ -21,11 +21,15 @@ class Validate {
//获取当前参数
$params = $request->param();
//获取访问控制器
$controller = explode(".", $request->controller());
if(\strripos($request->controller(), ".")){
$controller = explode(".", $request->controller());
}else{
$controller = ['', ucfirst($request->controller())];
}
//获取操作名,用于验证场景scene
$scene = $controller[0] . $request->action();
$validate = "app\\http\\validate\\" . strtolower($controller[1]);
$scene = strtolower($controller[0]) . $request->action();
$validate = "app\\http\\validate\\" . ucfirst($controller[1]);
//仅当验证器存在时 进行校验
if (class_exists($validate) && $request->isPost()) {
$v = new $validate;

View File

@@ -16,6 +16,11 @@ use app\model\Attribute;
* 菜单验证
*/
class Content extends Validate{
protected $rule = [];
protected $message = [];
protected $scene = [];
public function __construct(){
parent::__construct();

View File

@@ -14,7 +14,129 @@ namespace app\model;
*/
class Addons extends \think\Model {
public static function refreshAddons(){
protected $auto = ['status', 'isinstall', 'update_time'];
protected $insert = ['create_time'];
protected $type = [
'hooks' => 'json'
];
protected function setStatusAttr($value) {
return $value ? $value : 0;
}
protected function setNameAttr($value){
return $value ? strtolower($value) : '';
}
protected function setIsinstallAttr($value) {
return $value ? $value : 0;
}
protected function getStatusTextAttr($value, $data) {
return $data['status'] ? "启用" : "禁用";
}
protected function getUninstallAttr($value, $data) {
return 0;
}
/**
* 更新插件列表
* @param string $addon_dir
*/
public static function refreshAddons($addon_dir = '') {
if (!$addon_dir) {
$addon_dir = SENT_ADDON_PATH;
}
$dirs = array_map('basename', glob($addon_dir . '*', GLOB_ONLYDIR));
if ($dirs === FALSE || !file_exists($addon_dir)) {
return FALSE;
}
$where[] = ['name', 'in', $dirs];
$addons = self::where($where)->column('*', 'name');
$save = [];
foreach ($dirs as $value) {
$value = strtolower($value);
$class = "\\addons\\" . $value . "\\Plugin";
if (!class_exists($class)) {
continue;
}
$item = get_addons_info($value);
if (isset($addons[$value])) {
$item['id'] = $addons[$value]['id'];
unset($item['status']);
}
$save[] = $item;
}
$class = new self();
return $class->saveAll($save);
}
/**
* 获取插件的后台列表
*/
public function getAdminList() {
$admin = [];
$map[] = ['status', '=', 1];
$map[] = ['has_adminlist', '=', 1];
$db_addons = self::where($map)->field('title,name')->select();
if ($db_addons) {
foreach ($db_addons as $value) {
$admin[] = array('title' => $value['title'], 'url' => "Addons/adminList?name={$value['name']}");
}
}
return $admin;
}
public function install($data) {
if ($data) {
$info = $this->where('name', $data['name'])->value('id');
if ($info) {
$result = $this->save(array('isinstall'=>1, 'status'=>1), array('id'=>$info));
}else{
$result = false;
}
if (false !== $result) {
return model('Hooks')->addHooks($data['name']);
}else{
return false;
}
} else {
return false;
}
}
public function uninstall($id) {
$info = $this->get($id);
if (!$info) {
$this->error = "无此插件!";
return false;
}
$class = get_addon_class($info['name']);
if (class_exists($class)) {
//插件卸载方法
$addons = new $class;
if (!method_exists($addons, 'uninstall')) {
$this->error = "插件卸载方法!";
return false;
}
$result = $addons->uninstall();
if ($result) {
//卸载挂载点中的插件
$result = model('Hooks')->removeHooks($info['name']);
//删除插件表中数据
$this->where(array('id' => $id))->delete();
return true;
} else {
$this->error = "无法卸载插件!";
return false;
}
}
}
public function build() {
}
}

View File

@@ -17,7 +17,7 @@ class Hooks extends \think\Model {
public static $keylist = [
['name' => 'name', 'title' => '钩子名称', 'type' => 'text', 'help' => '需要在程序中先添加钩子,否则无效'],
['name' => 'description', 'title' => '钩子描述', 'type' => 'text', 'help' => '钩子的描述信息'],
['name' => 'type_text', 'title' => '钩子类型', 'type' => 'select', 'option' => '', 'help' => '钩子的描述信息'],
['name' => 'type_text', 'title' => '钩子类型', 'type' => 'select', 'option' => [['key'=>1, 'label'=>'视图'], ['key' => 2, 'label' => '控制器']], 'help' => '钩子的描述信息'],
['name' => 'addons', 'title' => '插件排序', 'type' => 'kanban'],
];
}

View File

@@ -1,4 +1,5 @@
$(function($) {
$('div#content-wrapper').css({'minHeight':$(window).height()-80});
var storage, fail, uid;
try {

2
public/uploads/file/.gitignore vendored Normal file
View File

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

2
public/uploads/image/.gitignore vendored Normal file
View File

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

View File

@@ -10,8 +10,6 @@
</div>
<div class="pull-right">
<a class="btn btn-info" href="{:url('/admin/addons/index', ['refresh'=>1])}">更 新</a>
<a class="btn btn-primary" href="{:url('/admin/addons/add')}">新 增</a>
<button class="btn btn-danger ajax-post confirm" url="{:url('/admin/addons/del')}" target-form="ids">删 除</button>
</div>
</header>
<div class="main-box-body clearfix">
@@ -64,30 +62,4 @@
</div>
{/block}
{block name="script"}
<script type="text/javascript" src="__static__/common/js/bootstrap-editable.min.js"></script>
<script type="text/javascript">
$(function() {
//点击排序
$('.item_sort').click(function(){
var url = $(this).attr('url');
var ids = $('.ids:checked');
var param = '';
if(ids.length > 0){
var str = new Array();
ids.each(function(){
str.push($(this).val());
});
param = str.join(',');
}
if(url != undefined && url != ''){
window.location.href = url + '/ids/' + param;
}
});
$.fn.editable.defaults.mode = 'popup';
$.fn.editableform.buttons = '<button type="submit" class="btn btn-success editable-submit btn-mini"><i class="fa fa-check-square-o fa-white"></i></button>' +
'<button type="button" class="btn editable-cancel btn-mini"><i class="fa fa-times"></i></button>';
$('.editable').editable();
});
</script>
{/block}

View File

@@ -13,25 +13,19 @@
<script type="text/javascript" src="__static__/plugins/jquery/jquery.min.js"></script>
<script type="text/javascript" src="__static__/plugins/layui/layui.all.js"></script>
<script src="__static__/common/js/messager.js"></script>
<script type="text/javascript">
var BASE_URL = "{:request()->domain()}"; //根目录地址
(function(){
var height = $(window).height();
if ($('#content-wrapper').height() < height) {
$('#content-wrapper').css({'minHeight':$(window).height()-80});
}
var SentCMS = window.Sent = {
"ROOT" : "__ROOT__", //当前网站地址
"APP" : "__APP__", //当前项目地址
"PUBLIC" : "__static__", //项目公共目录地址
}
})();
</script>
<script src="__static__/common/js/core.js"></script>
<!--[if lt IE 9]>
<script src="__static__/common/js/html5shiv.js"></script>
<script src="__static__/common/js/respond.min.js"></script>
<![endif]-->
<script type="text/javascript">
var BASE_URL = "{:request()->domain()}"; //根目录地址
var SentCMS = window.Sent = {
"ROOT" : BASE_URL, //当前网站地址
"APP" : "__APP__", //当前项目地址
"PUBLIC" : "__static__", //项目公共目录地址
}
</script>
<script src="__static__/common/js/core.js"></script>
</head>
<body>