AddonController.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <?php
  2. namespace Admin\Controller;
  3. use Think\Page;
  4. use Util\Sql;
  5. /**
  6. * 扩展后台管理页面
  7. * 该类参考了OneThink的部分实现
  8. *
  9. */
  10. class AddonController extends AdminController
  11. {
  12. /**
  13. * 插件列表
  14. *
  15. */
  16. public function index()
  17. {
  18. // 获取所有插件信息
  19. $p = !empty($_GET["p"]) ? $_GET['p'] : 1;
  20. $addon_object = D('Addon');
  21. $addons = $addon_object
  22. ->getAllAddon();
  23. // 使用Builder快速建立列表页面。
  24. $builder = new \Common\Builder\ListBuilder();
  25. $builder->setMetaTitle('插件列表') // 设置页面标题
  26. ->addTopButton('resume') // 添加启用按钮
  27. ->addTopButton('forbid') // 添加禁用按钮
  28. ->addTableColumn('name', '标识')
  29. ->addTableColumn('title', '名称')
  30. ->addTableColumn('description', '描述')
  31. ->addTableColumn('status', '状态')
  32. ->addTableColumn('author', '作者')
  33. ->addTableColumn('version', '版本')
  34. ->addTableColumn('right_button', '操作', 'btn')
  35. ->setTableDataList($addons) // 数据列表
  36. ->display();
  37. }
  38. /**
  39. * 设置插件页面
  40. *
  41. */
  42. public function config()
  43. {
  44. if (IS_POST) {
  45. $id = (int) I('id');
  46. $config = I('config');
  47. $flag = D('Addon')
  48. ->where("id={$id}")
  49. ->setField('config', json_encode($config));
  50. if ($flag !== false) {
  51. $this->success('保存成功', U('index'));
  52. } else {
  53. $this->error('保存失败');
  54. }
  55. } else {
  56. $id = (int) I('id');
  57. $addon = D('Addon')->find($id);
  58. if (!$addon) {
  59. $this->error('插件未安装');
  60. }
  61. $addon_class = get_addon_class($addon['name']);
  62. if (!class_exists($addon_class)) {
  63. trace("插件{$addon['name']}无法实例化,", 'ADDONS', 'ERR');
  64. }
  65. $data = new $addon_class;
  66. $addon['addon_path'] = $data->addon_path;
  67. $addon['custom_config'] = $data->custom_config;
  68. $this->meta_title = '设置插件-' . $data->info['title'];
  69. $db_config = $addon['config'];
  70. $addon['config'] = include $data->config_file;
  71. if ($db_config) {
  72. $db_config = json_decode($db_config, true);
  73. foreach ($addon['config'] as $key => $value) {
  74. if ($value['type'] != 'group') {
  75. $addon['config'][$key]['value'] = $db_config[$key];
  76. } else {
  77. foreach ($value['options'] as $gourp => $options) {
  78. foreach ($options['options'] as $gkey => $value) {
  79. $addon['config'][$key]['options'][$gourp]['options'][$gkey]['value'] = $db_config[$gkey];
  80. }
  81. }
  82. }
  83. }
  84. }
  85. // 构造表单名
  86. foreach ($addon['config'] as $key => $val) {
  87. if ($val['type'] == 'group') {
  88. foreach ($val['options'] as $key2 => $val2) {
  89. foreach ($val2['options'] as $key3 => $val3) {
  90. $addon['config'][$key]['options'][$key2]['options'][$key3]['name'] = 'config[' . $key3 . ']';
  91. }
  92. }
  93. } else {
  94. $addon['config'][$key]['name'] = 'config[' . $key . ']';
  95. }
  96. }
  97. $this->assign('data', $addon);
  98. $this->assign('form_items', $addon['config']);
  99. if ($addon['custom_config']) {
  100. $this->assign('custom_config', $this->fetch($addon['addon_path'] . $addon['custom_config']));
  101. $this->display($addon['addon_path'] . $addon['custom_config']);
  102. } else {
  103. //使用FormBuilder快速建立表单页面。
  104. $builder = new \Common\Builder\FormBuilder();
  105. $builder->setMetaTitle('插件设置') //设置页面标题
  106. ->setPostUrl(U('config')) //设置表单提交地址
  107. ->addFormItem('id', 'hidden', 'ID', 'ID')
  108. ->setExtraItems($addon['config']) //直接设置表单数据
  109. ->setFormData($addon)
  110. ->display();
  111. }
  112. }
  113. }
  114. /**
  115. * 安装插件
  116. *
  117. */
  118. public function install()
  119. {
  120. $addon_name = trim(I('addon_name'));
  121. $class = get_addon_class($addon_name);
  122. if (!class_exists($class)) {
  123. $this->error('插件不存在');
  124. }
  125. $addons = new $class;
  126. $info = $addons->info;
  127. $hooks = $addons->hooks;
  128. // 检测信息的正确性
  129. if (!$info || !$addons->checkInfo()) {
  130. $this->error('插件信息缺失');
  131. }
  132. session('addons_install_error', null);
  133. $install_flag = $addons->install();
  134. if (!$install_flag) {
  135. $this->error('执行插件预安装操作失败' . session('addons_install_error'));
  136. }
  137. // 检查该插件所需的钩子
  138. if ($hooks) {
  139. $hook_object = D('Hook');
  140. foreach ($hooks as $val) {
  141. $hook_object->existHook($val, array('description' => $info['description']));
  142. }
  143. }
  144. // 安装数据库
  145. $sql_file = realpath(C('ADDON_PATH') . $addon_name) . '/Sql/install.sql';
  146. if (file_exists($sql_file)) {
  147. $sql_object = new Sql();
  148. $sql_status = $sql_object->execute_sql_from_file($sql_file);
  149. if (!$sql_status) {
  150. $this->error('执行插件SQL安装语句失败' . session('addons_install_error'));
  151. }
  152. }
  153. $addon_object = D('Addon');
  154. $data = $addon_object->create($info);
  155. if (is_array($addons->admin_list) && $addons->admin_list !== array()) {
  156. $data['adminlist'] = 1;
  157. } else {
  158. $data['adminlist'] = 0;
  159. }
  160. if (!$data) {
  161. $this->error($addon_object->getError());
  162. }
  163. if ($addon_object->add($data)) {
  164. $config = array('config' => json_encode($addons->getConfig()));
  165. $addon_object->where("name='{$addon_name}'")->save($config);
  166. $hooks_update = D('Hook')->updateHooks($addon_name);
  167. if ($hooks_update) {
  168. S('hooks', null);
  169. $this->success('安装成功');
  170. } else {
  171. $addon_object->where("name='{$addon_name}'")->delete();
  172. $this->error('更新钩子处插件失败,请卸载后尝试重新安装');
  173. }
  174. } else {
  175. $this->error('写入插件数据失败');
  176. }
  177. }
  178. /**
  179. * 卸载插件
  180. *
  181. */
  182. public function uninstall()
  183. {
  184. $addon_object = D('Addon');
  185. $id = trim(I('id'));
  186. $db_addons = $addon_object->find($id);
  187. $class = get_addon_class($db_addons['name']);
  188. $this->assign('jumpUrl', U('index'));
  189. if (!$db_addons || !class_exists($class)) {
  190. $this->error('插件不存在');
  191. }
  192. session('addons_uninstall_error', null);
  193. $addons = new $class;
  194. $uninstall_flag = $addons->uninstall();
  195. if (!$uninstall_flag) {
  196. $this->error('执行插件预卸载操作失败' . session('addons_uninstall_error'));
  197. }
  198. $hooks_update = D('Hook')->removeHooks($db_addons['name']);
  199. if ($hooks_update === false) {
  200. $this->error('卸载插件所挂载的钩子数据失败');
  201. }
  202. S('hooks', null);
  203. $delete = $addon_object->where("name='{$db_addons['name']}'")->delete();
  204. // 卸载数据库
  205. $sql_file = realpath(C('ADDON_PATH') . $db_addons['name']) . '/Sql/uninstall.sql';
  206. if (file_exists($sql_file)) {
  207. $sql_object = new Sql();
  208. $sql_status = $sql_object->execute_sql_from_file($sql_file);
  209. if (!$sql_status) {
  210. $this->error('执行插件SQL卸载语句失败' . session('addons_uninstall_error'));
  211. }
  212. }
  213. if ($delete === false) {
  214. $this->error('卸载插件失败');
  215. } else {
  216. $this->success('卸载成功');
  217. }
  218. }
  219. /**
  220. * 外部执行插件方法
  221. *
  222. */
  223. public function execute($_addons = null, $_controller = null, $_action = null)
  224. {
  225. if (C('URL_CASE_INSENSITIVE')) {
  226. $_addons = ucfirst(parse_name($_addons, 1));
  227. $_controller = parse_name($_controller, 1);
  228. }
  229. $TMPL_PARSE_STRING = C('TMPL_PARSE_STRING');
  230. $TMPL_PARSE_STRING['__ADDONROOT__'] = __ROOT__ . "/Addons/{$_addons}";
  231. C('TMPL_PARSE_STRING', $TMPL_PARSE_STRING);
  232. if (!empty($_addons) && !empty($_controller) && !empty($_action)) {
  233. $Addons = A("Addons://{$_addons}/{$_controller}")->$_action();
  234. } else {
  235. $this->error('没有指定插件名称,控制器或操作!');
  236. }
  237. }
  238. /**
  239. * 插件后台显示页面
  240. * @param string $name 插件名
  241. *
  242. */
  243. public function adminList($name, $tab = 1)
  244. {
  245. // 获取插件实例
  246. $addon_class = get_addon_class($name);
  247. if (!class_exists($addon_class)) {
  248. $this->error('插件不存在');
  249. } else {
  250. $addon = new $addon_class();
  251. }
  252. // 自定义插件后台页面
  253. if ($addon->custom_adminlist) {
  254. $this->assign('custom_adminlist', $this->fetch($addon->custom_adminlist));
  255. $this->display($addon->custom_adminlist);
  256. } else {
  257. // 获取插件的$admin_list配置
  258. $admin_list = $addon->admin_list;
  259. $tab_list = array();
  260. foreach ($admin_list as $key => $val) {
  261. $tab_list[$key]['title'] = $val['title'];
  262. $tab_list[$key]['href'] = U('Admin/Addon/adminList', array(
  263. 'name' => $name,
  264. 'tab' => $key,
  265. ));
  266. }
  267. $admin = $admin_list[$tab];
  268. $param = D('Addons://' . $name . '/' . $admin['model'] . '')->adminList;
  269. if ($param) {
  270. // 搜索
  271. $keyword = (string) I('keyword');
  272. $condition = array('like', '%' . $keyword . '%');
  273. $map['id|' . $param['search_key']] = array(
  274. $condition,
  275. $condition,
  276. '_multi' => true,
  277. );
  278. // 获取数据列表
  279. $p = !empty($_GET["p"]) ? $_GET['p'] : 1;
  280. $data_list = M($param['model'])
  281. ->page($p, C('ADMIN_PAGE_ROWS'))
  282. ->where($map)
  283. ->field(true)
  284. ->order($param['order'])
  285. ->select();
  286. $page = new Page(M($param['model'])
  287. ->where($map)
  288. ->count(), C('ADMIN_PAGE_ROWS'));
  289. // 使用Builder快速建立列表页面。
  290. $builder = new \Common\Builder\ListBuilder();
  291. $builder->setMetaTitle($addon->info['title']) // 设置页面标题
  292. ->AddTopButton('addnew', array('href' => U('Admin/Addon/adminAdd', array('name' => $name, 'tab' => $tab)))) // 添加新增按钮
  293. ->AddTopButton('resume', array('model' => $param['model'])) // 添加启用按钮
  294. ->AddTopButton('forbid', array('model' => $param['model'])) // 添加禁用按钮
  295. ->setSearch('请输入关键字', U('Admin/Addon/adminList', array('name' => $name, 'tab' => $tab)))
  296. ->SetTabNav($tab_list, $tab) // 设置Tab按钮列表
  297. ->setTableDataList($data_list) // 数据列表
  298. ->setTableDataPage($page->show()); // 数据列表分页
  299. // 根据插件的list_grid设置后台列表字段信息
  300. foreach ($param['list_grid'] as $key => $val) {
  301. $builder->addTableColumn($key, $val['title'], $val['type']);
  302. }
  303. // 根据插件的right_button设置后台列表右侧按钮
  304. foreach ($param['right_button'] as $key => $val) {
  305. $builder->addRightButton('self', $val);
  306. }
  307. // 定义编辑按钮
  308. $attr = array();
  309. $attr['name'] = 'edit';
  310. $attr['title'] = '编辑';
  311. $attr['class'] = 'label label-info-outline label-pill';
  312. $attr['href'] = U('Admin/Addon/adminEdit', array(
  313. 'name' => $name,
  314. 'tab' => $tab,
  315. 'id' => '__data_id__',
  316. ));
  317. // 显示列表
  318. $builder->addTableColumn('right_button', '操作', 'btn')
  319. ->addRightButton('self', $attr) //添加编辑按钮
  320. ->addRightButton('forbid', array('model' => $param['model'])) // 添加禁用/启用按钮
  321. ->addRightButton('delete', array('model' => $param['model'])) // 添加删除按钮
  322. ->display();
  323. } else {
  324. $this->error('插件列表信息不正确');
  325. }
  326. }
  327. }
  328. /**
  329. * 插件后台数据增加
  330. * @param string $name 插件名
  331. *
  332. */
  333. public function adminAdd($name, $tab)
  334. {
  335. // 获取插件实例
  336. $addon_class = get_addon_class($name);
  337. if (!class_exists($addon_class)) {
  338. $this->error('插件不存在');
  339. } else {
  340. $addon = new $addon_class();
  341. }
  342. // 获取插件的$admin_list配置
  343. $admin_list = $addon->admin_list;
  344. $admin = $admin_list[$tab];
  345. $addon_model_object = D('Addons://' . $name . '/' . $admin['model']);
  346. $param = $addon_model_object->adminList;
  347. if ($param) {
  348. if (IS_POST) {
  349. $data = $addon_model_object->create();
  350. if ($data) {
  351. $result = $addon_model_object->add($data);
  352. } else {
  353. $this->error($addon_model_object->getError());
  354. }
  355. if ($result) {
  356. $this->success('新增成功', U('Admin/Addon/adminlist', array('name' => $name, 'tab' => $tab)));
  357. } else {
  358. $this->error('更新错误');
  359. }
  360. } else {
  361. // 使用FormBuilder快速建立表单页面。
  362. $builder = new \Common\Builder\FormBuilder();
  363. $builder->setMetaTitle('新增数据') //设置页面标题
  364. ->setPostUrl(U('Admin/Addon/adminAdd', array('name' => $name, 'tab' => $tab))) // 设置表单提交地址
  365. ->setExtraItems($param['field'])
  366. ->display();
  367. }
  368. } else {
  369. $this->error('插件列表信息不正确');
  370. }
  371. }
  372. /**
  373. * 插件后台数据编辑
  374. * @param string $name 插件名
  375. *
  376. */
  377. public function adminEdit($name, $tab, $id)
  378. {
  379. // 获取插件实例
  380. $addon_class = get_addon_class($name);
  381. if (!class_exists($addon_class)) {
  382. $this->error('插件不存在');
  383. } else {
  384. $addon = new $addon_class();
  385. }
  386. // 获取插件的$admin_list配置
  387. $admin_list = $addon->admin_list;
  388. $admin = $admin_list[$tab];
  389. $addon_model_object = D('Addons://' . $name . '/' . $admin['model']);
  390. $param = $addon_model_object->adminList;
  391. if ($param) {
  392. if (IS_POST) {
  393. $data = $addon_model_object->create();
  394. if ($data) {
  395. $result = $addon_model_object->save($data);
  396. } else {
  397. $this->error($addon_model_object->getError());
  398. }
  399. if ($result) {
  400. $this->success('更新成功', U('Admin/Addon/adminlist', array('name' => $name, 'tab' => $tab)));
  401. } else {
  402. $this->error('更新错误');
  403. }
  404. } else {
  405. // 使用FormBuilder快速建立表单页面。
  406. $builder = new \Common\Builder\FormBuilder();
  407. $builder->setMetaTitle('编辑数据') // 设置页面标题
  408. ->setPostUrl(U('admin/addon/adminedit', array('name' => $name, 'tab' => $tab))) // 设置表单提交地址
  409. ->addFormItem('id', 'hidden', 'ID', 'ID')
  410. ->setExtraItems($param['field'])
  411. ->setFormData(M($param['model'])->find($id))
  412. ->display();
  413. }
  414. } else {
  415. $this->error('插件列表信息不正确');
  416. }
  417. }
  418. }