1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/buwangyun-bwsaas

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
PluginService.php 59 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hnlg666 Отправлено 4 лет назад 9700799
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------
namespace buwang\service;
use app\common\model\Cache as CacheModel;
use app\common\model\member\Wallet;
use app\common\model\MemberPluginOrder;
use app\common\model\Miniapp;
use app\common\model\MiniappModule;
use app\manage\model\admin\Plugin;
use app\manage\model\AuthGroup;
use app\manage\model\AuthGroupAccess;
use app\manage\model\AuthGroupNode;
use app\manage\model\AuthNode;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use think\Exception;
use think\facade\Cache;
use think\facade\Db;
use buwang\util\File;
use buwang\util\Sql;
use ZipArchive;
use buwang\traits\ErrorTrait;
use app\manage\model\Member;
use app\manage\model\Config;
use app\manage\model\ConfigTab;
use app\manage\model\ConfigGroup;
use app\manage\model\ConfigGroupData;
/**
* 插件服务类
* Class PluginService
* @package buwang\service
*/
class PluginService
{
use ErrorTrait;
protected static $name;//插件目录名
/**
* 安装插件.
*
* @param string $name 插件名称
* @param bool $force 是否覆盖
* @param array $extend 扩展参数
*
* @return bool
* @throws Exception
*
*/
public static function install($name, $force = false, $extend = [])
{
define('ADDONS_DIR', $name);//定义一个常量表示插件目录名
self::$name = $name;
try {
// 检查插件是否完整
self::check($name);
if (!$force) {
//检查有没有冲突的文件
self::noconflict($name);
}
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
Db::startTrans();
try {
$info = get_addons_info($name);
//TODO 引入角色组和节点
self::createMenu($name, $info);
// 默认启用该插件
if (!$info['status']) {
$info['status'] = 1;
set_addons_info($name, $info);
}
// 执行安装脚本
$class = get_addons_class($name);
if (class_exists($class)) {
$addon = new $class(app());
$addon->install();
//TODO 设置缓存 若addons/demoPlugin/Plugin.php存在$cache数组
/*if (isset($addon->cache) && is_array($addon->cache)) {
self::installAddonCache($addon->cache, $name);
}*/
}
self::runSQL($name);
//插件表中增加记录
$info['logo_image'] = '/static/addons/' . strtolower($name) . '/logo.png';//插件logos
Plugin::create($info);
//把插件目录下的app和public目录复制至对应目录下 addons/demoPlugin/app => app
//201130 app和public目录移至addons/demoPlugin/install目录下
foreach (self::getCheckDirs() as $k => $dir) {
if (is_dir(ADDON_PATH . $name . DS . 'install' . DS . $dir)) {
File::copy_dir(ADDON_PATH . $name . DS . 'install' . DS . $dir, app()->getRootPath() . $dir);
}
}
//拷贝静态资源文件 addons/demoPlugin/static/ => public/static/addons/demoPlugin/
//201130 静态资源文件目录移至addons/demoPlugin/install/static/目录下
if (file_exists(ADDON_PATH . $name . DS . 'install' . DS . "static" . DS)) {
File::copy_dir(ADDON_PATH . $name . DS . 'install' . DS . "static" . DS, root_path() . 'public' . DS . 'static' . DS . 'addons' . DS . strtolower($name) . DS);
}
//TODO 2021/5/11 安装插件配置
self::installConfigAndGroupData($name, $info);
Db::commit();
} catch (Exception $e) {
Db::rollback();
throw new Exception($e->getMessage());
}
// 刷新
self::refresh();
return true;
}
/**
* 卸载插件.
*
* @param string $name
* @param bool $force 是否强制卸载
*
* @return bool
* @throws Exception
*
*/
public static function uninstall($name, $force = false)
{
//监测插件目录是否存在
if (!$name || !is_dir(ADDON_PATH . $name)) {
throw new Exception('插件不存在');
}
define('ADDONS_DIR', $name);//定义一个常量表示插件目录名
//set插件名称
self::$name = $name;
//查找插件
$plugin = Plugin::where('name', self::$name)->find();
if (!$plugin) throw new Exception('插件尚未安装');
//插件已被购买就无法卸载
if (MemberPluginOrder::where('plugin_id', $plugin['id'])->find()) throw new Exception('插件已被购买,无法卸载');
// 执行卸载脚本
Db::startTrans();
try {
// 默认禁用该插件
$info = get_addons_info($name);
//删除插件节点 用户组 用户组节点 应用功能的记录
self::deleteMenu();
//如果插件未禁用则改成禁用(还原插件配置)
if ($info['status']) {
$info['status'] = 0;
set_addons_info($name, $info);
}
//得到插件对应的 Plugin.php 类的全命名空间类名
$class = get_addons_class($name);
//判断该类是否存在
if (class_exists($class)) {
//如果存在则实例化
$addon = new $class(app());
//清除插件列表缓存
Cache::has('addonslist') && Cache::delete('addonslist');
//执行插件应用Plugin.php自定义的卸载方法
$addon->uninstall();
}
//执行卸载sql
self::runSQL($name, 'uninstall');
//删除插件表中记录
Plugin::where('name', $name)->delete();
// 移除插件全局资源文件
if ($force) {
$list = self::getGlobalFiles($name);
foreach ($list as $k => $v) {
@unlink(app()->getRootPath() . $v);
}
}
//删除模块前台模板
if (is_dir(TEMPLATE_PATH . 'addons' . DS . $name . DS)) {
File::del_dir(TEMPLATE_PATH . 'addons' . DS . $name . DS);
}
//静态资源移除
if (is_dir(root_path() . 'public' . DS . 'static' . DS . 'addons' . DS . strtolower($name) . DS)) {
File::del_dir(root_path() . 'public' . DS . 'static' . DS . 'addons' . DS . strtolower($name) . DS);
}
Db::commit();
} catch (Exception $e) {
Db::rollback();
throw new Exception($e->getMessage());
}
// 刷新
self::refresh();
return true;
}
/**
* 启用.
*
* @param string $name 插件名称
* @param bool $force 是否强制覆盖
*
* @return bool
*/
public static function enable($name, $force = false)
{
if (!$name || !is_dir(ADDON_PATH . $name)) {
throw new Exception('插件不存在!');
}
define('ADDONS_DIR', $name);//定义一个常量表示插件目录名
self::$name = $name;
$info = get_addons_info($name);
//执行启用脚本
try {
self::enableMenu();
//更新插件记录表记录状态为1
Plugin::update(['status' => 1], ['name' => $name]);
$class = get_addons_class($name);
if (class_exists($class)) {
$addon = new $class(app());
if (method_exists($class, 'enabled')) {
$addon->enabled();
}
}
$info['status'] = 1;
unset($info['url']);
set_addons_info($name, $info);
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
// 刷新
self::refresh();
return true;
}
/**
* 禁用.
*
* @param string $name 插件名称
* @param bool $force 是否强制禁用
*
* @return bool
* @throws Exception
*
*/
public static function disable($name, $force = false)
{
if (!$name || !is_dir(ADDON_PATH . $name)) {
throw new Exception('插件不存在!');
}
define('ADDONS_DIR', $name);//定义一个常量表示插件目录名
self::$name = $name;
$info = get_addons_info($name);
// 执行禁用脚本
try {
self::disableMenu();
//更新插件记录表记录状态为0
Plugin::update(['status' => 0], ['name' => $name]);
$class = get_addons_class($name);
if (class_exists($class)) {
$addon = new $class(app());
if (method_exists($class, 'disabled')) {
$addon->disabled();
}
}
$info['status'] = 0;
unset($info['url']);
set_addons_info($name, $info);
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
// 刷新
self::refresh();
return true;
}
/**
* 租户购买应用
* @param $user_id
* @param $plugin
* @return bool
* @throws Exception
*/
public static function buy($user_id, $plugin)
{
define('ADDONS_DIR', $plugin['name']);//定义一个常量表示插件目录名
self::$name = $plugin['name'];
list($scopes, $type) = explode('_', $plugin['type']);
if (!in_array($scopes, ['member','all'])) throw new Exception('平台插件不可购买');
//检查是否有menu.php TODO: 2021/4/29修复BUG 没有插件菜单也可购买,不能算无法购买
$path = root_path() . "addons/" . self::$name . "/install/menu.php";
// if (!file_exists($path)) return true; //原逻辑:没有菜单
// $data = include $path;
// if (empty($data)) return true; //原逻辑:没有菜单
try {
//NOTE 账户余额
//如果价格<=0,就不在查询数据库
if ($plugin['price'] > 0 && $plugin['price'] > Wallet::getMoney($user_id)) throw new Exception('余额不足');
//NOTE 扣余额
$plugin['price'] > 0 && Wallet::changeMoney($user_id, 'plugin', 0 - $plugin['price'], '购买插件');
//如果插件存在菜单,则处理菜单逻辑
if (file_exists($path)) {
$data = include $path;
if ($data) {
$group_name_arr = [];//用户组唯一标识
foreach ($data as $item) {
//租户购买时只给租户插入租户角色组
$item['scopes'] === 'member' && $group_name_arr[] = strpos($item['group_name'],self::$name) !== false? $item['group_name'] : self::$name . '_' . $item['group_name'];
}
// TODO 2021/4/29 租户拥有的角色组类型为plugin ,租户角色的app_name = 租户标识
$group_type = 'plugin';//角色类型
$app_name = self::$name; //角色app标识
//查询租户拥有的角色
$group_ids_arr = AuthGroup::where('group_name', 'IN', $group_name_arr)->where('type', $group_type)->fetchSql(false)->where('app_name', $app_name)->column('id');
//给租户添加该插件的角色组
if ($type === 'system') {//系统插件
//给租户增加角色组
foreach ($group_ids_arr as $group_id) {
$groupAccessParam[] = [
'uid' => $user_id,
'group_id' => $group_id,
'name' => AuthGroup::where('id', $group_id)->value('name'),
'scopes' => 'member'
];
//TODO:购买插件角色删除再添加防止冲突
AuthGroupAccess::where('uid', '=', $user_id)->where('group_id', '=', $group_id)->where('scopes', '=', 'member')->delete();
}
//给租户分配角色
if (!empty($groupAccessParam)) {
$authGroupAccess = new AuthGroupAccess();
$authGroupAccess->saveAll($groupAccessParam);
}
} else {//应用插件 需要调用应用功能购买
//获取所有功能模块
$miniapp_module_ids = MiniappModule::where('group_id', 'IN', $group_ids_arr)->column('id');
foreach ($miniapp_module_ids as $miniapp_module_id) {
MiniappService::buy($user_id, $miniapp_module_id, '', false);
}
}
}
}
//创建订单
$pluginOrderParam = [
'member_id' => $user_id,
'plugin_id' => $plugin['id'],
'price' => $plugin['price'],
];
MemberPluginOrder::create($pluginOrderParam);
//TODO: 初始化租户配置和组合数据(租户配置和)
self::initMemberConfigAndData($user_id, $plugin['name'], $plugin);
} catch (\Throwable $e) {
throw new Exception($e->getMessage());
}
return true;
}
/**
* 刷新插件缓存文件.
*
* @return bool
* @throws Exception
*
*/
public static function refresh()
{
$file = app()->getRootPath() . 'config' . DS . 'addons.php';
$config = get_addons_autoload_config(true);
if ($config['autoload']) {
return;
}
if (!File::is_really_writable($file)) {
throw new Exception('addons.php文件没有写入权限');
}
if ($handle = fopen($file, 'w')) {
fwrite($handle, "<?php\n\n" . 'return ' . var_export($config, true) . ';');
fclose($handle);
} else {
throw new Exception('文件没有写入权限');
}
return true;
}
/**
* 解压插件.
*
* @param string $name 插件名称
*
* @return string
* @throws Exception
*
*/
public static function unzip($name)
{
$file = app()->getRootPath() . 'runtime' . DS . 'addons' . DS . $name . '.zip';
$dir = ADDON_PATH . $name . DS;
if (class_exists('ZipArchive')) {
$zip = new ZipArchive();
if ($zip->open($file) !== true) {
throw new Exception('Unable to open the zip file');
}
if (!$zip->extractTo($dir)) {
$zip->close();
throw new Exception('Unable to extract the file');
}
$zip->close();
return $dir;
}
throw new Exception('无法执行解压操作,请确保ZipArchive安装正确');
}
/**
* 注册插件缓存
* @return boolean
*/
public static function installAddonCache(array $cache, $name)
{
$data = array();
foreach ($cache as $key => $rs) {
$add = array(
'key' => $key,
'name' => $rs['name'],
'module' => isset($rs['module']) ? $rs['module'] : $name,
'model' => $rs['model'],
'action' => $rs['action'],
//'param' => isset($rs['param']) ? $rs['param'] : '',
'system' => 0,
);
CacheModel::create($add);
}
return true;
}
/**
* 执行数据库脚本
* @param string $name
* @param string $Dir
* @return bool
* @throws Exception
*/
public static function runSQL(string $name = '', string $Dir = 'install')
{
//数据库安装脚本文件地址 addons/demoPlugin/install/install.sql
//数据库卸载脚本文件地址 addons/demoPlugin/uninstall/uninstall.sql
$sql_file = ADDON_PATH . "{$name}" . DS . "{$Dir}" . DS . "{$Dir}.sql";
if (file_exists($sql_file)) {
$sql_statement = Sql::getSqlFromFile($sql_file);
if (!empty($sql_statement)) {
//TODO 修改表前缀
$table_prefix = config('database.connections.mysql.prefix');
if (!empty($table_prefix)) {
$sql_statement = str_replace('bw_', $table_prefix, $sql_statement);
$sql_statement = str_replace('__BWPREFIX__', $table_prefix, $sql_statement);
}
foreach ($sql_statement as $value) {
try {
Db::execute($value);
} catch (\Exception $e) {
throw new Exception('导入SQL失败,请检查{$name}应用的sql的语句是否正确');
}
}
}
}
return true;
}
/**
* 是否有冲突
*
* @param string $name 插件名称
* @return boolean
* @throws AddonException
*/
public static function noconflict($name)
{
// 检测冲突文件
$list = self::getGlobalFiles($name, true);
if ($list) {
//发现冲突文件,抛出异常
throw new Exception("发现冲突文件");
}
return true;
}
/**
* 获取插件在全局的文件
*
* @param string $name 插件名称
* @return array
*/
public static function getGlobalFiles($name, $onlyconflict = false)
{
$list = [];
$addonDir = ADDON_PATH . $name . DS;
// 扫描插件目录是否有覆盖的文件
foreach (self::getCheckDirs() as $k => $dir) {
$checkDir = root_path() . $dir . DS;
if (!is_dir($checkDir)) {
continue;
}
//检测到存在插件外目录
if (is_dir($addonDir . $dir)) {
//匹配出所有的文件
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($addonDir . $dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $fileinfo) {
if ($fileinfo->isFile()) {
$filePath = $fileinfo->getPathName();
$path = str_replace($addonDir, '', $filePath);
if ($onlyconflict) {
$destPath = app()->getRootPath() . $path;
if (is_file($destPath)) {
if (filesize($filePath) != filesize($destPath) || md5_file($filePath) != md5_file($destPath)) {
$list[] = $path;
}
}
} else {
$list[] = $path;
}
}
}
}
}
return $list;
}
/**
* 获取检测的全局文件夹目录
* @return array
*/
protected static function getCheckDirs()
{
return [
'app',
];
}
/**
* 检测插件是否完整.
*
* @param string $name 插件名称
*
* @return bool
* @throws Exception
*
*/
public static function check($name)
{
if (!$name || !is_dir(ADDON_PATH . $name)) {
throw new Exception('插件不存在!');
}
$addonClass = get_addons_class($name);
if (!$addonClass) {
throw new Exception('插件主启动程序文件Plugin.php不存在');
}
$addon = new $addonClass(app());
if (!$addon->checkInfo()) {
throw new Exception('配置文件不完整,必须配置项:' . implode(",", ADDON_INFO_TYPE));
}
return true;
}
/**
* 导入角色数据
* @param string $name 插件标识
* @param array $info 插件信息
* @return bool
*/
private static function createMenu(string $name, array $info)
{
//检查是否有menu.php
$path = root_path() . "/addons/{$name}/install/menu.php";
if (!file_exists($path)) return true;
$data = include $path;
if (empty($data)) return true;
//校验type是否合法
list($scopes, $type) = explode('_', $info['type']);
if (!in_array($scopes, ['admin', 'member','all'])) throw new Exception('插件类型一有误,应为admin或member或all');
if (in_array($scopes, ['admin','all'])&&$type !== 'system') throw new Exception('平台插件类型二有误,应为system');
//TODO 2021/4/29 更改插件角色类型为插件类型
$group_type = 'plugin';
//TODO 2021/4/29 更改角色app_name为插件名称
$app_name = $name;
$is_app = false;//是否是应用
//应用插件判断
if ($scopes === 'member' && $type !== 'system') {
$is_app = true;
//如果是应用插件,则须确保应用节点存在
//获取应用
$miniapp = Miniapp::where(['dir' => $type])->find();
if (!$miniapp) throw new Exception("插件依赖{$type}应用,请先安装{$type}应用");
//获取应用根节点
if (!AuthNode::where(["pid" => 0, "app_name" => $type, "menu_path" => $type, "scopes" => $scopes])->find()) throw new Exception("应用{$type}根节点未找到");
}
if($scopes == 'all') $scopes = null; //TODO: 如果不指定all类型的角色组,则报错:all类型必须指定角色组范围
//待插入应用功能
$modules = [];
foreach ($data as $item) {
//参数验证
if (!isset($item['scopes']) || !in_array($item['scopes'], ['admin', 'member'])) throw new Exception("{$item['name']}角色scopes属性有误");
//插件角色组可同时包含 平台的角色组和租户的角色组
$scopes = in_array($item['scopes'], ['admin', 'member']) ? $item['scopes'] : $scopes;
if(!$scopes)throw new Exception("{$item['name']}角色scopes属性未填写,可填写admin或member");
//是否自定义了菜单type类型,如果没有自定义菜单类型,则使用默认
if (!isset($item['type'])||$item['type'] == "app_plugin") $item['type'] = $is_app ? "app_plugin_{$type}" : "system_plugin";
if (!in_array($item['type'], ['system_plugin', "app_plugin_{$type}"])) throw new Exception("{$item['name']}角色type属性未定义或非法");
//角色记录
$groupParam = [
//角色名称,展示在角色列表中
'name' => $item['name'],
//角色唯一标识,不可重复
'group_name' =>strpos($item['group_name'],$name) !== false? $item['group_name'] : $name . '_' . $item['group_name'] ,
//角色备注
'remark' => isset($item['remark']) ? $item['remark'] : '',
//登陆类型 admin=总后台,member=租户后台
'scopes' => $scopes,
'type' => $group_type,//角色组类型:system=系统,app=应用,plugin=插件
'app_name' => $app_name,//更改为插件名称
];
//创建角色
$group = AuthGroup::create($groupParam);
if (!$group) throw new Exception("{$item['name']}角色导入失败");
//应用模块记录
if ($is_app) $modules[] = [
'group_id' => $group['id'], //角色组id
'miniapp_id' => $miniapp['id'],//应用id
'name' => $item['name'], //角色名(功能名)
'type' => 3,//把功能类型修改为插件功能,在应用购买页面禁止直接购买插件功能
'price' => 0, //默认价格
'desc' => $item['remark'] ?: '', //备注
];
//父节点唯一标识
$parent_node_auth_node = isset($item['parent']) ? $item['parent'] : '';
//插入节点
if (isset($item['nodes']) && !empty($item['nodes'])) self::importNodeData($name, $scopes, $type, $group, $item['nodes'], $parent_node_auth_node, $item['type']);
}
//如果有应用插件则插入应用模块记录
if ($modules) {
$miniappModule = new MiniappModule();
$miniappModule->saveAll($modules);
}
return true;
}
/**
* 导入节点
* @param string $scopes admin/member
* @param string $type system/bwmall
* @param array $group 角色组
* @param array $nodes 节点
* @param string $parent_node_auth_node 父节点唯一标识
* @return bool
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private static function importNodeData($name, $scopes, $type, $group, $nodes, $parent_node_auth_node = '', $node_type = '')
{
//是否是应用
$is_app = false;
//应用插件判断
if ($scopes === 'member' && $type !== 'system') $is_app = true;
//菜单节点type类型
if (!$node_type||$node_type == 'app_plugin') $node_type = $is_app ? "app_plugin_{$type}" : "system_plugin";
//TODO 2021/4/29 更改角色app_name为插件名称
$app_name = $name;
//如果传入了父节点则插入到父节点下面
if ($parent_node_auth_node) {
$parent_node = [
"app_name" => $app_name,//插件名
"type" => $node_type,//权限分类 系统插件/应用插件
"auth_name" => $parent_node_auth_node,//权限标识,必填
"scopes" => $scopes //scopes
];
//判断父节点是否存在
$pid = AuthNode::where($parent_node)->value('id');
if (!$pid) throw new Exception("根节点{$parent_node_auth_node}未找到");
//废弃的原逻辑:如果不存在父节点
//①总后台插件,父节点是188
//②租户后台系统插件,父节点是1314
//③排除以上两者则是应用插件,父id是应用根节点
// } else $pid = $scopes === 'admin' ? 188 : ($type === 'system' ? 1314 : AuthNode::where(["pid" => 0, "app_name" => $type, "menu_path" => $type, "scopes" => $scopes])->value('id'));
} else {
//TODO 2021/4/29 非自定义父级菜单逻辑改为
//①总后台插件,父节点为总后台插件中心
//②租户插件,父节点为租户插件中心(系统的和应用的)
if ($scopes == 'admin') {
//得到总后台插件中心的id
$pid = AuthNode::where('name', '/manage/admin.plugin.Core/index')->where('scopes', $scopes)->value('id');
if (!$pid) throw new Exception("总后台插件中心节点未找到");
} else {
//得到租户后台插件中心节点
$pid = AuthNode::where('name', '/manage/member.plugin.Core/index')->where('scopes', $scopes)->value('id');
if (!$pid) throw new Exception("租户后台插件中心节点未找到");
}
}
//找到该角色组所需的根节点 admin_system是在插件管理/plugin下 member_system是在插件管理member/addons下 member_bwmall是在应用bwmall下
$rootNodeParam = [
"pid" => $pid,//上级菜单id,填0代表是顶部选项卡
"title" => (get_addons_info(self::$name))['title'],//菜单名称
"app_name" => $app_name,//插件名
"type" => $node_type,//权限分类 系统/应用/插件
"menu_path" => self::$name,//根节点路径
"name" => self::$name,//根节点路径
"auth_name" => '',//权限标识,必填
"param" => '',//参数
"target" => '_self',//打开方式
"ismenu" => 1,//是否菜单
"icon" => '',//图标
"remark" => '',//备注
"scopes" => $scopes//scopes
];
//插入插件根节点
$rootNode = AuthNode::where($rootNodeParam)->find();
if (!$rootNode) $rootNode = AuthNode::create($rootNodeParam);
//把插件根节点导入该角色组中
$groupNodeParam = [
'group_id' => $group['id'], //角色id
'node_id' => $rootNode['id'], //节点id
'node_name' => $rootNode['name'], //节点名
'auth_name' => $rootNode['auth_name'],
'type' => $rootNode['type'], //节点类型
];
//创建角色菜单中间节点
AuthGroupNode::create($groupNodeParam);
//执行节点导入
self::importNode($name, $scopes, $type, $group, $nodes, $rootNode['id'], $node_type);
return true;
}
/**
* 导入节点与角色节点中间表
* @param array $groups
* @param array $data
* @param int $pid 1172是应用管理的节点id
* @return bool
* @throws Exception
*/
private static function importNode($name, $scopes, $type, $group, $nodes, $pid, $node_type)
{
//TODO 2021/4/29 更改角色app_name为插件名称
$app_name = $name;
foreach ($nodes as $item) {
//插入节点
$nodeParam = [
"pid" => $pid,//上级菜单id,填0代表是顶部选项卡
"title" => $item['title'],//菜单名称
"app_name" => $app_name,//应用/插件名
"type" => $node_type,//系统/应用
"menu_path" => $item['menu_path'],//后台url
"name" => $item['name'],//后台url
"auth_name" => isset($item['auth_name']) ? $item['auth_name'] : '',//权限标识,必填
"param" => isset($item['param']) ? $item['param'] : '',//参数
"target" => isset($item['target']) ? $item['target'] : '_self',//打开方式
"ismenu" => isset($item['ismenu']) ? $item['ismenu'] : 0,//是否菜单
"icon" => isset($item['icon']) ? $item['icon'] : '',//图标
"remark" => isset($item['remark']) ? $item['remark'] : '',//备注
"scopes" => $scopes//scopes
];
//节点插入
$node = AuthNode::create($nodeParam);
if (!$node) throw new Exception("{$item['title']}节点插入失败");
//插入节点中间表
$groupNodeParam = [
'group_id' => $group['id'],
'node_id' => $node['id'],
'node_name' => $node['name'],
'auth_name' => $node['auth_name'],
'type' => $node['type'],
];
AuthGroupNode::create($groupNodeParam);
if (isset($item['children']) && !empty($item['children'])) self::importNode($name, $scopes, $type, $group, $item['children'], $node['id'], $node_type);
}
return true;
}
/**
* 删除菜单
* @return bool
*/
private static function deleteMenu(): bool
{
//得到插件信息
$info = get_addons_info(self::$name);
//得到范围和类型
list($scopes, $type) = explode('_', $info['type']);
//TODO 2021/4/29 变更插件角色类型为plugin,app_name为插件标识
$addon_type = 'plugin'; //角色类型
$addon_app_name = self::$name;//角色插件标识
//检查是否有menu.php
$path = root_path() . "addons/" . self::$name . "/install/menu.php";
if (!file_exists($path)) return true; //没有菜单
$data = include $path;
if (empty($data)) return true; //没有菜单
$group_name_arr = [];//用户组唯一标识
//得到插件全部角色标识
foreach ($data as $item) {
$group_name_arr[] = strpos($item['group_name'],self::$name) !== false? $item['group_name'] : self::$name . '_' . $item['group_name'];
}
//根据角色标识得到插件拥有的角色id
$group_ids_arr = AuthGroup::where('group_name', 'IN', $group_name_arr)->where('type', $addon_type)->where('app_name', $addon_app_name)->column('id');
//根据角色id得到插件拥有的节点id
$node_ids_arr = AuthGroupNode::where('group_id', 'IN', $group_ids_arr)->column('node_id');
//删除插件角色
AuthGroup::where('id', 'IN', $group_ids_arr)->delete();
//删除插件节点
AuthNode::where('id', 'IN', $node_ids_arr)->delete();
//删除插件角色节点中间表
AuthGroupNode::where('group_id', 'IN', $group_ids_arr)->delete();
//如果是应用插件则删除对应的应用模块
if ($scopes === 'member' && $type !== 'system') MiniappModule::where('group_id', 'IN', $group_ids_arr)->delete();
return true;
}
/**
* 启动菜单
*/
private static function enableMenu()
{
$info = get_addons_info(self::$name);
list($scopes, $type) = explode('_', $info['type']);
//检查是否有menu.php
$path = root_path() . "addons/" . self::$name . "/install/menu.php";
if (!file_exists($path)) return true;
$data = include $path;
if (empty($data)) return true;
$group_name_arr = [];//用户组唯一标识
foreach ($data as $item) {
$group_name_arr[] = strpos($item['group_name'],self::$name) !== false? $item['group_name'] : self::$name . '_' . $item['group_name'];
}
//角色组设置为启用
AuthGroup::where('group_name', 'IN', $group_name_arr)->where('type', $type === 'system' ? 'system' : 'app')->where('app_name', $type === 'system' ? 'manage' : $type)->update(['status' => 1]);
return true;
}
/**
* 禁用菜单
*/
private static function disableMenu()
{
$info = get_addons_info(self::$name);
list($scopes, $type) = explode('_', $info['type']);
//检查是否有menu.php
$path = root_path() . "addons/" . self::$name . "/install/menu.php";
if (!file_exists($path)) return true;
$data = include $path;
if (empty($data)) return true;
$group_name_arr = [];//用户组唯一标识
foreach ($data as $item) {
$group_name_arr[] = strpos($item['group_name'],self::$name) !== false? $item['group_name'] : self::$name . '_' . $item['group_name'];
}
//角色组设置为禁用
AuthGroup::where('group_name', 'IN', $group_name_arr)->where('type', $type === 'system' ? 'system' : 'app')->where('app_name', $type === 'system' ? 'manage' : $type)->update(['status' => 0]);
return true;
}
/**安装插件的配置和组合数据(修正分类id)
* @param $name
*/
public static function installConfigAndGroupData($plugin_name, array $info, $trans = false)
{
list($scopes, $type) = explode('_', $info['type']);
if ($scopes === 'member' && $type !== 'system') $app_name = $type; else $app_name = '';
//得到插件的
if ($trans) {
Db::startTrans();
}
try {
//如果存在插件应用配置则更新插件应用配置和组合数据
if ($app_name) {
//查询所有的应用插件配置并更新配置id
$config_tab_ids = ConfigTab::valiWhere('', null, $app_name, false)->where('plugin_name', '=', $plugin_name)->where('dir', $app_name)->where('scopes', 'member')->column('id', 'tab_name');
//遍历配置分类,给租户插入配置数据
foreach ($config_tab_ids as $tab_name => $tab_id) {
//修正分类id参数
Config::valiWhere('', null, $app_name, false)->where('tab_name', '=', $tab_name)->where('dir', $app_name)->where('plugin_name', '=', $plugin_name)->update(['tab_id' => $tab_id]);
}
$group_ids = ConfigGroup::valiWhere('', null, $app_name)->where('plugin_name', '=', $plugin_name)->where('dir', $app_name)->where('scopes', 'member')->column('id', 'config_name');
//遍历数据组,给租户插入组合数据
foreach ($group_ids as $config_name => $group_id) {
//修正数据组id参数
ConfigGroupData::valiWhere('', null, $app_name)->where('config_name', '=', $config_name)->where('plugin_name', '=', $plugin_name)->where('dir', $app_name)->update(['group_id' => $group_id]);
}
}
//如果存在系统配置和系统租户配置,更新对应分类id
//查询所有的应用插件配置并更新配置id
$config_tab_ids = ConfigTab::valiWhere('', null, '', false)->where('plugin_name', '=', $plugin_name)->column('id', 'tab_name');
//遍历配置分类,给租户插入配置数据
foreach ($config_tab_ids as $tab_name => $tab_id) {
//修正分类id参数
Config::valiWhere('', null, '', false)->where('tab_name', '=', $tab_name)->where('plugin_name', '=', $plugin_name)->update(['tab_id' => $tab_id]);
}
$group_ids = ConfigGroup::valiWhere('', null, '')->where('plugin_name', '=', $plugin_name)->column('id', 'config_name');
//遍历数据组,给租户插入组合数据
foreach ($group_ids as $config_name => $group_id) {
//修正数据组id参数
ConfigGroupData::valiWhere('', null, '')->where('config_name', '=', $config_name)->where('plugin_name', '=', $plugin_name)->update(['group_id' => $group_id]);
}
if ($trans) {
Db::commit();
}
} catch (\Exception $e) {
if ($trans) {
Db::rollback();
}
throw new Exception("安装配置和组合数据失败:" . $e->getMessage());
}
return true;
}
/**初始化租户配置和数据组(购买时)
* @param $member_id
* @param $dir
*/
public static function initMemberConfigAndData($member_id, $plugin_name, $info, $trans = false)
{
list($scopes, $type) = explode('_', $info['type']);
if ($scopes === 'member' && $type !== 'system') $app_name = $type; else $app_name = '';
if ($trans) {
Db::startTrans();
}
$config_data = $group_data = $config_data_sys = $group_data_sys = [];
//查看插件是否有应用配置,如果有,则插入配置
if ($app_name) {
//得到租户的初始化数据
//配置列表
$config_list = Config::valiWhere('', null, $app_name, false)->where('member_id', 0)->where('scopes', 'member')->where('dir', '=', $app_name)->where('plugin_name', '=', $plugin_name)->select()->toArray(); //组装提交数据
//组合数据
$config_data_list = ConfigGroupData::valiWhere('', null, $app_name)->where('member_id', 0)->where('scopes', 'member')->where('dir', '=', $app_name)->where('plugin_name', '=', $plugin_name)->select()->toArray();
//组装提交数据
//租户配置
foreach ($config_list as $config) {
$member_config = Config::valiWhere('', null, $app_name, false)->where('member_id', $member_id)->where('scopes', 'member')->where('dir', '=', $app_name)->where('plugin_name', '=', $plugin_name)->where('config_name', $config['config_name'])->find();
if (!$member_config) {
unset($config['id']);
$config['member_id'] = $member_id;
$config_data[] = $config;
}
}
//租户组合数据
foreach ($config_data_list as $data) {
$member_data = ConfigGroupData::valiWhere('', null, $app_name)->where('member_id', $member_id)->where('scopes', 'member')->where('dir', '=', $app_name)->where('plugin_name', '=', $plugin_name)->where('config_name', $data['config_name'])->find();
if (!$member_data) {
unset($data['id']);
$data['member_id'] = $member_id;
$group_data[] = $data;
}
}
}
//查看插件是否有租户系统配置,如果有,则插入
//得到租户的初始化数据
//配置列表
$config_list = Config::valiWhere('', null, '', false)->where('member_id', 0)->where('scopes', 'member')->where('plugin_name', '=', $plugin_name)->select()->toArray(); //组装提交数据
//组合数据
$config_data_list = ConfigGroupData::valiWhere('', null, '')->where('member_id', 0)->where('scopes', 'member')->where('plugin_name', '=', $plugin_name)->select()->toArray();
//组装提交数据
//租户配置
foreach ($config_list as $config) {
$member_config = Config::valiWhere('', null, '', false)->where('member_id', $member_id)->where('scopes', 'member')->where('plugin_name', '=', $plugin_name)->where('config_name', $config['config_name'])->find();
if (!$member_config) {
unset($config['id']);
$config['member_id'] = $member_id;
$config_data_sys[] = $config;
}
}
//租户组合数据
foreach ($config_data_list as $data) {
$member_data = ConfigGroupData::valiWhere('', null, '')->where('member_id', $member_id)->where('scopes', 'member')->where('plugin_name', '=', $plugin_name)->where('config_name', $data['config_name'])->find();
if (!$member_data) {
unset($data['id']);
$data['member_id'] = $member_id;
$group_data_sys[] = $data;
}
}
try {
//执行提交
if ($config_data) { //应用配置
$config = Config::valiWhere('', null, $app_name, false);
$config->saveAll($config_data);
}
if ($group_data) { //应用组合数据
$data = ConfigGroupData::valiWhere('', null, $app_name);
$data->saveAll($group_data);
}
if ($config_data_sys) { //系统配置
$config = Config::valiWhere('', null, '', false);
$config->saveAll($config_data_sys);
}
if ($group_data_sys) { //系统组合数据
$data = ConfigGroupData::valiWhere('', null, '');
$data->saveAll($group_data_sys);
}
if ($trans) {
Db::commit();
}
} catch (\Exception $e) {
if ($trans) {
Db::rollback();
}
throw new Exception("安装租户配置和组合数据失败:" . $e->getMessage());
}
}
/**
* 导出插件安装的配置和数据组文件
*/
public static function exportPluginConfig($plugin_name, $dir_path, $un_dir_path)
{
//插件信息
$info = Plugin::where('name', $plugin_name)->find();
if (!$info) return true;
list($scopes, $type) = explode('_', $info['type']);
if ($scopes === 'member' && $type !== 'system') $app_name = $type; else $app_name = '';
$config_tab_sql = '';//配置分类安装sql
$config_sql = ''; //配置安装sql
$group_sql = ''; //数据组安装sql
$group_data_sql = ''; //数据组数据安装sql
$install_sql = '';
$config_tab_delete_sql = ''; //配置分类卸载sql
$config_delete_sql = ''; //配置卸载sql
$group_delete_sql = ''; //数据组卸载sql
$group_data_delete_sql = ''; //数据组数据卸载sql
$uninstall_sql = '';
$tableSql = MiniappService::getInstallSql($plugin_name); //得到所有的插件安装表
if ($app_name) {
//查询应用配置
//查询应用配置分类
$configTabs = ConfigTab::valiWhere('', null, $app_name, false)->where('dir', $app_name)->where('scopes', 'member')->where('plugin_name', $plugin_name)->column('tab_name');
$configTabList = ConfigTab::valiWhere('', null, $app_name, false)->where('dir', $app_name)->where('scopes', 'member')->where('plugin_name', $plugin_name)->select()->toArray();
if ($configTabs) {
foreach ($configTabList as $tab) {
unset($tab['id']);
//得到配置分类插入sql
$insertSQL = ConfigTab::valiWhere('', null, $app_name, false)->fetchSql(true)->save($tab);
$config_tab_sql .= $insertSQL . ';' . PHP_EOL;
//得到配置分类卸载sql
$deleteSQL = ConfigTab::valiWhere('', null, $app_name, false)->fetchSql(true)->where('tab_name', $tab['tab_name'])->where('plugin_name', $plugin_name)->delete();
$config_tab_delete_sql .= $deleteSQL . ';' . PHP_EOL;
//得到配置卸载sql
$deleteSQL = Config::valiWhere('', null, $app_name, false)->fetchSql(true)->where('tab_name', $tab['tab_name'])->where('plugin_name', $plugin_name)->delete();
$config_delete_sql .= $deleteSQL . ';' . PHP_EOL;
}
//查询所有初始化配置
$configs = Config::valiWhere('', null, $app_name, false)->where('dir', $app_name)->where('member_id', 0)->where('scopes', 'member')->where('tab_name', 'in', $configTabs)->where('plugin_name', $plugin_name)->select()->toArray();
foreach ($configs as $config) {
//得到配置值插入sql
unset($config['id']);
$insertSQL = Config::valiWhere('', null, $app_name, false)->fetchSql(true)->save($config);
$config_sql .= $insertSQL . ';' . PHP_EOL;
}
}
//生成bwdata
$configGroups = ConfigGroup::valiWhere('', null, $app_name)->where('dir', $app_name)->where('plugin_name', $plugin_name)->where('scopes', 'member')->column('config_name');
$configGroupList = ConfigGroup::valiWhere('', null, $app_name)->where('dir', $app_name)->where('plugin_name', $plugin_name)->where('scopes', 'member')->select()->toArray();
foreach ($configGroupList as $configGroup) {
//得到数据组插入sql
unset($configGroup['id']);
$insertSQL = ConfigGroup::valiWhere('', null, $app_name)->fetchSql(true)->save($configGroup);
$group_sql .= $insertSQL . ';' . PHP_EOL;
//得到数据组卸载sql
$deleteSQL = ConfigGroup::valiWhere('', null, $app_name)->fetchSql(true)->where('config_name', $configGroup['config_name'])->where('plugin_name', $plugin_name)->delete();
$group_delete_sql .= $deleteSQL . ';' . PHP_EOL;
//得到数据组数据卸载sql
$deleteSQL = ConfigGroupData::valiWhere('', null, $app_name)->fetchSql(true)->where('config_name', $configGroup['config_name'])->where('plugin_name', $plugin_name)->delete();
$group_data_delete_sql .= $deleteSQL . ';' . PHP_EOL;
}
//查询所有组合数据的初始化数据
$configGroupDatas = ConfigGroupData::valiWhere('', null, $app_name)->where('dir', $app_name)->where('member_id', 0)->where('scopes', 'member')->where('config_name', 'in', $configGroups)->where('plugin_name', $plugin_name)->select()->toArray();
foreach ($configGroupDatas as $configGroupData) {
//得到数据组插入sql
unset($configGroupData['id']);
$insertSQL = ConfigGroupData::valiWhere('', null, $app_name)->fetchSql(true)->save($configGroupData);
$group_data_sql .= $insertSQL . ';' . PHP_EOL;
}
}
//查询系统配置
//查询系统配置分类
$configTabs = ConfigTab::valiWhere('', null, '', false)->where('plugin_name', $plugin_name)->column('tab_name');
$configTabList = ConfigTab::valiWhere('', null, '', false)->where('plugin_name', $plugin_name)->select()->toArray();
if ($configTabs) {
foreach ($configTabList as $tab) {
unset($tab['id']);
//得到配置分类插入sql
$insertSQL = ConfigTab::valiWhere('', null, '', false)->fetchSql(true)->save($tab);
$config_tab_sql .= $insertSQL . ';' . PHP_EOL;
//得到配置分类卸载sql
$deleteSQL = ConfigTab::valiWhere('', null, '', false)->fetchSql(true)->where('tab_name', $tab['tab_name'])->where('plugin_name', $plugin_name)->delete();
$config_tab_delete_sql .= $deleteSQL . ';' . PHP_EOL;
//得到配置卸载sql
$deleteSQL = Config::valiWhere('', null, '', false)->fetchSql(true)->where('tab_name', $tab['tab_name'])->where('plugin_name', $plugin_name)->delete();
$config_delete_sql .= $deleteSQL . ';' . PHP_EOL;
}
//查询所有初始化配置
$configs = Config::valiWhere('', null, '', false)->where('member_id', 0)->where('tab_name', 'in', $configTabs)->where('plugin_name', $plugin_name)->select()->toArray();
foreach ($configs as $config) {
//得到配置值插入sql
unset($config['id']);
$insertSQL = Config::valiWhere('', null, '', false)->fetchSql(true)->save($config);
$config_sql .= $insertSQL . ';' . PHP_EOL;
}
}
//生成bwdata
$configGroups = ConfigGroup::valiWhere('', null, '')->where('plugin_name', $plugin_name)->column('config_name');
$configGroupList = ConfigGroup::valiWhere('', null, '')->where('plugin_name', $plugin_name)->select()->toArray();
foreach ($configGroupList as $configGroup) {
//得到数据组插入sql
unset($configGroup['id']);
$insertSQL = ConfigGroup::valiWhere('', null, '')->fetchSql(true)->save($configGroup);
$group_sql .= $insertSQL . ';' . PHP_EOL;
//得到数据组卸载sql
$deleteSQL = ConfigGroup::valiWhere('', null, '')->fetchSql(true)->where('config_name', $configGroup['config_name'])->where('plugin_name', $plugin_name)->delete();
$group_delete_sql .= $deleteSQL . ';' . PHP_EOL;
//得到数据组数据卸载sql
$deleteSQL = ConfigGroupData::valiWhere('', null, '')->fetchSql(true)->where('config_name', $configGroup['config_name'])->where('plugin_name', $plugin_name)->delete();
$group_data_delete_sql .= $deleteSQL . ';' . PHP_EOL;
}
//查询所有组合数据的初始化数据
$configGroupDatas = ConfigGroupData::valiWhere('', null, '')->where('member_id', 0)->where('config_name', 'in', $configGroups)->where('plugin_name', $plugin_name)->select()->toArray();
foreach ($configGroupDatas as $configGroupData) {
//得到数据组插入sql
unset($configGroupData['id']);
$insertSQL = ConfigGroupData::valiWhere('', null, '')->fetchSql(true)->save($configGroupData);
$group_data_sql .= $insertSQL . ';' . PHP_EOL;
}
//修改表前缀
$table_prefix = config('database.connections.mysql.prefix');
//组装表安装sql
if ($tableSql['install']) $install_sql .= PHP_EOL . $tableSql['install'] . PHP_EOL;
//组装配置的安装sql
if ($config_tab_sql) $install_sql .= PHP_EOL . $config_tab_sql . PHP_EOL;
if ($config_sql) $install_sql .= PHP_EOL . $config_sql . PHP_EOL;
if ($group_sql) $install_sql .= PHP_EOL . $group_sql . PHP_EOL;
if ($group_data_sql) $install_sql .= PHP_EOL . $group_data_sql . PHP_EOL;
//生成配置插入语句
if ($install_sql) file_put_contents($dir_path . 'install.sql', str_replace($table_prefix, '__BWPREFIX__', $install_sql));
//组装表卸载sql
if ($tableSql['uninstall']) $uninstall_sql .= PHP_EOL . $tableSql['uninstall'] . PHP_EOL;
//组装配置的卸载sql
if ($config_tab_delete_sql) $uninstall_sql .= PHP_EOL . $config_tab_delete_sql . PHP_EOL;
if ($config_delete_sql) $uninstall_sql .= PHP_EOL . $config_delete_sql . PHP_EOL;
if ($group_delete_sql) $uninstall_sql .= PHP_EOL . $group_delete_sql . PHP_EOL;
if ($group_data_delete_sql) $uninstall_sql .= PHP_EOL . $group_data_delete_sql . PHP_EOL;
//生成配置卸载sql
if ($uninstall_sql) file_put_contents($un_dir_path . 'uninstall.sql',str_replace($table_prefix, '__BWPREFIX__', $uninstall_sql));
}
/**导出安装目录
* @param $dir
* @param string $target_dir
*/
public static function exportPath($dir)
{
$dir_path = root_path() . 'public' . DS . 'addons' . DS . $dir . DS.'install' . DS;
$un_dir_path = root_path() . 'public' . DS . 'addons' . DS . $dir . DS . 'uninstall' .DS;
$target_dir = root_path() . 'public' . DS . 'addons' . DS . $dir . DS . 'install' . DS . 'static' . DS;
return [
'static' => $target_dir . '*',
'group' => $dir_path . 'menu.php',
'event' => $dir_path . 'listen.php',
'install' => $dir_path . 'install.sql',
'uninstall' => $un_dir_path . 'uninstall.sql',
'app' => root_path() .DS . $dir . '======>'. root_path() . 'public' . DS .'addons' . DS . $dir,
'zip' => '以上文件将被打包进:'.root_path() . 'public' . DS .'addons' . DS . $dir.'.zip',
];
}
/**打包当前应用
* @param $dir
*/
public static function exportPackage($dir)
{
$dir_path = root_path() . 'public' . DS .'addons' . DS . $dir . DS . 'install';
@mkdir($dir_path, 0777, true);
$dir_path .= DS;
$un_dir_path = root_path() . 'public' . DS . 'addons' . DS .$dir . DS . 'uninstall';
@mkdir($un_dir_path, 0777, true);
$un_dir_path .= DS;
$sorce_dir = root_path() . 'public' . DS . 'static' . DS .'addons' . DS . strtolower($dir) . DS;
$target_dir = root_path() . 'public' . DS .'addons' . DS . $dir . DS . 'install' . DS . 'static' . DS;
$sorce_app = root_path() . 'addons' . DS . $dir . DS;
$target_app = root_path() . 'public' . DS .'addons' . DS . $dir . DS;
$zip_path = root_path() . 'public' . DS .'addons' . DS . $dir . '.zip';
$event_ini = $dir_path . 'listen.php';
$menu = $dir_path . 'menu.php';
MiniappService::exportMiniappStatic($sorce_app, $target_app);//迁移项目文件
self::exportPluginConfig($dir, $dir_path, $un_dir_path);//导入配置文件
MiniappService::exportMiniappStatic($sorce_dir, $target_dir);//导入静态文件
MiniappService::exportMiniappEventInit($event_ini);//导入钩子配置文件
self::exportPluginMenu($dir, $menu);//导入菜单配置
//项目打压缩包
File::createSimpleZip($zip_path, $target_app);
//删除生成文件夹
File::del_dir($target_app);
}
/**
* 导出插件用户组数据至文件
* @param string $dir 应用目录名
*/
public static function exportPluginMenu($dir, $target_dir = 'menu.php')
{
//插件
$miniapp = Plugin::where('name', $dir)->find();
if (!$miniapp) return true;
//查询插件所有角色()
$miniapp_modules = AuthGroup::alias('auth_group')
->field('auth_group.id, auth_group.name, auth_group.group_name, auth_group.remark, auth_group.type,auth_group.scopes')
->where('auth_group.app_name',$dir)
->where('auth_group.type','plugin')
->order(['auth_group.id' => 'asc'])
->select()->toArray();
if (!$miniapp_modules) return true;//不存在角色
//总后台插件中心根节点
$admin_root_node = AuthNode::where('menu_path', '/manage/admin/plugin/core/index')->where('type', 'system')->where('scopes', 'admin')->field('id, pid, title')->find();
//租户插件中心根节点
$member_root_node = AuthNode::where('menu_path', '/manage/member/plugin/core/index')->where('type', 'system')->where('scopes', 'member')->field('id, pid, title')->find();
if (!$admin_root_node) return true;
if (!$member_root_node) return true;
//插入角色节点
foreach ($miniapp_modules as &$miniapp_module) {
$nodes = AuthNode::alias('node')
->join('auth_group_node', 'node.id = auth_group_node.node_id')
->where([
['auth_group_node.group_id', '=', $miniapp_module['id']],
])
->field('node.id, node.pid, node.title, node.menu_path, node.name, node.auth_name, node.ismenu, node.param, node.target, node.icon, node.remark, node.type')
->order('node.sort desc, node.id asc')
->select()->toArray();
if(!$nodes)continue;
$miniapp_module['type'] = $nodes[0]['type'];
if($miniapp_module['scopes'] == 'admin'){
$nodes = deal_list_to_tree($nodes, 'id', 'pid', 'children', false, $admin_root_node['id']);
}else{
$nodes = deal_list_to_tree($nodes, 'id', 'pid', 'children', false, $member_root_node['id']);
}
$miniapp_module['nodes'] = $nodes ? $nodes[0]['children']:$nodes;
unset($miniapp_module['id']);
}
file_put_contents($target_dir, '<?php' . "\n\nreturn " . var_export($miniapp_modules, true) . ";");
self::filterMenu($target_dir);
return true;
}
/**
* 菜单生成文件正则过滤
* @param string $name 插件名称
* @return boolean
*/
public static function filterMenu($file_path)
{
if (is_file($file_path)) {
$lines = file($file_path);
$templine = '';
foreach ($lines as $line) {
if (strpos($line,"'id'") !== false||strpos($line,"'pid'") !== false)continue;
$templine .= $line;
}
}
file_put_contents($file_path, $templine);
return true;
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/buwangyun-bwsaas.git
git@gitlife.ru:oschina-mirror/buwangyun-bwsaas.git
oschina-mirror
buwangyun-bwsaas
buwangyun-bwsaas
v1.3.2