You are here

nodehierarchy_views.module in Node Hierarchy 5

Views.module integration for nodehierarchy.module.

Provides node hierarchy specific views arguments and allows users to embed a view of a node's children into the node.

File

nodehierarchy_views/nodehierarchy_views.module
View source
<?php

/**
 * @file
 * Views.module integration for nodehierarchy.module.
 *
 * Provides node hierarchy specific views arguments and allows users to embed
 * a view of a node's children into the node.
 */

/**
 * Implementation of hook_nodeapi().
 */
function nodehierarchy_views_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'insert':
      return nodehierarchy_views_insert($node);
      break;
    case 'update':
      return nodehierarchy_views_update($node);
      break;
    case 'load':
      return nodehierarchy_views_load_node($node);
      break;
    case 'delete':
      nodehierarchy_views_delete_node($node);
      break;
    case 'submit':
      break;
    case 'validate':
      break;
    case 'view':
      if ($page && user_access('access embedded child view')) {
        nodehierarchy_views_embed_children($node);
      }
      break;
  }
}

/**
 * Implementation of hook_nodehierarchyapi().
 */
function nodehierarchy_views_nodehierarchyapi($op, $node) {
  switch ($op) {
    case "node_type_form":
      $form = array();
      if (nodehierarchy_node_can_be_parent($node)) {
        $form['nh_default_children_view'] = array(
          '#type' => 'select',
          '#title' => "Default Children View",
          '#multiple' => FALSE,
          '#options' => _nodehierarchy_views_view_options(),
          '#required' => FALSE,
          '#default_value' => variable_get('nh_default_children_view_' . $node->type, NULL),
          '#description' => t("Default for the embed children view feature."),
        );
      }
      return $form;
      break;
    case "node_form":
      $form = array();
      if (user_access('edit embedded child view') && nodehierarchy_node_can_be_parent($node)) {
        $form['nh_children_view'] = array(
          '#type' => 'select',
          '#title' => "Embed Children View",
          '#multiple' => FALSE,
          '#options' => _nodehierarchy_views_view_options(),
          '#required' => FALSE,
          '#default_value' => $node->nh_children_view === NULL ? variable_get('nh_default_children_view_' . $node->type, NULL) : $node->nh_children_view,
          '#description' => t("Embed a view containing this node's children into the node's page view"),
        );
      }
      return $form;
      break;
  }
}

/**
 * Implementation of hook_perm().
 */
function nodehierarchy_views_perm() {
  return array(
    'access embedded child view',
    'edit embedded child view',
  );
}

/**
 * Implementation of hook_load().
 */
function nodehierarchy_views_load_node($node) {
  $additions = db_fetch_array(db_query('SELECT nh_children_view FROM {nodehierarchy_views} WHERE nid = %d', $node->nid));
  return $additions;
}

/**
 * Delete the node_hierarchy_views row when a node is deleted.
 */
function nodehierarchy_views_delete_node($node) {
  db_query('DELETE FROM {nodehierarchy_views} WHERE nid = %d', $node->nid);
}

/**
 * Update the given embedded view.
 */
function nodehierarchy_views_update($node) {
  if (user_access('edit embedded child view')) {
    db_query('DELETE FROM {nodehierarchy_views} WHERE nid = %d', $node->nid);
    $valid_views = _nodehierarchy_views_view_options();
    if ($node->nh_children_view && isset($valid_views[$node->nh_children_view])) {
      db_query("INSERT INTO {nodehierarchy_views} (nid, nh_children_view) VALUES (%d, '%s')", $node->nid, $node->nh_children_view);
    }
    else {
      if (variable_get('nh_default_children_view_' . $node->type, NULL) !== NULL && !$node->nh_children_view) {
        db_query("INSERT INTO {nodehierarchy_views} (nid, nh_children_view) VALUES (%d, '')", $node->nid);
      }
    }
  }
}

/**
 * Insert the given embedded view.
 */
function nodehierarchy_views_insert($node) {

  // If the user has access to edit the view, update as usual.
  if (user_access('edit embedded child view')) {
    nodehierarchy_views_update($node);
  }
  else {
    db_query("INSERT INTO {nodehierarchy_views} (nid, nh_children_view) VALUES (%d, '%s')", $node->nid, variable_get('nh_default_children_view_' . $node->type, NULL));
  }
}

/**
 * Add the embedded children view to the node body if appropriate.
 */
function nodehierarchy_views_embed_children(&$node) {
  if ($node->nh_children_view && ($view = views_get_view($node->nh_children_view))) {

    // make sure the first argument is a node hierarchy parent argument
    $first_arg = $view->argument[0];
    if (!$first_arg || $first_arg['type'] !== "parent" && $first_arg['type'] !== "antecedent") {
      array_unshift($view->argument, array(
        'type' => 'parent',
        'argdefault' => '1',
        'title' => '',
        'options' => '',
        'wildcard' => '',
        'wildcard_substitution' => '',
      ));
    }

    // Get the arguments to send to the view.
    $arguments = explode('/', $_GET['q']);

    // First arg will be 'node', remove it.
    array_shift($arguments);

    // The next argument is the nid, this we will pass as the parent,
    // The rest may be added by the view (feed selectors, calendar params etc).
    // Set the url of the view so that filters and arguments work.
    // NB: setting this to just 'node' works since the nid will be added by the
    // argument code in views (first arg is always the nid). This works but may
    // be taking advantage of a non-api side effect and should be treated with
    // caution.
    $view->url = "node";
    $node->content['nodehierarchy_children'] = array(
      "#value" => views_build_view('embed', $view, $arguments, $view->use_pager, $view->nodes_per_page),
      "#weight" => 10,
    );
  }
}

/**
 * Prepare a list of views for selection.
 */
function _nodehierarchy_views_view_options() {
  $options = array();
  $options[0] = '-- ' . t('NONE') . ' --';
  include_once drupal_get_path('module', 'views') . '/views_cache.inc';
  $default_views = _views_get_default_views();
  $res = db_query("SELECT name FROM {view_view} ORDER BY name");
  while ($view = db_fetch_object($res)) {
    $options[$view->name] = $view->name;
  }
  if (is_array($default_views)) {
    foreach ($default_views as $key => $view) {
      $options[$key] = $view->name;
    }
  }
  return $options;
}

// Implementations of Views Hooks.

/**
 * Implementation of hook_views_tables().
 */
function nodehierarchy_views_tables() {
  $tables['nodehierarchy'] = array(
    'name' => 'nodehierarchy',
    'provider' => 'internal',
    'join' => array(
      'left' => array(
        'table' => 'node',
        'field' => 'nid',
      ),
      'right' => array(
        'field' => 'nid',
      ),
    ),
    'fields' => array(
      'order_by' => array(
        'name' => t('Node Hierarchy: Sort Order'),
        'sortable' => TRUE,
        'help' => t('This will display the sort order of a node in the hierarchy.'),
      ),
      'nid' => array(
        'name' => t('Node Hierarchy: Actions'),
        'sortable' => FALSE,
        'handler' => 'views_handler_field_nodehierarchy_actions',
        'help' => t('This will display hierarchy actions such as move up, move down, view and edit.'),
      ),
      'parent' => array(
        'name' => t('Node Hierarchy: Parent'),
        'sortable' => FALSE,
        'handler' => 'views_handler_field_nodehierarchy_parent',
        'help' => t('This will display the nodehierarchy parent for the node.'),
        'option' => array(
          '#type' => 'select',
          '#options' => array(
            'default' => 'Title (link)',
            'plain' => 'Title (no link)',
          ),
        ),
      ),
    ),
    'sorts' => array(
      'order_by' => array(
        'name' => t('Node Hierarchy: Sort Order'),
        'help' => t('This will allow you to sort by the heirarchical sort order.'),
      ),
    ),
  );
  return $tables;
}

/**
 * Implementation of hook_views_arguments().
 */
function nodehierarchy_views_arguments() {
  $arguments = array(
    'parent' => array(
      'name' => t('Node Hierarchy: Parent Node ID'),
      'handler' => 'views_handler_arg_nodehierarchy_parent',
      'help' => t('Get all of the children of the given node'),
    ),
    'antecedent' => array(
      'name' => t('Node Hierarchy: Descendant Of'),
      'handler' => 'views_handler_arg_nodehierarchy_antecedent',
      'help' => t('Get all of the descendants of the given node'),
    ),
  );
  return $arguments;
}

/**
 * Handle the parent argument.
 */
function views_handler_arg_nodehierarchy_parent($op, &$query, $argtype, $arg = '') {
  switch ($op) {
    case 'summary':
      $query
        ->add_field('nid');
      $query
        ->add_field("title");
      $fieldinfo['field'] = 'nodehierarchy.parent';
      return $fieldinfo;
    case 'sort':
      $query
        ->add_orderby('nodehierarchy', 'order_by', $argtype);
      break;
    case 'filter':
      $query
        ->ensure_table("nodehierarchy");
      $query
        ->add_where("nodehierarchy.parent = %d", $arg);
      break;
    case 'link':
      return l($query->title, "{$arg}/{$query->nid}");
    case 'title':
      $node = db_fetch_object(db_query("SELECT title FROM {node} WHERE nid=%d", $query));
      return $node->title;
  }
}

/**
 * Handle the antecedent argument.
 */
function views_handler_arg_nodehierarchy_antecedent($op, &$query, $argtype, $arg = '') {
  switch ($op) {
    case 'summary':
      $query
        ->add_field('nid');
      $query
        ->add_field("title");
      $fieldinfo['field'] = 'nodehierarchy.parent';
      return $fieldinfo;
    case 'sort':
      $query
        ->add_orderby('nodehierarchy', 'order_by', $argtype);
      break;
    case 'filter':
      $query
        ->ensure_table("nodehierarchy");
      $descendants = _nodehierarchy_views_get_descendant_parents($arg);
      $descendant_list = implode(",", $descendants);
      $query
        ->add_where("nodehierarchy.parent IN ( {$descendant_list} )");
      break;
    case 'link':
      return l($query->title, "{$arg}/{$query->nid}");
    case 'title':
      $node = db_fetch_object(db_query("SELECT title FROM {node} WHERE nid=%d", $query));
      return $node->title;
  }
}

/**
 * Returnt the list of descendants of the given node which can also themselves be parents.
 */
function _nodehierarchy_views_get_descendant_parents($nid) {
  static $parent_types = NULL;
  if (!$parent_types) {
    $types = _nodehierarchy_get_parent_types("", TRUE);
    $parent_types = implode(",", $types);
  }
  $out = array(
    $nid,
  );
  $result = db_query("SELECT n.nid FROM {node} n LEFT JOIN {nodehierarchy} h ON h.nid = n.nid WHERE h.parent = %d and n.type IN (" . $parent_types . ")", $nid);
  while ($child = db_fetch_object($result)) {
    $out = array_merge($out, _nodehierarchy_views_get_descendant_parents($child->nid));
  }
  return $out;
}

/**
 * Useful default views which can be used to display children.
 */
function nodehierarchy_views_default_views() {
  $view = new stdClass();
  $view->name = 'nodehierarchy_children_teasers';
  $view->description = 'Display a node\'s children as a list';
  $view->access = array();
  $view->view_args_php = '';
  $view->page = TRUE;
  $view->page_title = '';
  $view->page_header = '';
  $view->page_header_format = '1';
  $view->page_footer = '';
  $view->page_footer_format = '1';
  $view->page_empty = '';
  $view->page_empty_format = '1';
  $view->page_type = 'teaser';
  $view->url = '';
  $view->use_pager = FALSE;
  $view->nodes_per_page = '99';
  $view->sort = array(
    array(
      'tablename' => 'nodehierarchy',
      'field' => 'order_by',
      'sortorder' => 'ASC',
      'options' => '',
    ),
  );
  $view->argument = array(
    array(
      'type' => 'parent',
      'argdefault' => '1',
      'title' => '',
      'options' => '',
      'wildcard' => '',
      'wildcard_substitution' => '',
    ),
  );
  $view->field = array(
    array(
      'tablename' => 'node',
      'field' => 'title',
      'label' => '',
      'handler' => 'views_handler_field_nodelink',
      'options' => 'link',
    ),
  );
  $view->filter = array(
    array(
      'tablename' => 'node',
      'field' => 'status',
      'operator' => '=',
      'options' => '',
      'value' => '1',
    ),
  );
  $view->exposed_filter = array();
  $view->requires = array(
    'nodehierarchy',
    'node',
  );
  $views[$view->name] = $view;

  // Duplicate the view.
  $view = unserialize(serialize($view));
  $view->page_type = 'list';
  $view->name = 'nodehierarchy_children_list';
  $view->description = t('Display a node\'s children as a list');
  $views[$view->name] = $view;
  return $views;
}

/**
 * Display the actions.
 */
function views_handler_field_nodehierarchy_actions($fieldinfo, $fielddata, $value, $data) {
  $node = new stdClass();
  $node->nid = $value;
  return theme("nodehierarchy_actions", $node);
}

/**
 * Display the parent.
 */
function views_handler_field_nodehierarchy_parent($fieldinfo, $fielddata, $value, $data) {
  static $titles = array();
  if (!isset($titles[$value])) {
    $title = db_result(db_query("SELECT title FROM {node} WHERE nid=%d", $value));
    $titles[$value] = $title ? $title : '';
  }
  switch ($fielddata['options']) {
    case 'plain':
      return check_plain($titles[$value]);
    default:
      return l($titles[$value], 'node/' . $value);
  }
}

Functions

Namesort descending Description
nodehierarchy_views_arguments Implementation of hook_views_arguments().
nodehierarchy_views_default_views Useful default views which can be used to display children.
nodehierarchy_views_delete_node Delete the node_hierarchy_views row when a node is deleted.
nodehierarchy_views_embed_children Add the embedded children view to the node body if appropriate.
nodehierarchy_views_insert Insert the given embedded view.
nodehierarchy_views_load_node Implementation of hook_load().
nodehierarchy_views_nodeapi Implementation of hook_nodeapi().
nodehierarchy_views_nodehierarchyapi Implementation of hook_nodehierarchyapi().
nodehierarchy_views_perm Implementation of hook_perm().
nodehierarchy_views_tables Implementation of hook_views_tables().
nodehierarchy_views_update Update the given embedded view.
views_handler_arg_nodehierarchy_antecedent Handle the antecedent argument.
views_handler_arg_nodehierarchy_parent Handle the parent argument.
views_handler_field_nodehierarchy_actions Display the actions.
views_handler_field_nodehierarchy_parent Display the parent.
_nodehierarchy_views_get_descendant_parents Returnt the list of descendants of the given node which can also themselves be parents.
_nodehierarchy_views_view_options Prepare a list of views for selection.