Skip to content
views_aggregator.module 7.27 KiB
Newer Older
<?php
/**
 * @file
 * views_aggregator.module
 *
 * Module implementig post-query aggregation functions for Views tables.
 */

require_once 'views/views_aggregator_functions.inc';
//require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'views_aggregator') . 'views/views_aggregator_functions.inc';

/**
 * Implements hook_help().
 */
function views_aggregator_help($path, $arg) {
  switch ($path) {
    case 'admin/help#views_aggregator':
      return t('See the <a href="@README">README</a> for View configuration instructions and examples or browse the <a href="@project">project</a> support queue.', array(
        '@project' => url('http://drupal.org/project/views_aggregator'),
        '@README' => url(drupal_get_path('module', 'views_aggregator') . '/README.txt'),
      ));
  }
}

/**
 * Implements hook_theme().
 */
function views_aggregator_theme() {
  $base_path = drupal_get_path('module', 'views_aggregator');
  $themes = array(
    'views_aggregator_plugin_style_table' => array(
      // Pass $form to theme_views_aggregator_plugin_style_table($vars)
      'render element' => 'form',
      'path' =>  $base_path . '/views',
      'file' => 'theme_views_aggregator_plugin_style_table.inc',
    ),
  );
  return $themes;
}

/**
 * Implements hook_views_api().
 */
function views_aggregator_views_api() {
  return array(
    'api' => views_api_version(),
    'path' => drupal_get_path('module', 'views_aggregator') . '/views',
  );
}

/**
 * Get all avaialble aggregation function definitions.
 *
 * @param string name
 *   The name of the desired function or NULL to retrieve an array of functions.
 *
 * @return array
 *   An array of aggregation function parameters.
 */
function views_aggregator_get_aggregation_functions_info($name = NULL) {

  $aggregation_functions = &drupal_static(__FUNCTION__);

  if (empty($aggregation_functions)) {
    // Collect aggregations functions defined in other modules via their
    // hook_views_aggregation_functions_info() implementations.
    $aggregation_functions = module_invoke_all('views_aggregation_functions_info');

    // Let other modules alter the aggregation functions by implementing
    // hook_views_aggregation_functions_alter().
    drupal_alter('views_aggregation_functions_info', $aggregation_functions);
  }
  //$aggregation_functions = (array)$aggregation_functions;
  if (empty($name)) {
    return $aggregation_functions;
  }
  if (isset($aggregation_functions[$name])) {
    return $aggregation_functions[$name];
  }
}

/**
 * Returns the result value at the intersection of column and row.
 *
 * @param object $field_handler
 *   The handler associated with the table column being requested.
 *
 * @param object $row_num
 *   index into the View result rows array
 * @param object $rendered
 *   Whether to return the rendered as opposed to the raw value of the cell
function views_aggregator_get_cell($field_handler, $row_num, $rendered) {
  return $field_handler->view->style_plugin->get_cell($field_handler, $row_num, $rendered);
 * Render a field from a raw value, with or without affecting the View result.
 * The field will be rendered without label, with appropriate CSS classes.
 *
 * NB: This is messy code. The lengths we have to go through for this are just
 * ridiculous. Patches welcome!
 *
 * @param object $views_field_handler
 *   The views_handler_field_field object belonging to the View result field
 * @param $row_num
 *   The view result row number to change. Pass NULL to simply render $raw_value
 *   outside the context of a View, without affecting any rows.
 * @param mixed $raw_value
 *   Compound or simple value. If NULL the field is re-rendered using its
 *   current (raw) value.
 * @return string
 *   The rendered value or FALSE, if the type of field is not supported.
function views_aggregator_render_field($views_field_handler, $row_num = NULL, $raw_value = NULL) {
  $field_alias = $views_field_handler->field_alias;
  $row = isset($row_num) ? $views_field_handler->view->result[$row_num] : reset($views_field_handler->view->result);
  if (!$row || empty($row->_field_data[$field_alias])) {
    // This happens for ViewsPHP fields, for instance.
    return !$row || isset($row_num) ? FALSE : (isset($raw_value) ? $raw_value : '?');
  $_field_data = $row->_field_data[$field_alias];
  $field_name = $views_field_handler->options['id'];
  if (!is_array($_field_data['entity']->{$field_name})) {
    // E.g. when the $views_field_handler refers to a node property (rather than
    // a field) that does not have a renderer.
    return isset($row_num) ? ($_field_data['entity']->{$field_name} = $raw_value) : $raw_value;
  // Clone entity if we don't want to affect the current View results.
  $entity = isset($row_num) ? $_field_data['entity'] : clone $_field_data['entity'];
  $entity_type = $_field_data['entity_type'];
  $lang = is_a($views_field_handler, 'views_handler_field_field') ? $views_field_handler->field_language($entity_type, $entity) : $entity->language;
  if (isset($raw_value)) {
    // Only supporting values of 1 item, at index 0.
    if (is_array($raw_value)) {
      $entity->{$field_name}[$lang][0] = $raw_value;
    }
    else {
      foreach ($entity->{$field_name}[$lang][0] as $name => $value) {
        if ($name != 'value' && !($name == 'tid' && is_numeric($raw_value))) {
          return isset($row_num) ? FALSE : (isset($raw_value) ? $raw_value : $value);
        // tid may be set in case of min, max, most frequent etc.
        $entity->{$field_name}[$lang][0][$name] = $raw_value;
    if (isset($row_num)) {
      // Next employ set_items() to re-render the $entity updated above,
      // placing both the 'raw' and 'rendered' versions in field_...[].
      $row->{'field_' . $field_name} = $views_field_handler->set_items($row, $row_num);
      // The final step is to theme the rendered values.
      return $views_field_handler->theme($row); // alt: $views_field_handler->advanced_render($row);
    }
  $display = array(
    'type' => $views_field_handler->options['type'],
    'settings' => $views_field_handler->options['settings'],
    'label' => 'hidden',
  );
  $render_array = field_view_field($entity_type, $entity, $field_name, $display, $lang);
  return drupal_render($render_array);
}

/**
 * Prepare to render the view results as a table style.
 *
 * The rendering to HTML happens in views-aggregator-results-table.tpl.php
 *
 * See also:
 * template_preprocess_views_view_table(&$vars) in Views
 */
function template_preprocess_views_aggregator_results_table(&$vars) {
  $view = $vars['view'];
Rik de Boer's avatar
Rik de Boer committed
  if (!empty($view->totals) && array_filter($view->totals) != array()) {
Rik de Boer's avatar
Rik de Boer committed
    $vars['footer'] = $view->totals;
  }
Rik de Boer's avatar
Rik de Boer committed
  if (!isset($view->row_index)) {
    // Have seen trouble when this is not set...
    $view->row_index = 0;
  // At this point template_preprocess_views_view(), will have put the (sorted)
  // $view->result on $vars['rows'].
  // template_preprocess_views_view_table() will add row and field classes,
  // caption etc. It will also call render_fields() but that won't do anything
  // as we've already done the rendering in view_aggregator_plugin_style_table::
  // pre_render().
  // The order of the rendered rows is determined by $view->result, while the
  // content of each row comes from $view->style_plugin->rendered_fields.
  template_preprocess_views_view_table($vars);
}