You are here

views_tree.module in Views tree 7.2

Same filename and directory in other branches
  1. 8.2 views_tree.module
  2. 6.2 views_tree.module
  3. 6 views_tree.module

Views Tree module.

File

views_tree.module
View source
<?php

/**
 * @file
 * Views Tree module.
 */

/**
 * Implements hook_views_api().
 */
function views_tree_views_api() {
  return array(
    'api' => '3',
    'path' => drupal_get_path('module', 'views_tree'),
  );
}

/**
 * Implements hook_theme().
 */
function views_tree_theme($existing, $type, $theme, $path) {
  return array(
    'views_tree' => array(
      'variables' => array(
        'view' => NULL,
        'options' => array(),
        'rows' => array(),
        'title' => NULL,
      ),
    ),
    'views_tree_inner' => array(
      'variables' => array(
        'view' => NULL,
        'options' => array(),
        'rows' => array(),
        'title' => NULL,
        'result' => array(),
        'parent' => NULL,
      ),
    ),
  );
}

/**
 * Theme function for the tree style plugin.
 *
 * We need to do some weirdness that makes more sense as a theme function than
 * as a template.
 *
 * @ingroup themeable
 * @link http://drupal.org/node/355919
 */
function theme_views_tree($variables) {
  $view = $variables['view'];
  $options = $variables['options'];
  $rows = $variables['rows'];
  $title = $variables['title'];
  $result = $view->result;
  $fields =& $view->field;
  $parents = array();
  if (!$fields[$options['main_field']] instanceof views_handler_field) {
    drupal_set_message(t('Main field is invalid: %field', array(
      '%field' => $options['main_field'],
    )), 'error');
    return '';
  }
  if (!$fields[$options['parent_field']] instanceof views_handler_field) {
    drupal_set_message(t('Parent field is invalid: %field', array(
      '%field' => $options['parent_field'],
    )), 'error');
    return '';
  }

  // The field structure of Field API fields in a views result object is...
  // ridiculous. To avoid having to deal with it, we'll first iterate over all
  // records and normalize out the main and parent IDs to new properties. That
  // vastly simplifies the code that follows. This particular magic incantation
  // extracts the value from each record for the appropriate field specified by
  // the user. It then normalizes that value down to just an int, even though in
  // some cases it is an array. See views_tree_normalize_key(). Finally, we
  // build up a list of all main keys in the result set so that we can normalize
  // top-level records below.
  foreach ($result as $i => $record) {
    $result[$i]->views_tree_main = views_tree_normalize_key($fields[$options['main_field']]
      ->get_value($record), $fields[$options['main_field']]);
    $result[$i]->views_tree_parent = views_tree_normalize_key($fields[$options['parent_field']]
      ->get_value($record), $fields[$options['parent_field']]);
    $parents[] = $record->views_tree_main;
  }

  // Normalize the top level of records to all point to 0 as their parent
  // We only have to do this once, so we do it here in the wrapping function.
  foreach ($result as $i => $record) {
    if (!in_array($record->views_tree_parent, $parents)) {
      $result[$i]->views_tree_parent = 0;
    }
  }

  // Recursively render each item.
  $tree = theme('views_tree_inner', array(
    'view' => $view,
    'options' => $options,
    'rows' => $rows,
    'title' => $title,
    'result' => $result,
    'parent' => 0,
  ));

  // Add JS and CSS for collapsible tree, if configured.
  if (!empty($options['collapsible_tree'])) {
    drupal_add_js(array(
      'views_tree_setting' => array(
        $view->name => $options['collapsible_tree'],
      ),
    ), 'setting');
    drupal_add_js(drupal_get_path('module', 'views_tree') . '/js/collapsible.js');
    drupal_add_css(drupal_get_path('module', 'views_tree') . '/css/collapsible.css');
  }
  return $title . $tree;
}

/**
 * Inner recursive theme function for views tree theming.
 *
 * @ingroup themeable
 * @param $view
 * @param $options
 * @param $row
 * @param $title
 * @param $result
 *   An array representing the raw data returned from the query.
 * @param $parent
 *   The id of the parent entry in the call stack.
 */
function theme_views_tree_inner($variables) {
  $view = $variables['view'];
  $options = $variables['options'];
  $rows = $variables['rows'];
  $title = $variables['title'];
  $result = $variables['result'];
  $parent = $variables['parent'];
  $items = array();
  foreach ($result as $i => $record) {
    if ($record->views_tree_parent == $parent) {
      $variables['parent'] = $record->views_tree_main;
      $items[] = $rows[$i] . call_user_func(__FUNCTION__, $variables);
    }
  }
  return count($items) ? theme('item_list', array(
    'items' => $items,
    'type' => $options['type'],
  )) : '';
}

/**
 * Normalize a value out of the record to an int.
 *
 * If the field in question comes from Field API, then it will be an array, not
 * an int. We need to detect that and extract the int value we want from it.
 * Note that because Field API structures are so free-form, we have to
 * specifically support each field type.  For now we support entityreference
 * (target_id), nodereference (nid), userreference (uid), organic groups (gid),
 * and taxonomyreference (tid).
 *
 * @param mixed $value
 *   The value to normalize. It should be either an int or an array. If an int,
 *   it is returned unaltered. If it's an array, we extract the int we want and
 *   return that.
 * @param views_handler_field $field
 *   Metadata about the field we are extracting information from.
 * @return int
 *   The value of this key, normalized to an int.
 */
function views_tree_normalize_key($value, views_handler_field $field) {
  if (is_array($value) && count($value)) {
    if (isset($field->field_info['columns'])) {
      $columns = array_keys($field->field_info['columns']);
      foreach ($columns as $column) {
        if (in_array($column, array(
          'target_id',
          'nid',
          'uid',
          'tid',
        ))) {
          $field_property = $column;
          break;
        }
      }
    }
    else {
      $field_property = '';
    }
    return $field_property ? $value[0][$field_property] : 0;
  }
  else {
    return $value ? $value : 0;
  }
}

Functions

Namesort descending Description
theme_views_tree Theme function for the tree style plugin.
theme_views_tree_inner Inner recursive theme function for views tree theming.
views_tree_normalize_key Normalize a value out of the record to an int.
views_tree_theme Implements hook_theme().
views_tree_views_api Implements hook_views_api().