<?php
// $Id: charts.module,v 1.22 2008/11/13 01:57:56 brmassa Exp $
/**
 * @author Bruno Massa http://drupal.org/user/67164
 * @file
 * Transform DATA into INFORMATION using beautiful CHARTS.
 *
 * @note only hooks are here.
 * @note For instructions about the API, see chart_api.txt file.
 */

/**
 * The main Chart API function, that calls any chart provider
 * to print the given data.
 *
 * @param &$data
 *   Array. The chart data, described on chart_api.txt
 * @return
 *   String. The HTML with the propper chart (might include Flash or
 *   JavaScript external files)
 */
function charts_chart(&$data) {
  // Get the previously saved data from database
  $settings = variable_get('charts_settings', array());

  if (empty($data['#plugin']) and empty($settings['#plugin'])) {
    return '';
  }

  // Split the color palette data into inidividual values
  $color_palette = explode(',', ereg_replace('#', '', $settings['#color_palette']));

  // Check if the Chart will use the color palette for individual values
  // instead for series, like Pie Charts
  $options = array('pie2D' => TRUE, 'pie3D' => TRUE);
  if ((!empty($data['#type']) and !empty($options[$data['#type']]) ) or
      (!empty($settings['#type']) and !empty($options[$settings['#type']]) ) ) {
    $individual_color_palette = TRUE;
  }

  // Merge all series option to the main data array,
  foreach (element_children($data) as $series) {
    if (!empty($settings[$series])) {
      $data[$series] = array_merge($settings[$series], $data[$series]);
    }
    unset($settings[$series]);

    // Apply the Color Palette: normally, apply one color to each series.
    // But for some types of charts, is one color to each value into the series
    if (empty($individual_color_palette) and empty($data[$series]['#color'])) {
      $data[$series]['#color'] = $color_palette[$series];
    }
    elseif (!empty($individual_color_palette)) {
      foreach (element_children($data[$series]) as $values) {
        if (!is_array($data[$series][$values])) {
          $data[$series][$values] = array(
            '#value' => $data[$series][$values],
            '#color' => $color_palette[$values],
          );
        }
        elseif (empty($data[$series][$values]['#color'])) {
          $data[$series][$values]['#color'] = $color_palette[$values];
        }
      }
    }
  }

  // Now, merge all the rest of the options saved by default
  $data = array_merge($settings, $data);

  // Get the information about chart modules
  $chart_provider = module_invoke_all('charts_info');

  // Include the file that has the rendering function
  include_once $chart_provider[$data['#plugin']]['file'];
  $func = $chart_provider[$data['#plugin']]['render'];

  // Using the filter's rendering function, print the chart
  return $func($data);
}

/**
 * Implementation of hook_menu().
 */
function charts_menu() {
  $items['admin/settings/charts'] = array(
    'access arguments'  => array('access administration pages'),
    'description'     => 'Set the default behaviour and look of all your charts',
    'file'            => 'charts.inc',
    'page callback'   => 'drupal_get_form',
    'page arguments'  => array('_charts_settings'),
    'title'           => 'Charts'
  );
  $items['admin/settings/charts/example'] = array(
    'access arguments'  => array('access content'),
    'file'            => 'charts.inc',
    'page callback'   => '_charts_example',
    'title'           => 'Example',
    'type'            => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_requirements().
 */
function charts_requirements($phase) {
  if ($phase == 'runtime' and !$modules = module_invoke_all('charts_info', 'list')) {
    $requirements['charts']['title']        = t('Charts');
    $requirements['charts']['value']        = t('No Charts provider installed');
    $requirements['charts']['severity']     = REQUIREMENT_ERROR;
    $requirements['charts']['description']  = t('Charts core module only provides a a common set of functions. You must install a Charts provider module to create charts.');

    return $requirements;
  }
  elseif ($phase == 'runtime' and !$settings = variable_get('charts_settings', array())) {
    $requirements['charts']['title']        = t('Charts');
    $requirements['charts']['value']        = t('Charts module not yet configured');
    $requirements['charts']['severity']     = REQUIREMENT_ERROR;
    $requirements['charts']['description']  = t('Charts core module needs to get some default options in order to operate. You must go to <a href="!link">settings page</a> and configure it.', array('!link' => url('admin/settings/charts')));

    return $requirements;
  }
}

/**
 * Even if the series have values with attributes,
 * return only the numeric values of them.
 *
 * @param
 *   Array. A given data series with or without attributes.
 * @return
 *   Array. A data series, but only with the values, without
 *   the attributes.
 */
function _charts_series_values($series) {
  $data = array();

  foreach ($series as $index => $value) {
    if (!is_numeric($index)) {
      continue;
    }

    if (is_array($value)) {
      $data[] = $value['#value'];
    }
    else {
      $data[] = $value;
    }
  }

  return $data;
}

/**
 * Implementation of hook_theme().
 */
function charts_theme() {
  return array(
    '_charts_settings' => array(
      'arguments' => array('form' => NULL),
    ),
  );
}

/**
* Implementation of hook_views_api().
*/
function charts_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'charts') .'/views',
  );
}