google_analytics_counter.module in Google Analytics Counter 7.3
Same filename and directory in other branches
Basic functions for this module.
File
google_analytics_counter.moduleView source
<?php
/**
* @file
* Basic functions for this module.
*/
/**
* Load the necessary include files.
*/
module_load_include('inc', 'google_analytics_counter', 'google_analytics_counter_settings');
module_load_include('inc', 'google_analytics_counter', 'google_analytics_counter_data');
module_load_include('inc', 'google_analytics_counter', 'google_analytics_counter_auth');
// Keep old start date in $_SESSION because we need to detect if it changes to a more recent date (higher timestamp); see https://www.drupal.org/node/2794797
$authsession = (bool) $GLOBALS['user']->uid;
// Could not use https://api.drupal.org/api/drupal/modules%21user%21user.module/function/user_is_logged_in/7.x because it gave "Call to undefined function user_is_logged_in()".
if ($authsession) {
// Only store something in $_SESSION if it's an authenticated user!
if (!isset($_SESSION['google_analytics_counter']['old_start_date'])) {
$old_start_date = google_analytics_counter_get_start_date();
$_SESSION['google_analytics_counter']['old_start_date'] = $old_start_date;
}
else {
$current_start_date = google_analytics_counter_get_start_date();
//dpm('old ' . $_SESSION['google_analytics_counter']['old_start_date']);
if (strtotime($_SESSION['google_analytics_counter']['old_start_date']) < strtotime($current_start_date)) {
// Only if we change from a older (smaller) date to a newer (bigger) date!
//dpm('current ' . $current_start_date);
db_truncate('google_analytics_counter')
->execute();
db_truncate('google_analytics_counter_storage')
->execute();
$message = t('The start date of the Google Analytics queries has been changed to a more recent one. The stats storage tables of this module had to be reset (they will repopulate during cron runs).');
// @TODO: Possibly show the old and new date in the message.
drupal_set_message($message);
watchdog('Google Analytics Counter', $message, NULL, WATCHDOG_INFO);
$_SESSION['google_analytics_counter']['old_start_date'] = $current_start_date;
}
}
}
/**
* Get the currently set query start date
*/
/**
* Implements hook_action_info().
*/
function google_analytics_counter_get_start_date() {
if (variable_get('google_analytics_counter_advanced_date_checkbox') == 1) {
$start_date = variable_get('google_analytics_counter_fixed_start_date', '2005-01-01');
}
else {
$period = variable_get('google_analytics_counter_variable_start_date', GOOGLE_ANALYTICS_COUNTER_YEAR);
$start_date = date('Y-m-d', REQUEST_TIME - $period);
}
return $start_date;
}
/**
* Implement admin settings validate
*/
function google_analytics_counter_admin_validate($form, &$form_state) {
if ($form_state['values']['google_analytics_counter_advanced_date_checkbox'] == 1 && strtotime($form_state['values']['google_analytics_counter_fixed_start_date']) > time()) {
form_set_error('google_analytics_counter_fixed_start_date', t('Your date is in the future, please select a valid static date value in the GA fixed starting date field'));
}
}
/**
* Implements hook_views_api().
*/
function google_analytics_counter_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'google_analytics_counter') . '/views',
);
}
/**
* Valid permissions for this module
* @return array An array of valid permissions for the test_module module
*/
function google_analytics_counter_permission() {
return array(
'administer google analytics counter' => array(
'title' => t('Administer Google Analytics Counter'),
),
);
}
/**
* Display help and module information
* Implements hook_help().
* @param path which path of the site we're displaying help
* @param arg array that holds the current path as would be returned from arg() function
* @return help text for the path
*/
function google_analytics_counter_help($path, $arg) {
if ($path == 'admin/help#google_analytics_counter') {
//admin/modules#description
//admin/help/google_analytics_counter
// '<p>' . t("Page view counter drawing on data collected by Google Analytics.") . '</p>';
$output = file_get_contents(drupal_get_path('module', 'google_analytics_counter') . '/README.txt');
return nl2br($output);
}
}
/**
* Menu for this module
* @return array An array with this module's settings.
*/
function google_analytics_counter_menu() {
$items = array();
$items['admin/config/system/google_analytics_counter'] = array(
'title' => t('Google Analytics Counter'),
'description' => t('Configure Google Analytics Counter module'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'google_analytics_counter_admin',
),
'access arguments' => array(
'administer google analytics counter',
),
'weight' => 0,
);
// For the default local task, we need very little configuration, as the callback and other conditions are handled by the parent callback.
$items['admin/config/system/google_analytics_counter/settings'] = array(
'title' => t('Settings'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 1,
);
$items['admin/config/system/google_analytics_counter/dashboard'] = array(
'title' => t('Dashboard'),
'description' => t('More information relevant to Google Analytics statistics for this site.'),
'page callback' => 'google_analytics_counter_details',
'access arguments' => array(
'administer google analytics counter',
),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
$items['admin/config/system/google_analytics_counter/authentication'] = array(
'title' => t('GA authentication'),
'description' => t('Authenticate access to a Google Analytics profile.'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'google_analytics_counter_auth_admin',
),
'access arguments' => array(
'administer google analytics counter',
),
'type' => MENU_LOCAL_TASK,
'weight' => 4,
);
$items['admin/config/system/google_analytics_counter/dashboard/reset'] = array(
'title' => t('Reset module settings'),
'description' => t('Reset all settings of this module. Sometimes useful if in trouble with OAuth authentication.'),
'page callback' => 'google_analytics_counter_confirm_reset',
'access arguments' => array(
'administer google analytics counter',
),
'type' => MENU_CALLBACK,
'weight' => 9,
);
return $items;
}
/**
* Implements hook_block_info().
*/
function google_analytics_counter_block_info() {
$block = array();
// Generate listing of blocks from this module, for the admin/block page
$block[0]["info"] = t('Google Analytics Counter');
return $block;
}
/**
* Implements hook_block_view().
*/
function google_analytics_counter_block_view($delta) {
$block = array();
// Generate our block content
$block_content = google_analytics_counter_display();
$block['subject'] = t('Google Analytics Counter');
if ($block_content == '') {
// If unknown, for some reason.
$block['content'] = 0;
// Instead of t('N/A'). Suppose better to use 0 because it's true, that path has been recorded zero times by GA. Path may not exist or be private or too new.
}
else {
$block['content'] = $block_content;
}
return $block;
}
/**
* Implements hook_filter_info().
*/
function google_analytics_counter_filter_info() {
$filters = array();
$filters['filter_google_analytics_counter'] = array(
'title' => t('Google Analytics Counter tag'),
'description' => t('Substitutes a special Google Analytics Counter tag [gac|...] with the actual content.'),
'prepare callback' => 'google_analytics_counter_filter_google_analytics_counter_prepare',
'process callback' => 'google_analytics_counter_filter_google_analytics_counter_process',
);
return $filters;
}
/**
* Implements hook_filter_FILTER_prepare().
*/
function google_analytics_counter_filter_google_analytics_counter_prepare($text, $filter) {
return $text;
}
/**
* Implements hook_filter_FILTER_process().
*/
function google_analytics_counter_filter_google_analytics_counter_process($text, $filter) {
$text = replace_google_analytics_counter_tags($text);
return $text;
}
/**
* Finds [gac|...] tags and replaces them by actual values.
*/
function replace_google_analytics_counter_tags($str) {
// [gac|path/to/page]
$matchlink = array();
$orig_match = array();
$matches = array();
preg_match_all("/(\\[)gac[^\\]]*(\\])/s", $str, $matches);
// This allows more than one pipe sign (|) ... does not hurt and leaves room for possible extension.
foreach ($matches[0] as $match) {
// Keep original value.
$orig_match[] = $match;
// Remove wrapping [].
$match = substr($match, 1, strlen($match) - 2);
// Create an array of parameter attributions.
$match = explode("|", $match);
$path = trim(check_plain(@$match[1]));
/* So now we can display the count based on the path.
* If no path was defined, the function will detect the current page's count.
*/
$matchlink[] = google_analytics_counter_display($path);
}
$str = str_replace($orig_match, $matchlink, $str);
return $str;
}
/**
* Displays the count.
*/
function google_analytics_counter_display($path = '') {
if ($path == '') {
//$path = $_GET['q'];
//dpm($language);
//$path = $lprefix.$path;
// We need a path that includes the language prefix, if any. E.g. en/my/path (of /en/my/path - the initial slash will be dealt with later).
$path = parse_url("http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", PHP_URL_PATH);
// @TODO: Works OK on non-Apache servers?
}
//dpm($path);
// Check all paths, to be sure.
//$path = check_plain($path);
$block_content = '';
//$block_content .= '<span id="google-analytics-counter-' . md5($path) . '">';
$block_content .= '<span class="google-analytics-counter">';
$count = google_analytics_counter_get_sum_per_path($path);
if ($count == '') {
// If unknown, for some reason.
$block_content .= 0;
// Better than t('N/A').
}
else {
$block_content .= $count;
}
$block_content .= '</span>';
return $block_content;
}
/**
* Implements hook_cron().
*
*/
function google_analytics_counter_cron() {
// Set a watchdog error if there is no Google Analytics profile enabled.
// It's a weak test but better than none.
if (variable_get('google_analytics_counter_profile_id') == '') {
watchdog('Google Analytics Counter', t('No Google Analytics profile has been authenticated! Google Analytics Counter can not fetch any new data. Please ' . l(t('authenticate here'), 'admin/config/system/google_analytics_counter/authentication') . '.'), NULL, WATCHDOG_ERROR);
return;
}
// Defaults to an hourly interval. Of course, cron has to be running at least hourly for this to work.
$interval = 60 * variable_get('google_analytics_counter_cron_interval', 30);
// $interval must contain value in seconds.
// We don't want to act every time cron runs (which could be every minute) so keep a time for the next run in a variable.
if (REQUEST_TIME >= variable_get('google_analytics_counter_cron_next_execution', 0)) {
// Important to set it before the job because if they take long and there is another cron triggered...
variable_set('google_analytics_counter_cron_next_execution', REQUEST_TIME + $interval);
// Retrieve path with counts from Google Analytics into a local table.
google_analytics_counter_update_path_counts();
// Now also update the storage table from the local table with the GA data.
google_analytics_counter_update_storage();
}
}
/**
* Sets the expiry timestamp for cached queries.
* Default is 1 day.
* @return The UNIX timestamp to expire the query at.
*/
function google_analytics_counter_cache_time() {
return time() + variable_get('google_analytics_counter_cache_length', GOOGLE_ANALYTICS_COUNTER_DAY);
}
/**
* More information relevant to Google Analytics statistics for this site.
*/
function google_analytics_counter_details() {
$result = '';
$result .= t('<p><h3>More information relevant to Google Analytics statistics for this site:</h3>');
$authenticated = FALSE;
// It's a weak test but better than none.
if (variable_get('google_analytics_counter_profile_id') != '') {
$authenticated = TRUE;
}
else {
$result .= t('<font color="red">No Google Analytics profile has been authenticated! Google Analytics Counter can not fetch any new data. Please ' . l(t('authenticate here'), 'admin/config/system/google_analytics_counter/authentication') . '.</font>');
// Don't show anything else.
return $result;
}
$result .= t('<p>Total number of hits registered by Google Analytics under this profile: %google_analytics_counter_totalhits. This is cumulative; counts for paths that may no longer exist on the website still have historical traces in Google Analytics.', array(
'%google_analytics_counter_totalhits' => check_plain(number_format(variable_get('google_analytics_counter_totalhits', 0))),
));
$result .= t('<p>Number of paths on this site as currently recorded by Google Analytics: %google_analytics_counter_totalpaths. This is cumulative; paths that may no longer exist on the website still have historical traces in Google Analytics.', array(
'%google_analytics_counter_totalpaths' => check_plain(number_format(variable_get('google_analytics_counter_totalpaths', 0))),
));
$dbresult = db_select('google_analytics_counter', 'gac')
->fields('gac')
->execute();
$num_of_results = $dbresult
->rowCount();
$result .= t('<br />Number of paths currently stored in local database table: %num_of_results. This table is initially built and then regularly updated during cron runs.', array(
'%num_of_results' => number_format($num_of_results),
));
$result .= t('<p>Total number of nodes on this site: %google_analytics_counter_totalnodes.', array(
'%google_analytics_counter_totalnodes' => check_plain(number_format(variable_get('google_analytics_counter_totalnodes', 0))),
));
if (variable_get('google_analytics_counter_storage', 0) == 0 && module_exists('statistics')) {
// See also https://www.drupal.org/node/2275575
$dbresult = db_select('node_counter', 'nc')
->fields('nc')
->execute();
}
else {
$dbresult = db_select('google_analytics_counter_storage', 'gacs')
->fields('gacs')
->execute();
}
$num_of_results = $dbresult
->rowCount();
$result .= t('<br />Number of nodes with known pageview counts on this site: %num_of_results.', array(
'%num_of_results' => check_plain(number_format($num_of_results)),
));
$apicalls = variable_get('google_analytics_counter_dayquota', array(
0,
0,
));
$result .= t('<p>Number of requests made to Google Analytics: %apicalls1. Only calls made by this module are counted here. Other modules and apps may be making more requests. ', array(
'%apicalls1' => check_plain(number_format($apicalls[1])),
));
$remainingcalls = variable_get('google_analytics_counter_api_dayquota', 10000) - $apicalls[1];
if ($remainingcalls < 1) {
$remainingcalls = '?';
}
else {
$remainingcalls = number_format($remainingcalls);
}
$result .= t('Remaining requests available in the current 24-hour period: %remainingcalls. ', array(
'%remainingcalls' => check_plain($remainingcalls),
));
if ($apicalls[0] == 0) {
$temp = 60 * 60 * 24;
}
else {
$temp = 60 * 60 * 24 - (REQUEST_TIME - $apicalls[0]);
}
$result .= t('The current 24-hour period ends in: %google_analytics_counter_sec2hms.', array(
'%google_analytics_counter_sec2hms' => check_plain(google_analytics_counter_sec2hms($temp)),
));
$temp = variable_get('google_analytics_counter_chunk_process_time', 0) + variable_get('google_analytics_counter_chunk_node_process_time', 0);
if ($temp < 0) {
$temp = 0;
}
$result .= t('<br/>The most recent retrieval of %google_analytics_counter_chunk_to_fetch paths from Google Analytics and node counts from its local mirror took %google_analytics_counter_sec2hms (%google_analytics_counter_chunk_process_time+%google_analytics_counter_chunk_node_process_times). ', array(
'%google_analytics_counter_chunk_to_fetch' => check_plain(number_format(variable_get('google_analytics_counter_chunk_to_fetch', 0))),
'%google_analytics_counter_sec2hms' => check_plain(google_analytics_counter_sec2hms($temp)),
'%google_analytics_counter_chunk_process_time' => check_plain(variable_get('google_analytics_counter_chunk_process_time', 0)),
'%google_analytics_counter_chunk_node_process_time' => check_plain(variable_get('google_analytics_counter_chunk_node_process_time', 0)),
));
$temp = variable_get('google_analytics_counter_cron_next_execution', 60 * variable_get('google_analytics_counter_cron_interval', 30)) - REQUEST_TIME;
if ($temp < 0) {
$temp = 0;
}
$result .= t('The next one will take place in %google_analytics_counter_sec2hms.', array(
'%google_analytics_counter_sec2hms' => check_plain(google_analytics_counter_sec2hms($temp)),
));
$result .= t('<p>' . l(t('Run cron immediately'), 'admin/reports/status/run-cron', array(
'query' => array(
'destination' => 'admin/config/system/google_analytics_counter/dashboard',
),
)) . '.');
$result .= t('<p>[' . l(t('Reset all module settings'), 'admin/config/system/google_analytics_counter/dashboard/reset') . '. Useful in some cases, e.g. if in trouble with OAuth authentication.]');
return $result;
}
/**
* Confirmation callback function for link admin/config/system/google_analytics_counter/dashboard/reset
*
*/
function google_analytics_counter_confirm_reset() {
// drupal_get_form is used to render the form into HTML code.
return drupal_get_form('google_analytics_counter_confirm_reset_form');
}
/**
* Configuration reset form
*/
function google_analytics_counter_confirm_reset_form($form_state) {
// Instead of building the form ourselves, we use confirm_form to automatically generate it.
$form = array();
return confirm_form($form, 'Are you sure that you wish to reset all configuration variables of module Google Analytics Counter to their default values?', 'admin/config/system/google_analytics_counter/dashboard', NULL, 'Yes', 'No');
}
/**
* Submit handler gets called when form is submitted, so code to be executed upon form submission goes here
*/
function google_analytics_counter_confirm_reset_form_submit($form, &$form_state) {
google_analytics_counter_reset();
drupal_goto('admin/config/system/google_analytics_counter/dashboard');
}
/**
* Convert seconds to hours, minutes and seconds.
*/
function google_analytics_counter_sec2hms($sec, $padHours = FALSE) {
// start with a blank string
$hms = "";
// do the hours first: there are 3600 seconds in an hour, so if we divide
// the total number of seconds by 3600 and throw away the remainder, we're
// left with the number of hours in those seconds
$hours = intval(intval($sec) / 3600);
// add hours to $hms (with a leading 0 if asked for)
$hms .= $padHours ? str_pad($hours, 2, "0", STR_PAD_LEFT) . "h " : $hours . "h ";
// dividing the total seconds by 60 will give us the number of minutes
// in total, but we're interested in *minutes past the hour* and to get
// this, we have to divide by 60 again and then use the remainder
$minutes = intval($sec / 60 % 60);
// add minutes to $hms (with a leading 0 if needed)
$hms .= str_pad($minutes, 2, "0", STR_PAD_LEFT) . "m ";
// seconds past the minute are found by dividing the total number of seconds
// by 60 and using the remainder
$seconds = intval($sec % 60);
// add seconds to $hms (with a leading 0 if needed)
$hms .= str_pad($seconds, 2, "0", STR_PAD_LEFT);
// done!
return $hms . 's';
}
/**
* Reset all module settings by deleting its variables.
*/
function google_analytics_counter_reset() {
google_analytics_counter_revoke();
drupal_goto('admin/config/system/google_analytics_counter/dashboard');
}