PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/system/cms/modules/navigation/controllers/admin.php

https://github.com/asalem/pyrocms
PHP | 473 lines | 299 code | 80 blank | 94 comment | 27 complexity | 4579c3774dc9fc9ecbf48c474b672477 MD5 | raw file
Possible License(s): CC-BY-3.0, BSD-3-Clause, CC0-1.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, MIT
  1. <?php
  2. use Pyro\Module\Users;
  3. use Pyro\Module\Navigation;
  4. use Pyro\Module\Pages;
  5. use Pyro\Module\Addons;
  6. /**
  7. * Admin controller for the navigation module. Handles actions such as editing links or creating new ones.
  8. *
  9. * @author PyroCMS Development Team
  10. * @package PyroCMS\Core\Modules\Navigation\Controllers
  11. *
  12. */
  13. class Admin extends Admin_Controller
  14. {
  15. /**
  16. * The current active section.
  17. *
  18. * @var int
  19. */
  20. protected $section = 'links';
  21. /**
  22. * The array containing the rules for the navigation items.
  23. *
  24. * @var array
  25. */
  26. private $validation_rules = array(
  27. array(
  28. 'field' => 'title',
  29. 'label' => 'lang:global:title',
  30. 'rules' => 'trim|required|max_length[100]'
  31. ),
  32. array(
  33. 'field' => 'link_type',
  34. 'label' => 'lang:nav_type_label',
  35. 'rules' => 'trim|required|alpha|callback__link_check'
  36. ),
  37. array(
  38. 'field' => 'url',
  39. 'label' => 'lang:nav_url_label',
  40. 'rules' => 'trim'
  41. ),
  42. array(
  43. 'field' => 'uri',
  44. 'label' => 'lang:nav_uri_label',
  45. 'rules' => 'trim'
  46. ),
  47. array(
  48. 'field' => 'module_name',
  49. 'label' => 'lang:nav_module_label',
  50. 'rules' => 'trim|alpha_dash'
  51. ),
  52. array(
  53. 'field' => 'page_id',
  54. 'label' => 'lang:nav_page_label',
  55. 'rules' => 'trim|numeric'
  56. ),
  57. array(
  58. 'field' => 'navigation_group_id',
  59. 'label' => 'lang:nav_group_label',
  60. 'rules' => 'trim|numeric'
  61. ),
  62. array(
  63. 'field' => 'current_group_id',
  64. 'label' => 'lang:nav_group_label',
  65. 'rules' => 'trim|numeric'
  66. ),
  67. array(
  68. 'field' => 'target',
  69. 'label' => 'lang:nav_target_label',
  70. 'rules' => 'trim|max_length[10]'
  71. ),
  72. array(
  73. 'field' => 'restricted_to',
  74. 'label' => 'lang:nav_restricted_to',
  75. 'rules' => ''
  76. ),
  77. array(
  78. 'field' => 'class',
  79. 'label' => 'lang:nav_class_label',
  80. 'rules' => 'trim'
  81. )
  82. );
  83. /**
  84. * Constructor method
  85. */
  86. public function __construct()
  87. {
  88. parent::__construct();
  89. // Load the required classes
  90. $this->load->library('form_validation');
  91. $this->lang->load('navigation');
  92. $this->template
  93. ->append_js('module::navigation.js')
  94. ->append_css('module::navigation.css');
  95. // Get Navigation Groups
  96. $this->template->groups = Navigation\Model\Group::all();
  97. $this->template->groups_select = Navigation\Model\Group::getGroupOptions();
  98. $all_modules = $this->moduleManager->getAll(array('is_frontend'=>true));
  99. //only allow modules that user has permissions for
  100. foreach($all_modules as $module) {
  101. if ($this->current_user->hasAccess($module['slug']) or $this->current_user->isSuperUser()) {
  102. $modules[] = $module;
  103. }
  104. }
  105. $this->template->modules_select = array_for_select($modules, 'slug', 'name');
  106. // Get Pages and create pages tree
  107. $tree = array();
  108. if ($pages = Pages\Model\Page::all()) {
  109. foreach ($pages as $page) {
  110. $tree[$page->parent_id][] = $page;
  111. }
  112. }
  113. unset($pages);
  114. $this->template->pages_select = $tree;
  115. // Set the validation rules for the navigation items
  116. $this->form_validation->set_rules($this->validation_rules);
  117. // Inject the model.
  118. $this->links = new Navigation\Model\Link();
  119. }
  120. /**
  121. * List all navigation elements
  122. */
  123. public function index()
  124. {
  125. $navigation = array();
  126. // Go through all the groups
  127. foreach ($this->template->groups as $group) {
  128. //... and get navigation links for each one
  129. $navigation[$group->id] = Navigation\Model\Link::getTreeByGroup($group->id);
  130. }
  131. // Create the layout
  132. $this->template
  133. ->append_js('jquery/jquery.ui.nestedSortable.js')
  134. ->append_js('jquery/jquery.cooki.js')
  135. ->title($this->module_details['name'])
  136. ->set('navigation', $navigation)
  137. ->build('admin/index');
  138. }
  139. /**
  140. * Order the links and record their children
  141. */
  142. public function order()
  143. {
  144. $order = $this->input->post('order');
  145. $data = $this->input->post('data');
  146. $group = isset($data['group']) ? (int) $data['group'] : 0;
  147. if (is_array($order)) {
  148. Navigation\Model\Link::setOrder($order, $group);
  149. $this->links->flushCacheCollection();
  150. Events::trigger('post_navigation_order', array(
  151. 'order' => $order,
  152. 'group' => $group
  153. ));
  154. }
  155. }
  156. /**
  157. * Get the details of a link using Ajax
  158. *
  159. * @param int $link_id The ID of the link
  160. */
  161. public function ajax_link_details($link_id)
  162. {
  163. $link = Navigation\Model\Link::getUrl($link_id);
  164. $ids = explode(',', $link->restricted_to);
  165. $group_options = Users\Model\Group::findManyGroupOptionsInId($ids);
  166. $link->restricted_to = implode(', ', $group_options);
  167. $this->load->view('admin/ajax/link_details', array('link' => $link));
  168. }
  169. /**
  170. * Create a new navigation item
  171. *
  172. * @param string $group_id
  173. *
  174. * @return
  175. */
  176. public function create($group_id = '')
  177. {
  178. // Set the options for restricted to
  179. $this->template->group_options = Users\Model\Group::getGroupOptions();
  180. // Run if valid
  181. if ($this->form_validation->run()) {
  182. $last_position = Navigation\Model\Link::findByGroupIdAndOrderByPosition($this->input->post('navigation_group_id'),'desc');
  183. $link = Navigation\Model\Link::create(array(
  184. 'title' => $this->input->post('title'),
  185. 'parent' => $this->input->post('parent') ? $this->input->post('parent') : 0,
  186. 'link_type' => $this->input->post('link_type'),
  187. 'url' => $this->input->post('url') ? $this->input->post('url') : '',
  188. 'uri' => $this->input->post('uri') ? $this->input->post('uri') : '',
  189. 'module_name' => $this->input->post('module_name') ? $this->input->post('module_name') : '',
  190. 'page_id' => (int) $this->input->post('page_id'),
  191. 'position' => $last_position ? $last_position->position + 1 : 1,
  192. 'target' => $this->input->post('target') ? $this->input->post('target') : '',
  193. 'class' => $this->input->post('class') ? $this->input->post('class') : '',
  194. 'navigation_group_id' => (int) $this->input->post('navigation_group_id'),
  195. 'restricted_to' => $this->input->post('restricted_to') ? implode(',', $this->input->post('restricted_to')) : 0
  196. ));
  197. if ($link) {
  198. //@TODO Fix Me Bro https://github.com/pyrocms/pyrocms/pull/2514
  199. $this->cache->forget('navigation_m');
  200. Events::trigger('post_navigation_create', $link);
  201. $this->session->set_flashdata('success', lang('nav:link_add_success'));
  202. // echo success to let the js refresh the page
  203. echo 'success';
  204. return;
  205. } else {
  206. $this->template->messages['error'] = lang('nav:link_add_error');
  207. echo $this->load->view('admin/partials/notices', $this->template);
  208. return;
  209. }
  210. }
  211. // check for errors
  212. if (validation_errors()) {
  213. echo $this->load->view('admin/partials/notices');
  214. return;
  215. }
  216. $link = (object) array();
  217. // Loop through each validation rule
  218. foreach ($this->validation_rules as $rule) {
  219. $link->{$rule['field']} = set_value($rule['field']);
  220. }
  221. $link->navigation_group_id = $group_id;
  222. $this->template
  223. ->set('link',$link);
  224. // Get Pages and create pages tree
  225. $this->template->tree_select = $this->_build_tree_select(array('current_parent' => $this->template->link->page_id));
  226. $this->template
  227. ->set_layout(false)
  228. ->build('admin/ajax/form');
  229. }
  230. /**
  231. * Edit a navigation item
  232. *
  233. * @param int $id The ID of the navigation item.
  234. */
  235. public function edit($id = 0)
  236. {
  237. // Got ID?
  238. if (empty($id)) {
  239. return;
  240. }
  241. // Get the navigation item based on the ID
  242. $link = Navigation\Model\Link::find($id);
  243. // Set the options for restricted to
  244. $group_options = Users\Model\Group::getGroupOptions();
  245. if (! $link) {
  246. $this->template->messages['error'] = lang('nav:link_not_exist_error');
  247. exit($this->load->view('admin/partials/notices', compact('link', 'group_options')));
  248. }
  249. // Valid data?
  250. if ($this->form_validation->run()) {
  251. if ($this->input->post('current_group_id') != $this->input->post('navigation_group_id')) {
  252. $link->parent = 0;
  253. Navigation\Model\Link::resetChildByParentId($id);
  254. }
  255. $link->title = $this->input->post('title');
  256. $link->link_type = $this->input->post('link_type');
  257. $link->url = $this->input->post('url') == 'http://' ? '' : $this->input->post('url');
  258. $link->uri = $this->input->post('uri');
  259. $link->module_name = $this->input->post('module_name');
  260. $link->page_id = (int) $this->input->post('page_id');
  261. $link->target = $this->input->post('target');
  262. $link->class = $this->input->post('class');
  263. $link->navigation_group_id = (int) $this->input->post('navigation_group_id');
  264. $link->restricted_to = $this->input->post('restricted_to') ? implode(',', $this->input->post('restricted_to')) : '';
  265. // Update the link and flush the cache
  266. if ($link->save()) {
  267. //@TODO Fix Me Bro https://github.com/pyrocms/pyrocms/pull/2514
  268. $this->cache->forget('navigation_m');
  269. Events::trigger('post_navigation_edit', $link);
  270. $this->session->set_flashdata('success', lang('nav:link_edit_success'));
  271. // echo success to let the js refresh the page
  272. exit('success');
  273. }
  274. }
  275. // check for errors
  276. if (validation_errors()) {
  277. exit($this->load->view('admin/partials/notices', $this->template));
  278. }
  279. // Loop through each rule
  280. foreach ($this->validation_rules as $rule) {
  281. if ($this->input->post($rule['field']) !== null) {
  282. $link->{$rule['field']} = $this->input->post($rule['field']);
  283. }
  284. }
  285. // Get Pages and create pages tree
  286. $this->template->tree_select = $this->_build_tree_select(array('current_parent' => $link->page_id));
  287. // Render the view
  288. $this->template
  289. ->set_layout(false)
  290. ->build('admin/ajax/form', compact('link', 'group_options'));
  291. }
  292. /**
  293. * Delete an existing navigation link
  294. *
  295. * @param int $id The ID of the navigation link
  296. */
  297. public function delete($id = 0)
  298. {
  299. $id_array = (!empty($id)) ? array($id) : $this->input->post('action_to');
  300. // Loop through each item to delete
  301. if (!empty($id_array)) {
  302. foreach ($id_array as $id) {
  303. Navigation\Model\Link::deleteLinkChildren($id);
  304. }
  305. Events::trigger('post_navigation_delete', $id_array);
  306. }
  307. // Flush the cache and redirect
  308. $this->links->flushCacheCollection();
  309. $this->session->set_flashdata('success', $this->lang->line('nav:link_delete_success'));
  310. redirect('admin/navigation');
  311. }
  312. /**
  313. * Tree select function
  314. *
  315. * Creates a tree to form select
  316. *
  317. * @param $params
  318. *
  319. * @return string
  320. */
  321. public function _build_tree_select($params)
  322. {
  323. $params = array_merge(array(
  324. 'tree' => array(),
  325. 'parent_id' => 0,
  326. 'current_parent'=> 0,
  327. 'current_id' => 0,
  328. 'level' => 0
  329. ), $params);
  330. extract($params);
  331. if (! $tree) {
  332. if ($pages = Pages\Model\Page::all()) {
  333. foreach ($pages as $page) {
  334. $tree[$page->parent_id][] = $page;
  335. }
  336. }
  337. }
  338. if ( ! isset($tree[$parent_id])) {
  339. return;
  340. }
  341. $html = '';
  342. foreach ($tree[$parent_id] as $item) {
  343. if ($current_id == $item->id) {
  344. continue;
  345. }
  346. $html .= '<option value="' . $item->id . '"';
  347. $html .= $current_parent == $item->id ? ' selected="selected">': '>';
  348. if ($level > 0) {
  349. for ($i = 0; $i < ($level*2); $i++) {
  350. $html .= '&nbsp;';
  351. }
  352. $html .= '-&nbsp;';
  353. }
  354. $html .= $item->title . '</option>';
  355. $html .= $this->_build_tree_select(array(
  356. 'tree' => $tree,
  357. 'parent_id' => (int) $item->id,
  358. 'current_parent'=> $current_parent,
  359. 'current_id' => $current_id,
  360. 'level' => $level + 1
  361. ));
  362. }
  363. return $html;
  364. }
  365. /**
  366. * Validate the link value.
  367. *
  368. * Only the URI field may be submitted blank.
  369. *
  370. * @param string $link The link value
  371. * @return bool
  372. */
  373. public function _link_check($link)
  374. {
  375. $status = true;
  376. switch ($link) {
  377. case 'url':
  378. $status = ($this->input->post('url') > '' AND $this->input->post('url') !== 'http://');
  379. break;
  380. case 'module':
  381. $status = ($this->input->post('module_name') > '');
  382. break;
  383. case 'page':
  384. $status = ($this->input->post('page_id') > '');
  385. break;
  386. }
  387. if (! $status) {
  388. $this->form_validation->set_message('_link_check', sprintf(lang('nav:choose_value'), lang('nav:'.$link.'_label')));
  389. return false;
  390. }
  391. return true;
  392. }
  393. }