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'] ?? '', 'rule' => isset($v['rule']) ? json_encode($v['rule']) : '', 'sort' => $v['sort'] ?? 0 ]; } } 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(); } /** * 刷新所有插件菜单 * @param bool $is_truncate_table * @return array */ public function cacheAddonMenu($is_truncate_table = false) { $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']); // 刷新收银端权限 $menu_model->refreshCashierAuth($v['name'], $is_truncate_table); } return $this->success($addon_menu_res); } /** * 刷新插件收银台权限 * @param bool $is_truncate_table * @return array */ public function refreshAddonCashierAuth($is_truncate_table = false) { $addon_list = model('addon')->getList([], 'name'); $menu_model = new Menu(); foreach ($addon_list as $k => $v) { $addon_menu_res = $menu_model->refreshCashierAuth($v['name'], $is_truncate_table); } return $this->success(); } /** * 获取插件快捷菜单配置 * @param $site_id * @param string $app_module * @return array */ public function getAddonQuickMenuConfig($site_id, $app_module = 'shop') { $config = new ConfigModel(); $res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'COMMON_ADDON']]); if (!empty($res['data']['value'])) { $res['data']['value']['promotion'] = explode(',', $res['data']['value']['promotion'] ?? ''); $res['data']['value']['tool'] = explode(',', $res['data']['value']['tool'] ?? ''); foreach ($res['data']['value']['promotion'] as $k => $v) { if (empty($v)) { unset($res['data']['value']['promotion'][$k]); } elseif (!empty($v) && addon_is_exit($v) == 0) { unset($res['data']['value']['promotion'][$k]); } } $res['data']['value']['promotion'] = array_values($res['data']['value']['promotion']); foreach ($res['data']['value']['tool'] as $k => $v) { if (empty($v)) { unset($res['data']['value']['tool'][$k]); } elseif (!empty($v) && addon_is_exit($v) == 0) { unset($res['data']['value']['tool'][$k]); } } $res['data']['value']['tool'] = array_values($res['data']['value']['tool']); } else { $res['data']['value'] = [ 'promotion' => [], 'tool' => [] ]; } return $res; } /** * 设置插件快捷菜单配置 * @param $data * @return array */ public function setAddonQuickMenuConfig($data) { $condition = [ ['site_id', '=', $data['site_id']], ['app_module', '=', $data['app_module']], ['config_key', '=', 'COMMON_ADDON'] ]; $config = new ConfigModel(); $value = $config->getConfig($condition)['data']['value']; $addon_array = empty($value) ? [] : explode(',', $value[$data['type']] ?? ''); if (in_array($data['addon'], $addon_array)) { $addon_array = array_diff($addon_array, [$data['addon']]); } else { array_push($addon_array, $data['addon']); } $value[$data['type']] = implode(',', $addon_array); return $config->setConfig($value, '常用功能设置', 1, $condition); } }