| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: panels_node.module,v 1.5.2.28 2010/10/29 21:50:22 merlinofchaos Exp $ 3 4 5 /** 6 * @file panels_node.module 7 * 8 * This module provides the "panel" node type. 9 * Panel nodes are useful to add additional content to the content area 10 * on a per-node base. 11 */ 12 13 // --------------------------------------------------------------------------- 14 // General Drupal hooks 15 16 /** 17 * Implementation of hook_perm(). 18 */ 19 function panels_node_perm() { 20 return array('create panel-nodes', 'edit any panel-nodes', 'edit own panel-nodes', 'administer panel-nodes', 'delete any panel-nodes', 'delete own panel-nodes'); 21 } 22 23 /** 24 * Implementation of hook_menu(). 25 */ 26 function panels_node_menu() { 27 // Safety: go away if CTools is not at an appropriate version. 28 if (!defined('PANELS_REQUIRED_CTOOLS_API') || !module_invoke('ctools', 'api_version', PANELS_REQUIRED_CTOOLS_API)) { 29 return array(); 30 } 31 32 $items['admin/build/panels/settings/panel-node'] = array( 33 'title' => 'Panel nodes', 34 'description' => 'Configure which content is available to add to panel node displays.', 35 'access arguments' => array('administer panel-nodes'), 36 'page callback' => 'panels_node_settings', 37 'type' => MENU_LOCAL_TASK, 38 ); 39 40 // Avoid some repetition on these: 41 $base = array( 42 'access callback' => 'panels_node_edit_node', 43 'access arguments' => array(1), 44 'page arguments' => array(1), 45 'type' => MENU_LOCAL_TASK, 46 ); 47 48 $items['node/%node/panel_layout'] = array( 49 'title' => 'Panel layout', 50 'page callback' => 'panels_node_edit_layout', 51 'weight' => 2, 52 ) + $base; 53 54 $items['node/%node/panel_content'] = array( 55 'title' => 'Panel content', 56 'page callback' => 'panels_node_edit_content', 57 'weight' => 3, 58 ) + $base; 59 60 $items['node/add/panel/choose-layout'] = array( 61 'title' => 'Choose layout', 62 'access arguments' => array('create panel-nodes'), 63 'page callback' => 'panels_node_add', 64 'type' => MENU_CALLBACK, 65 ); 66 67 return $items; 68 } 69 70 function panels_node_edit_node($node) { 71 if (!isset($node->panels_node)) { 72 return FALSE; 73 } 74 75 return node_access('update', $node); 76 } 77 78 // --------------------------------------------------------------------------- 79 // Node hooks 80 81 /** 82 * Implementation of hook_node_info(). 83 */ 84 function panels_node_node_info() { 85 // Safety: go away if CTools is not at an appropriate version. 86 if (!defined('PANELS_REQUIRED_CTOOLS_API') || !module_invoke('ctools', 'api_version', PANELS_REQUIRED_CTOOLS_API)) { 87 return array(); 88 } 89 90 return array( 91 'panel' => array( 92 'name' => t('Panel'), 93 'module' => 'panels_node', 94 'body_label' => t('Teaser'), 95 'description' => t("A panel layout broken up into rows and columns."), 96 ), 97 ); 98 } 99 100 /** 101 * Implementation of hook_access(). 102 */ 103 function panels_node_access($op, $node, $account) { 104 if (user_access('administer panel-nodes', $account)) { 105 return TRUE; 106 } 107 108 if ($op == 'create' && user_access('create panel-nodes', $account)) { 109 return TRUE; 110 } 111 112 if ($op == 'update' && (user_access('edit any panel-nodes', $account) || $node->uid == $account->uid && user_access('edit own panel-nodes', $account))) { 113 return TRUE; 114 } 115 116 117 if ($op == 'delete' && (user_access('delete any panel-nodes') || $node->uid == $account->uid && user_access('delete own panel-nodes'))) { 118 return TRUE; 119 } 120 } 121 122 function panels_node_add() { 123 $output = ''; 124 125 ctools_include('plugins', 'panels'); 126 ctools_include('common', 'panels'); 127 128 $layouts = panels_common_get_allowed_layouts('panels_node'); 129 return panels_common_print_layout_links($layouts, 'node/add/panel', array('query' => $_GET)); 130 } 131 132 /** 133 * Implementation of hook_form(). 134 */ 135 function panels_node_form(&$node, &$param) { 136 ctools_include('plugins', 'panels'); 137 138 $form['panels_node']['#tree'] = TRUE; 139 if (empty($node->nid) && arg(0) == 'node' && arg(1) == 'add') { 140 // Grab our selected layout from the $node, If it doesn't exist, try arg(3) 141 // and if that doesn't work present them with a list to pick from. 142 $panel_layout = isset($node->panel_layout) ? $node->panel_layout : arg(3); 143 if (empty($panel_layout)) { 144 $opts = $_GET; 145 unset($opts['q']); 146 return drupal_goto('node/add/panel/choose-layout', $opts); 147 } 148 149 $layout = panels_get_layout($panel_layout); 150 if (empty($layout)) { 151 return drupal_not_found(); 152 } 153 $form['panels_node']['layout'] = array( 154 '#type' => 'value', 155 '#value' => $panel_layout, 156 ); 157 } 158 159 $type = node_get_types('type', $node); 160 161 $form['title'] = array( 162 '#type' => 'textfield', 163 '#title' => check_plain($type->title_label), 164 '#required' => TRUE, 165 '#default_value' => $node->title, 166 ); 167 168 if (!empty($type->body_label)) { 169 $form['body_field']['#prefix'] = '<div class="body-field-wrapper">'; 170 $form['body_field']['#suffix'] = '</div>'; 171 $form['body_field']['body'] = array( 172 '#type' => 'textarea', 173 '#title' => check_plain($type->body_label), 174 '#rows' => 10, 175 '#required' => TRUE, 176 '#description' => t('The teaser is a piece of text to describe when the panel is listed (such as when promoted to front page); the actual content will only be displayed on the full node view.'), 177 '#default_value' => $node->body, 178 ); 179 $form['body_field']['format'] = filter_form($node->format); // Now we can set the format! 180 } 181 182 // drupal_set_message('<pre>' . check_plain(var_export($node, true)) . '</pre>'); 183 $css_id = ''; 184 if (!empty($node->panels_node['css_id'])) { 185 $css_id = $node->panels_node['css_id']; 186 } 187 188 $form['panels_node']['css_id'] = array( 189 '#type' => 'textfield', 190 '#title' => t('CSS ID'), 191 '#size' => 30, 192 '#description' => t('An ID that can be used by CSS to style the panel.'), 193 '#default_value' => $css_id, 194 ); 195 196 // Support for different rendering pipelines 197 // Mostly borrowed from panel_context.inc 198 $pipelines = panels_get_renderer_pipelines(); 199 200 // If there are no pipelines, that probably means we're operating in 201 // legacy mode. 202 if (empty($pipelines)) { 203 // We retain the original pipeline so we don't wreck things by installing 204 // old modules. 205 $form['panels_node']['pipeline'] = array( 206 '#type' => 'value', 207 '#value' => $node->panels_node['pipeline'], 208 ); 209 } 210 else { 211 $options = array(); 212 foreach ($pipelines as $name => $pipeline) { 213 $options[$name] = check_plain($pipeline->admin_title) . '<div class="description">' . check_plain($pipeline->admin_description) . '</div>'; 214 } 215 216 $form['panels_node']['pipeline'] = array( 217 '#type' => 'radios', 218 '#options' => $options, 219 '#title' => t('Renderer'), 220 '#default_value' => !empty($node->panels_node['pipeline']) ? $node->panels_node['pipeline'] : 'standard', 221 ); 222 } 223 224 return $form; 225 } 226 227 /** 228 * Implementation of hook_validate(). 229 */ 230 function panels_node_validate($node) { 231 if (!$node->nid && empty($node->panels_node['layout'])) { 232 form_set_error('', t('Please select a layout.')); 233 } 234 } 235 236 /** 237 * Implementation of hook_load(). 238 * 239 * Panels does not use revisions for nodes because that would open us up 240 * to have completely separate displays, and we'd have to copy them, 241 * and that's going to be a LOT of data. 242 */ 243 function panels_node_load($node) { 244 // We shortcut this because only in some really drastic corruption circumstance will this 245 // not work. 246 $additions['panels_node'] = db_fetch_array(db_query("SELECT * FROM {panels_node} WHERE nid = %d", $node->nid)); 247 return $additions; 248 } 249 250 /** 251 * Implementation of hook_insert(). 252 */ 253 function panels_node_insert(&$node) { 254 // Create a new display and record that. 255 $display = panels_new_display(); 256 $display->layout = $node->panels_node['layout']; 257 258 // Special handling for nodes being imported from an export.module data dump. 259 if (!empty($node->export_display)) { 260 // This works by overriding the $display set above 261 eval($node->export_display); 262 unset($node->export_display); 263 } 264 265 panels_save_display($display); 266 $css_id = $node->panels_node['css_id']; 267 268 db_query("INSERT INTO {panels_node} (nid, did, css_id, pipeline) VALUES (%d, %d, '%s', '%s')", $node->nid, $display->did, $node->panels_node['css_id'], $node->panels_node['pipeline']); 269 270 $node->panels_node['did'] = $display->did; 271 } 272 273 /** 274 * Implementation of hook_delete(). 275 */ 276 function panels_node_delete(&$node) { 277 db_query("DELETE FROM {panels_node} WHERE nid = %d", $node->nid); 278 if (!empty($node->panels_node['did'])) { 279 panels_delete_display($node->panels_node['did']); 280 } 281 } 282 283 /** 284 * Implementation of hook_update(). 285 */ 286 function panels_node_update($node) { 287 db_query("UPDATE {panels_node} SET css_id = '%s', pipeline = '%s' WHERE nid = %d", $node->panels_node['css_id'], $node->panels_node['pipeline'], $node->nid); 288 } 289 290 /** 291 * Implementation of hook_view(). 292 */ 293 function panels_node_view($node, $teaser = FALSE, $page = FALSE) { 294 static $rendering = array(); 295 296 // Prevent loops if someone foolishly puts the node inside itself: 297 if (!empty($rendering[$node->nid])) { 298 return $node; 299 } 300 301 $rendering[$node->nid] = TRUE; 302 ctools_include('plugins', 'panels'); 303 if ($teaser) { 304 // Do the standard view for teaser. 305 $node = node_prepare($node, $teaser); 306 // Because our teasier is never the same as our content, *always* provide 307 // the read more flag. 308 $node->readmore = TRUE; 309 } 310 else { 311 if (!empty($node->panels_node['did'])) { 312 $display = panels_load_display($node->panels_node['did']); 313 $display->css_id = $node->panels_node['css_id']; 314 // TODO: Find a way to make sure this can't node_view. 315 $display->context = panels_node_get_context($node); 316 $renderer = panels_get_renderer($node->panels_node['pipeline'], $display); 317 $node->content['body'] = array( 318 '#value' => panels_render_display($display, $renderer), 319 '#weight' => 0, 320 ); 321 } 322 } 323 324 unset($rendering[$node->nid]); 325 return $node; 326 } 327 328 // --------------------------------------------------------------------------- 329 // Administrative pages 330 331 /** 332 * Settings for panel nodes. 333 */ 334 function panels_node_settings() { 335 ctools_include('common', 'panels'); 336 return drupal_get_form('panels_common_settings', 'panels_node'); 337 } 338 339 // --------------------------------------------------------------------------- 340 // Meat of the Panels API; almost completely passing through to panels.module 341 342 /** 343 * Pass through to the panels layout editor. 344 */ 345 function panels_node_edit_layout($node) { 346 // ctools_include('plugins', 'panels'); 347 ctools_include('context'); 348 $display = panels_load_display($node->panels_node['did']); 349 $display->context = panels_node_get_context($node); 350 return panels_edit_layout($display, t('Save'), "node/$node->nid/panel_layout", 'panels_node'); 351 } 352 353 /** 354 * Pass through to the panels content editor. 355 */ 356 function panels_node_edit_content($node) { 357 // ctools_include('plugins', 'panels'); 358 ctools_include('context'); 359 $display = panels_load_display($node->panels_node['did']); 360 $display->context = panels_node_get_context($node); 361 ctools_include('common', 'panels'); 362 $content_types = panels_common_get_allowed_types('panels_node', $display->context); 363 364 // Print this with theme('page') so that blocks are disabled while editing a display. 365 // This is important because negative margins in common block layouts (i.e, Garland) 366 // messes up the drag & drop. 367 print theme('page', panels_edit($display, "node/$node->nid/panel_content", $content_types), FALSE); 368 } 369 370 /** 371 * Build the context to use for a panel node. 372 */ 373 function panels_node_get_context(&$node) { 374 ctools_include('context'); 375 $context = ctools_context_create('node', $node); 376 $context->identifier = t('This node'); 377 $context->keyword = 'node'; 378 return array('panel-node' => $context); 379 } 380 381 /** 382 * Implementation of hook_export_node_alter() 383 * 384 * Integrate with export.module for saving panel_nodes into code. 385 */ 386 function panels_node_export_node_alter(&$node, $original_node, $method) { 387 if ($method == 'export') { 388 $node_export_omitted = variable_get('node_export_omitted', array()); 389 if (variable_get('node_export_method', '') != 'save-edit' && (array_key_exists('panel', $node_export_omitted) && !$node_export_omitted['panel'])) { 390 drupal_set_message(t("NOTE: in order to import panel_nodes you must first set the export.module settings to \"Save as a new node then edit\", otherwise it won't work.")); 391 } 392 $display = panels_load_display($node->panels_node['did']); 393 $export = panels_export_display($display); 394 $node->export_display = $export; 395 } 396 } 397 398 /** 399 * Implementation of hook_panels_dashboard_blocks(). 400 * 401 * Adds panel nodes information to the Panels dashboard. 402 */ 403 function panels_node_panels_dashboard_blocks(&$vars) { 404 $vars['links']['panels_node'] = array( 405 'title' => l(t('Panel node'), 'node/add/panel'), 406 'description' => t('Panel nodes are node content and appear in your searches, but are more limited than panel pages.'), 407 'weight' => -1, 408 ); 409 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |