PluginLogic.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2013-present http://www.thinkcmf.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 老猫 <thinkcmf@126.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\admin\logic;
  12. use app\admin\model\AdminMenuModel;
  13. use app\admin\model\AuthRuleModel;
  14. use app\admin\model\HookPluginModel;
  15. use app\admin\model\PluginModel;
  16. use mindplay\annotations\Annotations;
  17. use think\facade\Cache;
  18. class PluginLogic
  19. {
  20. /**
  21. * 安装插件
  22. */
  23. public static function install($pluginName)
  24. {
  25. $class = cmf_get_plugin_class($pluginName);
  26. if (!class_exists($class)) {
  27. return '插件不存在!';
  28. }
  29. $pluginModel = new PluginModel();
  30. $pluginCount = $pluginModel->where('name', $pluginName)->count();
  31. if ($pluginCount > 0) {
  32. return '插件已安装!';
  33. }
  34. $plugin = new $class;
  35. $info = $plugin->info;
  36. if (!$info || !$plugin->checkInfo()) {//检测信息的正确性
  37. return '插件信息缺失!';
  38. }
  39. $installSuccess = $plugin->install();
  40. if (!$installSuccess) {
  41. return '插件预安装失败!';
  42. }
  43. $methods = get_class_methods($plugin);
  44. foreach ($methods as $methodKey => $method) {
  45. $methods[$methodKey] = cmf_parse_name($method);
  46. }
  47. $systemHooks = $pluginModel->getHooks(true);
  48. $pluginHooks = array_intersect($systemHooks, $methods);
  49. //$info['hooks'] = implode(",", $pluginHooks);
  50. if (!empty($plugin->hasAdmin)) {
  51. $info['has_admin'] = 1;
  52. } else {
  53. $info['has_admin'] = 0;
  54. }
  55. $info['config'] = json_encode($plugin->getConfig());
  56. $pluginModel->save($info);
  57. foreach ($pluginHooks as $pluginHook) {
  58. $hookPluginModel = new HookPluginModel();
  59. $hookPluginModel->save(['hook' => $pluginHook, 'plugin' => $pluginName, 'status' => 1]);
  60. }
  61. self::getActions($pluginName);
  62. Cache::clear('init_hook_plugins');
  63. Cache::clear('admin_menus');// 删除后台菜单缓存
  64. return true;
  65. }
  66. public static function update($pluginName)
  67. {
  68. $class = cmf_get_plugin_class($pluginName);
  69. if (!class_exists($class)) {
  70. return '插件不存在!';
  71. }
  72. $plugin = new $class;
  73. $info = $plugin->info;
  74. if (!$info || !$plugin->checkInfo()) {//检测信息的正确性
  75. return '插件信息缺失!';
  76. }
  77. if (method_exists($plugin, 'update')) {
  78. $updateSuccess = $plugin->update();
  79. if (!$updateSuccess) {
  80. return '插件预升级失败!';
  81. }
  82. }
  83. $methods = get_class_methods($plugin);
  84. foreach ($methods as $methodKey => $method) {
  85. $methods[$methodKey] = cmf_parse_name($method);
  86. }
  87. $pluginModel = new PluginModel();
  88. $systemHooks = $pluginModel->getHooks(true);
  89. $pluginHooks = array_intersect($systemHooks, $methods);
  90. if (!empty($plugin->hasAdmin)) {
  91. $info['has_admin'] = 1;
  92. } else {
  93. $info['has_admin'] = 0;
  94. }
  95. $config = $plugin->getConfig();
  96. $defaultConfig = $plugin->getDefaultConfig();
  97. $pluginModel = new PluginModel();
  98. $config = array_merge($defaultConfig, $config);
  99. $info['config'] = json_encode($config);
  100. $pluginModel->where('name', $pluginName)->update($info);
  101. $hookPluginModel = new HookPluginModel();
  102. $pluginHooksInDb = $hookPluginModel->where('plugin', $pluginName)->column('hook');
  103. $samePluginHooks = array_intersect($pluginHooks, $pluginHooksInDb);
  104. $shouldDeleteHooks = array_diff($pluginHooksInDb,$pluginHooks);
  105. $newHooks = array_diff($pluginHooks, $samePluginHooks);
  106. if (count($shouldDeleteHooks) > 0) {
  107. $hookPluginModel->where('plugin', $pluginName)->where('hook', 'in', $shouldDeleteHooks)->delete();
  108. }
  109. foreach ($newHooks as $pluginHook) {
  110. $hookPluginModel->save(['hook' => $pluginHook, 'plugin' => $pluginName]);
  111. }
  112. self::getActions($pluginName);
  113. Cache::clear('init_hook_plugins');
  114. Cache::clear('admin_menus');// 删除后台菜单缓存
  115. return true;
  116. }
  117. public static function getActions($pluginName)
  118. {
  119. Annotations::$config['cache'] = false;
  120. $annotationManager = Annotations::getManager();
  121. $annotationManager->registry['adminMenu'] = 'app\admin\annotation\AdminMenuAnnotation';
  122. $annotationManager->registry['adminMenuRoot'] = 'app\admin\annotation\AdminMenuRootAnnotation';
  123. $newMenus = [];
  124. $pluginDir = cmf_parse_name($pluginName);
  125. $filePatten = WEB_ROOT . 'plugins/' . $pluginDir . '/controller/Admin*Controller.php';
  126. $controllers = cmf_scan_dir($filePatten);
  127. $app = 'plugin/' . $pluginName;
  128. if (!empty($controllers)) {
  129. foreach ($controllers as $controller) {
  130. $controller = preg_replace('/\.php$/', '', $controller);
  131. $controllerName = preg_replace("/Controller$/", '', $controller);
  132. $controllerClass = "plugins\\$pluginDir\\controller\\$controller";
  133. $menuAnnotations = Annotations::ofClass($controllerClass, '@adminMenuRoot');
  134. if (!empty($menuAnnotations)) {
  135. foreach ($menuAnnotations as $menuAnnotation) {
  136. $name = $menuAnnotation->name;
  137. $icon = $menuAnnotation->icon;
  138. $type = 0;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单
  139. $action = $menuAnnotation->action;
  140. $status = empty($menuAnnotation->display) ? 0 : 1;
  141. $listOrder = floatval($menuAnnotation->order);
  142. $param = $menuAnnotation->param;
  143. $remark = $menuAnnotation->remark;
  144. if (empty($menuAnnotation->parent)) {
  145. $parentId = 0;
  146. } else {
  147. $parent = explode('/', $menuAnnotation->parent);
  148. $countParent = count($parent);
  149. if ($countParent > 3) {
  150. throw new \Exception($controllerClass . ':' . $action . ' @adminMenuRoot parent格式不正确!');
  151. }
  152. $parentApp = $app;
  153. $parentController = $controllerName;
  154. $parentAction = '';
  155. switch ($countParent) {
  156. case 1:
  157. $parentAction = $parent[0];
  158. break;
  159. case 2:
  160. $parentController = $parent[0];
  161. $parentAction = $parent[1];
  162. break;
  163. case 3:
  164. $parentApp = $parent[0];
  165. $parentController = $parent[1];
  166. $parentAction = $parent[2];
  167. break;
  168. }
  169. $findParentAdminMenu = AdminMenuModel::where([
  170. 'app' => $parentApp,
  171. 'controller' => $parentController,
  172. 'action' => $parentAction
  173. ])->find();
  174. if (empty($findParentAdminMenu)) {
  175. $parentId = AdminMenuModel::insertGetId([
  176. 'app' => $parentApp,
  177. 'controller' => $parentController,
  178. 'action' => $parentAction,
  179. 'name' => '--new--'
  180. ]);
  181. } else {
  182. $parentId = $findParentAdminMenu['id'];
  183. }
  184. }
  185. $findAdminMenu = AdminMenuModel::where([
  186. 'app' => $app,
  187. 'controller' => $controllerName,
  188. 'action' => $action
  189. ])->find();
  190. if (empty($findAdminMenu)) {
  191. AdminMenuModel::insert([
  192. 'parent_id' => $parentId,
  193. 'type' => $type,
  194. 'status' => $status,
  195. 'list_order' => $listOrder,
  196. 'app' => $app,
  197. 'controller' => $controllerName,
  198. 'action' => $action,
  199. 'param' => $param,
  200. 'name' => $name,
  201. 'icon' => $icon,
  202. 'remark' => $remark
  203. ]);
  204. $menuName = $name;
  205. // array_push($newMenus, $app . "/$controllerName/$action 已导入");
  206. } else {
  207. if ($findAdminMenu['name'] == '--new--') {
  208. AdminMenuModel::where([
  209. 'app' => $app,
  210. 'controller' => $controllerName,
  211. 'action' => $action
  212. ])->update([
  213. 'parent_id' => $parentId,
  214. 'type' => $type,
  215. 'status' => $status,
  216. 'list_order' => $listOrder,
  217. 'param' => $param,
  218. 'name' => $name,
  219. 'icon' => $icon,
  220. 'remark' => $remark
  221. ]);
  222. $menuName = $name;
  223. } else {
  224. // 只关注菜单层级关系,是否有视图
  225. AdminMenuModel::where([
  226. 'app' => $app,
  227. 'controller' => $controllerName,
  228. 'action' => $action
  229. ])->update([
  230. //'parent_id' => $parentId,
  231. 'type' => $type,
  232. ]);
  233. $menuName = $findAdminMenu['name'];
  234. }
  235. // array_push($newMenus, $app."/$controllerName/$action 层级关系已更新");
  236. }
  237. $authRuleName = "plugin/{$pluginName}/{$controllerName}/{$action}";
  238. $findAuthRuleCount = AuthRuleModel::where([
  239. 'app' => $app,
  240. 'name' => $authRuleName,
  241. 'type' => 'admin_url'
  242. ])->count();
  243. if ($findAuthRuleCount == 0) {
  244. AuthRuleModel::insert([
  245. 'app' => $app,
  246. 'name' => $authRuleName,
  247. 'type' => 'admin_url',
  248. 'param' => $param,
  249. 'title' => $menuName
  250. ]);
  251. } else {
  252. AuthRuleModel::where([
  253. 'app' => $app,
  254. 'name' => $authRuleName,
  255. 'type' => 'admin_url',
  256. ])->update([
  257. 'param' => $param,
  258. 'title' => $menuName
  259. ]);
  260. }
  261. }
  262. }
  263. $reflect = new \ReflectionClass($controllerClass);
  264. $methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC);
  265. if (!empty($methods)) {
  266. foreach ($methods as $method) {
  267. if ($method->class == $controllerClass && strpos($method->name, '_') !== 0) {
  268. $menuAnnotations = Annotations::ofMethod($controllerClass, $method->name, '@adminMenu');
  269. if (!empty($menuAnnotations)) {
  270. $menuAnnotation = $menuAnnotations[0];
  271. $name = $menuAnnotation->name;
  272. $icon = $menuAnnotation->icon;
  273. $type = $menuAnnotation->hasView ? 1 : 2;//1:有界面可访问菜单,2:无界面可访问菜单,0:只作为菜单
  274. $action = $method->name;
  275. $status = empty($menuAnnotation->display) ? 0 : 1;
  276. $listOrder = floatval($menuAnnotation->order);
  277. $param = $menuAnnotation->param;
  278. $remark = $menuAnnotation->remark;
  279. if (empty($menuAnnotation->parent)) {
  280. $parentId = 0;
  281. } else {
  282. $parent = explode('/', $menuAnnotation->parent);
  283. $countParent = count($parent);
  284. if ($countParent > 3) {
  285. throw new \Exception($controllerClass . ':' . $action . ' @menuRoot parent格式不正确!');
  286. }
  287. $parentApp = $app;
  288. $parentController = $controllerName;
  289. $parentAction = '';
  290. switch ($countParent) {
  291. case 1:
  292. $parentAction = $parent[0];
  293. break;
  294. case 2:
  295. $parentController = $parent[0];
  296. $parentAction = $parent[1];
  297. break;
  298. case 3:
  299. $parentApp = $parent[0];
  300. $parentController = $parent[1];
  301. $parentAction = $parent[2];
  302. break;
  303. }
  304. $findParentAdminMenu = AdminMenuModel::where([
  305. 'app' => $parentApp,
  306. 'controller' => $parentController,
  307. 'action' => $parentAction
  308. ])->find();
  309. if (empty($findParentAdminMenu)) {
  310. $parentId = AdminMenuModel::insertGetId([
  311. 'app' => $parentApp,
  312. 'controller' => $parentController,
  313. 'action' => $parentAction,
  314. 'name' => '--new--'
  315. ]);
  316. } else {
  317. $parentId = $findParentAdminMenu['id'];
  318. }
  319. }
  320. $findAdminMenu = AdminMenuModel::where([
  321. 'app' => $app,
  322. 'controller' => $controllerName,
  323. 'action' => $action
  324. ])->find();
  325. if (empty($findAdminMenu)) {
  326. AdminMenuModel::insert([
  327. 'parent_id' => $parentId,
  328. 'type' => $type,
  329. 'status' => $status,
  330. 'list_order' => $listOrder,
  331. 'app' => $app,
  332. 'controller' => $controllerName,
  333. 'action' => $action,
  334. 'param' => $param,
  335. 'name' => $name,
  336. 'icon' => $icon,
  337. 'remark' => $remark
  338. ]);
  339. $menuName = $name;
  340. //array_push($newMenus, "$app/$controllerName/$action 已导入");
  341. } else {
  342. if ($findAdminMenu['name'] == '--new--') {
  343. AdminMenuModel::where([
  344. 'app' => $app,
  345. 'controller' => $controllerName,
  346. 'action' => $action
  347. ])->update([
  348. 'parent_id' => $parentId,
  349. 'type' => $type,
  350. 'status' => $status,
  351. 'list_order' => $listOrder,
  352. 'param' => $param,
  353. 'name' => $name,
  354. 'icon' => $icon,
  355. 'remark' => $remark
  356. ]);
  357. $menuName = $name;
  358. } else {
  359. // 只关注是否有视图
  360. AdminMenuModel::where([
  361. 'app' => $app,
  362. 'controller' => $controllerName,
  363. 'action' => $action
  364. ])->update([
  365. //'parent_id' => $parentId,
  366. 'type' => $type,
  367. ]);
  368. $menuName = $findAdminMenu['name'];
  369. }
  370. // array_push($newMenus, "$app/$controllerName/$action 已更新");
  371. }
  372. $authRuleName = "plugin/{$pluginName}/{$controllerName}/{$action}";
  373. $findAuthRuleCount = AuthRuleModel::where([
  374. 'app' => $app,
  375. 'name' => $authRuleName,
  376. 'type' => 'plugin_url'
  377. ])->count();
  378. if ($findAuthRuleCount == 0) {
  379. AuthRuleModel::insert([
  380. 'app' => $app,
  381. 'name' => $authRuleName,
  382. 'type' => 'plugin_url',
  383. 'param' => $param,
  384. 'title' => $menuName
  385. ]);
  386. } else {
  387. AuthRuleModel::where([
  388. 'app' => $app,
  389. 'name' => $authRuleName,
  390. 'type' => 'plugin_url',
  391. ])->update([
  392. 'param' => $param,
  393. 'title' => $menuName
  394. ]);
  395. }
  396. }
  397. }
  398. }
  399. }
  400. }
  401. }
  402. }
  403. }