' . t('The statistics module keeps track of numerous site usage statistics, including the number of times, and from where, each of your posts is viewed. These statistics are useful in determining how users are interacting with each other and with your site, and are required for the display of some Drupal blocks.') . '

'; $output .= '

' . t('The statistics module provides:') . '

'; $output .= ''; $output .= '

' . t('Configuring the statistics module') . '

'; $output .= ''; $output .= '

' . t('For more information, see the online handbook entry for Statistics module.', array('@statistics' => 'http://drupal.org/handbook/modules/statistics/')) . '

'; return $output; case 'admin/settings/statistics': return '

' . t('Settings for the statistical information that Drupal will keep about the site. See site statistics for the actual information.', array('@statistics' => url('admin/reports/hits'))) . '

'; case 'admin/reports/hits': return '

' . t("This page displays the site's most recent hits.") . '

'; case 'admin/reports/referrers': return '

' . t('This page displays all external referrers, or external references to your website.') . '

'; case 'admin/reports/visitors': return '

' . t("When you ban a visitor, you prevent the visitor's IP address from accessing your site. Unlike blocking a user, banning a visitor works even for anonymous users. This is most commonly used to block resource-intensive bots or web crawlers.") . '

'; } } /** * Implement hook_exit(). * * This is where statistics are gathered on page accesses. */ function statistics_exit() { global $user; drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH); if (variable_get('statistics_count_content_views', 0)) { // We are counting content views. if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') { // A node has been viewed, so update the node's counters. db_merge('node_counter') ->key(array('nid' => arg(1))) ->fields(array( 'daycount' => 1, 'totalcount' => 1, 'timestamp' => REQUEST_TIME, )) ->expression('daycount', 'daycount + 1') ->expression('totalcount', 'totalcount + 1') ->execute(); } } if (variable_get('statistics_enable_access_log', 0)) { // Log this page access. db_insert('accesslog') ->fields(array( 'title' => strip_tags(drupal_get_title()), 'path' => $_GET['q'], 'url' => $_SERVER['HTTP_REFERER'], 'hostname' => ip_address(), 'uid' => $user->uid, 'sid' => session_id(), 'timer' => (int) timer_read('page'), 'timestamp' => REQUEST_TIME, )) ->execute(); } } /** * Implement hook_permission(). */ function statistics_permission() { return array( 'access statistics' => array( 'title' => t('Access statistics'), 'description' => t('View content access statistics.'), ), 'administer statistics' => array( 'title' => t('Administer statistics'), 'description' => t('Configure statistics settings.'), ), 'view post access counter' => array( 'title' => t('View post access counter'), 'description' => t('View the total number of times a piece of content has been accessed.'), ), ); } /** * Implement hook_node_view(). */ function statistics_node_view($node, $build_mode) { if ($build_mode != 'rss') { $links = array(); if (user_access('view post access counter')) { $statistics = statistics_get($node->nid); if ($statistics) { $links['statistics_counter']['title'] = format_plural($statistics['totalcount'], '1 read', '@count reads'); } } $node->content['links']['statistics'] = array( '#theme' => 'links', '#links' => $links, '#attributes' => array('class' => array('links', 'inline')), ); } } /** * Implement hook_menu(). */ function statistics_menu() { $items['admin/reports/hits'] = array( 'title' => 'Recent hits', 'description' => 'View pages that have recently been visited.', 'page callback' => 'statistics_recent_hits', 'access arguments' => array('access statistics'), 'file' => 'statistics.admin.inc', ); $items['admin/reports/pages'] = array( 'title' => 'Top pages', 'description' => 'View pages that have been hit frequently.', 'page callback' => 'statistics_top_pages', 'access arguments' => array('access statistics'), 'weight' => 1, 'file' => 'statistics.admin.inc', ); $items['admin/reports/visitors'] = array( 'title' => 'Top visitors', 'description' => 'View visitors that hit many pages.', 'page callback' => 'statistics_top_visitors', 'access arguments' => array('access statistics'), 'weight' => 2, 'file' => 'statistics.admin.inc', ); $items['admin/reports/referrers'] = array( 'title' => 'Top referrers', 'description' => 'View top referrers.', 'page callback' => 'statistics_top_referrers', 'access arguments' => array('access statistics'), 'file' => 'statistics.admin.inc', ); $items['admin/reports/access/%'] = array( 'title' => 'Details', 'description' => 'View access log.', 'page callback' => 'statistics_access_log', 'page arguments' => array(3), 'access arguments' => array('access statistics'), 'type' => MENU_CALLBACK, 'file' => 'statistics.admin.inc', ); $items['admin/settings/statistics'] = array( 'title' => 'Statistics', 'description' => 'Control details about what and how your site logs access statistics.', 'page callback' => 'drupal_get_form', 'page arguments' => array('statistics_settings_form'), 'access arguments' => array('administer statistics'), 'file' => 'statistics.admin.inc', ); $items['user/%user/track/navigation'] = array( 'title' => 'Track page visits', 'page callback' => 'statistics_user_tracker', 'access callback' => 'user_access', 'access arguments' => array('access statistics'), 'type' => MENU_LOCAL_TASK, 'weight' => 2, 'file' => 'statistics.pages.inc', ); $items['node/%node/track'] = array( 'title' => 'Track', 'page callback' => 'statistics_node_tracker', 'access callback' => 'user_access', 'access arguments' => array('access statistics'), 'type' => MENU_LOCAL_TASK, 'weight' => 2, 'file' => 'statistics.pages.inc', ); return $items; } /** * Implement hook_user_cancel(). */ function statistics_user_cancel($edit, $account, $method) { switch ($method) { case 'user_cancel_reassign': db_update('accesslog') ->fields(array('uid' => 0)) ->condition('uid', $account->uid) ->execute(); break; case 'user_cancel_delete': db_delete('accesslog') ->condition('uid', $account->uid) ->execute(); break; } } /** * Implement hook_cron(). */ function statistics_cron() { $statistics_timestamp = variable_get('statistics_day_timestamp', ''); if ((REQUEST_TIME - $statistics_timestamp) >= 86400) { // Reset day counts. db_update('node_counter') ->fields(array('daycount' => 0)) ->execute(); variable_set('statistics_day_timestamp', REQUEST_TIME); } // Clean up expired access logs. db_delete('accesslog') ->condition('timestamp', REQUEST_TIME - variable_get('statistics_flush_accesslog_timer', 259200), '<') ->execute(); } /** * Returns all time or today top or last viewed node(s). * * @param $dbfield * one of * - 'totalcount': top viewed content of all time. * - 'daycount': top viewed content for today. * - 'timestamp': last viewed node. * * @param $dbrows * number of rows to be returned. * * @return * A query result containing n.nid, n.title, u.uid, u.name of the selected node(s) * or FALSE if the query could not be executed correctly. */ function statistics_title_list($dbfield, $dbrows) { if (in_array($dbfield, array('totalcount', 'daycount', 'timestamp'))) { $query = db_select('node', 'n'); $query->addTag('node_access'); $query->join('node_counter', 's', 'n.nid = s.nid'); $query->join('users', 'u', 'n.uid = u.uid'); return $query ->fields('n', array('nid', 'title')) ->fields('u', array('uid', 'name')) ->condition($dbfield, 0, '<>') ->condition('n.status', 1) ->orderBy($dbfield, 'DESC') ->range(0, $dbrows) ->execute(); } return FALSE; } /** * Retrieves a node's "view statistics". * * @param $nid * node ID * * @return * An array with three entries: [0]=totalcount, [1]=daycount, [2]=timestamp * - totalcount: count of the total number of times that node has been viewed. * - daycount: count of the total number of times that node has been viewed "today". * For the daycount to be reset, cron must be enabled. * - timestamp: timestamp of when that node was last viewed. */ function statistics_get($nid) { if ($nid > 0) { // Retrieve an array with both totalcount and daycount. return db_query('SELECT totalcount, daycount, timestamp FROM {node_counter} WHERE nid = :nid', array(':nid' => $nid))->fetchAssoc(); } } /** * Implement hook_block_list(). */ function statistics_block_list() { if (variable_get('statistics_count_content_views', 0)) { $blocks['popular']['info'] = t('Popular content'); // Too dynamic to cache. $blocks['popular']['cache'] = BLOCK_NO_CACHE; return $blocks; } } /** * Implement hook_block_configure(). */ function statistics_block_configure($delta = '') { // Popular content block settings $numbers = array('0' => t('Disabled')) + drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40)); $form['statistics_block_top_day_num'] = array('#type' => 'select', '#title' => t("Number of day's top views to display"), '#default_value' => variable_get('statistics_block_top_day_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "day" list.')); $form['statistics_block_top_all_num'] = array('#type' => 'select', '#title' => t('Number of all time views to display'), '#default_value' => variable_get('statistics_block_top_all_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "all time" list.')); $form['statistics_block_top_last_num'] = array('#type' => 'select', '#title' => t('Number of most recent views to display'), '#default_value' => variable_get('statistics_block_top_last_num', 0), '#options' => $numbers, '#description' => t('How many content items to display in "recently viewed" list.')); return $form; } /** * Implement hook_block_save(). */ function statistics_block_save($delta = '', $edit = array()) { variable_set('statistics_block_top_day_num', $edit['statistics_block_top_day_num']); variable_set('statistics_block_top_all_num', $edit['statistics_block_top_all_num']); variable_set('statistics_block_top_last_num', $edit['statistics_block_top_last_num']); } /** * Implement hook_block_view(). */ function statistics_block_view($delta = '') { if (user_access('access content')) { $content = array(); $daytop = variable_get('statistics_block_top_day_num', 0); if ($daytop && ($result = statistics_title_list('daycount', $daytop)) && ($node_title_list = node_title_list($result, t("Today's:")))) { $content[] = $node_title_list; } $alltimetop = variable_get('statistics_block_top_all_num', 0); if ($alltimetop && ($result = statistics_title_list('totalcount', $alltimetop)) && ($node_title_list = node_title_list($result, t('All time:')))) { $content[] = $node_title_list; } $lasttop = variable_get('statistics_block_top_last_num', 0); if ($lasttop && ($result = statistics_title_list('timestamp', $lasttop)) && ($node_title_list = node_title_list($result, t('Last viewed:')))) { $content[] = $node_title_list; } if (count($content)) { $block['content'] = implode('
', $content); $block['subject'] = t('Popular content'); return $block; } } } /** * It is possible to adjust the width of columns generated by the * statistics module. */ function _statistics_link($path, $width = 35) { $title = drupal_get_path_alias($path); $title = truncate_utf8($title, $width, FALSE, TRUE); return l($title, $path); } function _statistics_format_item($title, $path) { $path = ($path ? $path : '/'); $output = ($title ? "$title
" : ''); $output .= _statistics_link($path); return $output; } /** * Implement hook_node_delete(). */ function statistics_node_delete($node) { // clean up statistics table when node is deleted db_delete('node_counter') ->condition('nid', $node->nid) ->execute(); } /** * Implement hook_ranking(). */ function statistics_ranking() { if (variable_get('statistics_count_content_views', 0)) { return array( 'views' => array( 'title' => t('Number of views'), 'join' => 'LEFT JOIN {node_counter} node_counter ON node_counter.nid = i.sid', // Inverse law that maps the highest view count on the site to 1 and 0 to 0. 'score' => '2.0 - 2.0 / (1.0 + node_counter.totalcount * CAST(%f AS DECIMAL))', 'arguments' => array(variable_get('node_cron_views_scale', 0)), ), ); } } /** * Implement hook_update_index(). */ function statistics_update_index() { variable_set('node_cron_views_scale', 1.0 / max(1, db_query('SELECT MAX(totalcount) FROM {node_counter}')->fetchField())); }