You are here

piwik_stats.module in Piwik Statistic Integration 7.2

Same filename and directory in other branches
  1. 7 piwik_stats.module

Integrates piwik statistics as entity fields.

File

piwik_stats.module
View source
<?php

/**
 * @file
 * Integrates piwik statistics as entity fields.
 */

/**
 * Definitions of all requested statistical data.
 *
 * Note that if definitions are added or removed here,
 * they have to be added/removed properly in the schema.
 *
 * @return array
 *  Associative array, keyed by piwik API machine names.
 *  Each one holds the following information as assoc array:
 *  - title: A short title.
 *  - description: A sentence describing the value.
 *  - format: How the value is formatted.
 *    Supported formats are
 *    - 'number': Simple numbers.
 *    - 'seconds': Number of seconds.
 *    - 'percent': Percentual value.
 */
function piwik_stats_definitions() {
  return array(
    'nb_visits' => array(
      'title' => t('Visits'),
      'description' => t('Unique pageviews.'),
      'format' => 'number',
    ),
    'nb_hits' => array(
      'title' => t('Hits'),
      'description' => t('Overall pageviews.'),
      'format' => 'number',
    ),
    'entry_nb_visits' => array(
      'title' => t('Entry visits'),
      'description' => t('Number of visits that started on a node.'),
      'format' => 'number',
    ),
    'entry_nb_actions' => array(
      'title' => t('Entry hits'),
      'description' => t('Number of page views for visits that started on that node.'),
      'format' => 'number',
    ),
    'entry_sum_visit_length' => array(
      'title' => t('Visit length'),
      'description' => t('Time spent, in seconds, by visits that started on this node.'),
      'format' => 'seconds',
    ),
    'entry_bounce_count' => array(
      'title' => t('Bounce count'),
      'description' => t('Number of visits that started on this node and bounced (viewed only one page).'),
      'format' => 'number',
    ),
    'exit_nb_visits' => array(
      'title' => t('Exiting visits'),
      'description' => t('Number of visits that finished on this node.'),
      'format' => 'number',
    ),
    'sum_time_spent' => array(
      'title' => t('Time spend'),
      'description' => t('Total time spent on this node, in seconds.'),
      'format' => 'seconds',
    ),
    'bounce_rate' => array(
      'title' => t('Bounce rate'),
      'description' => t('Ratio of visitors leaving the website after landing on this node (in percent).'),
      'format' => 'percent',
    ),
    'exit_rate' => array(
      'title' => t('Exit rate'),
      'description' => t('Ratio of visitors that do not view any other page after this node (in percent).'),
      'format' => 'percent',
    ),
  );
}

/**
 * Implements hook_menu().
 */
function piwik_stats_menu() {
  $items = array();

  // Provide a piwik statistics tab for some entities.
  // @TODO determine all possible entities automatically.
  $entities = array(
    // path => entity_type.
    'node' => 'node',
    'user' => 'user',
  );
  foreach ($entities as $uri => $entity) {
    $items[$uri . '/%' . $entity . '/piwik'] = array(
      'title' => 'Piwik statistics',
      'page callback' => 'piwik_stats_tab_page',
      'page arguments' => array(
        $entity,
        1,
      ),
      'access callback' => 'piwik_stats_tab_page_access',
      'access arguments' => array(
        $entity,
        1,
      ),
      'type' => MENU_LOCAL_TASK,
      'file' => 'piwik_stats.pages.inc',
      'weight' => 10,
    );
  }
  return $items;
}

/**
 * Statistics tab page access callback.
 */
function piwik_stats_tab_page_access($entity_type, $entity) {

  // Check whether the user is allowed to view the statistics page.
  if (!user_access('access piwik information')) {
    return FALSE;
  }

  // Extract entity bundle (type).
  $ids = entity_extract_ids($entity_type, $entity);

  // Get fields of this bundle.
  $fields = field_info_instances($entity_type, $ids[2]);

  // Count how many piwik fields exist and are visible for this bundle.
  $visible_fields = 0;
  foreach (array_keys($fields) as $field_name) {

    // Get field information.
    $field = field_info_field($field_name);

    // A piwik field?
    if ($field['type'] == 'piwik_stats') {

      // If the "show in statistics page" setting is available,
      // check its value. Otherwise the default is visible.
      if ($field['settings']['show_in_statistics_page']) {
        $visible_fields++;
      }
    }
  }
  return $visible_fields > 0;
}

/**
 * Helper function for formatting an statistical value according to its type.
 *
 * @param string $value
 *  The value to format properly.
 * @param string $format
 *  How the value should be formatted.
 *   - 'number': Simple numbers.
 *   - 'seconds': Number of seconds.
 *   - 'percent': Percentual value.
 */
function piwik_stats_format_value($value, $format) {
  switch ($format) {
    case 'number':
      return $value;
    case 'percent':
      return $value . '%';
    case 'seconds':
      return format_interval($value);
  }
}

/**
 * Implements hook_permission().
 */
function piwik_stats_permission() {
  return array(
    // Permission for accessing the statistics tab on nodes, users etc.
    'access piwik information' => array(
      'description' => t('View piwik statistics tab on nodes, users etc.'),
      'title' => t('Access piwik information'),
    ),
  );
}

/**
 * Implements hook_field_info().
 *
 * Provides the description of the field.
 */
function piwik_stats_field_info() {
  return array(
    'piwik_stats' => array(
      'label' => t('Piwik Statistical Field'),
      'description' => t('Holds piwiks statistical information of a node.'),
      'default_widget' => 'piwik_stats_hidden',
      'default_formatter' => 'piwik_stats_list',
      'settings' => array(
        'period' => 'day',
        'show_in_statistics_page' => TRUE,
      ),
    ),
  );
}

/**
 * Implements hook_field_settings_form().
 */
function piwik_stats_field_settings_form($field, $instance, $has_data) {
  $settings = $field['settings'];

  // Add field settings for statistic period.
  $form['period'] = array(
    '#type' => 'select',
    '#title' => t('Period'),
    '#default_value' => $settings['period'],
    '#options' => array(
      'day' => t('Day'),
      'week' => t('Week'),
      'month' => t('Month'),
      'year' => t('Year'),
    ),
    '#required' => TRUE,
    '#description' => t('The period of the requested statistics.'),
  );
  $form['show_in_statistics_page'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show on "Piwik statistics page"'),
    '#default_value' => $settings['show_in_statistics_page'],
    '#description' => t('Show this fields statistics on the "Piwik statistics" page. If no fields are enabled to be shown on the statistics page the page itself will be hidden.'),
  );
  return $form;
}

/**
 * Implements hook_field_formatter_info().
 */
function piwik_stats_field_formatter_info() {
  return array(
    // The default piwik stats formatter lists statistics as configured.
    'piwik_stats_list' => array(
      'label' => t('Statistics list'),
      'field types' => array(
        'piwik_stats',
      ),
      'settings' => array(
        // Default visibility setting for each stat (all of them TRUE).
        'visibility' => array_map('is_array', piwik_stats_definitions()),
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function piwik_stats_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = '';

  // Generate a summary string for list formatter display settings.
  if ($display['type'] === 'piwik_stats_list') {
    $summary_elements = array();

    // Get key -> description listing of piwik.
    $definitions = piwik_stats_definitions();

    // Iterate through all keys and add them as summary element if set.
    foreach ($definitions as $key => $definition) {
      if ($settings['visibility'][$key]) {
        $summary_elements[] = $definition['title'];
      }
    }

    // Build the summary string.
    if (!empty($summary_elements)) {
      $summary = implode(', ', $summary_elements);
    }
    else {
      $summary = t('None');
    }
  }
  return $summary;
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function piwik_stats_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $element = array();
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  // Field display settings for the list formatter.
  if ($display['type'] === 'piwik_stats_list') {

    // Get key -> description listing of piwik.
    $definitions = piwik_stats_definitions();

    // Iterate through all keys and add them as checkbox.
    foreach ($definitions as $key => $definition) {
      $element['visibility'][$key] = array(
        '#type' => 'checkbox',
        '#title' => $definition['title'],
        '#default_value' => $settings['visibility'][$key],
      );
    }
  }
  return $element;
}

/**
 * Implements hook_field_formatter_view().
 */
function piwik_stats_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];
  if ($display['type'] === 'piwik_stats_list') {
    foreach ($items as $delta => $item) {

      // Print the values in a html list as configured by field settings.
      $list_elements = array();

      // Get descriptions for piwik value keys.
      $definitions = piwik_stats_definitions();

      // Iterate trough all describing keys.
      foreach ($definitions as $key => $definition) {
        if ($settings['visibility'][$key]) {

          // Set the statistical value depending on its type.
          $list_elements[] = $definition['title'] . ': ' . piwik_stats_format_value($item[$key], $definition['format']);
        }
      }
      $element[$delta] = array(
        '#theme' => 'item_list',
        '#items' => $list_elements,
      );
    }
  }
  return $element;
}

/**
 * Implements hook_field_is_empty().
 */
function piwik_stats_field_is_empty($item, $field) {
  return empty($item);
}

/**
 * Implements hook_field_widget_info().
 *
 * Defining a hidden pseudo widget.
 */
function piwik_stats_field_widget_info() {
  return array(
    'piwik_stats_hidden' => array(
      'label' => t('None'),
      'field types' => array(
        'piwik_stats',
      ),
    ),
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Form ID: field_ui_field_edit_form (Edit page of a field instance).
 *
 * Remove some unneeded stuff from the field config.
 */
function piwik_stats_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#field']['type'] === 'piwik_stats') {
    hide($form['field']['cardinality']);
    hide($form['instance']['required']);
    hide($form['instance']['description']);
    hide($form['instance']['default_value_widget']);
  }
}

/**
 * Implements hook_flush_caches().
 */
function piwik_stats_flush_caches() {
  return array(
    'cache_piwik_stats',
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Form ID: piwik_admin_settings (Settings page of piwik module).
 *
 * Adds piwik stats settings to piwik configuration.
 */
function piwik_stats_form_piwik_admin_settings_form_alter(&$form, &$form_state, $form_id) {
  $form['account']['piwik_stats_token_auth'] = array(
    '#type' => 'textfield',
    '#title' => t('Piwik authentication token'),
    '#default_value' => variable_get('piwik_stats_token_auth', ''),
    '#size' => 80,
    '#maxlength' => 34,
    '#required' => TRUE,
    '#description' => t('This is needed by Piwik Statistical Field to request statistic data.'),
  );

  // Add cron run settings.
  $form['advanced']['piwik_stats_cron_fill'] = array(
    '#type' => 'checkbox',
    '#title' => t('Fill Piwik fields on cron run'),
    '#default_value' => variable_get('piwik_stats_cron_fill', TRUE),
    '#description' => t('If enabled, Piwik Statistical fields will be filled on cron run.'),
  );
  $form['advanced']['piwik_stats_cron_fill_time'] = array(
    '#type' => 'select',
    '#title' => t('Time to spend filling fields'),
    '#default_value' => variable_get('piwik_stats_cron_fill_time', 30),
    '#options' => array(
      15 => '15 ' . t('seconds'),
      30 => '30  ' . t('seconds'),
      60 => '1 ' . t('minute'),
      120 => '2 ' . t('minutes'),
      300 => '5 ' . t('minutes'),
    ),
    '#description' => t('Maximum of time to spend with filling fields per cron-run.'),
  );
  $form['advanced']['piwik_stats_request_timeout'] = array(
    '#type' => 'select',
    '#title' => t('Piwik API request timeout'),
    '#default_value' => variable_get('piwik_stats_request_timeout', 30),
    '#options' => array(
      15 => '15 ' . t('seconds'),
      30 => '30  ' . t('seconds'),
      60 => '1 ' . t('minute'),
      120 => '2 ' . t('minutes'),
      300 => '5 ' . t('minutes'),
    ),
    '#description' => t('Maximum of time a piwik API request can take.'),
  );

  // Add submit callback to save input.
  $form['#submit'][] = 'piwik_stats_piwik_admin_settings_form_submit';

  // Submit button for refreshing piwik_stats table.
  $form['actions']['fill_piwik_stats'] = array(
    '#type' => 'submit',
    '#submit' => array(
      'piwik_stats_piwik_admin_settings_batch_submit',
    ),
    '#value' => t('Fill statistical Piwik fields'),
  );
}

/**
 * Submit callback for piwik configuration form.
 */
function piwik_stats_piwik_admin_settings_form_submit($form, &$form_state) {

  // Trim and save authentication token.
  variable_set('piwik_stats_token_auth', trim($form_state['input']['piwik_stats_token_auth']));
}

/**
 * Submit callback for filling piwik_stats fields manually by batch.
 */
function piwik_stats_piwik_admin_settings_batch_submit($form, &$form_state) {

  // We want some fresh data here, remove cached data.
  cache_clear_all('piwik_stats:xml:', 'cache_piwik_stats', TRUE);

  // Get the queue of fields to fill.
  $queue = piwik_stats_get_queue_items();
  if ($queue === FALSE) {
    drupal_set_message(t('There was an error during the requests. Further information can be found in the logs.'), 'error');
  }
  elseif (empty($queue)) {
    drupal_set_message(t('There are no fields to process.'));
  }
  else {
    $operations = array();
    foreach ($queue as $item) {
      $operations[] = array(
        'piwik_stats_process_queue_item',
        array(
          $item,
        ),
      );
    }
    batch_set(array(
      'operations' => $operations,
      'title' => t('Processing all piwik field instances..'),
    ));
  }
}

/**
 * Implements hook_cron().
 *
 * Add items to process to cron queue.
 */
function piwik_stats_cron() {
  if (variable_get('piwik_stats_cron_fill', TRUE)) {

    // If the queue is empty and we should process them on cron run
    // let's add them to our cron queue.
    $queue = DrupalQueue::get("piwik_stats_fields_to_fill");
    if ($queue
      ->numberOfItems() == 0) {
      $items = piwik_stats_get_queue_items();
      foreach ($items as $item) {
        $queue
          ->createItem($item);
      }

      // We want some fresh statistics, remove cached data.
      cache_clear_all('piwik_stats:xml:', 'cache_piwik_stats', TRUE);
    }
  }
  else {

    // We should not process any items on cron run, delete the queue.
    $queue = DrupalQueue::get("piwik_stats_fields_to_fill");
    $queue
      ->deleteQueue();
  }
}

/**
 * Implements hook_cron_queue_info().
 *
 * Process queued items on cron run.
 */
function piwik_stats_cron_queue_info() {
  $queues = array();
  if (variable_get('piwik_stats_cron_fill', TRUE)) {
    $queues['piwik_stats_fields_to_fill'] = array(
      'worker callback' => 'piwik_stats_process_queue_item',
      'time' => variable_get('piwik_stats_cron_fill_time', 30),
    );
  }
  return $queues;
}

/**
 * Returns a dataset of fields to fill.
 *
 * @return array
 *  An associative dataset array on success, empty array
 *  when failsave, FALSE otherwise.
 */
function piwik_stats_get_queue_items() {
  $queue = array();

  // Get all fields of type piwik_stats.
  $piwik_fields = field_read_fields(array(
    'type' => 'piwik_stats',
  ));

  // Iterate through all piwik fields.
  foreach ($piwik_fields as $field_name => $field) {

    // Get all instances of a piwik_stats field.
    $field_instances = field_read_instances(array(
      'field_id' => $field['id'],
    ));

    // Iterate through all instances of a piwik field.
    foreach ($field_instances as $field_instance) {

      // Get a list of all entity objects holding the needed id's.
      $entities = _piwik_stats_get_entities($field_instance['entity_type'], $field_instance['bundle']);

      // Iterate through entities and add all items to queue.
      foreach ($entities as $entity) {
        $queue[] = array(
          'entity' => $entity,
          'entity_type' => $field_instance['entity_type'],
          'field' => $field,
        );
      }
    }
  }
  return $queue;
}

/**
 * Processes a dataset for filling a field.
 *
 * @param array $item
 *  An associative array containing:
 *  - 'entity': The entity having a piwik field to update.
 *  - 'entity_type': Machine readable type of the entity.
 *  - 'field': Array of the field config.
 */
function piwik_stats_process_queue_item($item) {

  // Request the statistical data (API request / cache).
  $xml = piwik_stats_get_xml_data($item['field']);
  if (!empty($xml)) {

    // Get the default URI of the current entity.
    $entity_uri = entity_uri($item['entity_type'], $item['entity']);

    // Get all URL aliases linked to the entity URI.
    $urls = _piwik_stats_get_aliases($entity_uri['path']);

    // Sum up all statistical data of each URL to a piwik field.
    $piwik_stats_field = _piwik_stats_summarize_field($urls, $xml);

    // Add the filled piwik stats field to the entity.
    $item['entity']->{$item['field']['field_name']} = $piwik_stats_field;

    // Save the updated piwik field (without touching the node or any other fields).
    _piwik_stats_field_update($item['entity_type'], $item['entity'], $item['field']);
  }
}

/**
 * Saves a piwik field without touching any other fields.
 */
function _piwik_stats_field_update($entity_type, $entity, $field) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

  // Get the storage backend used by the field.
  $storage_info = field_info_storage_types($field['storage']['type']);

  // Invoke the proper storage backend.
  module_invoke($storage_info['module'], 'field_storage_write', $entity_type, $entity, FIELD_STORAGE_UPDATE, array(
    $field['id'] => $field['id'],
  ));
  $entity_info = entity_get_info($entity_type);
  if ($entity_info['field cache']) {
    cache_clear_all("field:{$entity_type}:{$id}", 'cache_field');
  }
}

/**
 * Get statistical XML data (either by fresh request or cached).
 *
 * @param array $field
 *  Array of the field config.
 *
 * @return object
 *  A SimpleXMLElement on success, FALSE otherwise.
 */
function piwik_stats_get_xml_data($field) {

  // Static caching for SimpleXMLElement data.
  // We cache by period as it is currently the only thing that
  // differs between each field configuration. If this gets more
  // complex later we should use the field name as cache key.
  static $xml;
  if (empty($xml)) {
    $xml = array();
  }

  // Check whether we already got this XML object in cache.
  if (!isset($xml[$field['settings']['period']])) {

    // Check for cached request result data (SimpleXMLElement cannot be cached).
    $cache = cache_get('piwik_stats:xml:' . $field['settings']['period'], 'cache_piwik_stats');
    if (!empty($cache) && $cache->created > REQUEST_TIME - 24 * 60 * 60) {
      $result = $cache;
    }
    else {
      $url = variable_get('piwik_url_http');
      $token = variable_get('piwik_stats_token_auth');
      $site_id = variable_get('piwik_site_id');

      // Check if connection credentials are provided.
      if (!isset($url, $token, $site_id)) {
        return FALSE;
      }

      // Request piwik XML data.
      $result = piwik_stats_api_request($url, $token, 'Actions.getPageUrls', $site_id, $field['settings']['period']);

      // Check HTTP status code of response.
      if ($result->code != 200) {
        $error = isset($result->error) ? "{$result->code}: {$result->error}" : $result->code;
        watchdog('piwik_stats', 'Requesting Piwik Statistics failed: HTTP returned: @error.', array(
          '@error' => $error,
        ), WATCHDOG_ERROR);
        return FALSE;
      }
      if ($result->headers['content-type'] != 'text/xml; charset=utf-8') {
        watchdog('piwik_stats', 'Requesting Piwik Statistics does not return expected data format.', array(), WATCHDOG_ERROR);
        return FALSE;
      }
      cache_set('piwik_stats:xml:' . $field['settings']['period'], $result->data, 'cache_piwik_stats');
    }

    // Parse XML data.
    $xml[$field['settings']['period']] = new SimpleXMLElement($result->data);

    // Be shure that there is really some data to work with.
    if (isset($xml[$field['settings']['period']]->error)) {
      watchdog('piwik_stats', 'Requesting Piwik Statistics failed: Could not parse XML.', array(), WATCHDOG_ERROR);
      return FAlSE;
    }
  }
  return $xml[$field['settings']['period']];
}

/**
 * Sends a Piwik API request.
 *
 * @param string $piwik_url
 *  URL to piwik.
 * @param string $token_auth
 *  Authentication token needed to authenticate with piwik.
 * @param string $method
 *  Piwik API request method.
 * @param int $site_id
 *  Unique site ID of piwik.
 * @param string $period
 *  Statistical period.
 *  Default is 'year' but also 'day', 'week' or 'month' is possible.
 * @param int $date
 *  Statistic base date.
 * @param string $format
 *  API return format. Default is XML but also CSV, TSV and JSON is possible.
 *
 * @return object
 *  The returned object of drupal_http_request().
 */
function piwik_stats_api_request($piwik_url, $token_auth, $method, $site_id, $period = 'year', $date = 'now', $format = 'xml') {

  // Send off the API request.
  return drupal_http_request(url($piwik_url, array(
    'query' => array(
      'module' => 'API',
      'method' => $method,
      'idSite' => $site_id,
      'period' => $period,
      'date' => $date,
      'format' => $format,
      'token_auth' => $token_auth,
      'expanded' => TRUE,
      'filter_limit' => -1,
    ),
  )), array(
    'timeout' => variable_get('piwik_stats_request_timeout', 30),
  ));
}

/**
 * Returns a list of entity objects only holding entity id's.
 *
 * @param string $type
 *  The entity type.
 * @param string $bundle
 *  The entity bundle.
 *
 * @return array
 *  An array of lightweight entity objects as returned from database.
 */
function _piwik_stats_get_entities($type, $bundle) {

  // Get information about entity type.
  $entity_info = entity_get_info($type);

  // Get all entity id's of a specific type and bundle.
  $select = db_select($entity_info['base table'], 'b');
  $select
    ->addField('b', $entity_info['entity keys']['id']);

  // Some entity tables neither have revisisons nor bundles.
  if (!empty($entity_info['entity keys']['revision'])) {
    $select
      ->addField('b', $entity_info['entity keys']['revision']);
  }
  if (!empty($entity_info['entity keys']['bundle'])) {
    $select
      ->addField('b', $entity_info['entity keys']['bundle']);
    $select
      ->condition('b.type', $bundle);
  }
  $entities = $select
    ->execute()
    ->fetchAll();
  return $entities;
}

/**
 * Returns a list of url aliases of a system path.
 *
 * @param string $uri
 *  A system path, eg. an entity URI.
 *
 * @return array
 *  An array of url aliases.
 */
function _piwik_stats_get_aliases($uri) {
  $urls = array();
  $languages = language_list('enabled');
  foreach ($languages[1] as $language) {

    // The URLs we get from piwik are absolute, so we transform them as needed.
    $urls[] = url($uri, array(
      'https' => FALSE,
      'language' => $language,
      'absolute' => TRUE,
      'alias' => TRUE,
    ));
    if (variable_get('https', FALSE)) {
      $urls[] = url($uri, array(
        'https' => TRUE,
        'language' => $language,
        'absolute' => TRUE,
        'alias' => TRUE,
      ));
    }

    // Grab all URL aliases of the system URI.
    $select = db_select('url_alias', 'u');
    $select
      ->addField('u', 'alias');
    $select
      ->condition('u.source', $uri);
    $select
      ->condition('u.language', array(
      LANGUAGE_NONE,
      $language->language,
    ));
    $aliases = $select
      ->execute()
      ->fetchAll();
    foreach ($aliases as $alias) {
      $urls[] = url($alias->alias, array(
        'https' => FALSE,
        'language' => $language,
        'absolute' => TRUE,
        'alias' => TRUE,
      ));
      if (variable_get('https', FALSE)) {
        $urls[] = url($alias->alias, array(
          'https' => TRUE,
          'language' => $language,
          'absolute' => TRUE,
          'alias' => TRUE,
        ));
      }
    }
  }
  return $urls;
}

/**
 * Summarizes all statistical data from XML with matching URLs.
 *
 * @param array $urls
 *  An array of url aliases.
 * @param object $xml
 *  A XML object containing piwik URL statistics.
 *
 * @return array
 *  An array representing the filled piwik_stats field.
 */
function _piwik_stats_summarize_field($urls, $xml) {

  // Initialize field values as needed.
  $definitions = piwik_stats_definitions();
  $stats = array();
  foreach ($definitions as $stat_key => $definition) {
    $stats[$stat_key] = 0;
  }

  // Iterate thorugh all url aliases and sum up statistics.
  foreach ($urls as $url) {

    // Grab statistical data from XML per URL.
    $url_stats = $xml
      ->xpath('//url[text()="' . $url . '"]/..');
    if (!empty($url_stats)) {

      // Sum up each statistical value.
      foreach ($definitions as $stat_key => $definition) {
        if (isset($url_stats[0]->{$stat_key})) {

          // These two are percent values (##% formatted).
          // We need to transform them to integers before we can sum them.
          if ($definition['format'] == 'percent') {
            $stats[$stat_key] += (int) drupal_substr($url_stats[0]->{$stat_key}, 0, -1);
          }
          else {
            $stats[$stat_key] += $url_stats[0]->{$stat_key};
          }
        }
      }
    }
  }
  return array(
    LANGUAGE_NONE => array(
      $stats,
    ),
  );
}

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

Functions

Namesort descending Description
piwik_stats_api_request Sends a Piwik API request.
piwik_stats_cron Implements hook_cron().
piwik_stats_cron_queue_info Implements hook_cron_queue_info().
piwik_stats_definitions Definitions of all requested statistical data.
piwik_stats_field_formatter_info Implements hook_field_formatter_info().
piwik_stats_field_formatter_settings_form Implements hook_field_formatter_settings_form().
piwik_stats_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
piwik_stats_field_formatter_view Implements hook_field_formatter_view().
piwik_stats_field_info Implements hook_field_info().
piwik_stats_field_is_empty Implements hook_field_is_empty().
piwik_stats_field_settings_form Implements hook_field_settings_form().
piwik_stats_field_widget_info Implements hook_field_widget_info().
piwik_stats_flush_caches Implements hook_flush_caches().
piwik_stats_format_value Helper function for formatting an statistical value according to its type.
piwik_stats_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
piwik_stats_form_piwik_admin_settings_form_alter Implements hook_form_FORM_ID_alter().
piwik_stats_get_queue_items Returns a dataset of fields to fill.
piwik_stats_get_xml_data Get statistical XML data (either by fresh request or cached).
piwik_stats_menu Implements hook_menu().
piwik_stats_permission Implements hook_permission().
piwik_stats_piwik_admin_settings_batch_submit Submit callback for filling piwik_stats fields manually by batch.
piwik_stats_piwik_admin_settings_form_submit Submit callback for piwik configuration form.
piwik_stats_process_queue_item Processes a dataset for filling a field.
piwik_stats_tab_page_access Statistics tab page access callback.
piwik_stats_views_api Implements hook_views_api().
_piwik_stats_field_update Saves a piwik field without touching any other fields.
_piwik_stats_get_aliases Returns a list of url aliases of a system path.
_piwik_stats_get_entities Returns a list of entity objects only holding entity id's.
_piwik_stats_summarize_field Summarizes all statistical data from XML with matching URLs.