You are here

nodehierarchy_views.module in Node Hierarchy 7.4

Embed a view of children onto a node.

File

nodehierarchy_views/nodehierarchy_views.module
View source
<?php

/**
 * @file
 * Embed a view of children onto a node.
 *
 */

/**
 * Implements hook_theme().
 */
function nodehierarchy_views_theme() {
  return array(
    'nodehierarchy_children_embed' => array(
      'render element' => 'element',
    ),
  );
}

/**
 * Implements hook_permission().
 */
function nodehierarchy_views_permission() {
  return array(
    'access embedded child view' => array(
      'title' => t('access embedded child view'),
      'description' => t('TODO Add a description for \'access embedded child view\''),
    ),
    'edit embedded child view' => array(
      'title' => t('edit embedded child view'),
      'description' => t('TODO Add a description for \'edit embedded child view\''),
    ),
  );
}

/**
 * Implements hook_content_extra_fields().
 */
function nodehierarchy_views_field_extra_fields() {
  module_load_include('inc', 'nodehierarchy', 'nodehierarchy.admin');
  $extra = array();
  foreach (node_type_get_names() as $type => $name) {
    if (nodehierarchy_node_can_be_parent($type)) {
      $extra['node'][$type] = array(
        'display' => array(
          'nodehierarchy_children' => array(
            'label' => t('Node Hierarchy Children'),
            'description' => t('Node Hierarchy embedded children view.'),
            'weight' => 10,
          ),
          'nodehierarchy_children_links' => array(
            'label' => t('Node Hierarchy Add Child Links'),
            'description' => t('Links to create a new child.'),
            'weight' => 11,
          ),
        ),
      );
    }
  }
  return $extra;
}

/**
 * Implements hook_views_api().
 */
function nodehierarchy_views_views_api() {
  return array(
    'api' => 3,
  );
}

/**
 * Implements hook_node_insert().
 */
function nodehierarchy_views_node_insert($node) {
  return nodehierarchy_views_insert($node);
}

/**
 * Implements hook_node_update().
 */
function nodehierarchy_views_node_update($node) {
  return nodehierarchy_views_update($node);
}

/**
 * Implements hook_node_prepare().
 */
function nodehierarchy_views_node_prepare($node) {
  return nodehierarchy_views_prepare_node($node);
}

/**
 * Implements hook_node_load().
 */
function nodehierarchy_views_node_load($node, $types) {
  return nodehierarchy_views_load_node($node);
}

/**
 * Implements hook_node_delete().
 */
function nodehierarchy_views_node_delete($node) {
  nodehierarchy_views_delete_node($node);
}

/**
 * Implements hook_node_validate().
 */
function nodehierarchy_views_node_validate($node, $form) {
}

/**
 * Implements hook_node_view().
 */
function nodehierarchy_views_node_view($node, $view_mode = 'full') {
  if ($view_mode == 'full' && user_access('access embedded child view')) {
    nodehierarchy_views_embed_children($node);
  }
}

/**
 * @todo Please document this function.
 * @see http://drupal.org/node/1354
 */
function nodehierarchy_views_nodehierarchy_node_form($node) {
  module_load_include('inc', 'nodehierarchy', 'nodehierarchy.admin');
  $form = array();
  $default_value = NULL;
  if (!empty($node->nh_children_view)) {
    $display = !empty($node->nh_children_view_display) ? $node->nh_children_view_display : 'default';
    $default_value = $node->nh_children_view . ':' . $display;
  }
  if ($node && nodehierarchy_node_can_be_parent($node)) {
    $form['nh_children_view'] = array(
      '#type' => user_access('edit embedded child view') ? 'select' : 'value',
      '#title' => t('Embed Children View'),
      '#multiple' => FALSE,
      '#options' => _nodehierarchy_views_view_options(),
      '#required' => FALSE,
      '#default_value' => $default_value,
      '#description' => t("Embed a view containing this node's children into the node's page view"),
    );
  }
  return $form;
}

/**
 * Implements hook_nodehierarchy_node_type_settings_form().
 */
function nodehierarchy_views_nodehierarchy_node_type_settings_form($type) {
  module_load_include('inc', 'nodehierarchy', 'nodehierarchy.admin');
  $form = array();
  if (nodehierarchy_node_can_be_parent($type)) {
    $form['nh_default_children_view'] = array(
      '#type' => 'select',
      '#title' => t('Default Children View'),
      '#multiple' => FALSE,
      '#options' => _nodehierarchy_views_view_options(),
      '#required' => FALSE,
      '#default_value' => variable_get('nh_default_children_view_' . $type, NULL),
      '#description' => t('Default for the embed children view feature.'),
    );
  }
  return $form;
}

/**
 * Implements hook_load().
 */
function nodehierarchy_views_load_node($nodes) {
  foreach ($nodes as $node) {
    if ($results = db_query('SELECT nh_children_view, nh_children_view_display FROM {nodehierarchy_views} WHERE nid = :nid', array(
      ':nid' => $node->nid,
    ))
      ->fetchObject()) {
      $node->nh_children_view = $results->nh_children_view;
      $node->nh_children_view_display = $results->nh_children_view_display;
    }
  }
}

/**
 * Set a default embedded view.
 */
function nodehierarchy_views_prepare_node(&$node) {

  // Set the default children view if there is one for this type and if the node has not been saved yet.
  if (empty($node->nid) && empty($node->nh_children_view) && ($children_view = variable_get('nh_default_children_view_' . $node->type, NULL))) {
    list($node->nh_children_view, $node->nh_children_view_display) = explode(':', $children_view);
  }
}

/**
 * Delete the node_hierarchy_views row when a node is deleted.
 */
function nodehierarchy_views_delete_node($node) {
  db_delete('nodehierarchy_views')
    ->condition('nid', $node->nid)
    ->execute();
}

/**
 * Update the given embedded view.
 */
function nodehierarchy_views_update($node) {
  if (user_access('edit embedded child view')) {
    db_delete('nodehierarchy_views')
      ->condition('nid', $node->nid)
      ->execute();
    if (!empty($node->nh_children_view)) {
      $parts = explode(':', $node->nh_children_view);
      if (!empty($parts[0])) {
        $view = $parts[0];
      }
      if (!empty($parts[1])) {
        $display = $parts[1];
      }
      else {

        // If this update is not from a form submit then the display may be stored separately.
        $display = !empty($node->nh_children_view_display) ? $node->nh_children_view_display : 'default';
      }
      $id = db_insert('nodehierarchy_views')
        ->fields(array(
        'nid' => $node->nid,
        'nh_children_view' => $view,
        'nh_children_view_display' => $display,
      ))
        ->execute();
    }
  }
}

/**
 * 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);
  }
  elseif ($children_view = variable_get('nh_default_children_view_' . $node->type, NULL)) {
    list($view, $display) = explode(':', $children_view);
    $id = db_insert('nodehierarchy_views')
      ->fields(array(
      'nid' => $node->nid,
      'nh_children_view' => $view,
    ))
      ->execute();
  }
}

/**
 * Add the embedded children view to the node body if appropriate.
 */
function nodehierarchy_views_embed_children(&$node) {
  static $depth = 0;

  // Make sure we don't go through more than 3 iterations to prevent memory or call stack errors.
  if ($depth++ < 3) {
    $display = @$node->nh_children_view_display ? @$node->nh_children_view_display : 'default';

    // Get the arguments to send to the view. This should allow other view arguments to still work.
    $arguments = explode('/', $_GET['q']);

    // First arg will be 'node', the second will be the node id. Remove them.
    array_shift($arguments);
    array_shift($arguments);

    // Add the node id of the given node.
    array_unshift($arguments, $node->nid);

    // Defer the rendering of the view until the theme function so it can be overriden or altered.
    $node->content['nodehierarchy_children'] = array(
      '#theme' => 'nodehierarchy_children_embed',
      '#nodehierarchy_view' => empty($node->nh_children_view) ? null : $node->nh_children_view,
      '#nodehierarchy_view_display' => @$node->nh_children_view_display ? @$node->nh_children_view_display : 'default',
      '#nodehierarchy_view_args' => $arguments,
    );
    $node->content['nodehierarchy_children_links'] = theme('nodehierarchy_new_child_links', array(
      'node' => $node,
    ));
  }
}

/**
 * Prepare a list of views for selection.
 */
function _nodehierarchy_views_view_options() {
  $options = array();
  $options[0] = '-- ' . t('NONE') . ' --';
  $views = _nodehierarchy_views_get_embed_views();
  foreach ($views as $item) {
    $options[$item['name'] . ':' . $item['display']] = $item['title'];
  }
  return $options;
}

/**
 * Get a list of views that can be embedded.
 */
function _nodehierarchy_views_get_embed_views($reset = FALSE) {
  $used_views =& drupal_static(__FUNCTION__);
  if (!isset($used_views) || $reset) {
    views_include('cache');

    // If we're not resetting, check the Views cache.
    if (!$reset) {
      $cache = views_cache_get("nodehierarchy_views");
      if (isset($cache->data)) {
        $used_views = $cache->data;
      }
    }

    // If it's still empty rebuild it.
    if (!isset($used_views)) {

      // Trigger a rebuild of the views object cache, which may not be fully loaded.
      ctools_include('export');
      ctools_export_load_object_reset('views_view');

      // Build and cache the data, both in the DB and statically.
      $views = views_get_applicable_views('nodehierarchy embed view');
      foreach ($views as $data) {
        list($view, $display_id) = $data;
        $tile = $view->display_handler
          ->get_option('nodehierarchy_embed_admin_name');
        if (empty($tile)) {
          $tile = $view
            ->get_human_name() . ' - ' . $view->display[$display_id]->display_title;
        }
        $used_views[] = array(
          'name' => $view->name,
          'display' => $display_id,
          'title' => $tile,
        );
        $view
          ->destroy();
      }
      views_cache_set("nodehierarchy_views", $used_views);
    }
  }
  return isset($used_views) ? $used_views : array();
}

/**
 * Determine if the given view/display is node hierarchy compatible.
 */
function _nodehierarchy_views_is_chilren_embed_view($view, $display = 'default') {
  $view
    ->set_display($display);
  $view
    ->build($display);
  $arg = (array) $view->argument !== array() ? reset($view->argument) : FALSE;
  if (!empty($arg->table) && ($arg->table == "nh_parent" || $arg->table == "nh_ancestor")) {
    return TRUE;
  }
  return FALSE;
}

/**
 * Render the embedded chidren for the given node.
 */
function theme_nodehierarchy_children_embed($variables) {
  $element = $variables['element'];
  if (!empty($element['#nodehierarchy_view']) && ($view = views_get_view($element['#nodehierarchy_view']))) {
    $display = $element['#nodehierarchy_view_display'];
    $arguments = $element['#nodehierarchy_view_args'];
    return $view
      ->execute_display($display, $arguments);
  }
  return '';
}

Functions

Namesort descending Description
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_field_extra_fields Implements hook_content_extra_fields().
nodehierarchy_views_insert Insert the given embedded view.
nodehierarchy_views_load_node Implements hook_load().
nodehierarchy_views_nodehierarchy_node_form @todo Please document this function.
nodehierarchy_views_nodehierarchy_node_type_settings_form Implements hook_nodehierarchy_node_type_settings_form().
nodehierarchy_views_node_delete Implements hook_node_delete().
nodehierarchy_views_node_insert Implements hook_node_insert().
nodehierarchy_views_node_load Implements hook_node_load().
nodehierarchy_views_node_prepare Implements hook_node_prepare().
nodehierarchy_views_node_update Implements hook_node_update().
nodehierarchy_views_node_validate Implements hook_node_validate().
nodehierarchy_views_node_view Implements hook_node_view().
nodehierarchy_views_permission Implements hook_permission().
nodehierarchy_views_prepare_node Set a default embedded view.
nodehierarchy_views_theme Implements hook_theme().
nodehierarchy_views_update Update the given embedded view.
nodehierarchy_views_views_api Implements hook_views_api().
theme_nodehierarchy_children_embed Render the embedded chidren for the given node.
_nodehierarchy_views_get_embed_views Get a list of views that can be embedded.
_nodehierarchy_views_is_chilren_embed_view Determine if the given view/display is node hierarchy compatible.
_nodehierarchy_views_view_options Prepare a list of views for selection.