PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/system/pyrocms/modules/pages/controllers/admin.php

https://github.com/Brucee/pyrocms
PHP | 562 lines | 346 code | 82 blank | 134 comment | 30 complexity | aa78def432b7e90a0b63543def4708a5 MD5 | raw file
  1. <?php defined('BASEPATH') OR exit('No direct script access allowed');
  2. /**
  3. * Pages controller
  4. *
  5. * @author Phil Sturgeon - PyroCMS Dev Team
  6. * @modified Yorick Peterse
  7. * @package PyroCMS
  8. * @subpackage Pages module
  9. * @category Modules
  10. */
  11. class Admin extends Admin_Controller
  12. {
  13. /**
  14. * Array containing the validation rules
  15. * @access private
  16. * @var array
  17. */
  18. private $validation_rules = array(
  19. array(
  20. 'field' => 'title',
  21. 'label' => 'lang:pages.title_label',
  22. 'rules' => 'trim|required|max_length[250]'
  23. ),
  24. array(
  25. 'field' => 'slug',
  26. 'label' => 'lang:pages.slug_label',
  27. 'rules' => 'trim|required|alpha_dot_dash|max_length[250]'
  28. ),
  29. array(
  30. 'field' => 'body',
  31. 'label' => 'lang:pages.body_label',
  32. 'rules' => 'trim|required'
  33. ),
  34. array(
  35. 'field' => 'layout_id',
  36. 'label' => 'lang:pages.layout_id_label',
  37. 'rules' => 'trim|numeric|required'
  38. ),
  39. array(
  40. 'field' => 'css',
  41. 'label' => 'lang:pages.css_label',
  42. 'rules' => 'trim'
  43. ),
  44. array(
  45. 'field' => 'js',
  46. 'label' => 'lang:pages.js_label',
  47. 'rules' => 'trim'
  48. ),
  49. array(
  50. 'field' => 'meta_title',
  51. 'label' => 'lang:pages.meta_title_label',
  52. 'rules' => 'trim|max_length[250]'
  53. ),
  54. array(
  55. 'field' => 'meta_keywords',
  56. 'label' => 'lang:pages.meta_keywords_label',
  57. 'rules' => 'trim|max_length[250]'
  58. ),
  59. array(
  60. 'field' => 'meta_description',
  61. 'label' => 'lang:pages.meta_description_label',
  62. 'rules' => 'trim'
  63. ),
  64. array(
  65. 'field' => 'restricted_to[]',
  66. 'label' => 'lang:pages.access_label',
  67. 'rules' => 'trim|numeric'
  68. ),
  69. array(
  70. 'field' => 'rss_enabled',
  71. 'label' => 'lang:pages.rss_enabled_label',
  72. 'rules' => 'trim|numeric'
  73. ),
  74. array(
  75. 'field' => 'comments_enabled',
  76. 'label' => 'lang:pages.comments_enabled_label',
  77. 'rules' => 'trim|numeric'
  78. ),
  79. array(
  80. 'field' => 'is_home',
  81. 'label' => 'lang:pages.is_home_label',
  82. 'rules' => 'trim|numeric'
  83. ),
  84. array(
  85. 'field' => 'status',
  86. 'label' => 'lang:pages.status_label',
  87. 'rules' => 'trim|alpha|required'
  88. ),
  89. array(
  90. 'field' => 'navigation_group_id',
  91. 'label' => 'lang:pages.navigation_label',
  92. 'rules' => 'numeric'
  93. )
  94. );
  95. /**
  96. * The ID of the page, used for the validation callback
  97. * @access private
  98. * @var int
  99. */
  100. private $page_id;
  101. /**
  102. * Constructor method
  103. * @access public
  104. * @return void
  105. */
  106. public function __construct()
  107. {
  108. // Call the parent's constructor
  109. parent::Admin_Controller();
  110. // Load the required classes
  111. $this->load->library('form_validation');
  112. // Versioning
  113. $this->load->library('versioning');
  114. $this->versioning->set_table('pages');
  115. $this->load->model('pages_m');
  116. $this->load->model('page_layouts_m');
  117. $this->load->model('navigation/navigation_m');
  118. $this->lang->load('pages');
  119. $this->template->set_partial('shortcuts', 'admin/partials/shortcuts');
  120. $this->form_validation->set_rules($this->validation_rules);
  121. }
  122. /**
  123. * Index methods, lists all pages
  124. * @access public
  125. * @return void
  126. */
  127. public function index()
  128. {
  129. // Get the page tree
  130. $this->data->pages = $this->pages_m->get_page_tree();
  131. $this->data->controller =& $this;
  132. $this->template
  133. ->title($this->module_details['name'])
  134. ->append_metadata( js('jquery/jquery.ui.nestedSortable.js') )
  135. ->append_metadata( js('jquery/jquery.cookie.js') )
  136. ->append_metadata( js('index.js', 'pages') )
  137. ->append_metadata( css('index.css', 'pages') )
  138. ->build('admin/index', $this->data);
  139. }
  140. /**
  141. * Order the pages and record their children
  142. *
  143. * @access public
  144. * @return string json message
  145. */
  146. public function order()
  147. {
  148. $order = $this->input->post('order');
  149. if (is_array($order))
  150. {
  151. //reset all parent > child relations
  152. $this->pages_m->update_all(array('parent_id' => 0));
  153. foreach ($order as $i => $page)
  154. {
  155. //set the order of the root pages
  156. $this->pages_m->update_by('id', str_replace('page_', '', $page['id']), array('order' => $i));
  157. //iterate through children and set their order and parent
  158. $this->pages_m->_set_children($page);
  159. }
  160. // rebuild page URIs
  161. $this->pages_m->update_lookup($this->input->post('root_pages'));
  162. $this->pyrocache->delete_all('navigation_m');
  163. $this->pyrocache->delete_all('pages_m');
  164. echo 'Success';
  165. }
  166. else
  167. {
  168. echo 'Fail';
  169. }
  170. }
  171. /**
  172. * Get the details of a page using Ajax
  173. * @access public
  174. * @param int $page_id The ID of the page
  175. * @return void
  176. */
  177. public function ajax_page_details($page_id)
  178. {
  179. $page = $this->pages_m->get($page_id);
  180. $this->load->view('admin/ajax/page_details', array('page' => $page));
  181. }
  182. /**
  183. * Show a page preview
  184. * @access public
  185. * @param int $id The ID of the page
  186. * @return void
  187. */
  188. public function preview($id = 0)
  189. {
  190. $data->page = $this->pages_m->get($id);
  191. $this->template->set_layout('modal', 'admin');
  192. $this->template->build('admin/preview', $data);
  193. }
  194. /**
  195. * Create a new page
  196. * @access public
  197. * @param int $parent_id The ID of the parent page
  198. * @return void
  199. */
  200. public function create($parent_id = 0)
  201. {
  202. // Validate the page
  203. if ($this->form_validation->run())
  204. {
  205. $input = $this->input->post();
  206. if ($input['status'] == 'live')
  207. {
  208. role_or_die('pages', 'put_live');
  209. }
  210. // First create the page
  211. $page_body = $input['body'];
  212. $nav_group_id = $input['navigation_group_id'];
  213. unset($input['body'], $input['navigation_group_id']);
  214. if ($id = $this->pages_m->create($input))
  215. {
  216. // Create the revision
  217. $revision_id = $this->versioning->create_revision(array('author_id' => $this->user->id, 'owner_id' => $id, 'body' => $page_body));
  218. // Update the page row
  219. $input['revision_id'] = $revision_id;
  220. $input['restricted_to'] = isset($input['restricted_to']) ? implode(',', $input['restricted_to']) : '';
  221. // Add a Navigation Link
  222. if ($nav_group_id)
  223. {
  224. $this->load->model('navigation/navigation_m');
  225. $this->navigation_m->insert_link(array(
  226. 'title' => $input['title'],
  227. 'link_type' => 'page',
  228. 'page_id' => $id,
  229. 'navigation_group_id' => (int) $nav_group_id
  230. ));
  231. // Clear navigation cache
  232. $this->pyrocache->delete_all('navigation_m');
  233. }
  234. if ($this->pages_m->update($id, $input))
  235. {
  236. $this->session->set_flashdata('success', lang('pages_create_success'));
  237. // Redirect back to the form or main page
  238. $this->input->post('btnAction') == 'save_exit'
  239. ? redirect('admin/pages')
  240. : redirect('admin/pages/edit/'.$id);
  241. }
  242. }
  243. // Fail
  244. else
  245. {
  246. $this->session->set_flashdata('notice', lang('pages_create_error'));
  247. }
  248. }
  249. // Loop through each rule
  250. foreach ($this->validation_rules as $rule)
  251. {
  252. $page->{$rule['field']} = $this->input->post($rule['field']);
  253. }
  254. $page->restricted_to = $this->input->post('restricted_to');
  255. // If a parent id was passed, fetch the parent details
  256. if ($parent_id > 0)
  257. {
  258. $page->parent_id = $parent_id;
  259. $parent_page = $this->pages_m->get($parent_id);
  260. }
  261. // Assign data for display
  262. $data['page'] = & $page;
  263. $data['parent_page'] = & $parent_page;
  264. // Set some data that both create and edit forms will need
  265. self::_form_data();
  266. // Load WYSIWYG editor
  267. $this->template
  268. ->title($this->module_details['name'], lang('pages.create_title'))
  269. ->append_metadata( $this->load->view('fragments/wysiwyg', $this->data, TRUE) )
  270. ->append_metadata( js('codemirror/codemirror.js') )
  271. ->append_metadata( js('form.js', 'pages') )
  272. ->build('admin/form', $data);
  273. }
  274. /**
  275. * Edit an existing page
  276. * @access public
  277. * @param int $id The ID of the page to edit
  278. * @return void
  279. */
  280. public function edit($id = 0)
  281. {
  282. $id OR redirect('admin/pages');
  283. role_or_die('pages', 'edit_live');
  284. // Set the page ID and get the current page
  285. $this->page_id = $id;
  286. $page = $this->versioning->get($id);
  287. $revisions = $this->versioning->get_revisions($id);
  288. // Got page?
  289. if ( ! $page)
  290. {
  291. $this->session->set_flashdata('error', lang('pages_page_not_found_error'));
  292. redirect('admin/pages/create');
  293. }
  294. // It's stored as a CSV list
  295. $page->restricted_to = explode(',', $page->restricted_to);
  296. if ($this->form_validation->run())
  297. {
  298. $input = $this->input->post();
  299. if ($page->status != 'live' and $input['status'] == 'live')
  300. {
  301. role_or_die('pages', 'put_live');
  302. }
  303. // Set the data for the revision
  304. $revision_data = array('author_id' => $this->user->id, 'owner_id' => $id, 'body' => $input['body']);
  305. // Did the user wanted to restore a specific revision?
  306. if ($input['use_revision_id'] == $page->revision_id )
  307. {
  308. $input['revision_id'] = $this->versioning->create_revision($revision_data);
  309. }
  310. // Manually restore a revision
  311. else
  312. {
  313. $input['revision_id'] = $input['use_revision_id'];
  314. }
  315. $input['restricted_to'] = isset($input['restricted_to']) ? implode(',', $input['restricted_to']) : '';
  316. // Run the update code with the POST data
  317. $this->pages_m->update($id, $input);
  318. // The slug has changed
  319. if ($this->input->post('slug') != $this->input->post('old_slug'))
  320. {
  321. $this->pages_m->reindex_descendants($id);
  322. }
  323. // Set the flashdata message and redirect the user
  324. $link = anchor('admin/pages/preview/'.$id, $this->input->post('title'), 'class="modal-large"');
  325. $this->session->set_flashdata('success', sprintf(lang('pages_edit_success'), $link));
  326. // Redirect back to the form or main page
  327. $this->input->post('btnAction') == 'save_exit'
  328. ? redirect('admin/pages')
  329. : redirect('admin/pages/edit/'.$id);
  330. }
  331. // Loop through each validation rule
  332. foreach ($this->validation_rules as $rule)
  333. {
  334. if ($this->input->post($rule['field']) !== FALSE)
  335. {
  336. $page->{$rule['field']} = set_value($rule['field']);
  337. }
  338. }
  339. // If a parent id was passed, fetch the parent details
  340. if ($page->parent_id > 0)
  341. {
  342. $parent_page = $this->pages_m->get($page->parent_id);
  343. }
  344. // Assign data for display
  345. $this->data->page =& $page;
  346. $this->data->revisions =& $revisions;
  347. $this->data->parent_page =& $parent_page;
  348. self::_form_data();
  349. $this->template
  350. ->title($this->module_details['name'], sprintf(lang('pages.edit_title'), $page->title))
  351. // Load WYSIWYG Editor
  352. ->append_metadata( $this->load->view('fragments/wysiwyg', $this->data, TRUE) )
  353. // Load form specific JavaScript
  354. ->append_metadata( js('codemirror/codemirror.js') )
  355. ->append_metadata( js('form.js', 'pages') )
  356. ->build('admin/form', $this->data);
  357. }
  358. private function _form_data()
  359. {
  360. $page_layouts = $this->page_layouts_m->get_all();
  361. $this->template->page_layouts = array_for_select($page_layouts, 'id', 'title');
  362. // Load navigation list
  363. $this->load->model('navigation/navigation_m');
  364. $navigation_groups = $this->navigation_m->get_groups();
  365. $this->template->navigation_groups = array_for_select($navigation_groups, 'id', 'title');
  366. $this->load->model('groups/group_m');
  367. $groups = $this->group_m->get_all();
  368. foreach($groups as $group)
  369. {
  370. $group->name !== 'admin' && $group_options[$group->id] = $group->name;
  371. }
  372. $this->template->group_options = $group_options;
  373. }
  374. /**
  375. * Delete an existing page
  376. * @access public
  377. * @param int $id The ID of the page to delete
  378. * @return void
  379. */
  380. public function delete($id = 0)
  381. {
  382. role_or_die('pages', 'delete_live');
  383. // Attention! Error of no selection not handeled yet.
  384. $ids = ($id) ? array($id) : $this->input->post('action_to');
  385. // Go through the array of slugs to delete
  386. foreach ($ids as $id)
  387. {
  388. if ($id !== 1)
  389. {
  390. $deleted_ids = $this->pages_m->delete($id);
  391. // Wipe cache for this model, the content has changd
  392. $this->pyrocache->delete_all('pages_m');
  393. $this->pyrocache->delete_all('navigation_m');
  394. }
  395. else
  396. {
  397. $this->session->set_flashdata('error', lang('pages_delete_home_error'));
  398. }
  399. }
  400. // Some pages have been deleted
  401. if ( ! empty($deleted_ids))
  402. {
  403. // Only deleting one page
  404. if ( count($deleted_ids) == 1 )
  405. {
  406. $this->session->set_flashdata('success', sprintf(lang('pages_delete_success'), $deleted_ids[0]));
  407. }
  408. else // Deleting multiple pages
  409. {
  410. $this->session->set_flashdata('success', sprintf(lang('pages_mass_delete_success'), count($deleted_ids)));
  411. }
  412. }
  413. else // For some reason, none of them were deleted
  414. {
  415. $this->session->set_flashdata('notice', lang('pages_delete_none_notice'));
  416. }
  417. redirect('admin/pages');
  418. }
  419. /**
  420. * Show a diff between two revisions
  421. *
  422. * @author Yorick Peterse - PyroCMS Dev Team
  423. * @access public
  424. * @param int $id_1 The ID of the first revision to compare
  425. * @param int $id_2 The ID of the second revision to compare
  426. * @return void
  427. */
  428. public function compare($id_1, $id_2)
  429. {
  430. // Create the diff using mixed mode
  431. $rev_1 = $this->versioning->get_by_revision($id_1);
  432. $rev_2 = $this->versioning->get_by_revision($id_2);
  433. $diff = $this->versioning->compare_revisions($rev_1->body, $rev_2->body, 'mixed');
  434. // Output the results
  435. $data['difference'] = $diff;
  436. $this->template->set_layout('modal', 'admin')
  437. ->build('admin/revisions/compare', $data);
  438. }
  439. /**
  440. * Show a preview of a revision
  441. *
  442. * @author Yorick Peterse - PyroCMS Dev Team
  443. * @access public
  444. * @param int $id The ID of the revision to preview
  445. * @return void
  446. */
  447. public function preview_revision($id)
  448. {
  449. // Easy isn't it?
  450. $data['revision'] = $this->versioning->get_by_revision($id);
  451. $this->template->set_layout('modal', 'admin')
  452. ->build('admin/revisions/preview', $data);
  453. }
  454. /**
  455. * Build the html for the admin page tree view
  456. *
  457. * @author Jerel Unruh - PyroCMS Dev Team
  458. * @access public
  459. * @param array $page Current page
  460. */
  461. public function tree_builder($page)
  462. {
  463. if(isset($page['children'])):
  464. foreach($page['children'] as $page): ?>
  465. <li id="page_<?php echo $page['id']; ?>">
  466. <div>
  467. <a href="#" rel="<?php echo $page['id'] . '">' . $page['title']; ?></a>
  468. </div>
  469. <?php if(isset($page['children'])): ?>
  470. <ol>
  471. <?php $this->tree_builder($page); ?>
  472. </ol>
  473. </li>
  474. <?php else: ?>
  475. </li>
  476. <?php endif; ?>
  477. <?php endforeach; ?>
  478. <?php endif;
  479. }
  480. }