statistics.module 22.6 KB
Newer Older
1 2 3
<?php
// $Id$

Dries's avatar
 
Dries committed
4 5 6 7 8
/**
 * @file
 * Logs access statistics for your site.
 */

Dries's avatar
 
Dries committed
9 10 11
/**
 * Implementation of hook_help().
 */
Dries's avatar
 
Dries committed
12
function statistics_help($section) {
Dries's avatar
 
Dries committed
13 14
  switch ($section) {
    case 'admin/help#statistics':
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
      $output = '<p>'. t('The statistics module keeps track of numerous statistics of site usage. It counts how many times, and from where each of your posts is viewed. The statistics module can be used to learn many useful things about how users are interacting with each other and with your site.') .'</p>';
      $output .= t('<p>Statistics module features</p>
<ul>
<li>Logs show statistics for how many times your site and specific content on your site has been accessed.</li>
<li>Referrers tells you from where visitors came from (referrer URL).</li>
<li>Top pages shows you what\'s hot, what is the most popular content on your site.</li>
<li>Top users shows you the most active users for your site.</li>
<li>Recent hits displays information about the latest activity on your site.</li>
<li>Node count displays the number of times a node has been accessed in the node\'s link section next to <em># comments</em>.</li>
<li>Popular content block creates a block that can display the day\'s top viewed content, the all time top viewed content, and the last content viewed.</li>
</ul>
');
      $output .= t('<p>Configuring the statistics module</p>
<ul>
<li>Enable access log allows you to turn the access log on and off. This log is used to store data about every page accessed, such as the remote host\'s IP address, where they came from (referrer), what node they\'ve viewed, and their user name. Enabling the log adds one database call per page displayed by Drupal.</li>
<li>Discard access logs older than allows you to configure how long an access log entry is saved, after which time it is deleted from the database table. To use this you need to run <em>cron.php</em></li>
<li>Enable node view counter allows you to turn on and off the node-counting functionality of this module. If it is turned on, an extra database query is added for each node displayed, which increments a counter.</li>
</ul>
');
      $output .= t('<p>You can</p>
<ul>
36
<li>administer statistics <a href="%admin-settings-statistics">administer &gt;&gt; settings &gt;&gt; statistics</a>.</li>
37 38 39 40 41
<li>access statistics logs <a href="%admin-logs">administer &gt;&gt; logs</a>.</li>
<li>view recent hits <a href="%admin-logs-hits">administer &gt;&gt; logs &gt;&gt; recent hits</a>.</li>
<li>enable \'popular content\' block in block administration <a href="%admin-block">administer &gt;&gt; blocks </a> but only after you have enabled \'Count content views\' in settings.</li>
</ul>
', array('%admin-settings-statistics' => url('admin/settings/statistics'), '%admin-logs' => url('admin/logs'), '%admin-logs-hits' => url('admin/logs/hits'), '%admin-block' => url('admin/block')));
42
      $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="%statistics">Statistics page</a>.', array('%statistics' => 'http://drupal.org/handbook/modules/statistics/')) .'</p>';
43
      return $output;
Dries's avatar
 
Dries committed
44
    case 'admin/modules#description':
Dries's avatar
 
Dries committed
45
      return t('Logs access statistics for your site.');
Dries's avatar
 
Dries committed
46
    case 'admin/settings/statistics':
47
      return t('<p>Settings for the statistical information that Drupal will keep about the site. See <a href="%statistics">site statistics</a> for the actual information.</p>', array('%statistics' => url('admin/logs/hits')));
48
    case 'admin/logs/hits':
49
      return t('<p>This page shows you the most recent hits.</p>');
Dries's avatar
 
Dries committed
50
    case 'admin/logs/referrers':
51
      return t('<p>This page shows you all external referrers. These are links pointing to your web site from outside your web site.</p>');
Dries's avatar
 
Dries committed
52 53
    case 'admin/logs/visitors':
      return t('<p>When you ban a visitor, you prevent his IP address from accessing your site. Unlike blocking a user, banning a visitor works even for anonymous users. The most common use for this is to block bots/web crawlers that are consuming too many resources.</p>');
Dries's avatar
 
Dries committed
54 55 56
  }
}

Dries's avatar
 
Dries committed
57 58 59 60 61
/**
 * Implementation of hook_exit().
 *
 * This is where statistics are gathered on page accesses.
 */
62
function statistics_exit() {
Dries's avatar
 
Dries committed
63
  global $user, $recent_activity;
64

65 66
  drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);

Dries's avatar
 
Dries committed
67 68
  if (variable_get('statistics_count_content_views', 0)) {
    // We are counting content views.
69
    if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
Dries's avatar
 
Dries committed
70
      // A node has been viewed, so update the node's counters.
71
      db_query('UPDATE {node_counter} SET daycount = daycount + 1, totalcount = totalcount + 1, timestamp = %d WHERE nid = %d', time(), arg(1));
Dries's avatar
 
Dries committed
72
      // If we affected 0 rows, this is the first time viewing the node.
73
      if (!db_affected_rows()) {
Dries's avatar
 
Dries committed
74
        // We must create a new row to store counters for the new node.
75
        db_query('INSERT INTO {node_counter} (nid, daycount, totalcount, timestamp) VALUES (%d, 1, 1, %d)', arg(1), time());
76 77 78
      }
    }
  }
79
  if ((variable_get('statistics_enable_access_log', 0)) && (module_invoke('throttle', 'status') == 0)) {
Dries's avatar
 
Dries committed
80
    // Log this page access.
81
    db_query("INSERT INTO {accesslog} (title, path, url, hostname, uid, sid, timer, timestamp) values('%s', '%s', '%s', '%s', %d, '%s', %d, %d)", strip_tags(drupal_get_title()), $_GET['q'], referer_uri(), $_SERVER['REMOTE_ADDR'], $user->uid, session_id(), timer_read('page'), time());
82 83 84
  }
}

Dries's avatar
 
Dries committed
85 86 87
/**
 * Implementation of hook_perm().
 */
88
function statistics_perm() {
Dries's avatar
Dries committed
89
  return array('access statistics', 'view post access counter');
90 91
}

Dries's avatar
 
Dries committed
92 93 94
/**
 * Implementation of hook_link().
 */
95 96 97 98
function statistics_link($type, $node = 0, $main = 0) {
  global $id;
  $links = array();

Dries's avatar
Dries committed
99
  if ($type != 'comment' && user_access('view post access counter')) {
100 101
    $statistics = statistics_get($node->nid);
    if ($statistics) {
102
      $links['statistics_counter']['title'] = format_plural($statistics['totalcount'], '1 read', '%count reads');
103 104
    }
  }
105

106 107 108
  return $links;
}

Dries's avatar
 
Dries committed
109 110 111
/**
 * Implementation of hook_menu().
 */
Dries's avatar
 
Dries committed
112
function statistics_menu($may_cache) {
Dries's avatar
 
Dries committed
113
  $items = array();
Dries's avatar
 
Dries committed
114

115
  $access = user_access('access statistics');
Dries's avatar
 
Dries committed
116
  if ($may_cache) {
Dries's avatar
Dries committed
117 118 119 120 121
    $items[] = array(
      'path' => 'admin/logs/hits',
      'title' => t('recent hits'),
      'callback' => 'statistics_recent_hits',
      'access' => $access,
Dries's avatar
 
Dries committed
122
      'weight' => 3);
Dries's avatar
Dries committed
123 124 125 126 127
    $items[] = array(
      'path' => 'admin/logs/pages',
      'title' => t('top pages'),
      'callback' => 'statistics_top_pages',
      'access' => $access,
Dries's avatar
 
Dries committed
128
      'weight' => 1);
Dries's avatar
Dries committed
129 130 131 132 133
    $items[] = array(
      'path' => 'admin/logs/visitors',
      'title' => t('top visitors'),
      'callback' => 'statistics_top_visitors',
      'access' => $access,
Dries's avatar
 
Dries committed
134
      'weight' => 2);
Dries's avatar
Dries committed
135 136 137 138 139 140 141 142 143 144
    $items[] = array(
      'path' => 'admin/logs/referrers',
      'title' => t('referrers'),
      'callback' => 'statistics_top_referrers',
      'access' => $access);
    $items[] = array(
      'path' => 'admin/logs/access',
      'title' => t('details'),
      'callback' => 'statistics_access_log',
      'access' => $access,
145
      'type' => MENU_CALLBACK);
Dries's avatar
Dries committed
146 147 148 149 150 151 152
    $items[] = array(
      'path' => 'admin/settings/access-logging',
      'title' => t('access logging'),
      'callback' => 'statistics_access_logging_settings',
      'access' => user_access('administer site configuration'),
      'type' => MENU_NORMAL_ITEM
    );
153 154
  }
  else {
155
    if (arg(0) == 'user' && is_numeric(arg(1)) && variable_get('statistics_enable_access_log', 0)) {
Dries's avatar
Dries committed
156 157 158 159 160 161 162
      $items[] = array(
        'path' => 'user/'. arg(1) .'/track/navigation',
        'title' => t('track page visits'),
        'callback' => 'statistics_user_tracker',
        'access' => $access,
        'type' => MENU_LOCAL_TASK,
        'weight' => 2);
163
    }
164
    if (arg(0) == 'node' && is_numeric(arg(1)) && variable_get('statistics_enable_access_log', 0)) {
Dries's avatar
Dries committed
165 166 167 168 169 170 171
      $items[] = array(
        'path' => 'node/'. arg(1) .'/track',
        'title' => t('track'),
        'callback' => 'statistics_node_tracker',
        'access' => $access,
        'type' => MENU_LOCAL_TASK,
        'weight' => 2);
172
    }
Dries's avatar
 
Dries committed
173 174
  }

Dries's avatar
 
Dries committed
175 176 177
  return $items;
}

178 179 180 181 182 183 184 185 186
/**
 * Implementation of hook_user().
 */
function statistics_user($op, &$edit, &$user) {
  if ($op == 'delete') {
    db_query('UPDATE {accesslog} SET uid = 0 WHERE uid = %d', $user->uid);
  }
}

187 188 189 190
function statistics_access_log($aid) {
  $result = db_query('SELECT a.*, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE aid = %d', $aid);
  if ($access = db_fetch_object($result)) {
    $output  = '<table border="1" cellpadding="2" cellspacing="2">';
191
    $output .= ' <tr><th>'. t('URL') ."</th><td>". l(url($access->path, NULL, NULL, TRUE), $access->path) ."</td></tr>";
192
    $output .= ' <tr><th>'. t('Title') .'</th><td>'. $access->title .'</td></tr>'; // safe because it comes from drupal_get_title()
193 194
    $output .= ' <tr><th>'. t('Referrer') ."</th><td>". ($access->url ? l($access->url, $access->url) : '') ."</td></tr>";
    $output .= ' <tr><th>'. t('Date') .'</th><td>'. format_date($access->timestamp, 'large') .'</td></tr>';
195
    $output .= ' <tr><th>'. t('User') .'</th><td>'. theme('username', $access) .'</td></tr>';
196
    $output .= ' <tr><th>'. t('Hostname') .'</th><td>'. check_plain($access->hostname) .'</td></tr>';
197
    $output .= '</table>';
Dries's avatar
 
Dries committed
198
    return $output;
199 200 201
  }
  else {
    drupal_not_found();
202
  }
203
}
204

205
function statistics_node_tracker() {
206
  if ($node = node_load(arg(1))) {
207 208 209 210 211 212 213

    $header = array(
        array('data' => t('Time'), 'field' => 'a.timestamp', 'sort' => 'desc'),
        array('data' => t('Referrer'), 'field' => 'a.url'),
        array('data' => t('User'), 'field' => 'u.name'),
        array('data' => t('Operations')));

Steven Wittens's avatar
Steven Wittens committed
214
    $result = pager_query('SELECT a.aid, a.timestamp, a.url, a.uid, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE a.path LIKE \'node/%d%%\'' . tablesort_sql($header), 30, 0, NULL, $node->nid);
215 216
    while ($log = db_fetch_object($result)) {
      $rows[] = array(
217
        array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
218
        _statistics_link($log->url),
219
        theme('username', $log),
220 221
        l(t('details'), "admin/logs/access/$log->aid"));
    }
Dries's avatar
 
Dries committed
222

223
    drupal_set_title(check_plain($node->title));
224
    $output = theme('table', $header, $rows);
225
    $output .= theme('pager', NULL, 30, 0);
226
    return $output;
227 228 229 230 231
  }
  else {
    drupal_not_found();
  }
}
232

233 234
function statistics_user_tracker() {
  if ($account = user_load(array('uid' => arg(1)))) {
Dries's avatar
 
Dries committed
235

236 237 238 239
    $header = array(
        array('data' => t('Timestamp'), 'field' => 'timestamp', 'sort' => 'desc'),
        array('data' => t('Page'), 'field' => 'path'),
        array('data' => t('Operations')));
240

241
    $result = pager_query('SELECT aid, timestamp, path, title FROM {accesslog} WHERE uid = %d' . tablesort_sql($header), 30, 0, NULL, $account->uid);
242 243
    while ($log = db_fetch_object($result)) {
      $rows[] = array(
244
        array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
Dries's avatar
 
Dries committed
245
        _statistics_format_item($log->title, $log->path),
246 247
        l(t('details'), "admin/logs/access/$log->aid"));
    }
248

249
    drupal_set_title($account->name);
250
    $output = theme('table', $header, $rows);
251
    $output .= theme('pager', NULL, 30, 0);
252
    return $output;
253 254 255 256
  }
  else {
    drupal_not_found();
  }
Dries's avatar
 
Dries committed
257 258 259
}

/**
Dries's avatar
 
Dries committed
260
 * Menu callback; presents the "recent hits" page.
Dries's avatar
 
Dries committed
261
 */
262
function statistics_recent_hits() {
Dries's avatar
 
Dries committed
263
  $header = array(
264 265 266
    array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
    array('data' => t('Page'), 'field' => 'a.path'),
    array('data' => t('User'), 'field' => 'u.name'),
Dries's avatar
 
Dries committed
267
    array('data' => t('Operations'))
Dries's avatar
 
Dries committed
268 269
  );

270 271 272 273 274
  $sql = 'SELECT a.aid, a.path, a.title, a.uid, u.name, a.timestamp FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid' . tablesort_sql($header);

  $result = pager_query($sql, 30);
  while ($log = db_fetch_object($result)) {
    $rows[] = array(
275
      array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
Dries's avatar
 
Dries committed
276
      _statistics_format_item($log->title, $log->path),
277
      theme('username', $log),
278
      l(t('details'), "admin/logs/access/$log->aid"));
Dries's avatar
 
Dries committed
279
  }
280

281
  $output = theme('table', $header, $rows);
282
  $output .= theme('pager', NULL, 30, 0);
283
  return $output;
Dries's avatar
 
Dries committed
284 285 286
}

/**
Dries's avatar
 
Dries committed
287
 * Menu callback; presents the "top pages" page.
Dries's avatar
 
Dries committed
288
 */
289
function statistics_top_pages() {
290
  $sql = "SELECT COUNT(path) AS hits, path, title, AVG(timer) AS average_time, SUM(timer) AS total_time FROM {accesslog} GROUP BY path, title";
291
  $sql_cnt = "SELECT COUNT(DISTINCT(path)) FROM {accesslog}";
Dries's avatar
 
Dries committed
292 293

  $header = array(
Dries's avatar
 
Dries committed
294
    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
Dries's avatar
 
Dries committed
295
    array('data' => t('Page'), 'field' => 'path'),
296 297
    array('data' => t('Average page generation time'), 'field' => 'average_time'),
    array('data' => t('Total page generation time'), 'field' => 'total_time')
Dries's avatar
 
Dries committed
298 299
  );
  $sql .= tablesort_sql($header);
300
  $result = pager_query($sql, 30, 0, $sql_cnt);
Dries's avatar
 
Dries committed
301

302
  while ($page = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
303
    $rows[] = array($page->hits, _statistics_format_item($page->title, $page->path), t('%time ms', array('%time' => round($page->average_time))), format_interval(round($page->total_time / 1000)));
Dries's avatar
 
Dries committed
304
  }
Dries's avatar
 
Dries committed
305

306
  drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
307
  $output = theme('table', $header, $rows);
308
  $output .= theme('pager', NULL, 30, 0);
309
  return $output;
Dries's avatar
 
Dries committed
310 311 312
}

/**
313
 * Menu callback; presents the "top visitors" page.
Dries's avatar
 
Dries committed
314
 */
315
function statistics_top_visitors() {
Dries's avatar
 
Dries committed
316 317

  $header = array(
Dries's avatar
 
Dries committed
318
    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
319 320
    array('data' => t('Visitor'), 'field' => 'u.name'),
    array('data' => t('Total page generation time'), 'field' => 'total'),
Dries's avatar
 
Dries committed
321
    array('data' => t('Operations'))
Dries's avatar
 
Dries committed
322 323
  );

324
  $sql = "SELECT COUNT(a.uid) AS hits, a.uid, u.name, a.hostname, SUM(a.timer) AS total, ac.aid FROM {accesslog} a LEFT JOIN {access} ac ON ac.type = 'host' AND LOWER(a.hostname) LIKE (ac.mask) LEFT JOIN {users} u ON a.uid = u.uid GROUP BY a.hostname, a.uid, u.name, ac.aid". tablesort_sql($header);
325 326 327 328
  $sql_cnt = "SELECT COUNT(DISTINCT(uid)) FROM {accesslog}";
  $result = pager_query($sql, 30, 0, $sql_cnt);

  while ($account = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
329 330
    $qs = drupal_get_destination();
    $ban_link = $account->aid ? l(t('unban'), "admin/access/rules/delete/$account->aid", array(), $qs) : l(t('ban'), "admin/access/rules/add/$account->hostname/host", array(), $qs);
331
    $rows[] = array($account->hits, ($account->uid ? theme('username', $account) : $account->hostname), format_interval(round($account->total / 1000)), $ban_link);
Dries's avatar
 
Dries committed
332
  }
333

334
  drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
335
  $output = theme('table', $header, $rows);
336
  $output .= theme('pager', NULL, 30, 0);
337
  return $output;
338 339
}

Dries's avatar
 
Dries committed
340
/**
Dries's avatar
 
Dries committed
341
 * Menu callback; presents the "referrer" page.
Dries's avatar
 
Dries committed
342
 */
343
function statistics_top_referrers() {
344 345
  $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE '%%%s%%' AND url <> '' GROUP BY url";
  $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE '%%%s%%'";
346
  drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))));
347

Dries's avatar
 
Dries committed
348
  $header = array(
Dries's avatar
 
Dries committed
349
    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
Dries's avatar
 
Dries committed
350 351
    array('data' => t('Url'), 'field' => 'url'),
    array('data' => t('Last visit'), 'field' => 'last'),
Dries's avatar
 
Dries committed
352
  );
Dries's avatar
 
Dries committed
353

354
  $query .= tablesort_sql($header);
355
  $result = pager_query($query, 30, 0, $query_cnt, $_SERVER['HTTP_HOST']);
356

Dries's avatar
 
Dries committed
357
  while ($referrer = db_fetch_object($result)) {
358
    $rows[] = array($referrer->hits, _statistics_link($referrer->url), t('%time ago', array('%time' => format_interval(time() - $referrer->last))));
Dries's avatar
 
Dries committed
359
  }
360

361
  $output = theme('table', $header, $rows);
362
  $output .= theme('pager', NULL, 30, 0);
363
  return $output;
364 365
}

Dries's avatar
Dries committed
366 367
function statistics_access_logging_settings() {
  // Access log settings:
368
  $options = array('1' => t('Enabled'), '0' => t('Disabled'));
Dries's avatar
Dries committed
369 370 371 372 373 374 375 376 377
  $form['access'] = array(
    '#type' => 'fieldset',
    '#title' => t('Access log settings'));
  $form['access']['statistics_enable_access_log'] = array(
    '#type' => 'radios',
    '#title' => t('Enable access log'),
    '#default_value' =>  variable_get('statistics_enable_access_log', 0),
    '#options' => $options,
    '#description' => t('Log each page access. Required for referrer statistics.'));
Dries's avatar
 
Dries committed
378
  $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
Dries's avatar
Dries committed
379 380 381 382 383 384
  $form['access']['statistics_flush_accesslog_timer'] = array(
    '#type' => 'select',
    '#title' => t('Discard access logs older than'),
    '#default_value'   => variable_get('statistics_flush_accesslog_timer', 259200),
    '#options' => $period,
    '#description' => t('Older access log entries (including referrer statistics) will be automatically discarded. Requires crontab.'));
385

Dries's avatar
 
Dries committed
386
  // count content views settings
Dries's avatar
Dries committed
387 388 389 390 391 392 393 394 395 396 397
  $form['content'] = array(
    '#type' => 'fieldset',
    '#title' => t('Content viewing counter settings'));
  $form['content']['statistics_count_content_views'] = array(
    '#type' => 'radios',
    '#title' => t('Count content views'),
    '#default_value' => variable_get('statistics_count_content_views', 0),
    '#options' => $options,
    '#description' => t('Increment a counter each time content is viewed.'));

  return system_settings_form('statistics_access_logging_settings', $form);
398 399
}

Dries's avatar
 
Dries committed
400 401 402
/**
 * Implementation of hook_cron().
 */
403
function statistics_cron() {
Dries's avatar
 
Dries committed
404
  $statistics_timestamp = variable_get('statistics_day_timestamp', '');
405 406 407

  if ((time() - $statistics_timestamp) >= 86400) {
    /* reset day counts */
Dries's avatar
 
Dries committed
408 409
    db_query('UPDATE {node_counter} SET daycount = 0');
    variable_set('statistics_day_timestamp', time());
410 411 412
  }

  /* clean expired access logs */
Dries's avatar
 
Dries committed
413
  db_query('DELETE FROM {accesslog} WHERE timestamp < %d', time() - variable_get('statistics_flush_accesslog_timer', 259200));
414 415
}

Dries's avatar
 
Dries committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
/**
 * 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.
 */
432
function statistics_title_list($dbfield, $dbrows) {
433
  return db_query_range(db_rewrite_sql("SELECT n.nid, n.title, u.uid, u.name FROM {node} n INNER JOIN {node_counter} s ON n.nid = s.nid INNER JOIN {users} u ON n.uid = u.uid WHERE %s <> '0' AND n.status = 1 ORDER BY %s DESC"), 's.'. $dbfield, 's.'. $dbfield, 0, $dbrows);
434 435
}

Dries's avatar
 
Dries committed
436

Dries's avatar
 
Dries committed
437 438 439 440 441 442 443 444 445 446 447 448 449
/**
 * 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.
 */
450 451 452 453
function statistics_get($nid) {

  if ($nid > 0) {
    /* retrieves an array with both totalcount and daycount */
Dries's avatar
 
Dries committed
454
    $statistics = db_fetch_array(db_query('SELECT totalcount, daycount, timestamp FROM {node_counter} WHERE nid = %d', $nid));
455 456 457 458 459
  }

  return $statistics;
}

Dries's avatar
 
Dries committed
460 461 462
/**
 * Implementation of hook_block().
 */
463 464 465 466 467 468 469 470 471 472 473
function statistics_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      if (variable_get('statistics_count_content_views', 0)) {
        $blocks[0]['info'] = t('Popular content');
      }
      return $blocks;

    case 'configure':
      // 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));
474 475 476
      $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.'));
477
      return $form;
478 479 480 481 482 483 484 485 486

    case 'save':
      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']);
      break;

    case 'view':
      if (user_access('access content')) {
Dries's avatar
 
Dries committed
487 488
        $content = array();

Dries's avatar
 
Dries committed
489
        $daytop = variable_get('statistics_block_top_day_num', 0);
490 491
        if ($daytop && ($result = statistics_title_list('daycount', $daytop)) && db_num_rows($result)) {
          $content[] = node_title_list($result, t("Today's:"));
Dries's avatar
 
Dries committed
492 493
        }

Dries's avatar
 
Dries committed
494
        $alltimetop = variable_get('statistics_block_top_all_num', 0);
495 496
        if ($alltimetop && ($result = statistics_title_list('totalcount', $alltimetop)) && db_num_rows($result)) {
          $content[] = node_title_list($result, t('All time:'));
Dries's avatar
 
Dries committed
497 498
        }

Dries's avatar
 
Dries committed
499
        $lasttop = variable_get('statistics_block_top_last_num', 0);
500 501
        if ($lasttop && ($result = statistics_title_list('timestamp', $lasttop)) && db_num_rows($result)) {
          $content[] = node_title_list($result, t('Last viewed:'));
Dries's avatar
 
Dries committed
502 503
        }

504
        if (count($content)) {
505
          $block['content'] = implode('<br />', $content);
506 507 508
          $block['subject'] = t('Popular content');
          return $block;
        }
509
      }
510 511 512
  }
}

Dries's avatar
 
Dries committed
513 514
/**
 * It is possible to adjust the width of columns generated by the
Dries's avatar
Dries committed
515
 * statistics module.
Dries's avatar
 
Dries committed
516
 */
517 518 519 520
function _statistics_link($path, $width = 35) {
  $title = drupal_get_path_alias($path);
  $title = truncate_utf8($title, $width, FALSE, TRUE);
  return l($title, $path);
Dries's avatar
Dries committed
521 522
}

523 524
function _statistics_format_item($title, $path) {
  $path = ($path ? $path : '/');
Dries's avatar
Dries committed
525
  $output  = ($title ? "$title<br />" : '');
526
  $output .= _statistics_link($path);
Dries's avatar
Dries committed
527
  return $output;
Dries's avatar
 
Dries committed
528 529
}

Dries's avatar
 
Dries committed
530 531 532
/**
 * Implementation of hook_nodeapi().
 */
533 534
function statistics_nodeapi(&$node, $op, $arg = 0) {
  switch ($op) {
Dries's avatar
 
Dries committed
535
    case 'delete':
536 537
      // clean up statistics table when node is deleted
      db_query('DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
538 539 540
  }
}

541