nd.module in Node displays 6.3
Same filename and directory in other branches
Node displays.
File
nd.moduleView source
<?php
/**
* @file
* Node displays.
*/
/**
* Implementation of hook_ds_api().
*/
function nd_ds_api() {
$help = array(
'<h3>Node displays</h3>
<p>This module comes with a nd.tpl.php, available in the templates folder, which is optimized for use with Node Displays. You can copy the file to your themes folder to use your own version if you want. Copying the file to your theme folder will only work if node.tpl.php is in the theme folder.</p>
<p>You can create a file called <strong>nd-<em>node_type</em>.tpl.php</strong>, <strong>nd-<em>node_type</em>-<em>build_mode</em>.tpl.php</strong> or <strong>nd-<em>node_type</em>-<em>build_mode</em>-<em>nid</em>.tpl.php</strong> for even more fine-grained theming.</p>
<p>If you exclude the RSS build mode, the default node feed is generated, but might render strange content. Make sure you do not choose the "Titles only" as your feed content setting, otherwhise, this screen will not have any effect. Choosing either "Full text" or "Titles + teaser" does not matter, this screen will have effect on both settings, apart from the read more link and the format of the body (full/teaser). Remember that some fields like upload and terms are added automatically to the feed and that this build mode manipulates the $description variable, it does not add extra keys to the feed.</p>
<p>If you have a problem with the content not being rendered through DS, please read <a href="http://drupal.org/node/572614">http://drupal.org/node/572614</a>.',
);
return array(
'title' => 'Node displays',
'module' => 'nd',
'object' => 'node',
'views_base' => array(
'node',
'apachesolr',
'apachesolr_node',
),
'types' => 'node_get_types',
'extra' => array(
'has_body',
),
'plugins_exclude' => array(
NODE_BUILD_RSS,
),
'regions_single' => array(
NODE_BUILD_RSS,
),
'help' => $help,
);
}
/**
* Implementation of hook_init().
*/
function nd_init() {
drupal_add_css(drupal_get_path('module', 'nd') . '/css/nd_regions.css');
}
/**
* Implementation of hook_rules_event_info().
*/
function nd_rules_event_info() {
return array(
'nd_node_is_build' => array(
'label' => t('DS has build the node display'),
'module' => 'nd',
'arguments' => array(
'node' => array(
'type' => 'node',
'label' => t('Content'),
),
),
),
);
}
/**
* Implementation of hook_rules_action_info().
*/
function nd_rules_action_info() {
return array(
'nd_rules_disable_fields' => array(
'label' => t('Do not show a ND field'),
'arguments' => array(
'node' => array(
'type' => 'node',
'label' => t('Content'),
),
),
'module' => 'nd',
),
);
}
/**
* Implementation of hook_content_build_modes().
*/
function nd_content_build_modes() {
$build_modes = array(
'nd' => array(
'title' => t('Node displays'),
'build modes' => array(
'full' => array(
'title' => t('Full node'),
'weight' => -1,
),
'teaser' => array(
'title' => t('Teaser'),
'weight' => 1,
),
'sticky' => array(
'title' => t('Sticky'),
'weight' => 2,
'views style' => TRUE,
),
NODE_BUILD_RSS => array(
'title' => t('RSS'),
'weight' => 3,
),
),
),
);
// Also add this here, so other modules (like views_attach)
// can profit from custom build modes from the UI.
$db_build_modes = variable_get('nd_build_modes', array());
foreach ($db_build_modes as $key => $build_mode) {
$build_modes[$key] = array(
'title' => $build_mode,
'build modes' => array(
$key => array(
'title' => $build_mode,
'views style' => TRUE,
),
),
);
}
return $build_modes;
}
/**
* Implementation of hook_registry_alter().
*/
function nd_theme_registry_alter(&$registry) {
$path = drupal_get_path('module', 'nd') . '/templates';
array_unshift($registry['node']['theme paths'], $path);
}
/**
* Implementation of hook_nodeapi().
*/
function nd_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
// Add has body property.
case 'load':
$node->has_body = node_get_types('type', $node->type)->has_body;
break;
// Determine build mode.
case 'view':
if ($node->build_mode == NODE_BUILD_RSS) {
// For the RSS build mode, we need to manipulate right now.
_nd_nodeapi($node);
}
elseif ($node->build_mode == NODE_BUILD_PREVIEW) {
$node->build_mode = $teaser ? 'teaser' : 'full';
$node->has_body = node_get_types('type', $node->type)->has_body;
// Prepare taxonomy
if (isset($node->taxonomy)) {
foreach ($node->taxonomy as $tid => $term) {
if (is_int($tid)) {
$node->taxonomy[$tid] = db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid));
}
}
}
}
elseif ($node->build_mode === NODE_BUILD_NORMAL) {
$build_mode = $teaser ? 'teaser' : 'full';
$node->build_mode = $build_mode;
}
drupal_alter('nd_build', $node);
break;
// Alter the node object for viewing.
case 'alter':
// We ignore the RSS build mode, which is handled in the view operation.
if ($node->build_mode == NODE_BUILD_RSS) {
return;
}
_nd_nodeapi($node);
break;
}
}
/**
* Implements hook_nd_build_alter
*/
function nd_nd_build_alter($node) {
/**
* Stickied Teasers
*
* Use of sticky as a stand-alone buildmode will be deprecated in 3.x,
* where it will be replaced with custom variant selection.
* For the time being, sticky can be ignored by setting
* $conf['ds_ignore_sticky'] = TRUE
* in settings.php
*/
if (variable_get('ds_ignore_sticky', FALSE) != TRUE) {
if ($node->build_mode == 'teaser' && $node->sticky == 1) {
$node->build_mode = 'sticky';
}
}
/**
* Switch buildmode based on query string
*
* Build modes can be changed by setting ?build_mode=name in the query
* string. Becuase this is potentially insecure, developers must enable
* this for specific build modes by setting which modes allow switching
* in a variable 'nd_parameter_switch_bm'.
*/
$parameter_build_modes = variable_get('nd_parameter_switch_bm', array());
if (isset($_GET['build_mode'])) {
$switch = check_plain($_GET['build_mode']);
if (in_array($switch, $parameter_build_modes)) {
$node->build_mode = $switch;
}
}
}
/**
* Helper function to alter node properties
*
* @param stdClass $node The complete node object.
*/
function _nd_nodeapi(&$node) {
// Build fields and regions.
nd_build_fields_and_regions($node);
// Special support for RSS.
if ($node->build_mode == NODE_BUILD_RSS && $node->render_by_ds == TRUE) {
foreach (element_children($node->content) as $key => $field) {
if (!isset($node->ds_fields[$field])) {
$node->content[$field]['#access'] = FALSE;
}
$node->content[$field]['#weight'] = $node->ds_fields[$field]['weight'];
unset($node->ds_fields[$field]);
}
foreach ($node->ds_fields as $key => $field) {
$render_key = $key . '_rendered';
$node->content[$key]['#value'] = theme('ds_field', $node->{$render_key}, $node->ds_fields[$key]);
$node->content['#content_extra_fields'][$key]['weight'] = $node->ds_fields[$key]['weight'];
}
// Body and title are tricky ones since their weights are set
// in #content_extra_fields, so update the value there!
$node->content['#content_extra_fields']['body_field']['weight'] = $node->content['body']['#weight'];
$node->content['#content_extra_fields']['title']['weight'] = $node->content['title']['#weight'];
}
if (function_exists('rules_invoke_event')) {
rules_invoke_event('nd_node_is_build', array(
'node' => &$node,
));
}
}
/**
* Statically cached version of ds_build_fields and regions
*/
function nd_build_fields_and_regions(&$node) {
static $displays = array();
if (isset($displays[$node->nid])) {
$node = $displays[$node->nid];
}
else {
ds_build_fields_and_regions($node, 'nd');
$displays[$node->nid] = $node;
}
}
/**
* Implementation of moduleName_preprocess_hook().
* The node data will be rendered in regions. This uses a helper function
* so themers/developers can call that helper function from within
* their preprocess_hooks if they are fiddling with some data. For information
* about this decision see http://drupal.org/node/570592 (issue) and
* http://drupal.org/node/572614 for information on howto implement.
*/
function nd_preprocess_node(&$vars, $hook) {
if (!variable_get('nd_preprocess_override', FALSE)) {
_nd_preprocess_node($vars, $hook);
}
}
/**
* Helper function used in either nd_preprocess_node or other preprocess function.
*/
function _nd_preprocess_node(&$vars, $hook) {
$node = $vars['node'];
// Break all the rendering if needed.
if (!$node->render_by_ds) {
return;
}
// Add nd-content_type-build_mode(-nid) template suggestion.
$vars['template_files'][] = 'nd';
$vars['template_files'][] = 'nd-' . $node->type;
$vars['template_files'][] = 'nd-' . $node->type . '-' . $node->build_mode;
$vars['template_files'][] = 'nd-' . $node->type . '-' . $node->build_mode . '-' . $node->nid;
$vars['content'] = ds_render_content($node, 'nd', $vars);
}
/**
* Render the node object through the DS views plugin.
*
* @param array $vars The variables to manipulate.
* @param string $build_mode The build mode to use on this object.
*/
function ds_views_row_node(&$vars, $build_mode) {
nd_views_node_helper($vars, $build_mode);
}
/**
* Render the apachesolr object through the DS views plugin.
*
* @param array $vars The variables to manipulate.
* @param string $build_mode The build mode to use on this object.
*/
function ds_views_row_apachesolr(&$vars, $build_mode) {
nd_views_node_helper($vars, $build_mode);
}
/**
* Render the apachesolr node object through the DS views plugin.
*
* @param array $vars The variables to manipulate.
* @param string $build_mode The build mode to use on this object.
*/
function ds_views_row_apachesolr_node(&$vars, $build_mode) {
nd_views_node_helper($vars, $build_mode);
}
/**
* Helper function for views node plugin.
*/
function nd_views_node_helper(&$vars, $build_mode) {
$nid = $vars['row']->nid;
if (!is_numeric($nid)) {
return;
}
if (module_exists('object_cache')) {
$node = object_cache_get('node', $nid);
}
else {
$node = node_load($nid);
}
if (empty($node)) {
return;
}
$node->build_mode = $build_mode;
// Check the teaser flag and show_links flag.
$teaser = $node->build_mode != 'full' ? TRUE : FALSE;
$show_links = ds_show_field('nd', $node->type, $build_mode, 'links');
// Build object.
$vars['object'] = node_view($node, $teaser, FALSE, $show_links);
}
/**
* Implementation of hook_theme().
*/
function nd_theme() {
$theme_functions = array();
// Single theming functions.
$formatters = array(
'nd_bodyfield',
'nd_title_h1_nolink',
'nd_title_h1_link',
'nd_title_h2_nolink',
'nd_title_h2_link',
'nd_title_h2_block_nolink',
'nd_title_h2_block_link',
'nd_title_p_nolink',
'nd_title_p_link',
'nd_book_add_new_child',
'nd_book_printer_version',
);
foreach ($formatters as $formatter) {
$theme_functions[$formatter] = array(
'arguments' => array(
'node' => NULL,
),
);
}
// Post date with Date API.
if (variable_get('nd_use_date_api', TRUE)) {
if (module_exists('date_api')) {
$date_formats = date_get_format_types('', TRUE);
}
else {
$date_formats = array(
'small' => array(
'title' => 'Small',
'type' => 'small',
),
'medium' => array(
'title' => 'Medium',
'type' => 'medium',
),
'large' => array(
'title' => 'Large',
'type' => 'large',
),
);
}
foreach ($date_formats as $formatter) {
$theme_functions['nd_post_date_' . $formatter['type']] = array(
'arguments' => array(
'node' => NULL,
),
'function' => 'theme_nd_post_date',
);
}
}
// Vocabulary.
$vocab_formatters = array(
'nd_terms_per_vocabulary_space',
'nd_terms_per_vocabulary_linked_space',
'nd_terms_per_vocabulary_comma',
'nd_terms_per_vocabulary_linked_comma',
'nd_terms_per_vocabulary_list',
'nd_terms_per_vocabulary_linked_list',
);
foreach ($vocab_formatters as $formatter) {
$theme_functions[$formatter] = array(
'arguments' => array(
'node' => NULL,
),
'function' => 'nd_terms_per_vocabulary',
);
}
return $theme_functions;
}
/**
* Implementation of hook_ds_fields().
*/
function nd_ds_fields($type_name, $build_mode, $extra) {
$fields = array(
'title' => array(
'title' => t('Title'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'nd_title_h1_nolink' => t('H1 title'),
'nd_title_h1_link' => t('H1 title, linked to node'),
'nd_title_h2_nolink' => t('H2 title'),
'nd_title_h2_link' => t('H2 title, linked to node'),
'nd_title_h2_block_nolink' => t('H2 block title'),
'nd_title_h2_block_link' => t('H2 block title, linked to node'),
'nd_title_p_nolink' => t('Paragraph title'),
'nd_title_p_link' => t('Paragraph title, linked to node'),
),
),
),
'author' => array(
'title' => t('Author'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'ds_author_nolink' => t('Author'),
'ds_author_link' => t('Author linked to profile'),
),
),
),
'links' => array(
'title' => t('Links'),
'type' => DS_FIELD_TYPE_PREPROCESS,
'status' => DS_FIELD_STATUS_STATIC,
),
'read_more' => array(
'title' => t('Read more'),
'type' => DS_FIELD_TYPE_CODE,
'status' => DS_FIELD_STATUS_DEFAULT,
'properties' => array(
'formatters' => array(
'ds_eval_code' => t('Default'),
),
'code' => '<?php echo l(t("Read more"), "node/$object->nid"); ?>',
),
),
);
// Updated and posted date formatters
if (module_exists('date_api')) {
$date_formats = date_get_format_types('', FALSE);
}
else {
$date_formats = array(
'small' => array(
'title' => 'Small',
'type' => 'small',
),
'medium' => array(
'title' => 'Medium',
'type' => 'medium',
),
'large' => array(
'title' => 'Large',
'type' => 'large',
),
);
}
$date_formatters = array();
foreach ($date_formats as $formatter) {
$date_formatters['nd_post_date_' . $formatter['type']] = t($formatter['title']);
}
// Regression. People upgrading from 6.x-2.2 to 6.x-2.3 will lose
// the post date PHP code field, we can't do that by default. The
// update_2 will make the nd_use_date_api variable false, and
// developers can set this variable to 1 in the variable table.
if (variable_get('nd_use_date_api', TRUE)) {
$fields['post_date'] = array(
'title' => t('Post date'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => $date_formatters,
),
);
}
else {
$fields['post_date'] = array(
'title' => t('Post date'),
'type' => DS_FIELD_TYPE_CODE,
'status' => DS_FIELD_STATUS_DEFAULT,
'properties' => array(
'formatters' => array(
'ds_eval_code' => t('Default'),
),
'code' => '<?php echo format_date($object->created, "custom", "d/m/Y"); ?>',
),
);
}
$fields['updated_date'] = array(
'title' => t('Last updated date'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => $date_formatters,
),
);
// Check for body.
if (isset($extra['has_body']) && $extra['has_body'] == TRUE) {
$fields['body'] = array(
'title' => t('Body'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'nd_bodyfield' => t('Default'),
),
),
);
}
// Taxonomy support.
if (module_exists('taxonomy')) {
$all = FALSE;
// All vocabularies per content type.
// We can't use taxonomy_get_vocabularies() here, see http://drupal.org/node/810352.
$result = db_query("SELECT v.vid, v.*, n.type FROM {vocabulary} v LEFT JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", $type_name);
while ($vocabulary = db_fetch_object($result)) {
$all = TRUE;
$fields['terms_' . $vocabulary->vid] = array(
'title' => t('Taxonomy: @vocab', array(
'@vocab' => $vocabulary->name,
)),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'css-class' => 'field-terms field-terms-' . $vocabulary->vid,
'formatters' => array(
'nd_terms_per_vocabulary_space' => t('Separated by space'),
'nd_terms_per_vocabulary_linked_space' => t('Separated by space, linked to term'),
'nd_terms_per_vocabulary_comma' => t('Separated by comma'),
'nd_terms_per_vocabulary_linked_comma' => t('Separated by comma, linked to term'),
'nd_terms_per_vocabulary_list' => t('Unordered list'),
'nd_terms_per_vocabulary_linked_list' => t('Unordered list, linked to term'),
),
),
);
}
if ($all) {
// All terms.
$fields['terms'] = array(
'title' => t('Taxonomy: all terms'),
'type' => DS_FIELD_TYPE_PREPROCESS,
'status' => DS_FIELD_STATUS_STATIC,
);
}
}
// Upload support.
if (module_exists('upload') && $build_mode != 'teaser' && variable_get("upload_{$type_name}", 1)) {
$fields['files'] = array(
'title' => t('Core upload'),
'type' => DS_FIELD_TYPE_IGNORE,
'status' => DS_FIELD_STATUS_STATIC,
);
}
// Book support.
if (module_exists('book') && book_type_is_allowed($type_name)) {
$fields['book_navigation'] = array(
'title' => t('Book navigation'),
'type' => DS_FIELD_TYPE_FUNCTION,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'nd_book_navigation' => t('Book navigation'),
),
),
);
$fields['book_add_new_child'] = array(
'title' => t('Book: add new child'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'nd_book_add_new_child' => t('Add new child'),
),
),
);
$fields['book_printer_version'] = array(
'title' => t('Book: printer version'),
'type' => DS_FIELD_TYPE_THEME,
'status' => DS_FIELD_STATUS_STATIC,
'properties' => array(
'formatters' => array(
'nd_book_printer_version' => t('Printer version'),
),
),
);
}
return array(
'nd' => $fields,
);
}
/**
* ND theming functions.
*/
function theme_nd_bodyfield($field) {
return $field['object']->content['body']['#value'];
}
function theme_nd_title_h1_nolink($field) {
return '<h1>' . check_plain($field['object']->title) . '</h1>';
}
function theme_nd_title_h1_link($field) {
return '<h1>' . l($field['object']->title, 'node/' . $field['object']->nid) . '</h1>';
}
function theme_nd_title_h2_nolink($field) {
return '<h2>' . check_plain($field['object']->title) . '</h2>';
}
function theme_nd_title_h2_link($field) {
return '<h2>' . l($field['object']->title, 'node/' . $field['object']->nid) . '</h2>';
}
function theme_nd_title_h2_block_nolink($field) {
return '<h2 class="block-title">' . check_plain($field['object']->title) . '</h2>';
}
function theme_nd_title_h2_block_link($field) {
return '<h2 class="block-title">' . l($field['object']->title, 'node/' . $field['object']->nid) . '</h2>';
}
function theme_nd_title_p_nolink($field) {
return '<p>' . check_plain($field['object']->title) . '</p>';
}
function theme_nd_title_p_link($field) {
return '<p>' . l($field['object']->title, 'node/' . $field['object']->nid) . '</p>';
}
/**
* Post date formatter.
*/
function theme_nd_post_date($field) {
$date_format = str_replace('nd_post_date_', '', $field['formatter']);
if (module_exists('date_api')) {
$datetime = date_make_date($field['object']->created, NULL, DATE_UNIX);
$format = variable_get('date_format_' . $date_format, 'd/m/Y');
return date_format_date($datetime, 'custom', $format);
}
else {
return format_date($field['object']->created, $date_format);
}
}
/**
* Terms per vocabulary.
*/
function nd_terms_per_vocabulary($field) {
$content = '';
if (isset($field['object']->taxonomy) && !empty($field['object']->taxonomy)) {
$terms = array();
$linked = FALSE;
$vid = end(explode('_', $field['key']));
$formatter_explode = explode('_', $field['formatter']);
$separators = array(
'space' => ' ',
'comma' => ', ',
);
$separator = $separators[end($formatter_explode)];
$list = end($formatter_explode) == 'list' ? TRUE : FALSE;
$linked = prev($formatter_explode);
foreach ($field['object']->taxonomy as $tid => $term) {
if ($term->vid == $vid) {
$terms[] = $linked == 'linked' ? l($term->name, taxonomy_term_path($term)) : check_plain($term->name);
}
}
if (!empty($terms)) {
if ($separator) {
$content = implode($separator, $terms);
}
elseif ($list) {
$content = theme('item_list', $terms);
}
}
}
return $content;
}
/**
* Book navigation theming.
*/
function nd_book_navigation($field) {
$content = '';
if (isset($field['object']->content['book_navigation'])) {
if (isset($field['object']->content['book_navigation']['#value'])) {
$content = $field['object']->content['book_navigation']['#value'];
}
elseif (isset($field['object']->book['bid']) && !empty($field['object']->book['bid'])) {
$content = theme('book_navigation', $field['object']->book);
}
}
else {
if (isset($field['object']->book['bid']) && !empty($field['object']->book['bid'])) {
$content = theme('book_navigation', $field['object']->book);
}
}
return $content;
}
/**
* Add new child for book.
*/
function theme_nd_book_add_new_child($field) {
if (user_access('add content to books')) {
$child = str_replace('_', '-', variable_get('book_child_type', 'book'));
return l(t('Add child page'), 'node/add/' . $child, array(
'query' => array(
'parent' => $field['object']->book['mlid'],
),
));
}
}
/**
* Printer friendly version
*/
function theme_nd_book_printer_version($field) {
return l(t('Printer-friendly version'), 'book/export/html/' . $field['object']->nid);
}
Functions
Name | Description |
---|---|
ds_views_row_apachesolr | Render the apachesolr object through the DS views plugin. |
ds_views_row_apachesolr_node | Render the apachesolr node object through the DS views plugin. |
ds_views_row_node | Render the node object through the DS views plugin. |
nd_book_navigation | Book navigation theming. |
nd_build_fields_and_regions | Statically cached version of ds_build_fields and regions |
nd_content_build_modes | Implementation of hook_content_build_modes(). |
nd_ds_api | Implementation of hook_ds_api(). |
nd_ds_fields | Implementation of hook_ds_fields(). |
nd_init | Implementation of hook_init(). |
nd_nd_build_alter | Implements hook_nd_build_alter |
nd_nodeapi | Implementation of hook_nodeapi(). |
nd_preprocess_node | Implementation of moduleName_preprocess_hook(). The node data will be rendered in regions. This uses a helper function so themers/developers can call that helper function from within their preprocess_hooks if they are fiddling with some data. For… |
nd_rules_action_info | Implementation of hook_rules_action_info(). |
nd_rules_event_info | Implementation of hook_rules_event_info(). |
nd_terms_per_vocabulary | Terms per vocabulary. |
nd_theme | Implementation of hook_theme(). |
nd_theme_registry_alter | Implementation of hook_registry_alter(). |
nd_views_node_helper | Helper function for views node plugin. |
theme_nd_bodyfield | ND theming functions. |
theme_nd_book_add_new_child | Add new child for book. |
theme_nd_book_printer_version | Printer friendly version |
theme_nd_post_date | Post date formatter. |
theme_nd_title_h1_link | |
theme_nd_title_h1_nolink | |
theme_nd_title_h2_block_link | |
theme_nd_title_h2_block_nolink | |
theme_nd_title_h2_link | |
theme_nd_title_h2_nolink | |
theme_nd_title_p_link | |
theme_nd_title_p_nolink | |
_nd_nodeapi | Helper function to alter node properties |
_nd_preprocess_node | Helper function used in either nd_preprocess_node or other preprocess function. |