panels_node.module

Go to the documentation of this file.
00001 <?php
00002 // $Id: panels_node.module,v 1.1.2.21 2008/10/23 21:28:06 merlinofchaos Exp $
00003 
00004 
00005 /**
00006  * @file panels_node.module
00007  *
00008  * This module provides the "panel" node type.
00009  * Panel nodes are useful to add additional content to the content area
00010  * on a per-node base.
00011  */
00012 
00013 // ---------------------------------------------------------------------------
00014 // General Drupal hooks
00015 
00016 /**
00017  * Implementation of hook_perm().
00018  */
00019 function panels_node_perm() {
00020   return array('create panel-nodes', 'edit own panel-nodes', 'administer panel-nodes');
00021 }
00022 
00023 /**
00024  * Implementation of hook_menu().
00025  */
00026 function panels_node_menu($may_cache) {
00027   if ($may_cache) {
00028     $items[] = array(
00029       'path' => 'node/add/panel',
00030       'title' => t('Panel'),
00031       'access' => user_access('create panel-nodes'),
00032       'type' => MENU_NORMAL_ITEM,
00033     );
00034     $items[] = array(
00035       'path' => 'admin/panels/panel-nodes',
00036       'title' => t('Panel nodes'),
00037       'access' => user_access('create panel-nodes') && user_access('access administration pages'),
00038       'type' => MENU_NORMAL_ITEM,
00039       'callback' => 'panels_node_admin',
00040       'description' => t('Information about panel nodes.'),
00041     );
00042 
00043     $items[] = array(
00044       'path' => 'admin/panels/panel-nodes/information',
00045       'title' => t('Information'),
00046       'access' => user_access('create panel-nodes') && user_access('access administration pages'),
00047       'type' => MENU_DEFAULT_LOCAL_TASK,
00048     );
00049 
00050     $items[] = array(
00051       'path' => 'admin/panels/panel-nodes/settings',
00052       'title' => t('Settings'),
00053       'description' => t('Configure panel node content availability.'),
00054       'access' => user_access('administer panel-nodes'),
00055       'callback' => 'panels_node_settings',
00056       'type' => MENU_LOCAL_TASK,
00057     );
00058   }
00059   else {
00060     if (arg(0) == 'node' && is_numeric(arg(1))) {
00061       $node = node_load(arg(1));
00062       if ($node && $node->type == 'panel' && node_access('update', $node)) {
00063         $base = 'node/' . arg(1) . '/panel_';
00064         $items[] = array(
00065           'path' => $base . 'layout',
00066           'title' => t('Panel layout'),
00067           'access' => TRUE,
00068           'callback' => 'panels_node_edit_layout',
00069           'callback arguments' => array($node),
00070           'weight' => 2,
00071           'type' => MENU_LOCAL_TASK,
00072         );
00073 
00074         $items[] = array(
00075           'path' => $base . 'settings',
00076           'title' => t('Panel layout settings'),
00077           'access' => TRUE,
00078           'callback' => 'panels_node_edit_layout_settings',
00079           'callback arguments' => array($node),
00080           'weight' => 2,
00081           'type' => MENU_LOCAL_TASK,
00082         );
00083 
00084         $items[] = array(
00085           'path' => $base . 'content',
00086           'title' => t('Panel content'),
00087           'access' => TRUE,
00088           'callback' => 'panels_node_edit_content',
00089           'callback arguments' => array($node),
00090           'weight' => 3,
00091           'type' => MENU_LOCAL_TASK,
00092         );
00093 
00094         $items[] = array(
00095           'path' => $base . 'context',
00096           'title' => t('Context'),
00097           'access' => TRUE,
00098           'callback' => 'panels_node_context_edit',
00099           'callback arguments' => array($node),
00100           'weight' => 4,
00101           'type' => MENU_LOCAL_TASK,
00102         );
00103       }
00104     }
00105     // Hard override of node/add
00106     if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'panel' && arg(3) == NULL) {
00107       $items[] = array(
00108         'path' => 'node/add/panel',
00109         'title' => t('Panel'),
00110         'access' => user_access('create panel-nodes'),
00111         'callback' => 'panels_node_add',
00112         'type' => MENU_NORMAL_ITEM,
00113       );
00114     }
00115   }
00116   return $items;
00117 }
00118 
00119 /**
00120  * Page callback for the very short admin page.
00121  */
00122 function panels_node_admin() {
00123   $output = '<p>';
00124   $output .= t('Panel nodes do not have a normal administrative UI, such as panels pages or mini panels. With this module, a new node type is created: a "panel" node. These are nodes that have panel layouts, but do not have the breadth of features that panel pages do; these features are sacrificed so that you gain all the capabilities of nodes.');
00125   $output .= '</p><p>';
00126   $output .= t('You may create a !panel_node using the normal !create_content menu, and you can administer your panel nodes under the normal !administer_nodes menu (administrative permission required).', array(
00127     '!panel_node' => l(t('panel node'), 'node/add/panel'),
00128     '!create_content' => l(t('create content'), 'node/add'),
00129     '!administer_nodes' => l(t('administer nodes'), 'admin/content/node'),
00130   ));
00131   $output .= '</p><p>';
00132   $output .= t('On the !settings page, you may control which panes may be added to panel nodes; this can be very valuable to limit what content is available if your users who can create panel nodes are not administrators.', array(
00133     '!settings' => l(t('settings'), 'admin/panels/panel-nodes/settings'),
00134   ));
00135   $output .= '</p>';
00136   return $output;
00137 }
00138 
00139 // ---------------------------------------------------------------------------
00140 // Node hooks
00141 
00142 /**
00143  * Implementation of hook_node_info().
00144  */
00145 function panels_node_node_info() {
00146   return array(
00147     'panel' => array(
00148       'name' => t('Panel'),
00149       'module' => 'panels_node',
00150       'body_label' => t('Teaser'),
00151       'description' => t("A panel a page layout broken up into rows and columns."),
00152     ),
00153   );
00154 }
00155 
00156 /**
00157  * Implementation of hook_access().
00158  */
00159 function panels_node_access($op, $node = NULL) {
00160   if (user_access('administer panel-nodes')) {
00161     return TRUE;
00162   }
00163 
00164   if ($op == 'create' && user_access('create panel-nodes')) {
00165     return TRUE;
00166   }
00167 
00168   if ($op == 'update' && $node->uid == $user->uid && user_access('edit own panel-nodes')) {
00169     return TRUE;
00170   }
00171 }
00172 
00173 function panels_node_add() {
00174   $output = '';
00175 
00176   panels_load_include('plugins');
00177   // If no layout selected, present a list of choices.
00178   foreach (panels_get_layouts() as $id => $layout) {
00179     $output .= panels_print_layout_link($id, $layout, $_GET['q'] . '/' . $id);
00180   }
00181   return $output;
00182 }
00183 
00184 /**
00185  * Implementation of hook_form().
00186  */
00187 function panels_node_form(&$node, &$param) {
00188   $form['panels_node']['#tree'] = TRUE;
00189   if (!$node->nid) {
00190     // Grab our selected layout from the $node, If it doesn't exist, try arg(3) 
00191     // and if that doesn't work present them with a list to pick from.
00192     $panel_layout = $node->panel_layout ? $node->panel_layout : arg(3);
00193 
00194     panels_load_include('plugins');
00195     $layout = panels_get_layout($panel_layout);
00196     if (empty($layout)) {
00197       return drupal_not_found();
00198     }
00199     $form['panels_node']['layout'] = array(
00200       '#type' => 'value',
00201       '#value' => $panel_layout,
00202     );
00203   }
00204 
00205   $type = node_get_types('type', $node);
00206 
00207   $form['title'] = array(
00208     '#type' => 'textfield',
00209     '#title' => check_plain($type->title_label),
00210     '#required' => TRUE,
00211     '#default_value' => $node->title,
00212   );
00213 
00214   if (!empty($type->body_label)) {
00215     $form['body'] = array(
00216       '#type' => 'textarea',
00217       '#title' => check_plain($type->body_label),
00218       '#rows' => 10,
00219       '#required' => TRUE,
00220       '#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.'),
00221       '#default_value' => $node->body,
00222     );
00223   }
00224 
00225 //  drupal_set_message('<pre>' . check_plain(var_export($node, true)) . '</pre>');
00226   $css_id = '';
00227   if (!empty($node->panels_node['css_id'])) {
00228     $css_id = $node->panels_node['css_id'];
00229   }
00230 
00231   $form['panels_node']['css_id'] = array(
00232     '#type' => 'textfield',
00233     '#title' => t('CSS ID'),
00234     '#size' => 30,
00235     '#description' => t('An ID that can be used by CSS to style the panel.'),
00236     '#default_value' => $css_id,
00237   );
00238   return $form;
00239 }
00240 
00241 /**
00242  * Implementation of hook_validate().
00243  */
00244 function panels_node_validate($node) {
00245   if (!$node->nid && empty($node->panels_node['layout'])) {
00246     form_set_error('', t('Please select a layout.'));
00247   }
00248 }
00249 
00250 /**
00251  * Implementation of hook_load().
00252  *
00253  * Panels does not use revisions for nodes because that would open us up
00254  * to have completely separate displays, and we'd have to copy them,
00255  * and that's going to be a LOT of data.
00256  */
00257 function panels_node_load($node) {
00258   // We shortcut this because only in some really drastic corruption circumstance will this
00259   // not work.
00260   $additions['panels_node'] = db_fetch_array(db_query("SELECT * FROM {panels_node} WHERE nid = %d", $node->nid));
00261 
00262   $additions['panels_node']['contexts'] = (!empty($additions['panels_node']['contexts'])) ? unserialize($additions['panels_node']['contexts']) : array();
00263   $additions['panels_node']['relationships'] = (!empty($additions['panels_node']['relationships'])) ? unserialize($additions['panels_node']['relationships']) : array();
00264   return $additions;
00265 }
00266 
00267 /**
00268  * Implementation of hook_insert().
00269  */
00270 function panels_node_insert(&$node) {
00271   // Create a new display and record that.
00272   $display = panels_new_display();
00273   $display->layout = $node->panels_node['layout'];
00274   panels_save_display($display);
00275   $css_id = $node->panels_node['css_id'];
00276 
00277   db_query("INSERT INTO {panels_node} (nid, did, css_id) VALUES (%d, %d, '%s')", $node->nid, $display->did, $node->panels_node['css_id']);
00278 
00279   $node->panels_node['did'] = $display->did;
00280 }
00281 
00282 /**
00283  * Implementation of hook_delete().
00284  */
00285 function panels_node_delete(&$node) {
00286   db_query("DELETE FROM {panels_node} WHERE nid = %d", $node->nid);
00287   if (!empty($node->panels_node['did'])) {
00288     panels_delete_display($node->panels_node['did']);
00289   }
00290 }
00291 
00292 /**
00293  * Implementation of hook_update().
00294  */
00295 function panels_node_update($node) {
00296   db_query("UPDATE {panels_node} SET css_id = '%s' WHERE nid = %d", $node->panels_node['css_id'], $node->nid);
00297 }
00298 
00299 /**
00300  * Implementation of hook_view().
00301  */
00302 function panels_node_view($node, $teaser = FALSE, $page = FALSE) {
00303   panels_load_include('plugins');
00304   if ($teaser) {
00305     // Do the standard view for teaser.
00306     $node = node_prepare($node, $teaser);
00307   }
00308   else {
00309     $display = panels_load_display($node->panels_node['did']);
00310     $display->css_id = $node->panels_node['css_id'];
00311     // TODO: Find a way to make sure this can't node_view.
00312     $display->context = array('panel-node' => panels_context_create('node', $node));
00313 
00314     // Load additional contexts.
00315     $panel_node = (object)$node->panels_node;
00316     $display->context += panels_context_load_contexts($panel_node);
00317 
00318     $node->content['body'] = array(
00319       '#value' => panels_render_display($display),
00320       '#weight' => 0,
00321     );
00322   }
00323 
00324   return $node;
00325 }
00326 
00327 /**
00328  * Save a panel node.
00329  *
00330  * While panels_node_update() is run when a panel node is edited, this function
00331  * must be run to update the enhanced panel node configuration, f.e. contexts,
00332  * which are not edited on the regular node edit page.
00333  *
00334  * @see panels_node_update(), panels_node_context_form_submit()
00335  */
00336 function panels_node_save($panel_node) {
00337   db_query("UPDATE {panels_node} SET contexts = '%s', relationships = '%s' WHERE nid = %d", serialize($panel_node->contexts), serialize($panel_node->relationships), $panel_node->nid);
00338 }
00339 
00340 // ---------------------------------------------------------------------------
00341 // Administrative pages
00342 
00343 /**
00344  * Settings for panel nodes.
00345  */
00346 function panels_node_settings() {
00347   panels_load_include('common');
00348   return drupal_get_form('panels_common_settings', 'panels_node');
00349 }
00350 
00351 // ---------------------------------------------------------------------------
00352 // Meat of the Panels API; almost completely passing through to panels.module
00353 
00354 /**
00355  * Pass through to the panels layout editor.
00356  */
00357 function panels_node_edit_layout($node) {
00358   panels_load_include('plugins');
00359   $display = panels_load_display($node->panels_node['did']);
00360   $display->context = array('panel-node' => panels_context_create('node', $node));
00361   return panels_edit_layout($display, t('Save'), "node/$node->nid/panel_layout");
00362 }
00363 
00364 /**
00365  * Pass through to the panels layout settings editor.
00366  */
00367 function panels_node_edit_layout_settings($node) {
00368   panels_load_include('plugins');
00369   $display = panels_load_display($node->panels_node['did']);
00370   return panels_edit_layout_settings($display, t('Save'), "node/$node->nid/panel_settings");
00371 }
00372 
00373 /**
00374  * Pass through to the panels content editor.
00375  */
00376 function panels_node_edit_content($node) {
00377   panels_load_include('plugins');
00378   $display = panels_load_display($node->panels_node['did']);
00379   $display->context = array('panel-node' => panels_context_create('node', $node));
00380   $display->context['panel-node']->identifier = $node->title;
00381 
00382   // Load additional contexts.
00383   $panel_node = (object)$node->panels_node;
00384   $display->context += panels_context_load_contexts($panel_node);
00385 
00386   panels_load_include('common');
00387   $content_types = panels_common_get_allowed_types('panels_node', $display->context);
00388 
00389   // Print this with theme('page') so that blocks are disabled while editing a display.
00390   // This is important because negative margins in common block layouts (i.e, Garland)
00391   // messes up the drag & drop.
00392   print theme('page', panels_edit($display, "node/$node->nid/panel_content", $content_types), FALSE);
00393 }
00394 
00395 /**
00396  * Edit contexts of a panel node.
00397  *
00398  * FIXME: panels_node_edit_context() already defined in arguments/node_edit.inc.
00399  */
00400 function panels_node_context_edit($node) {
00401   panels_load_include('plugins');
00402 
00403   $panel_node = (object)$node->panels_node;
00404   $panel_node->nid = $node->nid;
00405 
00406   $cache = panels_common_cache_get('panel_object:panel_node', $panel_node->did);
00407   if (!$cache) {
00408     panels_common_cache_set('panel_object:panel_node', $panel_node->did, $panel_node);
00409   }
00410   else {
00411     $panel_node = $cache;
00412   }
00413 
00414   drupal_set_title(check_plain($node->title));
00415   return drupal_get_form('panels_node_context_form', $panel_node);
00416 }
00417 
00418 /**
00419  * The form to edit the context settings of a panel node.
00420  */
00421 function panels_node_context_form($panel_node) {
00422   drupal_add_css(panels_get_path('css/panels_admin.css'));
00423 
00424   $form['panel_node'] = array(
00425     '#type' => 'value',
00426     '#value' => $panel_node,
00427   );
00428 
00429   $form['right'] = array(
00430     '#prefix' => '<div class="right-container">',
00431     '#suffix' => '</div>',
00432   );
00433 
00434   $form['left'] = array(
00435     '#prefix' => '<div class="left-container">',
00436     '#suffix' => '</div>',
00437   );
00438 
00439   panels_load_include('common');
00440   // FIXME: Common panels forms are based on $object->name instead of did.
00441   $panel_node->name = $panel_node->did;
00442 
00443   $settings = panels_common_add_context_form('panel_node', $form, $form['right']['contexts_table'], $panel_node);
00444   $settings += panels_common_add_relationship_form('panel_node', $form, $form['left']['relationships_table'], $panel_node);
00445   panels_common_add_context_js($settings);
00446 
00447   $label = t('Save');
00448   $form['submit'] = array(
00449     '#type' => 'submit',
00450     '#value' => $label,
00451   );
00452 
00453   return $form;
00454 }
00455 
00456 /**
00457  * Process submission of the panel node edit form.
00458  */
00459 function panels_node_context_form_submit($form_id, $form_values) {
00460   $panel_node = $form_values['panel_node'];
00461 
00462   // Organize these from the common form.
00463   panels_common_save_context('context', $panel_node->contexts, $form_values);
00464   panels_common_save_context('relationship', $panel_node->relationships, $form_values);
00465 
00466   drupal_set_message(t('Your changes have been saved.'));
00467   panels_node_save($panel_node);
00468   panels_common_cache_clear('panel_object:panel_node', $panel_node->did);
00469 }
00470 

Generated on Thu Jul 29 05:00:15 2010 for Panels 2 by  doxygen 1.5.6