<?php
// $Id: stats.inc,v 1.1.2.7 2010/09/26 00:36:49 tomdude48 Exp $

/**
 * @file 
 * Functions for generating data for keyword stats reports. 
 * Implements a kwresearch_sources API.
 */

/**
 * Generates analysis data for keyword stats report. Data is generated by
 * 
 * @param string|array $keywords - list of keywords for which to generate data
 * @param array $msgs - used to return error messages
 * @param array $params - extra parmaters
 */
function kwresearch_get_keyword_stats_data($keywords, &$msgs, $params = array()) {
  
  // make api calls
  $sources = module_invoke_all('kwresearch_sources');
  foreach ($sources AS $aid => $source) {
    $data[$aid] = call_user_func($source['stats_callback'], $keywords, $msgs, $params[$aid]);  
  }
  $ret = array();
  if (!empty($data) && is_array($data)) {
    foreach ($data AS $aid => $d) {
      if (!empty($d) && is_array($d)) {
        foreach ($d AS $kw => $d2) {
          if (!empty($d2) && is_array($d2)) {
            foreach ($d2 AS $stat => $v) {
              if (!$ret[$kw]) {
                $ret[$kw] = array(
                  'term' => $kw,
                  $aid . '_' . $stat => $v,
                );
              }
              else {
                $ret[$kw][$aid . '_' . $stat] = $v;
              }
            }
          }
        }
      }
    }
    // calculate total count
    $source_count = count($sources);
    $srch_max = 0;
    $comptn_max = 0;
    $bd_max = 0;
    foreach ($ret AS $kw => $v) {
      $srch = 0;
      $cmptn = 0;
      $bd = 0;
      $source_cmptn_entries = 0;
      $source_bd_entries = 0;
      foreach ($sources AS $aid => $s) {
        $srch += $s['searches_ratio'] * $v[$aid . '_searches'];
        if (!is_null($v[$aid . '_competition'])) {
          $source_cmptn_entries++;
          if ($v[$aid . '_competition'] < 0) {
            $cmptn += 0;
          }
          elseif ($v[$aid . '_competition'] > 100) {
            $cmptn += 100;
          }
          else {
            $cmptn += $v[$aid . '_competition'];
          }          
        }
        if (!is_null($v[$aid . '_bid'])) {
          $source_bd_entries++;
          if ($v[$aid . '_bid'] < 0) {
            $bd += 0;
          }
          elseif ($v[$aid . '_bid'] > 100) {
            $bd += 100;
          }
          else {
            $bd += $v[$aid . '_bid'];
          }
        }
      }
      $ret[$kw]['_searches'] = $srch / $source_count;
      if ($source_cmptn_entries > 0) {
        $ret[$kw]['_competition'] = $cmptn / $source_cmptn_entries;
      }
      if ($source_bd_entries > 0) {
        $ret[$kw]['_bid'] = $bd / $source_bd_entries;
      }
      if ($ret[$kw]['_searches'] > $srch_max) {
        $srch_max = $ret[$kw]['_searches'];
      }
      if ($ret[$kw]['_competition'] > $cmptn_max) {
        $cmptn_max = $ret[$kw]['_competition'];
      }
      if ($ret[$kw]['_bid'] > $bd_max) {
        $bd_max = $ret[$kw]['_bid'];
      }
    }
    uasort($ret, 'kwresearch_count_sort');

  }
  
  $ret = array_slice($ret, 0, 50);

  $ret = kwresearch_save_keyword_record_stats($ret, $params);
  
  $ret['_meta'] = array(
    'searches_max' => $srch_max,
    'competition_max' => $cmptn_max,
    'bid_max' => $bd_max,
  );
  return $ret;
}

/**
 * Saves keyword stats data to site keywords table
 * @param $keywords_data
 * @param $params
 */
function kwresearch_save_keyword_record_stats($keywords_data, $params) {
  if (is_array($keywords_data)) {
    foreach ($keywords_data AS $k => $data) { 
      if (substr($k, 0, 1) == '_') {
        continue;
      }
      $kw_obj = kwresearch_load_site_keyword($data['term']);
      if (!$kw_obj) {
        $kid = kwresearch_save_site_keyword($data['term']); 
        $kw_obj = kwresearch_load_site_keyword($kid);
      } 
      else {
        $kid = $kw_obj->kid;
      } 
      $keywords_data[$k]['kid'] = (int)$kw_obj->kid;
      $keywords_data[$k]['priority'] = (int)$kw_obj->priority;
      $keywords_data[$k]['value'] = (float)$kw_obj->value;
      $keywords_data[$k]['page_count'] = (int)$kw_obj->page_count;

      $sql = '
        UPDATE {kwresearch_keyword}
        SET 
          stats_update = %d,
          daily_volume = %d,
          competition = %d,
          bid = %f          
        WHERE kid = "%d"
      ';
      db_query($sql, time(), $data['_searches'], $data['_competition'], $data['_bid'], $kid);
    }
  }
  return $keywords_data;
}

/**
 * Generates keyword search volume data from Wordtracker
 * 
 * @param $keywords
 * @param $msgs
 * @param $params
 */
function kwresearch_wordtracker_get_words_popularity($keywords, &$msgs, $params) {

  $connection = ($params['connection'])?$params['connection']:NULL;
  $type = ($params['type'])?$params['type']:NULL;
  $include_misspellings = ($params['include_misspellings'])?$params['include_misspellings']:NULL;
  $include_plurals = ($params['include_plurals'])?$params['include_plurals']:NULL;
  $adult_filter = ($params['adult_filter'])?$params['adult_filter']:NULL;
  $limit = ($params['limit'])?$params['limit']:NULL;

  if (is_null($include_misspellings)) {
    $include_misspellings = variable_get('kwresearch_include_misspellings', FALSE);
  }
  if (is_null($include_plurals)) {
    $include_plurals = variable_get('kwresearch_include_plurals', TRUE);
  }
  if (is_null($adult_filter)) {
    $adult_filter = variable_get('kwresearch_adult_filter', 'remove_dubious');
  }
//print "include_plurals=$include_plurals, adult_filter=$adult_filter";
  if (!$type) {
    $type = 'all';
  }
  if (strpos($type, '_words_popularity')) { // type is full callabv
    $call = 'get_' . $type;
    $callabv = $type;  
  }
  elseif ($type) {
    $call = 'get_' . $type . '_words_popularity';
    $callabv = $type . '_words_popularity';
  }
  
  if (!is_array($keywords)) {    
    $keywords_arr = explode(',', $keywords);
    foreach ($keywords_arr AS $i => $kw) {
      $keywords_arr[$i] = trim($kw);
    }
  }
  else {
    $keywords_arr = $keywords;
    $keywords = implode(',', $keywords);
  }
  if (!$limit) {
    if ($perms = variable_get('kwresearch_api_perms', '')) {
      $limit = $perms[$call]['result_limit'];
    }
    if (!$limit) { 
      $limit = 15; 
    }
  }
  
  $last_cache = variable_get('kwresearch_last_cache', 0);
  $cachecheck = FALSE;
  if ((time - $last_cache) > KWANALYSIS_CACHE_TIMEOUT) {
    $cachecheck = TRUE;
  }
  
  $sql = '
    SELECT *
    FROM {kwresearch_wordtracker_data}
    WHERE 
    keyphrase = "%s" AND
    include_misspellings = %d AND
    include_plurals = %d AND
    adult_filter = %d
  ';

  // translate adult filter to index
  $afv = kwresearch_get_adult_filter_values();
  $afi = array_search($adult_filter, $afv);
  $dbresult = db_fetch_array(db_query($sql, $keywords, $include_misspellings, $include_plurals, $afi));
  if ($dbresult[$callabv] && ($dbresult[$callabv . "_limit"] >= $limit)) {
    $dbret = unserialize($dbresult[$callabv]);
    if (!$cachecheck) {
      return array_slice($dbret, 0, $limit);   
    }    
  }  

  if (!$connection) {
    if (!$connection = kwresearch_get_xml_connect()) {
      $msg = t('The API key is not set. To get full reporting <a href="!url" target="settings">set the api key in settings</a>',
        array(
          '!url' => base_path() . 'admin/settings/kwresearch'
        )
      );
      $msgs[] = kwresearch_format_message($msg, 'error');
      return FALSE;
    }  
  }
  if ($connection['l10seoapi_call']) {
    $apiret = xmlrpc(
      $connection['endpoint'],
      $connection['l10seoapi_call'],
      $call,
      $connection['apikey'],
      $keywords_arr,
      'case_folded',
      (bool)$include_misspellings,
      (bool)$include_plurals,
      $adult_filter,
      $limit,
      15
    );  
  }
  else {
    $apiret = xmlrpc(
      $connection['endpoint'],
      $call,
      $connection['apikey'],
      $keywords_arr,
      'case_folded',
      (bool)$include_misspellings,
      (bool)$include_plurals,
      $adult_filter,
      $limit,
      15
    );
  }

  if ($error = xmlrpc_error()) {
    if ($error->code <= 0) {
      $error->message = t('Outgoing HTTP request to %endpoint failed because the socket could not be opened.', array('%endpoint' => $endpoint));
    }
    $errmsg = t('Could not get wordtracker keyword popularity because the remote site gave an error: %message (@code)', 
      array(
        '%message' => $error->message,
        '@code' => $error->code,
      )
    );
    $msgs[] = kwresearch_format_message($errmsg, 'error');
    return FALSE;
  }
  
  if (!is_array($apiret)) {
      $errmsg = t('Expected return of type array, but got [@type]', array('@type' => gettype($apiret)));
      $msgs[] = kwresearch_format_message($errmsg, 'error');
      return FALSE;
  }

//dsm($apiret);

  if (!$dbresult) {
    $sql = '
      INSERT INTO {kwresearch_wordtracker_data}
      (keyphrase, include_misspellings, include_plurals, adult_filter, ' . $callabv . ', ' . $callabv . '_limit)
      VALUES ("%s",%d,%d,%d,"%s",%d)
    ';
    $afv = kwresearch_get_adult_filter_values();
    $afi = array_search($adult_filter, $afv);
    $query = db_query($sql, $keywords, $include_misspellings, $include_plurals, $afi, serialize($apiret), $limit);
  } 
  elseif (!$dbret) {
    $sql = '
      UPDATE {kwresearch_wordtracker_data}
      SET 
        ' . $callabv . ' = "%s",
        ' . $callabv . '_limit = %d
      WHERE 
        keyphrase = "%s" AND
        include_misspellings = %d AND
        include_plurals = %d AND
        adult_filter = %d
    ';
    $afv = kwresearch_get_adult_filter_values();
    $afi = array_search($adult_filter, $afv);
    $query = db_query($sql, $afi, serialize($apiret), $limit, $keywords, '', $include_misspellings, $include_plurals, $afi);
  } 
  elseif (array_slice($dbret, 0, 10) != array_slice($apiret, 0, 10)) { // empty cache, it is out of date
    $sql = '
      DELETE FROM {kwresearch_wordtracker_data}
    ';
    $query = db_query($sql);
    drupal_set_message(t('Keyword cache reset.'));
    variable_set('kwresearch_last_cache', time());
  }  
  return $apiret;
}

/**
 * Checks API permissions and sets endpoint based on type of API key
 */
function kwresearch_api_query_permissions() {

  if (!$c = kwresearch_get_xml_connect()) {
    drupal_set_message(t('API key is missing.'), 'error'); 
  }
  $call = 'query_permissions';
  if ($c['l10seoapi_call']) {
    $apiret = xmlrpc(
      $c['endpoint'],
      'l10seoapi.wordtracker_user',
      $call,
      $c['apikey']
    );    
  }
  else {
    $apiret = xmlrpc(
      $c['endpoint'],
      $call,
      $c['apikey']
    );   
  }
  
  return $apiret;
}

/**
 *  Implentation of hook_kwresearch_sources()
 */
function kwresearch_kwresearch_sources() {
  $sources['wordtracker'] = array(
    'title' => t('Wordtracker'),
    'module' => 'kwresearch',
    'stats_callback' => 'kwresearch_wordtracker_get_keyword_stats',
    'searches_ratio' => 1.7636, // ratio = total daily searches / count from data
    'stats_report_columns' => array(
      'wordtracker_searches' => t('WT count')
    ),
    'stats_report_values_callback' => 'kwresearch_kwresearch_format_stats_values',
  );
  return $sources;  
}

/**
 * Implementation of hook_stats_callback() via custom define callback in hook_kwresearch_sources()
 * @param string|array $keywords
 * @param array $msgs
 * @param array $params
 */
function kwresearch_wordtracker_get_keyword_stats($keywords, &$msgs, $params) {
  $data = kwresearch_wordtracker_get_words_popularity($keywords, &$msgs, $params); 
//dsm($data);

  $ret = array();
  if (is_array($data)) {
    foreach ($data AS $kw => $v) {
      $ret[$kw] = array(
        'searches' => $v
      );
    }
  }
  return $ret;
}

/**
 * Implementation of hook_stats_report_values_callback() via custom define callback in hook_kwresearch_sources()
 * @param $values
 * @param $keyword
 * @param $type
 */
function kwresearch_kwresearch_format_stats_values($values, $keyword='', $type = 'term') {
  switch ($type) {
    case 'wordtracker_searches':
      if ($values['wordtracker_searches'] > 0) {
        $output = ($values['wordtracker_searches']=='NA') ? 'NA': number_format($values['wordtracker_searches']);
      }
      else {
        $output = $values['wordtracker_searches'];
      }
      break;
    default:
      return FALSE;
  }  
  return $output;
}

/**
 * Returns xml connection data for Wordtracker data
 * TODO ??? move/rename this function
 */
function kwresearch_get_xml_connect() { 
  $c = array();
  $c['apikey'] = variable_get('kwresearch_apikey', '');
  if (!$c['apikey']) {
    $c['apikey'] = variable_get('levelten_apikey', '');
  }
  if (!$c['apikey']) {
    return FALSE;
  }
  if (substr($c['apikey'], 0, 8) == 'levelten') {
    $c['endpoint'] = 'http://www.leveltendesign.com/xmlrpc.php';
    $c['l10seoapi_call'] = 'l10seoapi.wordtracker';
  }
  else {
    $c['endpoint'] = 'http://xmlrpc.wordtracker.com';
  }
  return $c;
}

function kwresearch_wordtracker_ping() {
  $url = 'http://test.xmlrpc.wordtracker.com';
  $call = 'ping';
  $apikey = 'guest';

         
  if (!$apiret = xmlrpc($url, $call, $apikey)) {
      print 'Procedure returned error message: ' . $client->getErrorMessage() . '.';
  }
  if ($apiret !== TRUE) {
      print 'The procedure returned an incorrect result.';
  }
  print 'Successfully pinged test account.';
}

function kwresearch_get_adult_filter_values() {
  return array(
    'off',
    'remove_dubious',
    'remove_offensive',
    'adult_only'
  );
}