<?php
/**
 * @file
 * Installation file for the Tether Stats module.
 */

/**
 * Implements hook_requirements().
 *
 * The active database where tether_stats will look for its stats related tables
 * may be set to something other then 'default'. As such, they are tested for
 * existence here and added as a requirement.
 */
function tether_stats_requirements($phase) {

  $requirements = array();
  // Ensure translations don't break during installation.
  $t = get_t();

  if ($phase == 'runtime') {

    $schema = tether_stats_schema();
    $tables_exist = TRUE;

    $old_db = db_set_active(variable_get('tether_stats_db', ''));
    foreach ($schema as $name => $table) {
      if (!db_table_exists($name)) {
        $tables_exist = FALSE;
        break;
      }
    }
    db_set_active($old_db);

    $requirements['tether_stats'] = array(
      'title' => $t('Tether Stats requirements'),
      'value' => l($t('Statistics settings'), 'admin/config/system/tether_stats/settings'),
    );

    if ($tables_exist) {

      if (variable_get('tether_stats_active', FALSE)) {
        $requirements['tether_stats'] += array(
          'description' => $t('Stats collection is currently active.'),
          'severity' => REQUIREMENT_OK,
        );
      }
      else {
        $requirements['tether_stats'] += array(
          'description' => $t('Stats collection is not turned on. You may activate it on the settings page.'),
          'severity' => REQUIREMENT_WARNING,
        );
      }
    }
    else {
      $requirements['tether_stats'] += array(
        'description' => $t('Your stat tables need to be generated manually before any data can be recorded.'),
        'severity' => REQUIREMENT_ERROR,
      );
    }
  }

  return $requirements;
}

/**
 * Implements hook_uninstall().
 *
 * Removes all associated variables.
 */
function tether_stats_uninstall() {

  variable_del('tether_stats_db');
  variable_del('tether_stats_active');
  variable_del('tether_stats_exclusion_mode');
  variable_del('tether_stats_element_ttl');
  variable_del('tether_stats_earliest_activation_time');
  variable_del('tether_stats_allow_query_string_to_define_new_elements');
}

/**
 * Defines the schema for our various stat tables.
 */
function tether_stats_schema() {

  $schema = array();

  $schema['tether_stats_derivative'] = array(
    'description' => 'A list of unique string ids that extends a standard entity item identifying set to derive a new element type. That is, the set {entity_id, entity_type} will uniquely define the default element for an entity object but the set {entity_id, entity_type, derivative} will define an additional unique element also bound to that entity object.',
    'fields' => array(
      'id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'entity_type' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
      ),
      'entity_bundle' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
      ),
      'name' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
      ),
      'description' => array(
        'type' => 'text',
        'size' => 'normal',
        'not null' => FALSE,
      ),
      'disabled' => array(
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ),
      'weight' => array(
        'type' => 'int',
        'size' => 'small',
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'unique keys' => array(
      'name' => array('name'),
    ),
    'primary key' => array('id'),
  );

  $schema['tether_stats_element'] = array(
    'description' => 'The base element or entity table. Each entry corresponds to one particular entity or thing such as a node, user, or field of a particular node.',
    'fields' => array(
      'elid' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'entity_id' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
      ),
      'entity_type' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
      ),
      'name' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'url' => array(
        'type' => 'varchar',
        'length' => 1024,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'query' => array(
        'type' => 'varchar',
        'length' => 1024,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'derivative_id' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'count' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'changed' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'last_activity' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
    ),
    'indexes' => array(
      'entity' => array(array('entity_type', 10), 'entity_id'),
      'name' => array('name'),
      'url' => array(array('url', 32)),
      'last_activity' => array('last_activity'),
    ),
    'foreign keys' => array(
      'derivative' => array(
        'table' => 'tether_stats_derivative',
        'columns' => array('derivative_id' => 'id'),
        'actions' => array('update' => 'restrict', 'delete' => 'restrict'),
      ),
    ),
    'primary key' => array('elid'),
  );

  $schema['tether_stats_activity_log'] = array(
    'description' => 'The activity log table to record each event.',
    'fields' => array(
      'alid' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'elid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'uid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'referrer' => array(
        'type' => 'varchar',
        'length' => 1024,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'ip_address' => array(
        'type' => 'varchar',
        'length' => 40,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'sid' => array(
        'type' => 'varchar',
        'length' => 128,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'browser' => array(
        'type' => 'varchar',
        'length' => 512,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'data' => array(
        'type' => 'varchar',
        'length' => 512,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'hour' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'day' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'month' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'year' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'created' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
    ),
    'indexes' => array(
      'elid' => array('elid', 'type'),
      'created' => array('created'),
      'type' => array('type'),
      'hour' => array('hour'),
      'day' => array('day'),
      'month' => array('month'),
      'year' => array('year'),
      'sid'  => array('sid'),
    ),
    'foreign keys' => array(
      'elid' => array(
        'table' => 'tether_stats_element',
        'columns' => array('elid' => 'elid'),
        'actions' => array('update' => 'restrict', 'delete' => 'restrict'),
      ),
    ),
    'primary key' => array('alid'),
  );

  $schema['tether_stats_hour_count'] = array(
    'description' => 'This table will store the counts of events on elements on a daily basis. Used for faster data mining in some situations.',
    'fields' => array(
      'hcid' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'elid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => FALSE,
        'default' => NULL,
      ),
      'count' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'hour' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'day' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'month' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'year' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'timestamp' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
    ),
    'indexes' => array(
      'elid' => array('elid', 'type'),
      'type' => array('type'),
      'hour' => array('hour'),
      'day' => array('day'),
      'month' => array('month'),
      'year' => array('year'),
    ),
    'unique keys' => array(
      'day_entry' => array('elid', 'type', 'hour'),
    ),
    'foreign keys' => array(
      'elid' => array(
        'table' => 'tether_stats_element',
        'columns' => array('elid' => 'elid'),
        'actions' => array('update' => 'restrict', 'delete' => 'restrict'),
      ),
    ),
    'primary key' => array('hcid'),
  );

  $schema['tether_stats_impression_log'] = array(
    'description' => 'Logs all of the elements that were impressed on a given event.',
    'fields' => array(
      'ilid' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'alid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'elid' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
    ),
    'indexes' => array(
      'elid' => array('elid'),
      'alid' => array('alid'),
    ),
    'foreign keys' => array(
      'alid' => array(
        'table' => 'tether_stats_activity_log',
        'columns' => array('alid' => 'alid'),
        'actions' => array('update' => 'restrict', 'delete' => 'restrict'),
      ),
      'elid' => array(
        'table' => 'tether_stats_element',
        'columns' => array('elid' => 'elid'),
        'actions' => array('update' => 'restrict', 'delete' => 'restrict'),
      ),
    ),
    'primary key' => array('ilid'),
  );

  return $schema;
}

/**
 * Populate stats tables with test activity data.
 *
 * This is a stand alone method that generates simple random activity
 * data for testing purposes. None of the granular activity information
 * such as the browser, ip_address, or sid fields are randomly generated.
 * This method only populates hit activity which can be used to generate
 * charts.
 *
 * Do not use this method in production as it will pollute your stats
 * data.
 *
 * @param array $elids
 *   An array of element elids from which to create hit activity on.
 *   Activity will be generated randomly amongst these elements.
 * @param int $start_time
 *   The start of the domain interval to populate.
 * @param int $finish_time
 *   The end of the domain interval to populate.
 */
function _tether_stats_generate_random_hit_data(array $elids, $start_time, $finish_time) {

  for ($current_time = $start_time; $current_time <= $finish_time; $current_time += rand(10, 600)) {

    $params = array(
      'type' => 'hit',
      'elid' => $elids[rand(0, count($elids) - 1)],
    );

    _tether_stats_track_element($params, $current_time);
  }
}

/**
 * Increase the field length of the ip_address field to support IPv6 addresses.
 */
function tether_stats_update_1() {

  $spec = array(
    'type' => 'varchar',
    'length' => 40,
    'not null' => FALSE,
    'default' => NULL,
  );

  $old_db = db_set_active(variable_get('tether_stats_db', ''));
  db_change_field('tether_stats_activity_log', 'ip_address', 'ip_address', $spec);
  db_set_active($old_db);
}
