admin/app/model/system/Addon.php

579 lines
22 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* ThinkShop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 成都云之牛科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.cdcloudshop.com
* =========================================================
*/
namespace app\model\system;
use app\model\BaseModel;
use app\model\diy\Template;
use app\model\diy\Theme;
use app\model\web\DiyView as DiyViewModel;
use app\model\web\DiyViewLink;
use think\facade\Cache;
use think\facade\Db;
/**
* 插件表
*/
class Addon extends BaseModel
{
/**
* 获取单条插件信息
* @param array $condition
* @param string $field
*/
public function getAddonInfo($condition, $field = "*")
{
$data = json_encode([ $condition, $field ]);
$cache = Cache::get("addon_getAddonInfo_" . $data);
if (!empty($cache)) {
return $this->success($cache);
}
$addon_info = model('addon')->getInfo($condition, $field);
Cache::tag("addon")->set("addon_getAddonInfo_" . $data, $addon_info);
return $this->success($addon_info);
}
/**
* 获取插件列表
*
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getAddonList($condition = [], $field = '*', $order = '', $limit = null)
{
$data = json_encode([ $condition, $field, $order, $limit ]);
$cache = Cache::get("addon_getAddonList_" . $data);
if (!empty($cache)) {
return $this->success($cache);
}
$addon_list = model('addon')->getList($condition, $field, $order, '', '', '', $limit);
Cache::tag("addon")->set("addon_getAddonList_" . $data, $addon_list);
return $this->success($addon_list);
}
/**
* 获取插件分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getAddonPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$data = json_encode([ $condition, $page, $page_size, $order, $field ]);
$cache = Cache::get("addon_getAddonPageList_" . $data);
if (!empty($cache)) {
return $this->success($cache);
}
$list = model('addon')->pageList($condition, $field, $order, $page, $page_size);
Cache::tag("addon")->set("addon_getAddonPageList_" . $data, $list);
return $this->success($list);
}
/**
* 获取所有插件
* @return array
*/
public function getAddonAllList()
{
//存在的插件
$existed_addons = array_map('basename', glob('addon/*', GLOB_ONLYDIR));
//已安装的插件
$installed_addon_array = model('addon')->getColumn([], 'name');
//初始化数据
$undownload_addons = [];
$uninstall_addons = [];
$install_addons = [];
foreach ($existed_addons as $key => $val) {
$info_file_path = 'addon/' . $val . '/config/info.php';
if (file_exists($info_file_path)) {
$info = include_once $info_file_path;
$info[ 'icon' ] = 'addon/' . $val . '/icon.png';
$info[ 'download' ] = 0;
$info[ 'auth' ] = true;
$info[ 'update' ] = false;
$info[ 'last_online_version_no' ] = '';
if (!in_array($val, $installed_addon_array)) {
$uninstall_addons[] = $info;
} else {
$install_addons[] = $info;
}
}
}
return $this->success([
'uninstall' => array_merge($undownload_addons, $uninstall_addons),
'install' => $install_addons,
]);
}
/**
* 获取未安装的插件列表
*/
public function getUninstallAddonList()
{
$dirs = array_map('basename', glob('addon/*', GLOB_ONLYDIR));
$addon_names = model('addon')->getColumn([], 'name');
$addons = [];
foreach ($dirs as $key => $value) {
if (!in_array($value, $addon_names)) {
$info_name = 'addon/' . $value . '/config/info.php';
if (file_exists($info_name)) {
$info = include_once $info_name;
$info[ 'icon' ] = 'addon/' . $value . '/icon.png';
$addons[] = $info;
}
}
}
return $this->success($addons);
}
/*******************************************************************插件安装方法开始****************************************************/
/**
* 插件安装
*
* @param string $addon_name
*/
public function install($addon_name)
{
Db::startTrans();
try {
// 插件预安装
$res2 = $this->preInstall($addon_name);
if ($res2[ 'code' ] != 0) {
Db::rollback();
return $res2;
}
// 安装菜单
$res3 = $this->installMenu($addon_name);
if ($res3[ 'code' ] != 0) {
Db::rollback();
return $res3;
}
// 安装自定义模板
$res4 = $this->refreshDiyView($addon_name);
if ($res4[ 'code' ] != 0) {
Db::rollback();
return $res4;
}
// 添加插件入表
$addons_model = model('addon');
$addon_info = require 'addon/' . $addon_name . '/config/info.php';
$addon_info[ 'create_time' ] = time();
$addon_info[ 'icon' ] = 'addon/' . $addon_name . '/icon.png';
$data = $addons_model->add($addon_info);
if (!$data) {
Db::rollback();
return $this->error($data, 'ADDON_ADD_FAIL');
}
// 清理缓存
Cache::clear();
Db::commit();
return $this->success();
} catch (\Exception $e) {
// 清理缓存
Cache::clear();
Db::rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 插件预安装
*/
private function preInstall($addon_name)
{
$class_name = "addon\\" . $addon_name . "\\event\\Install";
$install = new $class_name;
$res = $install->handle($addon_name);
if ($res[ 'code' ] != 0) {
return $res;
}
return $this->success();
}
/**
* 安装插件菜单
*/
private function installMenu($addon)
{
$menu = new Menu();
$menu->refreshMenu('shop', $addon);
return $this->success();
}
/**
* 刷新插件自定义页面配置
* @param $addon
* @param $site_id
* @return array
*/
public function refreshDiyView($addon)
{
try {
if (empty($addon)) {
$diy_view_file = 'config/diy_view.php';
} else {
$diy_view_file = 'addon/' . $addon . '/config/diy_view.php';
}
if (!file_exists($diy_view_file)) {
return $this->success();
}
$link_model = new DiyViewLink();
$diy_view_model = new DiyViewModel();
$diy_template_model = new Template();
$diy_theme_model = new Theme();
// 查询原模板组列表用于更新自定义页面的所属模板id
$diy_template_goods_list_old = $diy_template_model->getTemplateGoodsList([ [ 'addon_name', '=', $addon ] ], 'goods_id,name')[ 'data' ];
// 清空数据
$link_model->deleteLink([ [ 'addon_name', '=', $addon ] ]); // 链接
$diy_view_model->deleteUtil([ [ 'addon_name', '=', $addon ] ]); // 组件
$diy_template_model->deleteTemplate([ [ 'addon_name', '=', $addon ] ]); // 页面类型
$diy_theme_model->deleteTheme([ [ 'addon_name', '=', $addon ] ]); // 主题风格
$diy_template_model->deleteTemplateGoods([ [ 'addon_name', '=', $addon ] ]); // 模板组
$diy_template_model->deleteTemplateGoodsItem([ [ 'addon_name', '=', $addon ] ]); // 模板页面
$diy_view = require $diy_view_file;
// 自定义链接
if (isset($diy_view[ 'link' ])) {
$diy_view_link_data = $link_model->getViewLinkList($diy_view[ 'link' ], $addon);
if ($diy_view_link_data) {
model('link')->addList($diy_view_link_data);
}
}
// 自定义模板组件
if (isset($diy_view[ 'util' ])) {
$diy_view_util_data = [];
foreach ($diy_view[ 'util' ] as $k => $v) {
$util_item = [
'name' => $v[ 'name' ], // 组件标识
'title' => $v[ 'title' ], // 组件名称
'type' => $v[ 'type' ], // 组件类型SYSTEM基础组件PROMOTION营销组件EXTEND扩展组件
'value' => $v[ 'value' ], // 组件数据结构json格式
'sort' => $v[ 'sort' ],
'support_diy_view' => $v[ 'support_diy_view' ] ?? '', // 支持的自定义页面(为空表示公共组件都支持)
'addon_name' => $addon,
'max_count' => $v[ 'max_count' ] ?? 0, // 限制添加次数0表示可以无限添加该组件
'is_delete' => $v[ 'is_delete' ] ?? 0, // 组件是否可以删除0 允许1 禁用
'icon' => $v[ 'icon' ] ?? '' // 组件字体图标
];
$diy_view_util_data[] = $util_item;
}
if ($diy_view_util_data) {
$diy_view_model->addUtilList($diy_view_util_data);
}
}
// 自定义模板页面类型
if (isset($diy_view[ 'template' ]) && !empty($diy_view[ 'template' ])) {
$template_data = [];
foreach ($diy_view[ 'template' ] as $k => $v) {
// 检测防重复
$count = $diy_template_model->getTemplateCount([ [ 'name', '=', $v[ 'name' ] ] ])[ 'data' ];
if ($count == 0) {
$template_data[] = [
'title' => $v[ 'title' ], // 模板名称
'name' => $v[ 'name' ], // 模板标识
'page' => $v[ 'path' ], // 页面路径
'addon_name' => $addon,
'value' => $v[ 'value' ] ?? '',
];
}
}
if (!empty($template_data)) {
$diy_template_model->addTemplateList($template_data);
}
}
// 主题风格配色
if (isset($diy_view[ 'theme' ]) && !empty($diy_view[ 'theme' ])) {
$theme_data = [];
foreach ($diy_view[ 'theme' ] as $k => $v) {
// 检测防重复
$count = $diy_theme_model->getThemeCount([ [ 'name', '=', $v[ 'name' ] ] ])[ 'data' ];
if ($count == 0) {
$theme_value = $v;
unset($theme_value[ 'title' ], $theme_value[ 'name' ], $theme_value[ 'main_color' ], $theme_value[ 'aux_color' ], $theme_value[ 'preview' ]);
$theme_data[] = [
'title' => $v[ 'title' ],
'name' => $v[ 'name' ],
'addon_name' => $addon,
'main_color' => $v[ 'main_color' ],
'aux_color' => $v[ 'aux_color' ],
'preview' => implode(',', $v[ 'preview' ]),
'color_img' => $v[ 'color_img' ],
'value' => json_encode($theme_value),
];
}
}
if (!empty($theme_data)) {
$diy_theme_model->addThemeList($theme_data);
}
}
// 模板信息
$diy_goods_id = 0;
if (isset($diy_view[ 'info' ]) && !empty($diy_view[ 'info' ])) {
$template_goods_data = [
'title' => $diy_view[ 'info' ][ 'title' ], // 模板名称
'name' => $diy_view[ 'info' ][ 'name' ], // 模板标识
'addon_name' => $addon,
'cover' => $diy_view[ 'info' ][ 'cover' ], // 模板封面图
'preview' => $diy_view[ 'info' ][ 'preview' ], // 模板预览图
'desc' => $diy_view[ 'info' ][ 'desc' ], // 模板描述
];
// 检测防重复
$count = $diy_template_model->getTemplateGoodsCount([ [ 'name', '=', $template_goods_data[ 'name' ] ] ])[ 'data' ];
if ($count == 0) {
$diy_goods_id = $diy_template_model->addTemplateGoods($template_goods_data)[ 'data' ];
}
if (!empty($diy_template_goods_list_old)) {
foreach ($diy_template_goods_list_old as $k => $v) {
// 更新自定义页面的所属模板id
// $diy_view_model->editSiteDiyView([
// 'template_id' => $diy_goods_id,
// ], [
// [ 'name', 'like', '%DIY_VIEW_RANDOM_%' ],
// [ 'template_id', '=', $v[ 'goods_id' ] ]
// ]);
// 更新店铺关联模板关系id
$diy_template_model->editSiteDiyTemplate([
'template_goods_id' => $diy_goods_id,
], [
[ 'addon_name', '=', $addon ],
[ 'name', '=', $v[ 'name' ] ],
[ 'template_goods_id', '=', $v[ 'goods_id' ] ]
]);
}
}
} else {
// 模板不存在,则清除店铺与模板之间的关系
$diy_template_model->deleteSiteDiyTemplate([ [ 'addon_name', '=', $addon ] ]); // 模板页面关联关系
}
// 自定义页面数据
if (isset($diy_view[ 'data' ]) && !empty($diy_view[ 'data' ])) {
$goods_item_id = 0;
foreach ($diy_view[ 'data' ] as $k => $v) {
$goods_item_data = [
'goods_id' => $diy_goods_id, // 模板组id
'title' => $v[ 'title' ], // 名称
'addon_name' => $addon,
'name' => $v[ 'name' ], // 所属页面(首页、分类,空为微页面)
'value' => json_encode($v[ 'value' ]), // 模板数据
'create_time' => time()
];
$item_id = $diy_template_model->addTemplateGoodsItem($goods_item_data)[ 'data' ];
// 默认装修第一个页面
if ($k == 0) {
$goods_item_id = $item_id;
}
}
$diy_template_model->editTemplateGoods([ 'goods_item_id' => $goods_item_id ], [ [ 'goods_id', '=', $diy_goods_id ] ]);
// 更新页面的所属模板id
$diy_template_goods_item_list = $diy_template_model->getTemplateGoodsItemList([ [ 'addon_name', '=', $addon ] ], 'goods_id,goods_item_id,name')[ 'data' ];
if (!empty($diy_template_goods_item_list)) {
foreach ($diy_template_goods_item_list as $k => $v) {
$diy_view_model->editSiteDiyView([
'template_id' => $v[ 'goods_id' ],
'template_item_id' => $v[ 'goods_item_id' ]
], [
[ 'name', '=', $v[ 'name' ] ],
[ 'addon_name', '=', $addon ]
]);
}
}
}
return $this->success();
} catch (\Exception $e) {
return $this->error('', $e->getMessage() . '-' . $e->getFile() . '-' . $e->getLine());
}
}
/**************************************************************插件安装结束*********************************************************/
/**************************************************************插件卸载开始*********************************************************/
public function uninstall($addon_name)
{
Db::startTrans();
try {
$addon_info = model("addon")->getInfo([ [ 'name', '=', $addon_name ] ], '*');
// 插件预卸载
$res1 = $this->preUninstall($addon_name);
if ($res1[ 'code' ] != 0) {
Db::rollback();
return $res1;
}
// 卸载菜单
$res2 = $this->uninstallMenu($addon_name);
if ($res2[ 'code' ] != 0) {
Db::rollback();
return $res2;
}
$res3 = $this->uninstallDiyView($addon_name);
if ($res3[ 'code' ] != 0) {
Db::rollback();
return $res3;
}
$delete_res = model('addon')->delete([
[ 'name', '=', $addon_name ]
]);
if ($delete_res === false) {
Db::rollback();
return $this->error();
}
//清理缓存
Cache::clear();
Db::commit();
return $this->success();
} catch (\Exception $e) {
//清理缓存
Cache::clear();
Db::rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 插件预卸载
*/
private function preUninstall($addon_name)
{
$class_name = "addon\\" . $addon_name . "\\event\\UnInstall";
$install = new $class_name;
$res = $install->handle($addon_name);
return $res;
}
/**
* 卸载插件菜单
*/
private function uninstallMenu($addon_name)
{
$res = model('menu')->delete([
[ 'addon', '=', $addon_name ]
]);
return $this->success($res);
}
/**
* 卸载自定义数据(清除:自定义链接、组件、主题风格、模板页面类型、模板组、模板组页面、店铺拥有的模板组、店铺自定义模板)
* @param $addon_name
* @return array
*/
private function uninstallDiyView($addon_name)
{
model('link')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 自定义链接
model('diy_view_util')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 自定义组件
model('diy_theme')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 主题风格
model('diy_template')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 模板页面类型
model('diy_template_goods')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 模板组
model('diy_template_goods_item')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 模板组页面
model('site_diy_template')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 店铺拥有的模板组
// model('site_diy_view')->delete([ [ 'addon_name', '=', $addon_name ] ]); // 店铺自定义模板
return $this->success();
}
/***************************************************************插件卸载结束********************************************************/
/************************************************************* 安装全部插件 start *************************************************************/
/**
* 安装全部插件
*/
public function installAllAddon()
{
$addon_list_result = $this->getUninstallAddonList();
$addon_list = $addon_list_result[ "data" ];
foreach ($addon_list as $k => $v) {
$item_result = $this->install($v[ "name" ]);
if ($item_result[ "code" ] < 0)
return $item_result;
}
return $this->success();
}
/************************************************************* 安装全部插件 end *************************************************************/
/**
* 刷新应用插件
* @return array
*/
public function cacheAddon()
{
//刷新插件信息
$addon_list = model('addon')->getList();
foreach ($addon_list as $k => $v) {
$data = require 'addon/' . $v[ 'name' ] . '/config/info.php';
if (empty($data)) {
$data = [];
}
$data[ 'create_time' ] = time();
$data[ 'icon' ] = 'addon/' . $v[ 'name' ] . '/icon.png';
model('addon')->update($data, [ 'name' => $v[ 'name' ] ]);
}
return $this->success();
}
/**
* 刷新所有插件菜单
*/
public function cacheAddonMenu()
{
$addon_list = model('addon')->getList([], 'name');
$menu_model = new Menu();
foreach ($addon_list as $k => $v) {
$addon_menu_res = $menu_model->refreshMenu('shop', $v[ 'name' ]);
}
return $this->success($addon_menu_res);
}
/**
* 刷新插件收银台权限
* @return array
*/
public function refreshAddonCashierAuth()
{
$addon_list = model('addon')->getList([], 'name');
$menu_model = new Menu();
foreach ($addon_list as $k => $v) {
$addon_menu_res = $menu_model->refreshCashierAuth($v[ 'name' ]);
}
return $this->success();
}
}