panels_node.module in Panels 5.2
Same filename and directory in other branches
This module provides the "panel" node type. Panel nodes are useful to add additional content to the content area on a per-node base.
File
panels_node/panels_node.moduleView source
<?php
/**
* @file panels_node.module
*
* This module provides the "panel" node type.
* Panel nodes are useful to add additional content to the content area
* on a per-node base.
*/
// ---------------------------------------------------------------------------
// General Drupal hooks
/**
* Implementation of hook_perm().
*/
function panels_node_perm() {
return array(
'create panel-nodes',
'edit own panel-nodes',
'administer panel-nodes',
);
}
/**
* Implementation of hook_menu().
*/
function panels_node_menu($may_cache) {
if ($may_cache) {
$items[] = array(
'path' => 'node/add/panel',
'title' => t('Panel'),
'access' => user_access('create panel-nodes'),
'type' => MENU_NORMAL_ITEM,
);
$items[] = array(
'path' => 'admin/panels/panel-nodes',
'title' => t('Panel nodes'),
'access' => user_access('create panel-nodes') && user_access('access administration pages'),
'type' => MENU_NORMAL_ITEM,
'callback' => 'panels_node_admin',
'description' => t('Information about panel nodes.'),
);
$items[] = array(
'path' => 'admin/panels/panel-nodes/information',
'title' => t('Information'),
'access' => user_access('create panel-nodes') && user_access('access administration pages'),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/panels/panel-nodes/settings',
'title' => t('Settings'),
'description' => t('Configure panel node content availability.'),
'access' => user_access('administer panel-nodes'),
'callback' => 'panels_node_settings',
'type' => MENU_LOCAL_TASK,
);
}
else {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
if ($node && $node->type == 'panel' && node_access('update', $node)) {
$base = 'node/' . arg(1) . '/panel_';
$items[] = array(
'path' => $base . 'layout',
'title' => t('Panel layout'),
'access' => TRUE,
'callback' => 'panels_node_edit_layout',
'callback arguments' => array(
$node,
),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => $base . 'settings',
'title' => t('Panel layout settings'),
'access' => TRUE,
'callback' => 'panels_node_edit_layout_settings',
'callback arguments' => array(
$node,
),
'weight' => 2,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => $base . 'content',
'title' => t('Panel content'),
'access' => TRUE,
'callback' => 'panels_node_edit_content',
'callback arguments' => array(
$node,
),
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => $base . 'context',
'title' => t('Context'),
'access' => TRUE,
'callback' => 'panels_node_context_edit',
'callback arguments' => array(
$node,
),
'weight' => 4,
'type' => MENU_LOCAL_TASK,
);
}
}
// Hard override of node/add
if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'panel' && arg(3) == NULL) {
$items[] = array(
'path' => 'node/add/panel',
'title' => t('Panel'),
'access' => user_access('create panel-nodes'),
'callback' => 'panels_node_add',
'type' => MENU_NORMAL_ITEM,
);
}
}
return $items;
}
/**
* Page callback for the very short admin page.
*/
function panels_node_admin() {
$output = '<p>';
$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.');
$output .= '</p><p>';
$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(
'!panel_node' => l(t('panel node'), 'node/add/panel'),
'!create_content' => l(t('create content'), 'node/add'),
'!administer_nodes' => l(t('administer nodes'), 'admin/content/node'),
));
$output .= '</p><p>';
$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(
'!settings' => l(t('settings'), 'admin/panels/panel-nodes/settings'),
));
$output .= '</p>';
return $output;
}
// ---------------------------------------------------------------------------
// Node hooks
/**
* Implementation of hook_node_info().
*/
function panels_node_node_info() {
return array(
'panel' => array(
'name' => t('Panel'),
'module' => 'panels_node',
'body_label' => t('Teaser'),
'description' => t("A panel a page layout broken up into rows and columns."),
),
);
}
/**
* Implementation of hook_access().
*/
function panels_node_access($op, $node = NULL) {
if (user_access('administer panel-nodes')) {
return TRUE;
}
if ($op == 'create' && user_access('create panel-nodes')) {
return TRUE;
}
if ($op == 'update' && $node->uid == $user->uid && user_access('edit own panel-nodes')) {
return TRUE;
}
}
function panels_node_add() {
$output = '';
panels_load_include('plugins');
// If no layout selected, present a list of choices.
foreach (panels_get_layouts() as $id => $layout) {
$output .= panels_print_layout_link($id, $layout, $_GET['q'] . '/' . $id);
}
return $output;
}
/**
* Implementation of hook_form().
*/
function panels_node_form(&$node, &$param) {
$form['panels_node']['#tree'] = TRUE;
if (!$node->nid) {
// Grab our selected layout from the $node, If it doesn't exist, try arg(3)
// and if that doesn't work present them with a list to pick from.
$panel_layout = $node->panel_layout ? $node->panel_layout : arg(3);
panels_load_include('plugins');
$layout = panels_get_layout($panel_layout);
if (empty($layout)) {
return drupal_not_found();
}
$form['panels_node']['layout'] = array(
'#type' => 'value',
'#value' => $panel_layout,
);
}
$type = node_get_types('type', $node);
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
);
if (!empty($type->body_label)) {
$form['body'] = array(
'#type' => 'textarea',
'#title' => check_plain($type->body_label),
'#rows' => 10,
'#required' => TRUE,
'#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.'),
'#default_value' => $node->body,
);
}
// drupal_set_message('<pre>' . check_plain(var_export($node, true)) . '</pre>');
$css_id = '';
if (!empty($node->panels_node['css_id'])) {
$css_id = $node->panels_node['css_id'];
}
$form['panels_node']['css_id'] = array(
'#type' => 'textfield',
'#title' => t('CSS ID'),
'#size' => 30,
'#description' => t('An ID that can be used by CSS to style the panel.'),
'#default_value' => $css_id,
);
return $form;
}
/**
* Implementation of hook_validate().
*/
function panels_node_validate($node) {
if (!$node->nid && empty($node->panels_node['layout'])) {
form_set_error('', t('Please select a layout.'));
}
}
/**
* Implementation of hook_load().
*
* Panels does not use revisions for nodes because that would open us up
* to have completely separate displays, and we'd have to copy them,
* and that's going to be a LOT of data.
*/
function panels_node_load($node) {
// We shortcut this because only in some really drastic corruption circumstance will this
// not work.
$additions['panels_node'] = db_fetch_array(db_query("SELECT * FROM {panels_node} WHERE nid = %d", $node->nid));
$additions['panels_node']['contexts'] = !empty($additions['panels_node']['contexts']) ? unserialize($additions['panels_node']['contexts']) : array();
$additions['panels_node']['relationships'] = !empty($additions['panels_node']['relationships']) ? unserialize($additions['panels_node']['relationships']) : array();
return $additions;
}
/**
* Implementation of hook_insert().
*/
function panels_node_insert(&$node) {
// Create a new display and record that.
$display = panels_new_display();
$display->layout = $node->panels_node['layout'];
panels_save_display($display);
$css_id = $node->panels_node['css_id'];
db_query("INSERT INTO {panels_node} (nid, did, css_id) VALUES (%d, %d, '%s')", $node->nid, $display->did, $node->panels_node['css_id']);
$node->panels_node['did'] = $display->did;
}
/**
* Implementation of hook_delete().
*/
function panels_node_delete(&$node) {
db_query("DELETE FROM {panels_node} WHERE nid = %d", $node->nid);
if (!empty($node->panels_node['did'])) {
panels_delete_display($node->panels_node['did']);
}
}
/**
* Implementation of hook_update().
*/
function panels_node_update($node) {
db_query("UPDATE {panels_node} SET css_id = '%s' WHERE nid = %d", $node->panels_node['css_id'], $node->nid);
}
/**
* Implementation of hook_view().
*/
function panels_node_view($node, $teaser = FALSE, $page = FALSE) {
panels_load_include('plugins');
if ($teaser) {
// Do the standard view for teaser.
$node = node_prepare($node, $teaser);
}
else {
$display = panels_load_display($node->panels_node['did']);
$display->css_id = $node->panels_node['css_id'];
// TODO: Find a way to make sure this can't node_view.
$display->context = array(
'panel-node' => panels_context_create('node', $node),
);
// Load additional contexts.
$panel_node = (object) $node->panels_node;
$display->context += panels_context_load_contexts($panel_node);
$node->content['body'] = array(
'#value' => panels_render_display($display),
'#weight' => 0,
);
}
return $node;
}
/**
* Save a panel node.
*
* While panels_node_update() is run when a panel node is edited, this function
* must be run to update the enhanced panel node configuration, f.e. contexts,
* which are not edited on the regular node edit page.
*
* @see panels_node_update(), panels_node_context_form_submit()
*/
function panels_node_save($panel_node) {
db_query("UPDATE {panels_node} SET contexts = '%s', relationships = '%s' WHERE nid = %d", serialize($panel_node->contexts), serialize($panel_node->relationships), $panel_node->nid);
}
// ---------------------------------------------------------------------------
// Administrative pages
/**
* Settings for panel nodes.
*/
function panels_node_settings() {
panels_load_include('common');
return drupal_get_form('panels_common_settings', 'panels_node');
}
// ---------------------------------------------------------------------------
// Meat of the Panels API; almost completely passing through to panels.module
/**
* Pass through to the panels layout editor.
*/
function panels_node_edit_layout($node) {
panels_load_include('plugins');
$display = panels_load_display($node->panels_node['did']);
$display->context = array(
'panel-node' => panels_context_create('node', $node),
);
return panels_edit_layout($display, t('Save'), "node/{$node->nid}/panel_layout");
}
/**
* Pass through to the panels layout settings editor.
*/
function panels_node_edit_layout_settings($node) {
panels_load_include('plugins');
$display = panels_load_display($node->panels_node['did']);
return panels_edit_layout_settings($display, t('Save'), "node/{$node->nid}/panel_settings");
}
/**
* Pass through to the panels content editor.
*/
function panels_node_edit_content($node) {
panels_load_include('plugins');
$display = panels_load_display($node->panels_node['did']);
$display->context = array(
'panel-node' => panels_context_create('node', $node),
);
$display->context['panel-node']->identifier = $node->title;
// Load additional contexts.
$panel_node = (object) $node->panels_node;
$display->context += panels_context_load_contexts($panel_node);
panels_load_include('common');
$content_types = panels_common_get_allowed_types('panels_node', $display->context);
// Print this with theme('page') so that blocks are disabled while editing a display.
// This is important because negative margins in common block layouts (i.e, Garland)
// messes up the drag & drop.
print theme('page', panels_edit($display, "node/{$node->nid}/panel_content", $content_types), FALSE);
}
/**
* Edit contexts of a panel node.
*
* FIXME: panels_node_edit_context() already defined in arguments/node_edit.inc.
*/
function panels_node_context_edit($node) {
panels_load_include('plugins');
$panel_node = (object) $node->panels_node;
$panel_node->nid = $node->nid;
$cache = panels_common_cache_get('panel_object:panel_node', $panel_node->did);
if (!$cache) {
panels_common_cache_set('panel_object:panel_node', $panel_node->did, $panel_node);
}
else {
$panel_node = $cache;
}
drupal_set_title(check_plain($node->title));
return drupal_get_form('panels_node_context_form', $panel_node);
}
/**
* The form to edit the context settings of a panel node.
*/
function panels_node_context_form($panel_node) {
drupal_add_css(panels_get_path('css/panels_admin.css'));
$form['panel_node'] = array(
'#type' => 'value',
'#value' => $panel_node,
);
$form['right'] = array(
'#prefix' => '<div class="right-container">',
'#suffix' => '</div>',
);
$form['left'] = array(
'#prefix' => '<div class="left-container">',
'#suffix' => '</div>',
);
panels_load_include('common');
// FIXME: Common panels forms are based on $object->name instead of did.
$panel_node->name = $panel_node->did;
$settings = panels_common_add_context_form('panel_node', $form, $form['right']['contexts_table'], $panel_node);
$settings += panels_common_add_relationship_form('panel_node', $form, $form['left']['relationships_table'], $panel_node);
panels_common_add_context_js($settings);
$label = t('Save');
$form['submit'] = array(
'#type' => 'submit',
'#value' => $label,
);
return $form;
}
/**
* Process submission of the panel node edit form.
*/
function panels_node_context_form_submit($form_id, $form_values) {
$panel_node = $form_values['panel_node'];
// Organize these from the common form.
panels_common_save_context('context', $panel_node->contexts, $form_values);
panels_common_save_context('relationship', $panel_node->relationships, $form_values);
drupal_set_message(t('Your changes have been saved.'));
panels_node_save($panel_node);
panels_common_cache_clear('panel_object:panel_node', $panel_node->did);
}
Functions
Name | Description |
---|---|
panels_node_access | Implementation of hook_access(). |
panels_node_add | |
panels_node_admin | Page callback for the very short admin page. |
panels_node_context_edit | Edit contexts of a panel node. |
panels_node_context_form | The form to edit the context settings of a panel node. |
panels_node_context_form_submit | Process submission of the panel node edit form. |
panels_node_delete | Implementation of hook_delete(). |
panels_node_edit_content | Pass through to the panels content editor. |
panels_node_edit_layout | Pass through to the panels layout editor. |
panels_node_edit_layout_settings | Pass through to the panels layout settings editor. |
panels_node_form | Implementation of hook_form(). |
panels_node_insert | Implementation of hook_insert(). |
panels_node_load | Implementation of hook_load(). |
panels_node_menu | Implementation of hook_menu(). |
panels_node_node_info | Implementation of hook_node_info(). |
panels_node_perm | Implementation of hook_perm(). |
panels_node_save | Save a panel node. |
panels_node_settings | Settings for panel nodes. |
panels_node_update | Implementation of hook_update(). |
panels_node_validate | Implementation of hook_validate(). |
panels_node_view | Implementation of hook_view(). |