PageRenderTime 38ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/gsake/pyrocms
PHP | 492 lines | 306 code | 76 blank | 110 comment | 29 complexity | a93482cfdf56783e64c2f25a4a230cf3 MD5 | raw file
Possible License(s): CC-BY-3.0, BSD-3-Clause, CC0-1.0, MIT
  1. <?php defined('BASEPATH') OR exit('No direct script access allowed');
  2. /**
  3. * Pages controller
  4. *
  5. * @author PyroCMS Dev Team
  6. * @package PyroCMS\Core\Modules\Pages\Controllers
  7. */
  8. class Admin extends Admin_Controller {
  9. /**
  10. * The current active section
  11. *
  12. * @var string
  13. */
  14. protected $section = 'pages';
  15. /**
  16. * Constructor method
  17. *
  18. * Loads the form_validation library, the pages, pages layout
  19. * and navigation models along with the language for the pages
  20. * module.
  21. */
  22. public function __construct()
  23. {
  24. parent::__construct();
  25. // Load the required classes
  26. $this->load->model('page_m');
  27. $this->load->model('page_chunk_m');
  28. $this->load->model('page_layouts_m');
  29. $this->load->model('navigation/navigation_m');
  30. $this->lang->load('pages');
  31. }
  32. /**
  33. * Index methods, lists all pages
  34. */
  35. public function index()
  36. {
  37. $this->template
  38. ->title($this->module_details['name'])
  39. ->append_js('jquery/jquery.ui.nestedSortable.js')
  40. ->append_js('jquery/jquery.cooki.js')
  41. ->append_js('jquery/jquery.stickyscroll.js')
  42. ->append_js('module::index.js')
  43. ->append_css('module::index.css')
  44. ->set('pages', $this->page_m->get_page_tree())
  45. ->build('admin/index');
  46. }
  47. /**
  48. * Order the pages and record their children
  49. *
  50. * Grabs `order` and `data` from the POST data.
  51. */
  52. public function order()
  53. {
  54. $order = $this->input->post('order');
  55. $data = $this->input->post('data');
  56. $root_pages = isset($data['root_pages']) ? $data['root_pages'] : array();
  57. if (is_array($order))
  58. {
  59. //reset all parent > child relations
  60. $this->page_m->update_all(array('parent_id' => 0));
  61. foreach ($order as $i => $page)
  62. {
  63. $id = str_replace('page_', '', $page['id']);
  64. //set the order of the root pages
  65. $this->page_m->update($id, array('order' => $i), true);
  66. //iterate through children and set their order and parent
  67. $this->page_m->_set_children($page);
  68. }
  69. // rebuild page URIs
  70. $this->page_m->update_lookup($root_pages);
  71. $this->pyrocache->delete_all('navigation_m');
  72. $this->pyrocache->delete_all('page_m');
  73. Events::trigger('page_ordered', array($order, $root_pages));
  74. }
  75. }
  76. /**
  77. * Get the details of a page.
  78. *
  79. * @param int $id The id of the page.
  80. */
  81. public function ajax_page_details($id)
  82. {
  83. $page = $this->page_m->get($id);
  84. $this->load->view('admin/ajax/page_details', array('page' => $page));
  85. }
  86. /**
  87. * Show a page preview
  88. *
  89. * @param int $id The id of the page.
  90. */
  91. public function preview($id = 0)
  92. {
  93. $this->template
  94. ->set_layout('modal', 'admin')
  95. ->build('admin/preview', array('page' => $this->page_m->get($id)));
  96. }
  97. /**
  98. * Duplicate a page
  99. *
  100. * @param int $id The ID of the page
  101. * @param null $parent_id The ID of the parent page, if this is a recursive nested duplication
  102. */
  103. public function duplicate($id, $parent_id = null)
  104. {
  105. $page = $this->page_m->get($id);
  106. // Steal their children
  107. $children = $this->page_m->get_many_by('parent_id', $id);
  108. $new_slug = $page['slug'];
  109. // No parent around? Do what you like
  110. if (is_null($parent_id))
  111. {
  112. do
  113. {
  114. // Turn "Foo" into "Foo 2"
  115. $page['title'] = increment_string($page['title'], ' ', 2);
  116. // Turn "foo" into "foo-2"
  117. $page['slug'] = increment_string($page['slug'], '-', 2);
  118. // Find if this already exists in this level
  119. $dupes = $this->page_m->count_by(array(
  120. 'slug' => $page['slug'],
  121. 'parent_id' => $page['parent_id'],
  122. ));
  123. }
  124. while ($dupes > 0);
  125. }
  126. // Oop, a parent turned up, work with that
  127. else
  128. {
  129. $page['parent_id'] = $parent_id;
  130. }
  131. $page['restricted_to'] = null;
  132. $page['navigation_group_id'] = 0;
  133. $page['is_home'] = true;
  134. foreach($page['chunks'] as $chunk)
  135. {
  136. $page['chunk_slug'][] = $chunk['slug'];
  137. $page['chunk_class'][] = $chunk['class'];
  138. $page['chunk_type'][] = $chunk['type'];
  139. $page['chunk_body'][] = $chunk['body'];
  140. }
  141. $new_page = $this->page_m->create($page);
  142. foreach ($children as $child)
  143. {
  144. $this->duplicate($child->id, $new_page['id']);
  145. }
  146. if ($parent_id === NULL)
  147. {
  148. redirect('admin/pages/edit/'.$new_page['id']);
  149. }
  150. }
  151. /**
  152. * Create a new page
  153. *
  154. * @param int $parent_id The id of the parent page.
  155. */
  156. public function create($parent_id = 0)
  157. {
  158. $page = new stdClass;
  159. // did they even submit?
  160. if ($input = $this->input->post())
  161. {
  162. // do they have permission to proceed?
  163. if ($input['status'] == 'live')
  164. {
  165. role_or_die('pages', 'put_live');
  166. }
  167. // validate and insert
  168. if ($id = $this->page_m->create($input))
  169. {
  170. Events::trigger('page_created', $id);
  171. $this->session->set_flashdata('success', lang('pages_create_success'));
  172. // Redirect back to the form or main page
  173. $input['btnAction'] == 'save_exit'
  174. ? redirect('admin/pages')
  175. : redirect('admin/pages/edit/'.$id);
  176. }
  177. else
  178. {
  179. // validation failed, we must repopulate the chunks form
  180. $chunk_slugs = $this->input->post('chunk_slug') ? array_values($this->input->post('chunk_slug')) : array();
  181. $chunk_classes = $this->input->post('chunk_class') ? array_values($this->input->post('chunk_class')) : array();
  182. $chunk_bodies = $this->input->post('chunk_body') ? array_values($this->input->post('chunk_body')) : array();
  183. $chunk_types = $this->input->post('chunk_type') ? array_values($this->input->post('chunk_type')) : array();
  184. $chunk_bodies_count = count($input['chunk_body']);
  185. for ($i = 0; $i < $chunk_bodies_count; $i++)
  186. {
  187. $page->chunks[] = array(
  188. 'id' => $i,
  189. 'slug' => ! empty($chunk_slugs[$i]) ? $chunk_slugs[$i] : '',
  190. 'class' => ! empty($chunk_classes[$i]) ? $chunk_classes[$i] : '',
  191. 'type' => ! empty($chunk_types[$i]) ? $chunk_types[$i] : '',
  192. 'body' => ! empty($chunk_bodies[$i]) ? $chunk_bodies[$i] : '',
  193. );
  194. }
  195. }
  196. }
  197. else
  198. {
  199. $page->chunks = array(array(
  200. 'id' => 'NEW',
  201. 'slug' => 'default',
  202. 'class' => '',
  203. 'body' => '',
  204. 'type' => 'wysiwyg-advanced',
  205. ));
  206. }
  207. // Loop through each rule
  208. foreach ($this->page_m->fields() as $field)
  209. {
  210. if ($field === 'restricted_to[]' or $field === 'strict_uri')
  211. {
  212. $page->restricted_to = set_value($field, array('0'));
  213. // we'll set the default for strict URIs here also
  214. $page->strict_uri = true;
  215. continue;
  216. }
  217. $page->{$field} = set_value($field);
  218. }
  219. $parent_page = new stdClass;
  220. // If a parent id was passed, fetch the parent details
  221. if ($parent_id > 0)
  222. {
  223. $page->parent_id = $parent_id;
  224. $parent_page = $this->page_m->get($parent_id);
  225. }
  226. // Set some data that both create and edit forms will need
  227. $this->_form_data();
  228. // Load WYSIWYG editor
  229. $this->template
  230. ->title($this->module_details['name'], lang('pages:create_title'))
  231. ->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
  232. ->set('page', $page)
  233. ->set('parent_page', $parent_page)
  234. ->build('admin/form');
  235. }
  236. /**
  237. * Edit an existing page
  238. *
  239. * @param int $id The id of the page.
  240. */
  241. public function edit($id = 0)
  242. {
  243. // We are lost without an id. Redirect to the pages index.
  244. $id OR redirect('admin/pages');
  245. // The user needs to be able to edit pages.
  246. role_or_die('pages', 'edit_live');
  247. // Retrieve the page data along with its chunk data as an array.
  248. $page = $this->page_m->get($id);
  249. // Turn the CSV list back to an array
  250. $page->restricted_to = explode(',', $page->restricted_to);
  251. // Got page?
  252. if ( ! $page OR empty($page))
  253. {
  254. // Maybe you would like to create one?
  255. $this->session->set_flashdata('error', lang('pages_page_not_found_error'));
  256. redirect('admin/pages/create');
  257. }
  258. // did they even submit?
  259. if ($input = $this->input->post())
  260. {
  261. // do they have permission to proceed?
  262. if ($input['status'] == 'live')
  263. {
  264. role_or_die('pages', 'put_live');
  265. }
  266. // validate and insert
  267. if ($this->page_m->edit($id, $input))
  268. {
  269. $this->session->set_flashdata('success', sprintf(lang('pages_edit_success'), $input['title']));
  270. Events::trigger('page_updated', $id);
  271. $this->pyrocache->delete_all('page_m');
  272. $this->pyrocache->delete_all('navigation_m');
  273. // Mission accomplished!
  274. $input['btnAction'] == 'save_exit'
  275. ? redirect('admin/pages')
  276. : redirect('admin/pages/edit/'.$id);
  277. }
  278. else
  279. {
  280. // validation failed, we must repopulate the chunks form
  281. $chunk_slugs = $this->input->post('chunk_slug') ? array_values($this->input->post('chunk_slug')) : array();
  282. $chunk_classes = $this->input->post('chunk_class') ? array_values($this->input->post('chunk_class')) : array();
  283. $chunk_bodies = $this->input->post('chunk_body') ? array_values($this->input->post('chunk_body')) : array();
  284. $chunk_types = $this->input->post('chunk_type') ? array_values($this->input->post('chunk_type')) : array();
  285. $page->chunks = array();
  286. $chunk_bodies_count = count($input['chunk_body']);
  287. for ($i = 0; $i < $chunk_bodies_count; $i++)
  288. {
  289. $page->chunks[] = array(
  290. 'id' => $i,
  291. 'slug' => ! empty($chunk_slugs[$i]) ? $chunk_slugs[$i] : '',
  292. 'class' => ! empty($chunk_classes[$i]) ? $chunk_classes[$i] : '',
  293. 'type' => ! empty($chunk_types[$i]) ? $chunk_types[$i] : '',
  294. 'body' => ! empty($chunk_bodies[$i]) ? $chunk_bodies[$i] : '',
  295. );
  296. }
  297. }
  298. }
  299. // Loop through each validation rule
  300. foreach ($this->page_m->fields() as $field)
  301. {
  302. // Nothing to do for these two fields.
  303. if (in_array($field, array('navigation_group_id', 'chunk_body[]')))
  304. {
  305. continue;
  306. }
  307. // Translate the data of restricted_to to something we can use in the form.
  308. if ($field === 'restricted_to[]')
  309. {
  310. $page->restricted_to = set_value($field, $page->restricted_to);
  311. $page->restricted_to[0] = ($page->restricted_to[0] == '') ? '0' : $page->restricted_to[0];
  312. continue;
  313. }
  314. // Set all the other fields
  315. $page->{$field} = set_value($field, $page->{$field});
  316. }
  317. // If this page has a parent.
  318. if ($page->parent_id > 0)
  319. {
  320. // Get only the details for the parent, no chunks.
  321. $parent_page = $this->page_m->get($page->parent_id, false);
  322. }
  323. else
  324. {
  325. $parent_page = false;
  326. }
  327. $this->_form_data();
  328. $this->template
  329. ->title($this->module_details['name'], sprintf(lang('pages:edit_title'), $page->title))
  330. // Load WYSIWYG Editor
  331. ->append_metadata( $this->load->view('fragments/wysiwyg', array() , true) )
  332. ->append_css('module::page-edit.css')
  333. ->set('page', $page)
  334. ->set('parent_page', $parent_page)
  335. ->build('admin/form');
  336. }
  337. /**
  338. * Sets up common form inputs.
  339. *
  340. * This is used in both the creation and editing forms.
  341. */
  342. private function _form_data()
  343. {
  344. $page_layouts = $this->page_layouts_m->get_all();
  345. $this->template->page_layouts = array_for_select($page_layouts, 'id', 'title');
  346. // Load navigation list
  347. $this->load->model('navigation/navigation_m');
  348. $navigation_groups = $this->navigation_m->get_groups();
  349. $this->template->navigation_groups = array_for_select($navigation_groups, 'id', 'title');
  350. $this->load->model('groups/group_m');
  351. $groups = $this->group_m->get_all();
  352. foreach ($groups as $group)
  353. {
  354. $group->name !== 'admin' && $group_options[$group->id] = $group->name;
  355. }
  356. $this->template->group_options = $group_options;
  357. $this->template
  358. ->append_js('jquery/jquery.tagsinput.js')
  359. ->append_js('jquery/jquery.cooki.js')
  360. ->append_js('module::form.js')
  361. ->append_css('jquery/jquery.tagsinput.css');
  362. }
  363. /**
  364. * Delete a page.
  365. *
  366. * @param int $id The id of the page to delete.
  367. */
  368. public function delete($id = 0)
  369. {
  370. $this->load->model('comments/comments_m');
  371. // The user needs to be able to delete pages.
  372. role_or_die('pages', 'delete_live');
  373. // @todo Error of no selection not handled yet.
  374. $ids = ($id) ? array($id) : $this->input->post('action_to');
  375. // Go through the array of slugs to delete
  376. if ( ! empty($ids))
  377. {
  378. foreach ($ids as $id)
  379. {
  380. if ($id !== 1)
  381. {
  382. $deleted_ids = $this->page_m->delete($id);
  383. $this->comments_m->where('module', 'pages')->delete_by('module_id', $id);
  384. // Wipe cache for this model, the content has changd
  385. $this->pyrocache->delete_all('page_m');
  386. $this->pyrocache->delete_all('navigation_m');
  387. }
  388. else
  389. {
  390. $this->session->set_flashdata('error', lang('pages_delete_home_error'));
  391. }
  392. }
  393. // Some pages have been deleted
  394. if ( ! empty($deleted_ids))
  395. {
  396. Events::trigger('page_deleted', $deleted_ids);
  397. // Only deleting one page
  398. if ( count($deleted_ids) == 1 )
  399. {
  400. $this->session->set_flashdata('success', sprintf(lang('pages_delete_success'), $deleted_ids[0]));
  401. }
  402. // Deleting multiple pages
  403. else
  404. {
  405. $this->session->set_flashdata('success', sprintf(lang('pages_mass_delete_success'), count($deleted_ids)));
  406. }
  407. }
  408. // For some reason, none of them were deleted
  409. else
  410. {
  411. $this->session->set_flashdata('notice', lang('pages_delete_none_notice'));
  412. }
  413. }
  414. redirect('admin/pages');
  415. }
  416. }