select(['title', 'name', 'group']) ->with('bindingMenu') ->asArray() ->all(); $isSuperAdmin = Yii::$app->services->auth->isSuperAdmin(); foreach ($models as $k => &$model) { $model['menuUrl'] = ''; foreach ($model['bindingMenu'] as $bindingMenu) { if (isset($bindingMenu['route']) && empty($model['menuUrl'])) { $params = isset($bindingMenu['params']) ? Json::decode($bindingMenu['params']) : []; $model['menuUrl'] = Url::to(ArrayHelper::merge([$bindingMenu['route']], $params)); if (!$isSuperAdmin && !Auth::verify($bindingMenu['route'])) { $model['menuUrl'] = ''; } } } if (empty($model['menuUrl'])) { unset($models[$k]); } else { $model['menuUrl'] = urldecode($model['menuUrl']); } } // 创建分类数组 $groups = array_keys(Yii::$app->params['addonsGroup']); $addons = []; foreach ($groups as $group) { !isset($addons[$group]) && $addons[$group] = []; } // 模块分类插入 foreach ($models as $record) { $addons[$record['group']][] = $record; } // 删除空模块分类 foreach ($addons as $key => $vlaue) { if (empty($vlaue)) { unset($addons[$key]); } } return $addons; } /** * 获取配置文件 * * @param $name * @return bool|string */ public function getConfigClass($name) { $class = AddonHelper::getAddonConfig($name); if (!class_exists($class)) { return false; } return $class; } /** * 获取本地插件列表 * * @return array */ public function getLocalList() { $addonDir = Yii::getAlias('@addons'); // 获取插件列表 $dirs = array_map('basename', glob($addonDir . '/*')); $list = Addons::find() ->where(['in', 'name', $dirs]) ->asArray() ->all(); $tmpAddons = []; foreach ($list as $addon) { $tmpAddons[$addon['name']] = $addon; } $addons = []; foreach ($dirs as $value) { // 判断是否安装 if (!isset($tmpAddons[$value])) { $class = AddonHelper::getAddonConfig($value); // 实例化插件失败忽略执行 if (class_exists($class)) { $config = new $class; $addons[$value] = $config->info; $addons[$value]['group'] = $config->group; } } } return $addons; } /** * 更新配置 * * @param $name * @param BaseAddonConfig $config * @param $default_config * @return array|Addons|\yii\db\ActiveRecord|null * @throws NotFoundHttpException */ public function update($name, $config, $default_config) { if (!($model = $this->findByName($name))) { $model = new Addons(); } if (!empty($model->title)) $config->info['title'] = $model->title; $model->attributes = $config->info; $model->is_setting = $config->isSetting ? StatusEnum::ENABLED : StatusEnum::DISABLED; $model->is_rule = $config->isRule ? StatusEnum::ENABLED : StatusEnum::DISABLED; $model->is_merchant_route_map = $config->isMerchantRouteMap ? StatusEnum::ENABLED : StatusEnum::DISABLED; $model->group = $config->group; $model->bootstrap = $config->bootstrap ?? ''; $model->service = $config->service ?? ''; $model->default_config = $default_config; $model->console = $config->console ?? []; $model->wechat_message = $config->wechatMessage; $model->updated_at = time(); // 首先字母转大写拼音 if (($chinese = StringHelper::strToChineseCharacters($model->title)) && !empty($chinese[0])) { $title_initial = mb_substr($chinese[0][0], 0, 1, 'utf-8'); // $model->title_initial = ucwords((new Pinyin())->abbr($title_initial)); } if (!$model->save()) { throw new NotFoundHttpException($model->getErrorMessage()); } // 更新缓存 Yii::$app->services->addons->updateCacheByName($name); return $model; } /** * 获取列表 * * @return array|\yii\db\ActiveRecord[] */ public function getList() { return Addons::find() ->where(['status' => StatusEnum::ENABLED]) ->asArray() ->all(); } /** * @param $name * @return array|null|\yii\db\ActiveRecord */ public function findByName($name) { return Addons::find() ->where(['name' => $name, 'status' => StatusEnum::ENABLED]) ->one(); } /** * @param array $names * @return array|\yii\db\ActiveRecord[] */ public function findByNames(array $names) { return Addons::find() ->select(['id', 'name', 'title']) ->where(['status' => StatusEnum::ENABLED]) ->andWhere(['in', 'name', $names]) ->all(); } /** * @param $name * @return array|null|\yii\db\ActiveRecord */ public function findByNameWithBinding($name, $noCache = false) { $cacheKey = 'addonsConfig'. ':' . Yii::$app->id . ':' . $name; if (!$noCache && Yii::$app->cache->exists($cacheKey)) { return Yii::$app->cache->get($cacheKey); } $data = Addons::find() ->where(['name' => $name, 'status' => StatusEnum::ENABLED]) ->with([ 'bindingMenu' => function (ActiveQuery $query) { return $query->andWhere(['app_id' => Yii::$app->id]); }, 'bindingCover' ]) ->one(); // 控制台避免写入缓存权限为 644 导致 www 用户组失败 if (Yii::$app->id != AppEnum::CONSOLE && false == Yii::$app->cache->exists($cacheKey) ) { Yii::$app->cache->set($cacheKey, $data, 7200); } return $data; } /** * 获取插件名称列表 * * @param bool $noCache * @return array|mixed|\yii\db\ActiveRecord[] */ public function findAllNames($noCache = false) { if (Yii::$app->id == AppEnum::CONSOLE) { return $this->findAllInitData(); } $cacheKey = RedisKeyEnum::suffix('addonsName'); if (!$noCache && Yii::$app->cache->exists($cacheKey)) { return Yii::$app->cache->get($cacheKey); } $models = $this->findAllInitData(); Yii::$app->cache->set($cacheKey, $models, 7200); return $models; } /** * @return array|\yii\db\ActiveRecord[] */ public function findAllInitData() { return Addons::find() ->select(['name', 'is_merchant_route_map', 'service', 'updated_at']) ->where(['status' => StatusEnum::ENABLED]) ->asArray() ->all(); } /** * 触发更新缓存 * * @param $name */ public function updateCacheByName($name) { $this->findAllNames(true); $this->findByNameWithBinding($name, true); } /** * 创建公共调用 */ public function createInvoker(string $addons_name, array $invokers) { if (empty($invokers)) return; $time = time(); $rows = []; $new_element_arr = []; foreach ($invokers as $key => $item) { foreach ($item as $k => $value) { $invoker_model = AddonsInvoker::findOne(['invoker_id'=>$value['invoker_id'],'addons_name' => $addons_name,'class'=>$value['class']]); if(!empty($invoker_model)){ if($invoker_model['class']!=$value['class']||$invoker_model['method']!=$value['method']){ $invoker_model->class = $value['class']; $invoker_model->method = $value['method']; $res = $invoker_model->save(); if($res==false) throw new Exception('更新invoker失败'); } }else{ $row = []; $row['addons_name'] = $addons_name; $row['invoker_id'] = $value['invoker_id']; $row['class'] = $value['class'] ; $row['method'] = $value['method']; $row['status'] = StatusEnum::ENABLED; $row['created_at'] = $time; $row['updated_at'] = $time; $rows[] = $row; } $new_element_arr[$value['invoker_id']][]=['class'=>$value['class'],'method'=>$value['method'],'addons_name'=>$addons_name]; } } $field = ['addons_name', 'invoker_id', 'class', 'method', 'status', 'created_at', 'updated_at']; // 批量插入数据 if(!empty($rows)){ $res = Yii::$app->db->createCommand()->batchInsert(AddonsInvoker::tableName(), $field, $rows)->execute(); if($res==false) throw new Exception('插入invoker失败'); } $redis = Yii::$app->redis; if(!empty($new_element_arr)){ foreach ($new_element_arr as $invoker_id => $new_elements){ $redis_key = RedisKeyEnum::suffix(RedisKeyEnum::GLOBAL_INVOKE, '',true) .':'. $invoker_id; $invokes = $redis->smembers($redis_key); $cache_arr = []; foreach ($invokes as $k=>$v){ $temp_v = json_decode($v,true); $cache_arr[$temp_v['addons_name']] = $temp_v; } foreach ($new_elements as $new_element) { $cache_arr[$new_element['addons_name']] = $new_element; } $redis->del($redis_key); foreach ($cache_arr as $new_element) { $redis->sadd($redis_key, json_encode($new_element)); } } } } }