panels_mini.module

Tracking 5.x-2.x branch
  1. drupal
    1. 5 contributions/panels/panels_mini/panels_mini.module
    2. 6 contributions/panels/panels_mini/panels_mini.module
    3. 7 contributions/panels/panels_mini/panels_mini.module

panels_mini.module

This module provides mini panels which are basically panels that can be used within blocks or other panels.

Functions & methods

NameDescription
panels_mini_add_mini_panelForm to add a mini panel to a panel.
panels_mini_add_pageHandle the add mini panel page.
panels_mini_blockImplementation of hook_block().
panels_mini_contentRender a mini panel called from a panels display.
panels_mini_content_typesReturn each available mini panel available as a subtype.
panels_mini_context_formForm to edit the context settings of a mini panel.
panels_mini_context_form_submitProcess submission of the mini panel edit form.
panels_mini_default_panelsGet all 'default' mini panels.
panels_mini_deleteDelete a mini panel.
panels_mini_delete_confirmProvide a form to confirm deletion of a mini panel.
panels_mini_delete_confirm_submitHandle the submit button to delete a mini panel.
panels_mini_disable_pageDisable a default mini panel.
panels_mini_editEdit a mini panel.
panels_mini_edit_contentPass through to the panels content editor.
panels_mini_edit_contextForm to edit context features of a mini panel.
panels_mini_edit_exportPage callback to export a mini panel to PHP code.
panels_mini_edit_formForm to edit the settings of a mini panel.
panels_mini_edit_form_submitProcess submission of the mini panel edit form.
panels_mini_edit_form_validateValidate submission of the mini panel edit form.
panels_mini_edit_layoutPass through to the panels layout editor.
panels_mini_edit_layout_settingsPass through to the panels layout settings editor.
panels_mini_edit_mini_panelReturns an edit form for the mini panel.
panels_mini_enable_pageEnable a default mini panel.
panels_mini_exportExport a mini panel into PHP code for use in import.
panels_mini_fieldsA list of the fields used in the panel_mini table.
panels_mini_get_idStatically store all used IDs to ensure all mini panels get a unique id.
panels_mini_helpImplementation of hook_help().
panels_mini_import_formForm for the mini panel import.
panels_mini_import_form_submitHandle the submit button on importing a mini panel.
panels_mini_import_miniPage callback to import a mini panel from PHP code.
panels_mini_list_pageProvide a list of mini panels, with links to edit or delete them.
panels_mini_loadLoad a mini panel.
panels_mini_load_allFetch all mini panels in the system.
panels_mini_menuImplementation of hook_menu().
panels_mini_menu_items
panels_mini_panels_block_infoRemove the block version of mini panels from being available content types.
panels_mini_panels_content_typesExpose all mini panels to our own system.
panels_mini_panels_exportablesImplementation of hook_panels_exportables().
panels_mini_permImplementation of hook_perm().
panels_mini_preview_panelProvide an administrative preview of a mini panel.
panels_mini_sanitizeSanitize a mini panel, to guarantee certain data is as we believe it will be.
panels_mini_saveSave a mini panel.
panels_mini_settingsSettings for mini panels.
panels_mini_title_mini_panel

File

View source
  1. <?php
  2. /**
  3. * @file panels_mini.module
  4. *
  5. * This module provides mini panels which are basically panels that can be
  6. * used within blocks or other panels.
  7. */
  8. /**
  9. * Implementation of hook_help().
  10. */
  11. function panels_mini_help($section = '') {
  12. switch ($section) {
  13. case 'admin/panels/panel-mini':
  14. case 'admin/panels/panel-mini/list':
  15. $output = '<p>';
  16. $output .= t('You can edit existing mini panels, or click add to create a new one.');
  17. $output .= '</p>';
  18. break;
  19. case 'admin/panels/panel-mini/add':
  20. $output = '<p>';
  21. $output .= t('Mini panels are the small variants of panel pages. Instead of pages, they define blocks.');
  22. $output .= '</p>';
  23. break;
  24. }
  25. return $output;
  26. }
  27. /**
  28. * Implementation of hook_perm().
  29. */
  30. function panels_mini_perm() {
  31. return array('create mini panels', 'administer mini panels');
  32. }
  33. /**
  34. * Implementation of hook_menu().
  35. */
  36. function panels_mini_menu($may_cache) {
  37. if ($may_cache) {
  38. $access = user_access('create mini panels');
  39. $items[] = array(
  40. 'path' => 'admin/panels/panel-mini',
  41. 'title' => t('Mini panels'),
  42. 'access' => $access,
  43. 'callback' => 'panels_mini_list_page',
  44. 'description' => t('Create and administer mini panels (panels exposed as blocks).'),
  45. );
  46. $items[] = array(
  47. 'path' => 'admin/panels/panel-mini/list',
  48. 'title' => t('List'),
  49. 'access' => $access,
  50. 'callback' => 'panels_mini_list_page',
  51. 'weight' => -10,
  52. 'type' => MENU_DEFAULT_LOCAL_TASK,
  53. );
  54. $items[] = array(
  55. 'path' => 'admin/panels/panel-mini/add',
  56. 'title' => t('Add'),
  57. 'access' => $access,
  58. 'callback' => 'panels_mini_add_page',
  59. 'type' => MENU_LOCAL_TASK,
  60. );
  61. $items[] = array(
  62. 'path' => 'admin/panels/panel-mini/import',
  63. 'title' => t('Import'),
  64. 'access' => $access,
  65. 'callback' => 'panels_mini_import_mini',
  66. 'type' => MENU_LOCAL_TASK,
  67. );
  68. $items[] = array(
  69. 'path' => 'admin/panels/panel-mini/settings',
  70. 'title' => t('Settings'),
  71. 'access' => $access,
  72. 'callback' => 'panels_mini_settings',
  73. 'type' => MENU_LOCAL_TASK,
  74. );
  75. $items[] = array(
  76. 'path' => 'admin/panels/panel-mini/disable',
  77. 'access' => $access,
  78. 'callback' => 'panels_mini_disable_page',
  79. 'weight' => -1,
  80. 'type' => MENU_CALLBACK,
  81. );
  82. $items[] = array(
  83. 'path' => 'admin/panels/panel-mini/enable',
  84. 'access' => $access,
  85. 'callback' => 'panels_mini_enable_page',
  86. 'weight' => -1,
  87. 'type' => MENU_CALLBACK,
  88. );
  89. }
  90. else {
  91. if (arg(0) == 'admin' && arg(1) == 'panels' && arg(2) == 'panel-mini') {
  92. $mini = panels_mini_load(arg(3));
  93. if ($mini && empty($mini->disabled)) {
  94. $items = array();
  95. panels_mini_menu_items($items, "admin/panels/panel-mini/$mini->name", $mini);
  96. }
  97. }
  98. }
  99. return $items;
  100. }
  101. function panels_mini_menu_items(&$items, $base, $panel_mini) {
  102. $access = user_access('administer mini panels');
  103. if ($access) {
  104. $items[] = array(
  105. 'path' => $base,
  106. 'title' => t('Preview'),
  107. 'access' => $access,
  108. 'callback' => 'panels_mini_preview_panel',
  109. 'callback arguments' => array($panel_mini),
  110. 'weight' => -10,
  111. 'type' => MENU_CALLBACK,
  112. );
  113. $items[] = array(
  114. 'path' => $base . '/preview',
  115. 'title' => t('Preview'),
  116. 'access' => $access,
  117. 'callback' => 'panels_mini_preview_panel',
  118. 'callback arguments' => array($panel_mini),
  119. 'weight' => -10,
  120. 'type' => MENU_DEFAULT_LOCAL_TASK,
  121. );
  122. $items[] = array(
  123. 'path' => $base .'/edit/layout',
  124. 'title' => t('Layout'),
  125. 'access' => $access,
  126. 'callback' => 'panels_mini_edit_layout',
  127. 'callback arguments' => array($panel_mini),
  128. 'weight' => -9,
  129. 'type' => MENU_LOCAL_TASK,
  130. );
  131. $items[] = array(
  132. 'path' => $base .'/edit/general',
  133. 'title' => t('Settings'),
  134. 'access' => $access,
  135. 'callback' => 'panels_mini_edit',
  136. 'callback arguments' => array($panel_mini),
  137. 'weight' => -5,
  138. 'type' => MENU_LOCAL_TASK,
  139. );
  140. $items[] = array(
  141. 'path' => $base .'/edit/settings',
  142. 'title' => t('Layout settings'),
  143. 'access' => $access,
  144. 'callback' => 'panels_mini_edit_layout_settings',
  145. 'callback arguments' => array($panel_mini),
  146. 'weight' => -3,
  147. 'type' => MENU_LOCAL_TASK,
  148. );
  149. $items[] = array(
  150. 'path' => $base . '/edit/context',
  151. 'title' => t('Context'),
  152. 'access' => $access,
  153. 'callback' => 'panels_mini_edit_context',
  154. 'callback arguments' => array($panel_mini),
  155. 'weight' => -2,
  156. 'type' => MENU_LOCAL_TASK,
  157. );
  158. $items[] = array(
  159. 'path' => $base .'/edit/content',
  160. 'title' => t('Content'),
  161. 'access' => $access,
  162. 'callback' => 'panels_mini_edit_content',
  163. 'callback arguments' => array($panel_mini),
  164. 'weight' => -1,
  165. 'type' => MENU_LOCAL_TASK,
  166. );
  167. $items[] = array(
  168. 'path' => $base . '/export',
  169. 'title' => t('Export'),
  170. 'access' => $access,
  171. 'callback' => 'drupal_get_form',
  172. 'callback arguments' => array('panels_mini_edit_export', $panel_mini),
  173. 'weight' => 0,
  174. 'type' => MENU_LOCAL_TASK,
  175. );
  176. $items[] = array(
  177. 'path' => $base .'/delete',
  178. 'title' => t('Delete mini panel'),
  179. 'access' => user_access('create mini panels'),
  180. 'callback' => 'drupal_get_form',
  181. 'callback arguments' => array('panels_mini_delete_confirm', $panel_mini),
  182. 'type' => MENU_CALLBACK,
  183. );
  184. }
  185. }
  186. // ---------------------------------------------------------------------------
  187. // Mini panel administrative pages.
  188. /**
  189. * Settings for mini panels.
  190. */
  191. function panels_mini_settings() {
  192. panels_load_include('common');
  193. return drupal_get_form('panels_common_settings', 'panels_mini');
  194. }
  195. /**
  196. * Provide a list of mini panels, with links to edit or delete them.
  197. */
  198. function panels_mini_list_page() {
  199. panels_load_include('plugins');
  200. $layouts = panels_get_layouts();
  201. $items = array();
  202. $sorts = array();
  203. $header = array(
  204. array('data' => t('Title'), 'field' => 'title'),
  205. array('data' => t('Name'), 'field' => 'name', 'sort' => 'asc'),
  206. array('data' => t('Type'), 'field' => 'type'),
  207. t('Layout'),
  208. t('Operations'),
  209. );
  210. // Load all mini panels and their displays.
  211. $panel_minis = panels_mini_load_all();
  212. $dids = array();
  213. foreach ($panel_minis as $panel_mini) {
  214. if (empty($panel_mini->display)) {
  215. $dids[] = $panel_mini->did;
  216. }
  217. }
  218. $displays = panels_load_displays($dids);
  219. foreach ($panel_minis as $panel_mini) {
  220. $ops = array();
  221. if (empty($panel_mini->disabled)) {
  222. $ops[] = l(t('Edit'), "admin/panels/panel-mini/$panel_mini->name/edit/general");
  223. $ops[] = l(t('Export'), "admin/panels/panel-mini/$panel_mini->name/export");
  224. }
  225. if ($panel_mini->type != t('Default')) {
  226. $text = ($panel_mini->type == t('Overridden')) ? t('Revert') : t('Delete');
  227. $ops[] = l($text, "admin/panels/panel-mini/$panel_mini->name/delete");
  228. }
  229. else {
  230. if (empty($panel_mini->disabled)) {
  231. $ops[] = l(t('Disable'), "admin/panels/panel-mini/disable/$panel_mini->name", NULL, drupal_get_destination());
  232. }
  233. else {
  234. $ops[] = l(t('Enable'), "admin/panels/panel-mini/enable/$panel_mini->name", NULL, drupal_get_destination());
  235. }
  236. }
  237. $item = array();
  238. $item[] = check_plain($panel_mini->title);
  239. $item[] = check_plain($panel_mini->name);
  240. // this is safe as it's always programmatic
  241. $item[] = $panel_mini->type;
  242. if (empty($panel_mini->display)) {
  243. $panel_mini->display = $displays[$panel_mini->did];
  244. }
  245. $item[] = check_plain($layouts[$panel_mini->display->layout]['title']);
  246. $item[] = implode(' | ', $ops);
  247. $items[] = $item;
  248. $ts = tablesort_init($header);
  249. switch ($ts['sql']) {
  250. case 'title':
  251. $sorts[] = $item[0];
  252. break;
  253. case 'name':
  254. default:
  255. $sorts[] = $item[1];
  256. break;
  257. case 'type':
  258. $sorts[] = $panel_mini->type . $item[0];
  259. break;
  260. }
  261. }
  262. if (drupal_strtolower($ts['sort']) == 'desc') {
  263. arsort($sorts);
  264. }
  265. else {
  266. asort($sorts);
  267. }
  268. $i = array();
  269. foreach ($sorts as $id => $title) {
  270. $i[] = $items[$id];
  271. }
  272. $output = theme('table', $header, $i);
  273. return $output;
  274. }
  275. /**
  276. * Provide a form to confirm deletion of a mini panel.
  277. */
  278. function panels_mini_delete_confirm($panel_mini) {
  279. if (!is_object($panel_mini)) {
  280. $panel_mini = panels_mini_load($panel_mini);
  281. }
  282. $form['pid'] = array('#type' => 'value', '#value' => $panel_mini->pid);
  283. $form['did'] = array('#type' => 'value', '#value' => $panel_mini->did);
  284. return confirm_form($form,
  285. t('Are you sure you want to delete the mini panel "@title"?', array('@title' => $panel_mini->title)),
  286. $_GET['destination'] ? $_GET['destination'] : 'admin/panels/panel-mini',
  287. t('This action cannot be undone.'),
  288. t('Delete'), t('Cancel')
  289. );
  290. }
  291. /**
  292. * Handle the submit button to delete a mini panel.
  293. */
  294. function panels_mini_delete_confirm_submit($form_id, $form) {
  295. if ($form['confirm']) {
  296. panels_mini_delete((object) $form);
  297. return 'admin/panels/panel-mini';
  298. }
  299. }
  300. /**
  301. * Provide an administrative preview of a mini panel.
  302. */
  303. function panels_mini_preview_panel($mini) {
  304. $mini->display->args = array();
  305. $mini->display->css_id = panels_mini_get_id($mini->name);
  306. panels_load_include('plugins');
  307. $mini->context = $mini->display->context = panels_context_load_contexts($mini);
  308. drupal_set_title(filter_xss_admin($mini->title));
  309. return panels_render_display($mini->display);
  310. }
  311. /**
  312. * Page callback to export a mini panel to PHP code.
  313. */
  314. function panels_mini_edit_export($panel_mini) {
  315. if (!is_object($panel_mini)) {
  316. $panel_mini = panels_mini_load($panel_mini);
  317. }
  318. drupal_set_title(check_plain($panel_mini->title));
  319. $code = panels_mini_export($panel_mini);
  320. $lines = substr_count($code, "\n");
  321. $form['code'] = array(
  322. '#type' => 'textarea',
  323. '#title' => $panel_mini->title,
  324. '#default_value' => $code,
  325. '#rows' => $lines,
  326. );
  327. return $form;
  328. }
  329. /**
  330. * Page callback to import a mini panel from PHP code.
  331. */
  332. function panels_mini_import_mini() {
  333. if ($_POST['form_id'] == 'panels_mini_edit_form') {
  334. $panel_mini = unserialize($_SESSION['pm_import']);
  335. drupal_set_title(t('Import panel mini "@s"', array('@s' => $panel_mini->title)));
  336. return drupal_get_form('panels_mini_edit_form', $panel_mini);
  337. }
  338. return drupal_get_form('panels_mini_import_form');
  339. }
  340. /**
  341. * Form for the mini panel import.
  342. */
  343. function panels_mini_import_form() {
  344. $form['panel_mini'] = array(
  345. '#type' => 'textarea',
  346. '#title' => t('Panel mini code'),
  347. '#cols' => 60,
  348. '#rows' => 15,
  349. '#description' => t('Cut and paste the results of an exported mini panel here.'),
  350. );
  351. $form['submit'] = array(
  352. '#type' => 'submit',
  353. '#value' => t('Import'),
  354. );
  355. $form['#redirect'] = NULL;
  356. return $form;
  357. }
  358. /**
  359. * Handle the submit button on importing a mini panel.
  360. */
  361. function panels_mini_import_form_submit($form_id, $form) {
  362. ob_start();
  363. eval($form['panel_mini']);
  364. ob_end_clean();
  365. if (isset($mini)) {
  366. drupal_set_title(t('Import mini panel "@s"', array('@s' => $mini->title)));
  367. // As $mini contains non-stdClass objects,
  368. // it needs to be serialized before being stored in the session variable.
  369. $_SESSION['pm_import'] = serialize($mini);
  370. $output = drupal_get_form('panels_mini_edit_form', $mini);
  371. print theme('page', $output);
  372. exit;
  373. }
  374. else {
  375. drupal_set_message(t('Unable to get a mini panel out of that.'));
  376. }
  377. }
  378. /**
  379. * Handle the add mini panel page.
  380. */
  381. function panels_mini_add_page($layout = NULL) {
  382. panels_load_include('plugins');
  383. $layouts = panels_get_layouts();
  384. if ($layout === NULL) {
  385. foreach ($layouts as $id => $layout) {
  386. $output .= panels_print_layout_link($id, $layout, $_GET['q'] .'/'. $id);
  387. }
  388. return $output;
  389. }
  390. if (!$layouts[$layout]) {
  391. return drupal_not_found();
  392. }
  393. $panel_mini = new stdClass();
  394. $panel_mini->display = panels_new_display();
  395. $panel_mini->display->layout = $layout;
  396. $panel_mini->pid = 'new';
  397. $panel_mini->did = 'new';
  398. return panels_mini_edit($panel_mini);
  399. }
  400. /**
  401. * Edit a mini panel.
  402. *
  403. * Called from both the add and edit points to provide for common flow.
  404. */
  405. function panels_mini_edit($panel_mini) {
  406. if (!is_object($panel_mini)) {
  407. $panel_mini = panels_mini_load($panel_mini);
  408. }
  409. drupal_set_title(check_plain($panel_mini->title));
  410. return drupal_get_form('panels_mini_edit_form', $panel_mini);
  411. }
  412. /**
  413. * Form to edit the settings of a mini panel.
  414. */
  415. function panels_mini_edit_form($panel_mini) {
  416. panels_load_include('common');
  417. drupal_add_css(panels_get_path('css/panels_admin.css'));
  418. $form['pid'] = array(
  419. '#type' => 'value',
  420. '#value' => $panel_mini->pid,
  421. );
  422. $form['panel_mini'] = array(
  423. '#type' => 'value',
  424. '#value' => $panel_mini,
  425. );
  426. $form['right'] = array(
  427. '#prefix' => '<div class="layout-container">',
  428. '#suffix' => '</div>',
  429. );
  430. $form['left'] = array(
  431. '#prefix' => '<div class="info-container">',
  432. '#suffix' => '</div>',
  433. );
  434. $form['left']['settings'] = array(
  435. '#type' => 'fieldset',
  436. '#title' => t('Settings'),
  437. );
  438. $form['left']['settings']['title'] = array(
  439. '#type' => 'textfield',
  440. '#size' => 24,
  441. '#default_value' => $panel_mini->title,
  442. '#title' => t('Mini panel title'),
  443. '#description' => t('The title for this mini panel. It can be overridden in the block configuration.'),
  444. );
  445. $form['left']['settings']['name'] = array(
  446. '#type' => 'textfield',
  447. '#size' => 24,
  448. '#default_value' => $panel_mini->name,
  449. '#title' => t('Mini panel name'),
  450. '#description' => t('A unique name used to identify this panel page internally. It must be only be alpha characters and underscores. No spaces, numbers or uppercase characters.'),
  451. );
  452. $form['left']['settings']['category'] = array(
  453. '#type' => 'textfield',
  454. '#size' => 24,
  455. '#default_value' => $panel_mini->category,
  456. '#title' => t('Mini panel category'),
  457. '#description' => t("The category that this mini-panel will be grouped into on the Add Content form. Only upper and lower-case alphanumeric characters are allowed. If left blank, defaults to 'Mini panels'."),
  458. );
  459. panels_load_include('plugins');
  460. $panel_mini->context = $panel_mini->display->context = panels_context_load_contexts($panel_mini);
  461. $form['right']['layout'] = array(
  462. '#type' => 'fieldset',
  463. '#title' => t('Layout'),
  464. );
  465. $layout = panels_get_layout($panel_mini->display->layout);
  466. $form['right']['layout']['layout-icon'] = array(
  467. '#value' => panels_print_layout_icon($panel_mini->display->layout, $layout),
  468. );
  469. $form['right']['layout']['layout-display'] = array(
  470. '#value' => check_plain($layout['title']),
  471. );
  472. $form['right']['layout']['layout-content'] = array(
  473. '#value' => theme('panels_common_content_list', $panel_mini->display),
  474. );
  475. $contexts = theme('panels_common_context_list', $panel_mini);
  476. if ($contexts) {
  477. $form['right']['context'] = array(
  478. '#type' => 'fieldset',
  479. '#title' => t('Contexts'),
  480. );
  481. $form['right']['context']['context'] = array(
  482. '#value' => $contexts,
  483. );
  484. }
  485. $label = ($panel_mini->pid == 'new') ? t('Save and proceed') : t('Save');
  486. $form['submit'] = array(
  487. '#type' => 'submit',
  488. '#value' => $label,
  489. );
  490. return $form;
  491. }
  492. /**
  493. * Validate submission of the mini panel edit form.
  494. */
  495. function panels_mini_edit_form_validate($form_id, $form_values, $form) {
  496. // Test uniqueness of name:
  497. if (!$form_values['name']) {
  498. form_error($form['left']['settings']['name'], t('Panel mini name is required.'));
  499. }
  500. else if (preg_match("/[^A-Za-z0-9_]/", $form_values['name'])) {
  501. form_error($form['left']['settings']['name'], t('Name must be alphanumeric or underscores only.'));
  502. }
  503. else if (preg_match("/[^A-Za-z0-9 ]/", $form_values['category'])) {
  504. form_error($form['left']['settings']['category'], t('Categories may contain only alphanumerics or spaces.'));
  505. }
  506. else {
  507. $query = "SELECT pid FROM {panels_mini} WHERE name = '%s'";
  508. if (!empty($form_values['pid']) && is_numeric($form_values['pid'])) {
  509. $query .= " AND pid != $form_values[pid]";
  510. }
  511. if (db_result(db_query($query, $form_values['name']))) {
  512. form_error($form['left']['settings']['name'], t('Panel name must be unique.'));
  513. }
  514. }
  515. }
  516. /**
  517. * Process submission of the mini panel edit form.
  518. */
  519. function panels_mini_edit_form_submit($form_id, $form_values) {
  520. $panel_mini = $form_values['panel_mini'];
  521. if ($panel_mini->pid != 'new' && $panel_mini->name != $form_values['name']) {
  522. // update all existing mini panels to point to this one appropriately.
  523. db_query("UPDATE {blocks} b SET delta = '%s' WHERE b.module = 'panels_mini' AND b.delta = '%s'", $form_values['name'], $panel_mini->name);
  524. // Above was blocks; these are actual panel panes.
  525. $result = db_query("SELECT * FROM {panels_pane} WHERE type = 'panels_mini' and subtype = '%s'", $panel_mini->name);
  526. while ($pane = db_fetch_object($result)) {
  527. $conf = unserialize($pane->configuration);
  528. $conf['name'] = $form_values['name'];
  529. db_query("UPDATE {panels_pane} SET configuration = '%s', subtype = '%s' WHERE pid = %d", serialize($conf), $conf['name'], $pane->pid);
  530. }
  531. }
  532. $panel_mini->title = $form_values['title'];
  533. $panel_mini->name = $form_values['name'];
  534. $panel_mini->category = empty($form_values['category']) ? '' : $form_values['category'];
  535. if ($panel_mini->pid == 'new') {
  536. unset($_SESSION['pm_import']);
  537. drupal_set_message(t('Your new mini panel %title has been saved.', array('%title' => $panel_mini->title)));
  538. panels_mini_save($panel_mini);
  539. $GLOBALS['form_values']['pid'] = $panel_mini->pid;
  540. $layout = panels_get_layout($panel_mini->display->layout);
  541. if ($layout['settings form']) {
  542. return "admin/panels/panel-mini/$panel_mini->name/edit/settings/next";
  543. }
  544. return "admin/panels/panel-mini/$panel_mini->name/edit/context/next";
  545. }
  546. else {
  547. drupal_set_message(t('Your changes have been saved.'));
  548. panels_mini_save($panel_mini);
  549. }
  550. }
  551. /**
  552. * Form to edit context features of a mini panel.
  553. */
  554. function panels_mini_edit_context($panel_mini, $next = NULL) {
  555. if (!empty($_POST)) {
  556. $panel_mini = panels_common_cache_get('panel_object:panel_mini', $panel_mini->name);
  557. }
  558. else {
  559. panels_common_cache_set('panel_object:panel_mini', $panel_mini->name, $panel_mini);
  560. }
  561. drupal_set_title(check_plain($panel_mini->title));
  562. return drupal_get_form('panels_mini_context_form', $panel_mini, $next);
  563. }
  564. /**
  565. * Form to edit the context settings of a mini panel.
  566. */
  567. function panels_mini_context_form($panel_mini, $next = NULL) {
  568. drupal_add_css(panels_get_path('css/panels_admin.css'));
  569. panels_load_include('plugins');
  570. $layout = panels_get_layout($panel_mini->display->layout);
  571. $form['pid'] = array(
  572. '#type' => 'value',
  573. '#value' => $panel_mini->pid,
  574. );
  575. $form['panel_mini'] = array(
  576. '#type' => 'value',
  577. '#value' => $panel_mini,
  578. );
  579. $form['right'] = array(
  580. '#prefix' => '<div class="right-container">',
  581. '#suffix' => '</div>',
  582. );
  583. $form['left'] = array(
  584. '#prefix' => '<div class="left-container">',
  585. '#suffix' => '</div>',
  586. );
  587. panels_load_include('common');
  588. $settings = panels_common_add_context_form('panel_mini', $form, $form['right']['contexts_table'], $panel_mini);
  589. $settings += panels_common_add_required_context_form('panel_mini', $form, $form['left']['required_contexts_table'], $panel_mini);
  590. $settings += panels_common_add_relationship_form('panel_mini', $form, $form['right']['relationships_table'], $panel_mini);
  591. panels_common_add_context_js($settings);
  592. $label = $next ? t('Save and proceed') : t('Save');
  593. $form['submit'] = array(
  594. '#type' => 'submit',
  595. '#value' => $label,
  596. );
  597. return $form;
  598. }
  599. /**
  600. * Process submission of the mini panel edit form.
  601. */
  602. function panels_mini_context_form_submit($form_id, $form_values) {
  603. $panel_mini = $form_values['panel_mini'];
  604. // Organize these from the common form.
  605. panels_common_save_context('context', $panel_mini->contexts, $form_values);
  606. panels_common_save_context('requiredcontext', $panel_mini->requiredcontexts, $form_values);
  607. panels_common_save_context('relationship', $panel_mini->relationships, $form_values);
  608. drupal_set_message(t('Your changes have been saved.'));
  609. panels_mini_save($panel_mini);
  610. panels_common_cache_clear('panel_object:panel_mini', $panel_mini->name);
  611. if ($form_values['submit'] == t('Save and proceed')) {
  612. return "admin/panels/panel-mini/$panel_mini->name/edit/content";
  613. }
  614. }
  615. /**
  616. * Enable a default mini panel.
  617. */
  618. function panels_mini_enable_page($name = NULL) {
  619. $defaults = panels_mini_default_panels();
  620. if (isset($defaults[$name])) {
  621. $status = variable_get('panel_mini_defaults', array());
  622. $status[$name] = FALSE;
  623. variable_set('panel_mini_defaults', $status);
  624. drupal_set_message(t('Panel mini enabled'));
  625. }
  626. drupal_goto();
  627. }
  628. /**
  629. * Disable a default mini panel.
  630. */
  631. function panels_mini_disable_page($name = NULL) {
  632. $defaults = panels_mini_default_panels();
  633. if (isset($defaults[$name])) {
  634. $status = variable_get('panel_mini_defaults', array());
  635. $status[$name] = TRUE;
  636. variable_set('panel_mini_defaults', $status);
  637. drupal_set_message(t('Panel mini disabled'));
  638. }
  639. drupal_goto();
  640. }
  641. /**
  642. * Pass through to the panels content editor.
  643. */
  644. function panels_mini_edit_content($panel_mini) {
  645. if (!is_object($panel_mini)) {
  646. $panel_mini = panels_mini_load($panel_mini);
  647. }
  648. panels_load_include('plugins');
  649. // Collect a list of contexts required by the arguments on this page.
  650. $panel_mini->display->context = $contexts = panels_context_load_contexts($panel_mini);
  651. panels_load_include('common');
  652. $content_types = panels_common_get_allowed_types('panels_mini', $contexts);
  653. $output = panels_edit($panel_mini->display, NULL, $content_types);
  654. if (is_object($output)) {
  655. $panel_mini->display = $output;
  656. $panel_mini->did = $output->did;
  657. panels_mini_save($panel_mini);
  658. drupal_goto("admin/panels/panel-mini/$panel_mini->name/edit/content");
  659. }
  660. // Print this with theme('page') so that blocks are disabled while editing a display.
  661. // This is important because negative margins in common block layouts (i.e, Garland)
  662. // messes up the drag & drop.
  663. drupal_set_title(check_plain($panel_mini->title));
  664. print theme('page', $output, FALSE);
  665. }
  666. /**
  667. * Pass through to the panels layout editor.
  668. */
  669. function panels_mini_edit_layout($panel_mini) {
  670. if (!is_object($panel_mini)) {
  671. $panel_mini = panels_mini_load($panel_mini);
  672. }
  673. $output = panels_edit_layout($panel_mini->display, t('Save'));
  674. if (is_object($output)) {
  675. $panel_mini->display = $output;
  676. $panel_mini->did = $output->did;
  677. panels_mini_save($panel_mini);
  678. drupal_goto("admin/panels/panel-mini/$panel_mini->name/edit/layout");
  679. }
  680. drupal_set_title(check_plain($panel_mini->title));
  681. return $output;
  682. }
  683. /**
  684. * Pass through to the panels layout settings editor.
  685. */
  686. function panels_mini_edit_layout_settings($panel_mini, $next = NULL) {
  687. if (!is_object($panel_mini)) {
  688. $panel_mini = panels_mini_load($panel_mini);
  689. }
  690. if (empty($next)) {
  691. $button = t('Save');
  692. $dest = "admin/panels/panel-mini/$panel_mini->name/edit/settings";
  693. }
  694. else {
  695. $button = t('Save and proceed');
  696. $dest = "admin/panels/panel-mini/$panel_mini->name/edit/context/next";
  697. }
  698. $output = panels_edit_layout_settings($panel_mini->display, $button, NULL, $panel_mini->title);
  699. if (is_object($output)) {
  700. $panel_mini->display = $output;
  701. $panel_mini->did = $output->did;
  702. panels_mini_save($panel_mini);
  703. drupal_goto($dest);
  704. }
  705. drupal_set_title(check_plain($panel_mini->title));
  706. return $output;
  707. }
  708. // ---------------------------------------------------------------------------
  709. // Allow the rest of the system access to mini panels
  710. /**
  711. * Implementation of hook_block().
  712. *
  713. * Expose qualifying mini panels to Drupal's block system.
  714. */
  715. function panels_mini_block($op = 'list', $delta = 0, $edit = array()) {
  716. if ($op == 'list') {
  717. $blocks = array();
  718. $minis = panels_mini_load_all();
  719. foreach ($minis as $panel_mini) {
  720. if (empty($panel_mini->disabled) && empty($panel_mini->requiredcontext)) {
  721. $title = $panel_mini->hide_title ? t('Mini panel: %title (Title will be hidden)', array('%title' => $panel_mini->title)) : t('Mini panel: %title', array('%title' => $panel_mini->title));
  722. $blocks[$panel_mini->pid] = array(
  723. 'info' => $title,
  724. );
  725. }
  726. }
  727. return $blocks;
  728. }
  729. elseif ($op == 'view') {
  730. $panel_mini = panels_mini_load($delta);
  731. panels_load_include('plugins');
  732. $panel_mini->context = $panel_mini->display->context = panels_context_load_contexts($panel_mini);
  733. $panel_mini->display->css_id = panels_mini_get_id($panel_mini->name);
  734. $block = array(
  735. 'subject' => $panel_mini->hide_title ? '' : check_plain($panel_mini->title),
  736. 'content' => panels_render_display($panel_mini->display),
  737. );
  738. return $block;
  739. }
  740. }
  741. /**
  742. * Expose all mini panels to our own system.
  743. */
  744. function panels_mini_panels_content_types() {
  745. $items['panels_mini'] = array(
  746. 'title' => t('Mini panels'),
  747. 'content_types' => 'panels_mini_content_types',
  748. 'render callback' => 'panels_mini_content',
  749. 'add callback' => 'panels_mini_add_mini_panel',
  750. 'edit callback' => 'panels_mini_edit_mini_panel',
  751. 'title callback' => 'panels_mini_title_mini_panel',
  752. );
  753. return $items;
  754. }
  755. /**
  756. * Return each available mini panel available as a subtype.
  757. */
  758. function panels_mini_content_types() {
  759. $types = array();
  760. foreach (panels_mini_load_all() as $mini) {
  761. if (!empty($mini->disabled)) {
  762. continue;
  763. }
  764. $types[$mini->name] = array(
  765. 'title' => filter_xss_admin($mini->title),
  766. // For now mini panels will just use the contrib block icon.
  767. 'icon' => 'icon_contrib_block.png',
  768. 'path' => panels_get_path("content_types/block"),
  769. 'description' => filter_xss_admin($mini->title),
  770. 'category' => array(!empty($mini->category) ? filter_xss_admin($mini->category) : t('Mini panel'), -8),
  771. );
  772. if (!empty($mini->requiredcontexts)) {
  773. $types[$mini->name]['required context'] = array();
  774. foreach ($mini->requiredcontexts as $context) {
  775. $info = panels_get_context($context['name']);
  776. // TODO: allow an optional setting
  777. $types[$mini->name]['required context'][] = new panels_required_context($context['identifier'], $info['context name']);
  778. }
  779. }
  780. }
  781. return $types;
  782. }
  783. /**
  784. * Statically store all used IDs to ensure all mini panels get a unique id.
  785. */
  786. function panels_mini_get_id($name) {
  787. static $id_cache = array();
  788. $id = 'mini-panel-' . $name;
  789. if (!empty($id_cache[$name])) {
  790. $id .= "-" . $id_cache[$name]++;
  791. }
  792. else {
  793. $id_cache[$name] = 1;
  794. }
  795. return $id;
  796. }
  797. /**
  798. * Render a mini panel called from a panels display.
  799. */
  800. function panels_mini_content($conf, $panel_args, &$contexts) {
  801. $mini = panels_mini_load($conf['name']);
  802. if (!$mini) {
  803. return FALSE;
  804. }
  805. panels_load_include('plugins');
  806. // Load up any contexts we might be using.
  807. $context = panels_context_match_required_contexts($mini->requiredcontexts, $contexts);
  808. $mini->context = $mini->display->context = panels_context_load_contexts($mini, FALSE, $context);
  809. if (empty($mini) || !empty($mini->disabled)) {
  810. return;
  811. }
  812. $mini->display->args = $panel_args;
  813. $mini->display->css_id = panels_mini_get_id($conf['name']);
  814. $mini->display->owner = $mini;
  815. // unique ID of this mini.
  816. $mini->display->owner->id = $mini->name;
  817. $block = new stdClass();
  818. $block->module = 'panels_mini';
  819. $block->delta = $conf['name'];
  820. $block->content = panels_render_display($mini->display);
  821. if (!$mini->hide_title) {
  822. $block->subject = filter_xss_admin($mini->title);
  823. }
  824. return $block;
  825. }
  826. /**
  827. * Form to add a mini panel to a panel.
  828. */
  829. function panels_mini_add_mini_panel($id, $parents, $conf = array()) {
  830. $conf['name'] = $id;
  831. return panels_mini_edit_mini_panel($id, $parents, $conf);
  832. }
  833. /**
  834. * Returns an edit form for the mini panel.
  835. *
  836. * There isn't much here as most of this is set up at mini panel creation time.
  837. */
  838. function panels_mini_edit_mini_panel($id, $parents, $conf) {
  839. $form['name'] = array(
  840. '#type' => 'value',
  841. '#value' => $conf['name'],
  842. );
  843. return $form;
  844. }
  845. function panels_mini_title_mini_panel($conf) {
  846. $mini = panels_mini_load($conf['name']);
  847. if (!$mini) {
  848. return t('Deleted/missing mini panel @name', array('@name' => $conf['name']));
  849. }
  850. $title = filter_xss_admin($mini->title);
  851. if (empty($title)) {
  852. $title = t('Untitled mini panel');
  853. }
  854. return $title;
  855. }
  856. // ---------------------------------------------------------------------------
  857. // Database functions.
  858. /**
  859. * A list of the fields used in the panel_mini table.
  860. */
  861. function panels_mini_fields() {
  862. return array(
  863. 'name' => "'%s'",
  864. 'category' => "'%s'",
  865. 'title' => "'%s'",
  866. 'contexts' => "'%s'",
  867. 'requiredcontexts' => "'%s'",
  868. 'relationships' => "'%s'",
  869. );
  870. }
  871. /**
  872. * Sanitize a mini panel, to guarantee certain data is as we believe it will be.
  873. */
  874. function panels_mini_sanitize($panel_mini) {
  875. foreach (array('contexts', 'relationships', 'requiredcontexts') as $id) {
  876. if (!is_array($panel_mini->$id)) {
  877. $panel_mini->$id = array();
  878. }
  879. }
  880. return $panel_mini;
  881. }
  882. /**
  883. * Fetch all mini panels in the system.
  884. *
  885. * This function does not cache.
  886. */
  887. function panels_mini_load_all($page_size = 0) {
  888. static $results = array();
  889. if (array_key_exists($page_size, $results)) {
  890. return $results[$page_size];
  891. }
  892. $panels = $dids = array();
  893. $query = "SELECT * FROM {panels_mini}";
  894. if ($page_size) {
  895. $result = pager_query($query, $page_size);
  896. }
  897. else {
  898. $result = db_query($query);
  899. }
  900. while ($panel_mini = db_fetch_object($result)) {
  901. $panel_mini->contexts = (!empty($panel_mini->contexts)) ? unserialize($panel_mini->contexts) : array();
  902. $panel_mini->requiredcontexts = (!empty($panel_mini->requiredcontexts)) ? unserialize($panel_mini->requiredcontexts) : array();
  903. $panel_mini->relationships = (!empty($panel_mini->relationships)) ? unserialize($panel_mini->relationships) : array();
  904. $panel_mini->category = (!empty($panel_mini->category)) ? $panel_mini->category : 'Mini panels';
  905. $panel_mini->hide_title = ((bool) db_result(db_query('SELECT hide_title FROM {panels_display} WHERE did = %d', $panel_mini->did)));
  906. $panel_mini->type = t('Local');
  907. $panels[$panel_mini->name] = panels_mini_sanitize($panel_mini);
  908. }
  909. $status = variable_get('panel_mini_defaults', array());
  910. foreach (panels_mini_default_panels() as $panel_mini) {
  911. // Determine if default panel is enabled or disabled.
  912. if (isset($status[$panel_mini->name])) {
  913. $panel_mini->disabled = $status[$panel_mini->name];
  914. }
  915. if (!empty($panels[$panel_mini->name])) {
  916. $panels[$panel_mini->name]->type = t('Overridden');
  917. }
  918. else {
  919. $panel_mini->type = t('Default');
  920. $panels[$panel_mini->name] = $panel_mini;
  921. }
  922. }
  923. $results[$page_size] = $panels;
  924. return $results[$page_size];
  925. }
  926. /**
  927. * Load a mini panel.
  928. */
  929. function panels_mini_load($pid) {
  930. static $cache = array();
  931. if (array_key_exists($pid, $cache)) {
  932. return $cache[$pid];
  933. }
  934. if (!is_numeric($pid)) {
  935. $where = "name = '%s'";
  936. }
  937. else {
  938. $where = 'pid = %d';
  939. }
  940. $panel_mini = db_fetch_object(db_query("SELECT m.*, d.hide_title FROM {panels_mini} AS m INNER JOIN {panels_display} AS d ON m.did = d.did WHERE $where", $pid));
  941. if (!$panel_mini) {
  942. $defaults = panels_mini_default_panels();
  943. if (isset($defaults[$pid])) {
  944. $panel_mini = $defaults[$pid];
  945. $status = variable_get('panel_mini_defaults', array());
  946. // Determine if default panel is enabled or disabled.
  947. if (isset($status[$panel_mini->name])) {
  948. $panel_mini->disabled = $status[$panel_mini->name];
  949. }
  950. $cache[$pid] = $panel_mini;
  951. return $panel_mini;
  952. }
  953. return;
  954. }
  955. $panel_mini->contexts = (!empty($panel_mini->contexts)) ? unserialize($panel_mini->contexts) : array();
  956. $panel_mini->requiredcontexts = (!empty($panel_mini->requiredcontexts)) ? unserialize($panel_mini->requiredcontexts) : array();
  957. $panel_mini->relationships = (!empty($panel_mini->relationships)) ? unserialize($panel_mini->relationships) : array();
  958. // $panel_mini->hide_title = ((bool) db_result(db_query('SELECT hide_title FROM {panels_display} WHERE did = %d', $panel_mini->did)));
  959. $cache[$pid] = panels_mini_sanitize($panel_mini);
  960. $cache[$pid]->display = panels_load_display($cache[$pid]->did);
  961. return $cache[$pid];
  962. }
  963. /**
  964. * Save a mini panel.
  965. */
  966. function panels_mini_save(&$panel_mini) {
  967. $fields = $types = $values = $pairs = array();
  968. // Save the display if one was given to us.
  969. if (!empty($panel_mini->display)) {
  970. $display = panels_save_display($panel_mini->display);
  971. }
  972. // Ensure empty values get translated correctly.
  973. // Also make sure we don't mess up the original.
  974. $mini_clone = drupal_clone(panels_mini_sanitize($panel_mini));
  975. // If pid is set to our "magic value", this is an insert, otherwise an update.
  976. $insert = $mini_clone->pid && $mini_clone->pid == 'new';
  977. // Build arrays of fields and types (resp. pairs of both) and of values.
  978. foreach (panels_mini_fields() as $field => $type) {
  979. // Skip empty values.
  980. if (isset($mini_clone->$field)) {
  981. if ($insert) {
  982. $fields[] = $field;
  983. $types[] = $type;
  984. }
  985. else {
  986. $pairs[] = "$field = $type";
  987. }
  988. // Build the $values array, serializing some fields.
  989. $serialize = in_array($field, array('contexts', 'requiredcontexts', 'relationships'));
  990. $values[] = $serialize ? serialize($mini_clone->$field) : $mini_clone->$field;
  991. }
  992. }
  993. if ($insert) {
  994. // Determine the new primary key.
  995. $mini_clone->pid = db_next_id('{panels_mini}_pid');
  996. // Build the query adding the new primary key and the did.
  997. $sql = 'INSERT INTO {panels_mini} (' . implode(', ', $fields) . ', did, pid) VALUES (' . implode(', ', $types) . ', %d, %d)';
  998. $values[] = $display->did;
  999. }
  1000. else {
  1001. // Build the query filtering by the primary key.
  1002. $sql = 'UPDATE {panels_mini} SET ' . implode(', ', $pairs) . ' WHERE pid = %d';
  1003. }
  1004. $values[] = $mini_clone->pid;
  1005. db_query($sql, $values);
  1006. return $mini_clone->pid;
  1007. }
  1008. /**
  1009. * Delete a mini panel.
  1010. */
  1011. function panels_mini_delete($panel_mini) {
  1012. db_query("DELETE FROM {panels_mini} WHERE pid = %d", $panel_mini->pid);
  1013. db_query("DELETE FROM {blocks} WHERE module = 'panels_mini' AND delta = %d", $panel_mini->pid);
  1014. return panels_delete_display($panel_mini->did);
  1015. }
  1016. /**
  1017. * Export a mini panel into PHP code for use in import.
  1018. *
  1019. * The code returned from can be used directly in panels_mini_save().
  1020. */
  1021. function panels_mini_export($panel_mini, $prefix = '') {
  1022. $output = '';
  1023. $fields = panels_mini_fields();
  1024. $output .= $prefix . '$mini = new stdClass()' . ";\n";
  1025. $output .= $prefix . '$mini->pid = \'new\'' . ";\n";
  1026. foreach ($fields as $field => $sub) {
  1027. $output .= $prefix . ' $mini->' . $field . ' = ' . panels_var_export($panel_mini->$field, ' ') . ";\n";
  1028. }
  1029. // Export the primary display
  1030. $display = !empty($panel_mini->display) ? $panel_mini->display : panels_load_display($panel_mini->did);
  1031. $output .= panels_export_display($display, $prefix);
  1032. $output .= $prefix . '$mini->display = $display' . ";\n";
  1033. return $output;
  1034. }
  1035. /**
  1036. * Get all 'default' mini panels.
  1037. *
  1038. * @ingroup HookInvokers
  1039. */
  1040. function panels_mini_default_panels() {
  1041. $panels = module_invoke_all('default_panel_minis');
  1042. if (!is_array($panels)) {
  1043. $panels = array();
  1044. }
  1045. return $panels;
  1046. }
  1047. /**
  1048. * Remove the block version of mini panels from being available content types.
  1049. */
  1050. function panels_mini_panels_block_info($module, $delta, &$info) {
  1051. $info = NULL;
  1052. }
  1053. /**
  1054. * Implementation of hook_panels_exportables().
  1055. */
  1056. function panels_mini_panels_exportables($op = 'list', $panels = NULL, $name = 'foo') {
  1057. static $all_panels = NULL;
  1058. if ($op == 'list') {
  1059. if (empty($all_panels)) {
  1060. $all_panels = panels_mini_load_all();
  1061. }
  1062. foreach ($all_panels as $name => $panel) {
  1063. $return[$name] = check_plain($name) . ' (' . check_plain($panel->title) . ')';
  1064. }
  1065. return $return;
  1066. }
  1067. if ($op == 'export') {
  1068. $code = "/**\n";
  1069. $code .= " * Implementation of hook_default_panel_minis()\n";
  1070. $code .= " */\n";
  1071. $code .= "function " . $name . "_default_panel_minis() {\n";
  1072. foreach ($panels as $panel => $truth) {
  1073. $code .= panels_mini_export($all_panels[$panel], ' ');
  1074. $code .= ' $minis[\'' . check_plain($panel) . '\'] = $mini;' . "\n\n\n";
  1075. }
  1076. $code .= " return \$minis;\n";
  1077. $code .= "}\n";
  1078. return $code;
  1079. }
  1080. }