listen; } /** * 设置listen数组 * @Author bing * @DateTime 2021-03-01 10:37:27 * @copyright: Copyright (c) 2020 广东七件事集团 * @param array $listen * @return void */ public function setListen(array $listen){ $this->listen = $listen; } /** * 事件调度器 * @Author bing * @DateTime 2021-03-01 10:35:25 * @copyright: Copyright (c) 2020 广东七件事集团 * @param \yii\base\Event $event * @param [type] $data * @param [type] $listeners * @return void */ public function dispatch(BaseEvent $event, $data = null, $listeners = null){ $listeners = is_object($listeners) ? [$listeners] : (array) $listeners; $addons_listeners = $this->addonsEventBind($event->name, $event->mall_id ?? 0); asort($addons_listeners);//将插件监听数据进行排序 $listeners = array_unique( array_merge( isset($this->listen[get_class($event)]) ? $this->listen[get_class($event)] : [], $listeners, $addons_listeners ) ); foreach ($listeners as $listener) { if ($listener instanceof Closure || function_exists($listener)) { $this->on($event->name, $listener, $data); continue; } if(!class_exists($listener)) continue; if(empty($event->name)){ $reflect_class = new ReflectionClass($event); $event->name = $reflect_class->name; } $listener = Yii::createObject($listener); if (! $listener instanceof ListenerInterface) { throw new Exception(sprintf('The %s muse be implement %s.', get_class($listener), ListenerInterface::class)); } $this->on($event->name, [$listener, 'handle'], $data); } $this->trigger($event->name, $event); $this->off($event->name);//常驻内存,内存泄漏处理 } /** * 获取事件对应的插件 * @Author: lun * @DateTime: 2022/3/17 0017 17:54 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $event_name * @param $mall_id * @return array|mixed */ public function addonsEventBind($event_name, $mall_id){ // 获取该商城所有有效的插件 $mall_addons = MallAddons::getValidAddons($mall_id); if (empty($mall_addons)) return []; // 根据事件名称获取所有属于该事件的所有插件 $redis = Yii::$app->redis; $redis_key = RedisKeyEnum::suffix(RedisKeyEnum::EVENT_LISTENERS, '',true) .':'. $event_name; $event_addons = $redis->hgetall($redis_key);// 获取缓存中的事件数据 if (empty($event_addons)) $event_addons = $this->getEventsByMysql($event_name); // 处理返回的hash数组,$event_addons数组的hash返回格式['Agent','addons\Agent\common\listeners\OrderPaidListener','Boss','addons\Boss\common\listeners\OrderPaidListener'] $event_addons_arr = $event_addons_keys = $event_addons_values = []; foreach ($event_addons as $key => $value) { if ($key % 2 == 0) { $event_addons_keys[] = $value;// 获取该事件的所有key } else { $event_addons_values[] = $value;// 获取该事件的所有value } } // 组合为简直相对的数组 foreach ($event_addons_values as $key => $value) { $event_addons_arr[$event_addons_keys[$key]] = $value; } $intersect = array_intersect($mall_addons, $event_addons_keys);// 获取应用名称交集 $listener = ''; foreach($event_addons_arr as $addons_name => $listener_str) { // 将商城所有属于此事件名称的方法进行字符串组合 if (in_array($addons_name, $intersect)) $listener .= $listener_str . ','; } if (empty($listener)) return []; // 移除右边逗号,再组合成数组返回 return explode(',', rtrim($listener, ',')); } /** * 从数据库中读取事件对应的listeners * @param $event_name * @return array */ public function getEventsByMysql($event_name) { // 事件为空时,则直接读取数据库 $event_list = AddonsEvent::find()->select('addons_name,event_name,listeners')->where(['event_name' => $event_name, 'status' => StatusEnum::ENABLED])->asArray()->all(); $event_addons = []; foreach ($event_list as $item) { $event_addons[] = $item['addons_name']; $event_addons[] = implode(',', json_decode($item['listeners'], true)); } return $event_addons; } /** * 创建链接菜单 * @Author: lun * @DateTime: 2021/10/14 0014 14:16 * @Copyright: copyright (c) 2021 广东七件事集团 * @param string $addons_name * @throws \yii\db\Exception */ public function create(string $addons_name, array $eventsMenu) { try { // 重组数组 foreach ($eventsMenu as $key => $menu) { $allMenu[$key] = ArrayHelper::regroupMapToArr($menu); } $time = time(); $event_addons = []; foreach ($allMenu as $key => $item) { foreach ($item as $k => $value) { // 根据事件名保存为数组 $event_addons[$value['event_name']] = implode(',', $value['listeners']); $listeners = Json::encode($value['listeners']); $event = AddonsEvent::findOne(['addons_name' => $addons_name, 'event_name' => $value['event_name'], 'status' => StatusEnum::ENABLED]); if ($event) { if (Json::encode($event['listeners']) != $listeners) { $event->listeners = $value['listeners']; $event->save(); } } else { $row = []; $row['addons_name'] = $addons_name; $row['event_name'] = $value['event_name'] ?? []; $row['listeners'] = $listeners; $row['created_at'] = $time; $row['updated_at'] = $time; $rows[] = $row; } } } if (!empty($rows)) { $field = ['addons_name', 'event_name', 'listeners', 'created_at', 'updated_at']; // 批量插入数据 $res = Yii::$app->db->createCommand()->batchInsert(AddonsEvent::tableName(), $field, $rows)->execute(); if (!$res) throw new \yii\base\Exception("事件创建失败"); } // 获取所有事件再进行组合 $list = AddonsEvent::find()->where(['status' => StatusEnum::ENABLED])->asArray()->all(); $addons_event = []; foreach ($list as $item) { $addons_event[$item['event_name']][$item['addons_name']] = implode(',', Json::decode($item['listeners'], true)); } // 将组合后的事件入存入redis中 $redis = Yii::$app->redis; foreach ($addons_event as $event_name => $item) { $redis_key = RedisKeyEnum::suffix(RedisKeyEnum::EVENT_LISTENERS, '',true) .':'. $event_name; // 删除对应事件名称hash $redis->del($redis_key); foreach ($item as $name => $value) { $redis->hset($redis_key, $name, $value);// 存入hash } } return true; } catch (Exception $e) { $this->setError($e->getMessage()); return false; } } /** * 商城安装插件绑定事件 * @Author: lun * @DateTime: 2022/1/15 0015 19:07 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $addons_name * @param $mall_id * @return array|mixed */ public function mallEventBind($addons_name, $mall_id){ $cache = Yii::$app->cache; // 缓存无数据则对表进行查询 $cond[] = ['addons_name' => $addons_name, 'status' => StatusEnum::ENABLED]; $event_list = AddonsEvent::getAddonsEvent($cond,[],true,'listeners,event_name'); if ($event_list) { // 循环组合对应事件的监听地址 foreach ($event_list as $listeners) { $cache_key = RedisKeyEnum::suffix(RedisKeyEnum::EVENT, $listeners['event_name'],true); $cache_key .= $mall_id; $listenerArr = Json::decode($listeners['listeners'], true); $event = []; foreach ($listenerArr as $listener) { $event[] = $listener; } if ($event) { $cache_data = $cache->get($cache_key); if ($cache_data) { $event = array_unique(array_merge($cache_data, $event)); } $cache->set($cache_key, $event);// 保存至缓存 } } } } /** * 所有商城重新对应应用的事件绑定 * @Author: lun * @DateTime: 2022/3/8 0008 17:44 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $addons_name * @return bool */ public function allMallEventBind($addons_name) { try { // 获取已购买了该应用的商城 $list = MallAddons::getMallAddons([['addons_name' => $addons_name]], [],true, 'mall_id'); foreach ($list as $item) { $this->mallEventBind($addons_name, $item['mall_id']); } return true; } catch (Exception $e) { $this->setError($e->getMessage()); return false; } } }