Commit 192986c6 authored by Dries's avatar Dries
Browse files

Issue #1446956 by timmillwood, iamEAP: Remove the accesslog from statistics.

parent 9e565e58
......@@ -22,7 +22,7 @@ class StatisticsAdminTest extends WebTestBase {
public static $modules = array('node', 'statistics');
/**
* A user that has permission to administer and access statistics.
* A user that has permission to administer statistics.
*
* @var object|FALSE
*
......@@ -31,7 +31,7 @@ class StatisticsAdminTest extends WebTestBase {
protected $privileged_user;
/**
* A page node for which to check access statistics.
* A page node for which to check content statistics.
*
* @var object
*/
......@@ -52,7 +52,7 @@ function setUp() {
if ($this->profile != 'standard') {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
}
$this->privileged_user = $this->drupalCreateUser(array('access statistics', 'administer statistics', 'view post access counter', 'create page content'));
$this->privileged_user = $this->drupalCreateUser(array('administer statistics', 'view post access counter', 'create page content'));
$this->drupalLogin($this->privileged_user);
$this->test_node = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->privileged_user->uid));
}
......@@ -62,18 +62,12 @@ function setUp() {
*/
function testStatisticsSettings() {
$config = config('statistics.settings');
$this->assertFalse($config->get('access_log.enabled'), 'Access log is disabled by default.');
$this->assertFalse($config->get('count_content_views'), 'Count content view log is disabled by default.');
$this->drupalGet('admin/reports/pages');
$this->assertRaw(t('No statistics available.'), 'Verifying text shown when no statistics is available.');
// Enable access log and counter on content view.
$edit['statistics_enable_access_log'] = 1;
// Enable counter on content view.
$edit['statistics_count_content_views'] = 1;
$this->drupalPost('admin/config/system/statistics', $edit, t('Save configuration'));
$config = config('statistics.settings');
$this->assertTrue($config->get('access_log.enabled'), 'Access log is enabled.');
$this->assertTrue($config->get('count_content_views'), 'Count content view log is enabled.');
// Hit the node.
......@@ -86,9 +80,6 @@ function testStatisticsSettings() {
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
$this->drupalGet('admin/reports/pages');
$this->assertText('node/1', 'Test node found.');
// Hit the node again (the counter is incremented after the hit, so
// "1 view" will actually be shown when the node is hit the second time).
$this->drupalGet('node/' . $this->test_node->nid);
......@@ -132,45 +123,12 @@ function testDeleteNode() {
$this->assertFalse($result, 'Verifying that the node counter is deleted.');
}
/**
* Tests that accesslog reflects when a user is deleted.
*/
function testDeleteUser() {
config('statistics.settings')->set('access_log.enabled', 1)->save();
config('user.settings')->set('cancel_method', 'user_cancel_delete')->save();
$this->drupalLogout($this->privileged_user);
$account = $this->drupalCreateUser(array('access content', 'cancel account'));
$this->drupalLogin($account);
$this->drupalGet('node/' . $this->test_node->nid);
$account = user_load($account->uid, TRUE);
$this->drupalGet('user/' . $account->uid . '/edit');
$this->drupalPost(NULL, NULL, t('Cancel account'));
$timestamp = time();
$this->drupalPost(NULL, NULL, t('Cancel account'));
// Confirm account cancellation request.
$mails = $this->drupalGetMails();
$mail = end($mails);
preg_match('@http.+?(user/\d+/cancel/confirm/\d+/[^\s]+)@', $mail['body'], $matches);
$path = $matches[1];
$this->drupalGet($path);
$this->assertFalse(user_load($account->uid, TRUE), 'User is not found in the database.');
$this->drupalGet('admin/reports/visitors');
$this->assertNoText($account->name, 'Did not find user in visitor statistics.');
}
/**
* Tests that cron clears day counts and expired access logs.
*/
function testExpiredLogs() {
config('statistics.settings')
->set('access_log.enabled', 1)
->set('count_content_views', 1)
->set('access_log.max_lifetime', 1)
->save();
state()->set('statistics.day_timestamp', 8640000);
......@@ -186,9 +144,6 @@ function testExpiredLogs() {
drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
$this->assertText('1 view', 'Node is viewed once.');
$this->drupalGet('admin/reports/pages');
$this->assertText('node/' . $this->test_node->nid, 'Hit URL found.');
// statistics_cron() will subtract
// statistics.settings:accesslog.max_lifetime config from REQUEST_TIME in
// the delete query, so wait two secs here to make sure the access log will
......
<?php
/**
* @file
* Definition of Drupal\statistics\Tests\StatisticsBlockVisitorsTest.
*/
namespace Drupal\statistics\Tests;
/**
* Tests that the visitor blocking functionality works.
*/
class StatisticsBlockVisitorsTest extends StatisticsTestBase {
public static function getInfo() {
return array(
'name' => 'Top visitor banning',
'description' => 'Tests banning of IP addresses via the top visitors report.',
'group' => 'Statistics'
);
}
/**
* Blocks an IP address via the top visitors report and then unblocks it.
*/
function testIPAddressBlocking() {
// IP address for testing.
$test_ip_address = '192.168.1.1';
// Verify the IP address from accesslog appears on the top visitors page
// and that a 'ban IP address' link is displayed.
$this->drupalLogin($this->blocking_user);
$this->drupalGet('admin/reports/visitors');
$this->assertText($test_ip_address, 'IP address found.');
$this->assertText(t('ban IP address'), 'Ban IP link displayed');
// Block the IP address.
$this->clickLink('ban IP address');
$this->assertText(t('IP address bans'), 'IP banning page displayed.');
$edit = array();
$edit['ip'] = $test_ip_address;
$this->drupalPost('admin/config/people/ban', $edit, t('Add'));
$ip = db_query("SELECT iid from {ban_ip} WHERE ip = :ip", array(':ip' => $edit['ip']))->fetchField();
$this->assertNotEqual($ip, FALSE, 'IP address found in database');
$this->assertRaw(t('The IP address %ip has been banned.', array('%ip' => $edit['ip'])), 'IP address was banned.');
// Verify that the block/unblock link on the top visitors page has been
// altered.
$this->drupalGet('admin/reports/visitors');
$this->assertText(t('unban IP address'), 'Unban IP address link displayed');
// Unblock the IP address.
$this->clickLink('unban IP address');
$this->assertRaw(t('Are you sure you want to unblock %ip?', array('%ip' => $test_ip_address)), 'IP address deletion confirmation found.');
$edit = array();
$this->drupalPost('admin/config/people/ban/delete/1', NULL, t('Delete'));
$this->assertRaw(t('The IP address %ip was deleted.', array('%ip' => $test_ip_address)), 'IP address deleted.');
}
}
......@@ -53,12 +53,10 @@ function setUp() {
// Enable access logging.
config('statistics.settings')
->set('access_log.enabled', 1)
->set('count_content_views', 1)
->save();
// Clear the logs.
db_truncate('accesslog');
db_truncate('node_counter');
}
......@@ -82,9 +80,6 @@ function testLogging() {
$stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
$this->assertIdentical($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Testing an uncached page.');
$log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
$this->assertTrue(is_array($log) && count($log) == 1, 'Page request was logged.');
$this->assertEqual(array_intersect_key($log[0], $expected), $expected);
$node_counter = statistics_get($this->node->nid);
$this->assertIdentical($node_counter['totalcount'], '1');
......@@ -93,9 +88,6 @@ function testLogging() {
// Manually calling statistics.php, simulating ajax behavior.
drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
$this->assertIdentical($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Testing a cached page.');
$log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
$this->assertTrue(is_array($log) && count($log) == 2, 'Page request was logged.');
$this->assertEqual(array_intersect_key($log[1], $expected), $expected);
$node_counter = statistics_get($this->node->nid);
$this->assertIdentical($node_counter['totalcount'], '2');
......@@ -104,37 +96,8 @@ function testLogging() {
$this->drupalGet($path);
// Manually calling statistics.php, simulating ajax behavior.
drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
$log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
// Check the 6th item since login and account pages are also logged
$this->assertTrue(is_array($log) && count($log) == 6, 'Page request was logged.');
$this->assertEqual(array_intersect_key($log[5], $expected), $expected);
$node_counter = statistics_get($this->node->nid);
$this->assertIdentical($node_counter['totalcount'], '3');
// Visit edit page to generate a title greater than 255.
$path = 'node/' . $this->node->nid . '/edit';
$expected = array(
'title' => truncate_utf8(t('Edit Basic page') . ' ' . $this->node->label(), 255),
'path' => $path,
);
$this->drupalGet($path);
$log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
$this->assertTrue(is_array($log) && count($log) == 7, 'Page request was logged.');
$this->assertEqual(array_intersect_key($log[6], $expected), $expected);
// Create a path longer than 255 characters. Drupal's .htaccess file
// instructs Apache to test paths against the file system before routing to
// index.php. Many file systems restrict file names to 255 characters
// (http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits), and
// Apache returns a 403 when testing longer file names, but the total path
// length is not restricted.
$long_path = $this->randomName(127) . '/' . $this->randomName(128);
// Test that the long path is properly truncated when logged.
$this->drupalGet($long_path);
$log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
$this->assertTrue(is_array($log) && count($log) == 8, 'Page request was logged for a path over 255 characters.');
$this->assertEqual($log[7]['path'], truncate_utf8($long_path, 255));
}
}
......@@ -15,58 +15,11 @@ class StatisticsReportsTest extends StatisticsTestBase {
public static function getInfo() {
return array(
'name' => 'Statistics reports tests',
'description' => 'Tests display of statistics report pages and access logging.',
'description' => 'Tests display of statistics report blocks.',
'group' => 'Statistics'
);
}
/**
* Verifies that 'Recent hits' renders properly and displays the added hit.
*/
function testRecentHits() {
$this->drupalGet('admin/reports/hits');
$this->assertText('test', 'Hit title found.');
$this->assertText('node/1', 'Hit URL found.');
$this->assertText('Anonymous', 'Hit user found.');
}
/**
* Verifies that 'Top pages' renders properly and displays the added hit.
*/
function testTopPages() {
$this->drupalGet('admin/reports/pages');
$this->assertText('test', 'Hit title found.');
$this->assertText('node/1', 'Hit URL found.');
}
/**
* Verifies that 'Top referrers' renders properly and displays the added hit.
*/
function testTopReferrers() {
$this->drupalGet('admin/reports/referrers');
$this->assertText('http://example.com', 'Hit referrer found.');
}
/**
* Verifies that 'Details' page renders properly and displays the added hit.
*/
function testDetails() {
$this->drupalGet('admin/reports/access/1');
$this->assertText('test', 'Hit title found.');
$this->assertText('node/1', 'Hit URL found.');
$this->assertText('Anonymous', 'Hit user found.');
}
/**
* Verifies that access logging is working and is reported correctly.
*/
function testAccessLogging() {
$this->drupalGet('admin/reports/referrers');
$this->drupalGet('admin/reports/hits');
$this->assertText('Top referrers in the past 3 days', 'Hit title found.');
$this->assertText('admin/reports/referrers', 'Hit URL found.');
}
/**
* Tests the "popular content" block.
*/
......
......@@ -33,7 +33,6 @@ function setUp() {
$this->blocking_user = $this->drupalCreateUser(array(
'access administration pages',
'access site reports',
'access statistics',
'ban IP addresses',
'administer blocks',
'administer statistics',
......@@ -41,23 +40,9 @@ function setUp() {
));
$this->drupalLogin($this->blocking_user);
// Enable access logging.
// Enable logging.
config('statistics.settings')
->set('access_log.enabled', 1)
->set('count_content_views', 1)
->save();
// Insert dummy access by anonymous user into access log.
db_insert('accesslog')
->fields(array(
'title' => 'test',
'path' => 'node/1',
'url' => 'http://example.com',
'hostname' => '192.168.1.1',
'uid' => 0,
'sid' => 10,
'timer' => 10,
'timestamp' => REQUEST_TIME,
))
->execute();
}
}
......@@ -7,320 +7,6 @@
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Page callback: Displays the "recent hits" page.
*
* This displays the pages with recent hits in a given time interval that
* haven't been flushed yet. The flush interval is set on the statistics
* settings form, but is dependent on cron running.
*
* @return array
* A render array containing information about the most recent hits.
*/
function statistics_recent_hits() {
$header = array(
array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'a.path'),
array('data' => t('User'), 'field' => 'u.name'),
t('Operations'),
);
$query = db_select('accesslog', 'a', array('target' => 'slave'))
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
$query->join('users', 'u', 'a.uid = u.uid');
$query
->fields('a', array('aid', 'timestamp', 'path', 'title', 'uid'))
->fields('u', array('name'))
->limit(30)
->orderByHeader($header);
$result = $query->execute();
$rows = array();
foreach ($result as $log) {
$row = array();
$row[] = array('data' => format_date($log->timestamp, 'short'), 'class' => array('nowrap'));
$row[] = _statistics_format_item($log->title, $log->path);
$row[] = theme('username', array('account' => $log));
$links = array();
$links['details'] = array(
'title' => t('details'),
'href' => "admin/reports/access/$log->aid",
);
$row[] = array(
'data' => array(
'#type' => 'operations',
'#links' => $links,
),
);
$rows[] = $row;
}
$build['statistics_table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No statistics available.'),
);
$build['statistics_pager'] = array('#theme' => 'pager');
return $build;
}
/**
* Page callback: Displays statistics for the "top pages" (most accesses).
*
* This displays the pages with the most hits (the "top pages") within a given
* time period that haven't been flushed yet. The flush interval is set on the
* statistics settings form, but is dependent on cron running.
*
* @return array
* A render array containing information about the the top pages.
*/
function statistics_top_pages() {
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Page'), 'field' => 'path'),
array('data' => t('Average page generation time'), 'field' => 'average_time'),
array('data' => t('Total page generation time'), 'field' => 'total_time')
);
$query = db_select('accesslog', 'a', array('target' => 'slave'))
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
$query->addExpression('COUNT(path)', 'hits');
// MAX(title) avoids having empty node titles which otherwise causes
// duplicates in the top pages list.
$query->addExpression('MAX(title)', 'title');
$query->addExpression('AVG(timer)', 'average_time');
$query->addExpression('SUM(timer)', 'total_time');
$query
->fields('a', array('path'))
->groupBy('path')
->limit(30)
->orderByHeader($header);
$count_query = db_select('accesslog', 'a', array('target' => 'slave'));
$count_query->addExpression('COUNT(DISTINCT path)');
$query->setCountQuery($count_query);
$result = $query->execute();
$rows = array();
foreach ($result as $page) {
$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)));
}
drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(config('statistics.settings')->get('access_log.max_lifetime')))), PASS_THROUGH);
$build['statistics_top_pages_table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No statistics available.'),
);
$build['statistics_top_pages_pager'] = array('#theme' => 'pager');
return $build;
}
/**
* Page callback: Displays the "top visitors" page.
*
* This displays the pages with the top number of visitors in a given time
* interval that haven't been flushed yet. The flush interval is set on the
* statistics settings form, but is dependent on cron running.
*
* @return array
* A render array containing the top visitors information.
*/
function statistics_top_visitors() {
$ban_exists = module_exists('ban');
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Visitor'), 'field' => 'u.name'),
array('data' => t('Total page generation time'), 'field' => 'total'),
$ban_exists && user_access('Ban IP addresses') ? t('Operations') : '',
);
$query = db_select('accesslog', 'a', array('target' => 'slave'))
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
if ($ban_exists) {
$query->leftJoin('ban_ip', 'b', 'a.hostname = b.ip');
}
$query->leftJoin('users', 'u', 'a.uid = u.uid');
$query->addExpression('COUNT(a.uid)', 'hits');
$query->addExpression('SUM(a.timer)', 'total');
$query
->fields('a', array('uid', 'hostname'))
->fields('u', array('name'))
->groupBy('a.hostname')
->groupBy('a.uid')
->groupBy('u.name')
->limit(30);
if ($ban_exists) {
$query
->fields('b', array('iid'))
->groupBy('b.iid');
}
$query->orderByHeader($header);
$uniques_query = db_select('accesslog')->distinct();
$uniques_query->fields('accesslog', array('uid', 'hostname'));
$count_query = db_select($uniques_query);
$count_query->addExpression('COUNT(*)');
$query->setCountQuery($count_query);
$result = $query->execute();
$rows = array();
$destination = drupal_get_destination();
foreach ($result as $account) {
$links = array();
if ($ban_exists && user_access('ban IP addresses') && !$account->uid) {
if ($account->iid) {
$links['unban'] = array(
'title' => t('unban IP address'),
'href' => "admin/config/people/ban/delete/$account->iid",
'query' => $destination,
);
}
else {
$links['ban'] = array(
'title' => t('ban IP address'),
'href' => "admin/config/people/ban/$account->hostname",
'query' => $destination,
);
}
}
$row = array();
$row[] = $account->hits;
$row[] = ($account->uid ? theme('username', array('account' => $account)) : $account->hostname);
$row[] = format_interval(round($account->total / 1000));
$row[] = array(
'data' => array(
'#type' => 'operations',
'#links' => $links,
),
);
$rows[] = $row;
}
drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(config('statistics.settings')->get('access_log.max_lifetime')))), PASS_THROUGH);
$build['statistics_top_visitors_table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No statistics available.'),
);
$build['statistics_top_visitors_pager'] = array('#theme' => 'pager');
return $build;
}
/**
* Page callback: Displays the "top referrers" in the access logs.
*
* This displays the pages with the top referrers in a given time interval that
* haven't been flushed yet. The flush interval is set on the statistics
* settings form, but is dependent on cron running.
*
* @return array
* A render array containing the top referrers information.
*/
function statistics_top_referrers() {
drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(config('statistics.settings')->get('access_log.max_lifetime')))), PASS_THROUGH);
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Url'), 'field' => 'url'),
array('data' => t('Last visit'), 'field' => 'last'),
);
$query = db_select('accesslog', 'a')
->extend('Drupal\Core\Database\Query\PagerSelectExtender')
->extend('Drupal\Core\Database\Query\TableSortExtender');
$query->addExpression('COUNT(url)', 'hits');
$query->addExpression('MAX(timestamp)', 'last');
$query
->fields('a', array('url'))
->condition('url', '%' . $_SERVER['HTTP_HOST'] . '%', 'NOT LIKE')
->condition('url', '', '<>')
->groupBy('url')
->limit(30)
->orderByHeader($header);
$count_query = db_select('accesslog', 'a', array('target' => 'slave'));
$count_query->addExpression('COUNT(DISTINCT url)');
$count_query