PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/viktorfabry/banditos
PHP | 503 lines | 312 code | 78 blank | 113 comment | 31 complexity | cfe30d8c8865d271f6540215e44b45df MD5 | raw file
Possible License(s): CC-BY-3.0, BSD-3-Clause, 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->model('keywords/keyword_m');
  85. $page->meta_keywords = Keywords::get_string($page->meta_keywords);
  86. $this->load->view('admin/ajax/page_details', array('page' => $page));
  87. }
  88. /**
  89. * Show a page preview
  90. *
  91. * @param int $id The id of the page.
  92. */
  93. public function preview($id = 0)
  94. {
  95. $this->template
  96. ->set_layout('modal', 'admin')
  97. ->build('admin/preview', array('page' => $this->page_m->get($id)));
  98. }
  99. /**
  100. * Duplicate a page
  101. *
  102. * @param int $id The ID of the page
  103. * @param null $parent_id The ID of the parent page, if this is a recursive nested duplication
  104. */
  105. public function duplicate($id, $parent_id = null)
  106. {
  107. $page = (array)$this->page_m->get($id);
  108. // Steal their children
  109. $children = $this->page_m->get_many_by('parent_id', $id);
  110. $new_slug = $page['slug'];
  111. // No parent around? Do what you like
  112. if (is_null($parent_id))
  113. {
  114. do
  115. {
  116. // Turn "Foo" into "Foo 2"
  117. $page['title'] = increment_string($page['title'], ' ', 2);
  118. // Turn "foo" into "foo-2"
  119. $page['slug'] = increment_string($page['slug'], '-', 2);
  120. // Find if this already exists in this level
  121. $dupes = $this->page_m->count_by(array(
  122. 'slug' => $page['slug'],
  123. 'parent_id' => $page['parent_id'],
  124. ));
  125. }
  126. while ($dupes > 0);
  127. }
  128. // Oop, a parent turned up, work with that
  129. else
  130. {
  131. $page['parent_id'] = $parent_id;
  132. }
  133. $page['restricted_to'] = null;
  134. $page['navigation_group_id'] = 0;
  135. foreach($page['chunks'] as $chunk)
  136. {
  137. $page['chunk_slug'][] = $chunk['slug'];
  138. $page['chunk_class'][] = $chunk['class'];
  139. $page['chunk_type'][] = $chunk['type'];
  140. $page['chunk_body'][] = $chunk['body'];
  141. }
  142. $new_page = $this->page_m->create($page);
  143. foreach ($children as $child)
  144. {
  145. $this->duplicate($child->id, $new_page);
  146. }
  147. redirect('admin/pages');
  148. }
  149. /**
  150. * Create a new page
  151. *
  152. * @param int $parent_id The id of the parent page.
  153. */
  154. public function create($parent_id = 0)
  155. {
  156. $page = new stdClass;
  157. // did they even submit?
  158. if ($input = $this->input->post())
  159. {
  160. // do they have permission to proceed?
  161. if ($input['status'] == 'live')
  162. {
  163. role_or_die('pages', 'put_live');
  164. }
  165. // validate and insert
  166. if ($id = $this->page_m->create($input))
  167. {
  168. Events::trigger('page_created', $id);
  169. $this->session->set_flashdata('success', lang('pages_create_success'));
  170. // Redirect back to the form or main page
  171. $input['btnAction'] == 'save_exit'
  172. ? redirect('admin/pages')
  173. : redirect('admin/pages/edit/'.$id);
  174. }
  175. else
  176. {
  177. // validation failed, we must repopulate the chunks form
  178. $chunk_slugs = $this->input->post('chunk_slug') ? array_values($this->input->post('chunk_slug')) : array();
  179. $chunk_classes = $this->input->post('chunk_class') ? array_values($this->input->post('chunk_class')) : array();
  180. $chunk_bodies = $this->input->post('chunk_body') ? array_values($this->input->post('chunk_body')) : array();
  181. $chunk_types = $this->input->post('chunk_type') ? array_values($this->input->post('chunk_type')) : array();
  182. $chunk_bodies_count = count($input['chunk_body']);
  183. for ($i = 0; $i < $chunk_bodies_count; $i++)
  184. {
  185. $page->chunks[] = array(
  186. 'id' => $i,
  187. 'slug' => ! empty($chunk_slugs[$i]) ? $chunk_slugs[$i] : '',
  188. 'class' => ! empty($chunk_classes[$i]) ? $chunk_classes[$i] : '',
  189. 'type' => ! empty($chunk_types[$i]) ? $chunk_types[$i] : '',
  190. 'body' => ! empty($chunk_bodies[$i]) ? $chunk_bodies[$i] : '',
  191. );
  192. }
  193. }
  194. }
  195. else
  196. {
  197. $page->chunks = array(array(
  198. 'id' => 'NEW',
  199. 'slug' => 'default',
  200. 'class' => '',
  201. 'body' => '',
  202. 'type' => 'wysiwyg-advanced',
  203. ));
  204. }
  205. // Loop through each rule
  206. foreach ($this->page_m->fields() as $field)
  207. {
  208. if ($field === 'restricted_to[]' or $field === 'strict_uri')
  209. {
  210. $page->restricted_to = set_value($field, array('0'));
  211. // we'll set the default for strict URIs here also
  212. $page->strict_uri = true;
  213. continue;
  214. }
  215. $page->{$field} = set_value($field);
  216. }
  217. $parent_page = new stdClass;
  218. // If a parent id was passed, fetch the parent details
  219. if ($parent_id > 0)
  220. {
  221. $page->parent_id = $parent_id;
  222. $parent_page = $this->page_m->get($parent_id);
  223. }
  224. // Set some data that both create and edit forms will need
  225. $this->_form_data();
  226. // Load WYSIWYG editor
  227. $this->template
  228. ->title($this->module_details['name'], lang('pages:create_title'))
  229. ->append_metadata($this->load->view('fragments/wysiwyg', array(), true))
  230. ->set('page', $page)
  231. ->set('parent_page', $parent_page)
  232. ->build('admin/form');
  233. }
  234. /**
  235. * Edit an existing page
  236. *
  237. * @param int $id The id of the page.
  238. */
  239. public function edit($id = 0)
  240. {
  241. // We are lost without an id. Redirect to the pages index.
  242. $id OR redirect('admin/pages');
  243. // The user needs to be able to edit pages.
  244. role_or_die('pages', 'edit_live');
  245. // Retrieve the page data along with its chunk data as an array.
  246. $page = $this->page_m->get($id);
  247. // If there's a keywords hash
  248. if ($page->meta_keywords != '') {
  249. // Get comma-separated meta_keywords based on keywords hash
  250. $this->load->model('keywords/keyword_m');
  251. $old_keywords_hash = $page->meta_keywords;
  252. $page->meta_keywords = Keywords::get_string($page->meta_keywords);
  253. }
  254. // Turn the CSV list back to an array
  255. $page->restricted_to = explode(',', $page->restricted_to);
  256. // Got page?
  257. if ( ! $page OR empty($page))
  258. {
  259. // Maybe you would like to create one?
  260. $this->session->set_flashdata('error', lang('pages_page_not_found_error'));
  261. redirect('admin/pages/create');
  262. }
  263. // did they even submit?
  264. if ($input = $this->input->post())
  265. {
  266. // do they have permission to proceed?
  267. if ($input['status'] == 'live')
  268. {
  269. role_or_die('pages', 'put_live');
  270. }
  271. // were there keywords before this update?
  272. if (isset($old_keywords_hash)) {
  273. $input['old_keywords_hash'] = $old_keywords_hash;
  274. }
  275. // validate and insert
  276. if ($this->page_m->edit($id, $input))
  277. {
  278. $this->session->set_flashdata('success', sprintf(lang('pages_edit_success'), $input['title']));
  279. Events::trigger('page_updated', $id);
  280. $this->pyrocache->delete_all('page_m');
  281. $this->pyrocache->delete_all('navigation_m');
  282. // Mission accomplished!
  283. $input['btnAction'] == 'save_exit'
  284. ? redirect('admin/pages')
  285. : redirect('admin/pages/edit/'.$id);
  286. }
  287. else
  288. {
  289. // validation failed, we must repopulate the chunks form
  290. $chunk_slugs = $this->input->post('chunk_slug') ? array_values($this->input->post('chunk_slug')) : array();
  291. $chunk_classes = $this->input->post('chunk_class') ? array_values($this->input->post('chunk_class')) : array();
  292. $chunk_bodies = $this->input->post('chunk_body') ? array_values($this->input->post('chunk_body')) : array();
  293. $chunk_types = $this->input->post('chunk_type') ? array_values($this->input->post('chunk_type')) : array();
  294. $page->chunks = array();
  295. $chunk_bodies_count = count($input['chunk_body']);
  296. for ($i = 0; $i < $chunk_bodies_count; $i++)
  297. {
  298. $page->chunks[] = array(
  299. 'id' => $i,
  300. 'slug' => ! empty($chunk_slugs[$i]) ? $chunk_slugs[$i] : '',
  301. 'class' => ! empty($chunk_classes[$i]) ? $chunk_classes[$i] : '',
  302. 'type' => ! empty($chunk_types[$i]) ? $chunk_types[$i] : '',
  303. 'body' => ! empty($chunk_bodies[$i]) ? $chunk_bodies[$i] : '',
  304. );
  305. }
  306. }
  307. }
  308. // Loop through each validation rule
  309. foreach ($this->page_m->fields() as $field)
  310. {
  311. // Nothing to do for these two fields.
  312. if (in_array($field, array('navigation_group_id', 'chunk_body[]')))
  313. {
  314. continue;
  315. }
  316. // Translate the data of restricted_to to something we can use in the form.
  317. if ($field === 'restricted_to[]')
  318. {
  319. $page->restricted_to = set_value($field, $page->restricted_to);
  320. $page->restricted_to[0] = ($page->restricted_to[0] == '') ? '0' : $page->restricted_to[0];
  321. continue;
  322. }
  323. // Set all the other fields
  324. $page->{$field} = set_value($field, $page->{$field});
  325. }
  326. // If this page has a parent.
  327. if ($page->parent_id > 0)
  328. {
  329. // Get only the details for the parent, no chunks.
  330. $parent_page = $this->page_m->get($page->parent_id, false);
  331. }
  332. else
  333. {
  334. $parent_page = false;
  335. }
  336. $this->_form_data();
  337. $this->template
  338. ->title($this->module_details['name'], sprintf(lang('pages:edit_title'), $page->title))
  339. // Load WYSIWYG Editor
  340. ->append_metadata( $this->load->view('fragments/wysiwyg', array() , true) )
  341. ->append_css('module::page-edit.css')
  342. ->set('page', $page)
  343. ->set('parent_page', $parent_page)
  344. ->build('admin/form');
  345. }
  346. /**
  347. * Sets up common form inputs.
  348. *
  349. * This is used in both the creation and editing forms.
  350. */
  351. private function _form_data()
  352. {
  353. $page_layouts = $this->page_layouts_m->get_all();
  354. $this->template->page_layouts = array_for_select($page_layouts, 'id', 'title');
  355. // Load navigation list
  356. $this->load->model('navigation/navigation_m');
  357. $navigation_groups = $this->navigation_m->get_groups();
  358. $this->template->navigation_groups = array_for_select($navigation_groups, 'id', 'title');
  359. $this->load->model('groups/group_m');
  360. $groups = $this->group_m->get_all();
  361. foreach ($groups as $group)
  362. {
  363. $group->name !== 'admin' && $group_options[$group->id] = $group->name;
  364. }
  365. $this->template->group_options = $group_options;
  366. $this->template
  367. ->append_js('jquery/jquery.tagsinput.js')
  368. ->append_js('jquery/jquery.cooki.js')
  369. ->append_js('module::form.js')
  370. ->append_css('jquery/jquery.tagsinput.css');
  371. }
  372. /**
  373. * Delete a page.
  374. *
  375. * @param int $id The id of the page to delete.
  376. */
  377. public function delete($id = 0)
  378. {
  379. $this->load->model('comments/comments_m');
  380. // The user needs to be able to delete pages.
  381. role_or_die('pages', 'delete_live');
  382. // @todo Error of no selection not handled yet.
  383. $ids = ($id) ? array($id) : $this->input->post('action_to');
  384. // Go through the array of slugs to delete
  385. if ( ! empty($ids))
  386. {
  387. foreach ($ids as $id)
  388. {
  389. if ($id !== 1)
  390. {
  391. $deleted_ids = $this->page_m->delete($id);
  392. $this->comments_m->where('module', 'pages')->delete_by('module_id', $id);
  393. // Wipe cache for this model, the content has changd
  394. $this->pyrocache->delete_all('page_m');
  395. $this->pyrocache->delete_all('navigation_m');
  396. }
  397. else
  398. {
  399. $this->session->set_flashdata('error', lang('pages_delete_home_error'));
  400. }
  401. }
  402. // Some pages have been deleted
  403. if ( ! empty($deleted_ids))
  404. {
  405. Events::trigger('page_deleted', $deleted_ids);
  406. // Only deleting one page
  407. if ( count($deleted_ids) == 1 )
  408. {
  409. $this->session->set_flashdata('success', sprintf(lang('pages_delete_success'), $deleted_ids[0]));
  410. }
  411. // Deleting multiple pages
  412. else
  413. {
  414. $this->session->set_flashdata('success', sprintf(lang('pages_mass_delete_success'), count($deleted_ids)));
  415. }
  416. }
  417. // For some reason, none of them were deleted
  418. else
  419. {
  420. $this->session->set_flashdata('notice', lang('pages_delete_none_notice'));
  421. }
  422. }
  423. redirect('admin/pages');
  424. }
  425. }