display-edit.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <?php
  2. /*
  3. * @file
  4. * Core Panels API include file containing various display-editing functions.
  5. * This includes all the basic editing forms (content, layout, layout settings)
  6. * as well as the ajax modal forms associated with them.
  7. */
  8. /**
  9. * Handle calling and processing of the form for editing display content.
  10. *
  11. * Helper function for panels_edit().
  12. *
  13. * @see panels_edit() for details on the various behaviors of this function.
  14. */
  15. function _panels_edit($display, $destination, $content_types, $title = FALSE) {
  16. $did = $display->did;
  17. if (!$did) {
  18. $display->did = $did = 'new';
  19. }
  20. // Load the display being edited from cache, if possible.
  21. if (!empty($_POST) && is_object($cache = panels_edit_cache_get($did))) {
  22. $display = $cache->display;
  23. }
  24. else {
  25. $cache = panels_edit_cache_get_default($display, $content_types, $title);
  26. }
  27. // Get a renderer.
  28. $renderer = panels_get_renderer_handler('editor', $display);
  29. $renderer->cache = $cache;
  30. $output = $renderer->edit();
  31. if (is_object($output) && $destination) {
  32. return panels_goto($destination);
  33. }
  34. return $output;
  35. }
  36. /**
  37. * Form definition for the panels display editor
  38. *
  39. * No validation function is necessary, as all 'validation' is handled
  40. * either in the lead-up to form rendering (through the selection of
  41. * specified content types) or by the validation functions specific to
  42. * the ajax modals & content types.
  43. *
  44. * @ingroup forms
  45. * @see panels_edit_display_submit()
  46. */
  47. function panels_edit_display_form($form, &$form_state) {
  48. $display = &$form_state['display'];
  49. $renderer = &$form_state['renderer'];
  50. // Make sure there is a valid cache key.
  51. $cache_key = isset($display->cache_key) ? $display->cache_key : $display->did;
  52. $display->cache_key = $cache_key;
  53. // Annoyingly, theme doesn't have access to form_state so we have to do this.
  54. $form['#display'] = $display;
  55. // The flexible layout maker wants to be able to edit a display without
  56. // actually editing a display, so we provide this 'setting' to allow
  57. // that to go away.
  58. if (empty($form_state['no display settings'])) {
  59. $links = $renderer->get_display_links();
  60. }
  61. else {
  62. $renderer->no_edit_links = TRUE;
  63. $links = '';
  64. }
  65. $form['hide']['display-settings'] = array(
  66. '#markup' => $links,
  67. );
  68. $form += panels_edit_display_settings_form($form, $form_state);
  69. $form['panel'] = array('#tree' => TRUE);
  70. $form['panel']['pane'] = array('#tree' => TRUE);
  71. $form['display'] = array(
  72. '#markup' => $renderer->render(),
  73. );
  74. foreach ($renderer->plugins['layout']['regions'] as $region_id => $title) {
  75. // Make sure we at least have an empty array for all possible locations.
  76. if (!isset($display->panels[$region_id])) {
  77. $display->panels[$region_id] = array();
  78. }
  79. $form['panel']['pane'][$region_id] = array(
  80. // Use 'hidden' instead of 'value' so the js can access it.
  81. '#type' => 'hidden',
  82. '#default_value' => implode(',', (array) $display->panels[$region_id]),
  83. );
  84. }
  85. if (empty($form_state['no buttons'])) {
  86. $form['buttons']['submit'] = array(
  87. '#type' => 'submit',
  88. '#value' => t('Save'),
  89. '#id' => 'panels-dnd-save',
  90. '#submit' => array('panels_edit_display_form_submit'),
  91. '#save-display' => TRUE,
  92. );
  93. $form['buttons']['cancel'] = array(
  94. '#type' => 'submit',
  95. '#value' => t('Cancel'),
  96. );
  97. }
  98. // Build up the preview portion of the form, if necessary.
  99. if (empty($form_state['no preview'])) {
  100. $form['preview'] = array(
  101. '#tree' => TRUE,
  102. '#prefix' => '<h2>' . t('Live preview') . '</h2>' . '<div id="panels-live-preview">',
  103. '#suffix' => '</div>',
  104. );
  105. ctools_context_replace_form($form['preview'], $display->context);
  106. $form['preview']['button'] = array(
  107. '#type' => 'submit',
  108. '#value' => t('Preview'),
  109. '#attributes' => array('class' => array('use-ajax-submit')),
  110. '#id' => 'panels-live-preview-button',
  111. '#submit' => array('panels_edit_display_form_submit', 'panels_edit_display_form_preview'),
  112. );
  113. }
  114. return $form;
  115. }
  116. /**
  117. * Handle form validation of the display content editor.
  118. */
  119. function panels_edit_display_form_validate($form, &$form_state) {
  120. panels_edit_display_settings_form_validate($form, $form_state);
  121. }
  122. /**
  123. * Handle form submission of the display content editor.
  124. *
  125. * This reads the location of the various panes from the form, which will
  126. * have been modified from the ajax, rearranges them and then saves
  127. * the display.
  128. */
  129. function panels_edit_display_form_submit($form, &$form_state) {
  130. $display = &$form_state['display'];
  131. $old_content = $display->content;
  132. $display->content = array();
  133. if (!empty($form_state['values']['panel']['pane'])) {
  134. foreach ($form_state['values']['panel']['pane'] as $region_id => $panes) {
  135. $display->panels[$region_id] = array();
  136. if ($panes) {
  137. $pids = explode(',', $panes);
  138. // need to filter the array, b/c passing it in a hidden field can generate trash
  139. foreach (array_filter($pids) as $pid) {
  140. if ($old_content[$pid]) {
  141. $display->panels[$region_id][] = $pid;
  142. $old_content[$pid]->panel = $region_id;
  143. $display->content[$pid] = $old_content[$pid];
  144. // If the panel has region locking, make sure that the region
  145. // the panel is in is applicable. This can happen if the panel
  146. // was moved and then the lock changed and the server didn't
  147. // know.
  148. if (!empty($old_content[$pid]->locks) && $old_content[$pid]->locks['type'] == 'regions') {
  149. $old_content[$pid]->locks['regions'][$region_id] = $region_id;
  150. }
  151. }
  152. }
  153. }
  154. }
  155. }
  156. panels_edit_display_settings_form_submit($form, $form_state);
  157. }
  158. /**
  159. * Submission of the preview button. Render the preview and put it into
  160. * the preview widget area.
  161. */
  162. function panels_edit_display_form_preview(&$form, &$form_state) {
  163. $display = &$form_state['display'];
  164. ctools_include('ajax');
  165. $display->context = ctools_context_replace_placeholders($display->context, $form_state['values']['preview']);
  166. $display->skip_cache = TRUE;
  167. $output = panels_render_display($display);
  168. // Add any extra CSS that some layouts may have added specifically for this.
  169. if (!empty($display->add_css)) {
  170. $output = "<style type=\"text/css\">\n$display->add_css</style>\n" . $output;
  171. }
  172. $commands = array();
  173. $commands[] = array(
  174. 'command' => 'panel_preview',
  175. 'output' => $output,
  176. );
  177. print ajax_render($commands);
  178. ajax_footer();
  179. exit;
  180. }
  181. /**
  182. * Form for display settings.
  183. */
  184. function panels_edit_display_settings_form($form, &$form_state) {
  185. $display = &$form_state['display'];
  186. $layout = panels_get_layout($display->layout);
  187. $form_state['layout'] = $layout;
  188. ctools_include('dependent');
  189. if ($form_state['display_title']) {
  190. $form['display_title'] = array (
  191. '#tree' => TRUE,
  192. );
  193. $form['display_title']['hide_title'] = array(
  194. '#type' => 'select',
  195. '#title' => t('Title type'),
  196. '#default_value' => (int) $display->hide_title,
  197. '#options' => array(
  198. PANELS_TITLE_NONE => t('No title'),
  199. PANELS_TITLE_FIXED => t('Manually set'),
  200. PANELS_TITLE_PANE => t('From pane'),
  201. ),
  202. );
  203. $form['display_title']['title'] = array(
  204. '#type' => 'textfield',
  205. '#default_value' => $display->title,
  206. '#title' => t('Title'),
  207. '#description' => t('The title of this panel. If left blank, a default title may be used. If you want the title actually to be blank, change the "Title type" dropdown from "Manually Set" to "No Title".'),
  208. '#process' => array('ctools_dependent_process'),
  209. '#dependency' => array('edit-display-title-hide-title' => array(PANELS_TITLE_FIXED)),
  210. '#maxlength' => 255,
  211. );
  212. if (!empty($display->context)) {
  213. $form['display_title']['title']['#description'] .= ' ' . t('You may use substitutions in this title.');
  214. // We have to create a manual fieldset because fieldsets do not support IDs.
  215. // Use 'hidden' instead of 'markup' so that the process will run.
  216. // Add js for collapsible fieldsets manually
  217. // drupal_add_js('misc/form.js');
  218. // drupal_add_js('misc/collapse.js');
  219. // $form['display_title']['contexts_prefix'] = array(
  220. // '#type' => 'hidden',
  221. // '#id' => 'edit-display-substitutions',
  222. // '#prefix' => '<div><fieldset id="edit-display-substitutions" class="collapsed collapsible"><legend>' . t('Substitutions') . '</legend><div class="fieldset-wrapper">',
  223. // '#process' => array('ctools_dependent_process'),
  224. // '#dependency' => array('edit-display-title-hide-title' => array(PANELS_TITLE_FIXED)),
  225. // );
  226. $rows = array();
  227. foreach ($display->context as $context) {
  228. foreach (ctools_context_get_converters('%' . check_plain($context->keyword) . ':', $context) as $keyword => $title) {
  229. $rows[] = array(
  230. check_plain($keyword),
  231. t('@identifier: @title', array('@title' => $title, '@identifier' => $context->identifier)),
  232. );
  233. }
  234. }
  235. $header = array(t('Keyword'), t('Value'));
  236. $form['display_title']['contexts'] = array(
  237. '#type' => 'fieldset',
  238. '#title' => t('Substitutions'),
  239. '#collapsible' => TRUE,
  240. '#collapsed' => TRUE,
  241. '#value' => theme('table', array('header' => $header, 'rows' => $rows)),
  242. // '#process' => array('form_process_fieldset', 'ctools_dependent_process'),
  243. // '#id' => 'edit-display-title-context',
  244. // '#dependency' => array('edit-display-title-hide-title' => array(PANELS_TITLE_FIXED)),
  245. );
  246. // $form['display_title']['contexts_suffix'] = array(
  247. // '#value' => '</div></fieldset></div>',
  248. // );
  249. }
  250. }
  251. // TODO doc the ability to do this as part of the API
  252. if (!empty($layout['settings form']) && function_exists($layout['settings form'])) {
  253. $form['layout_settings'] = $layout['settings form']($display, $layout, $display->layout_settings);
  254. }
  255. $form['layout_settings']['#tree'] = TRUE;
  256. return $form;
  257. }
  258. /**
  259. * Validate the layout settings form.
  260. */
  261. function panels_edit_display_settings_form_validate($form, &$form_state) {
  262. if ($function = panels_plugin_get_function('layouts', $form_state['layout'], 'settings validate')) {
  263. $function($form_state['values']['layout_settings'], $form['layout_settings'], $form_state['display'], $form_state['layout'], $form_state['display']->layout_settings);
  264. }
  265. }
  266. /**
  267. * Store changes from the layout settings form.
  268. */
  269. function panels_edit_display_settings_form_submit($form, &$form_state) {
  270. $display = &$form_state['display'];
  271. if ($function = panels_plugin_get_function('layouts', $form_state['layout'], 'settings submit')) {
  272. $function($form_state['values']['layout_settings'], $display, $form_state['layout'], $display->layout_settings);
  273. }
  274. // Since not all layouts have layout settings, check here in case of notices.
  275. if (isset($form_state['values']['layout_settings'])) {
  276. $display->layout_settings = $form_state['values']['layout_settings'];
  277. }
  278. if (isset($form_state['values']['display_title']['title'])) {
  279. $display->title = $form_state['values']['display_title']['title'];
  280. $display->hide_title = $form_state['values']['display_title']['hide_title'];
  281. }
  282. }