From 52d7970bad92e6fc35b217345cf9fd1f242e932b Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 26 Apr 2012 13:05:27 +0900
Subject: [PATCH] Issue #1209532 by timmillwood: Count node views via AJAX in
 the statistics module.

---
 core/modules/search/search.test           |  8 +++-
 core/modules/statistics/statistics.js     | 12 ++++++
 core/modules/statistics/statistics.module | 30 ++++++--------
 core/modules/statistics/statistics.php    | 33 +++++++++++++++
 core/modules/statistics/statistics.test   | 49 +++++++++++++++++++++++
 5 files changed, 114 insertions(+), 18 deletions(-)
 create mode 100644 core/modules/statistics/statistics.js
 create mode 100644 core/modules/statistics/statistics.php

diff --git a/core/modules/search/search.test b/core/modules/search/search.test
index b6f5ae8e0447..b01fcf7c46fb 100644
--- a/core/modules/search/search.test
+++ b/core/modules/search/search.test
@@ -450,8 +450,14 @@ class SearchRankingTestCase extends SearchWebTestCase {
     variable_set('statistics_count_content_views', 1);
 
     // Then View one of the nodes a bunch of times.
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $nodes['views'][1]->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $stats_path = $base_url . '/' . drupal_get_path('module', 'statistics'). '/statistics.php';
     for ($i = 0; $i < 5; $i ++) {
-      $this->drupalGet('node/' . $nodes['views'][1]->nid);
+      drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
     }
 
     // Test each of the possible rankings.
diff --git a/core/modules/statistics/statistics.js b/core/modules/statistics/statistics.js
new file mode 100644
index 000000000000..65793d36e646
--- /dev/null
+++ b/core/modules/statistics/statistics.js
@@ -0,0 +1,12 @@
+(function ($) {
+  $(document).ready(function() {
+    var nid = Drupal.settings.statistics.nid;
+    var basePath = Drupal.settings.basePath
+    $.ajax({
+      type: "POST",
+      cache: false,
+      url: basePath+"core/modules/statistics/statistics.php",
+      data: "nid="+nid
+    });
+  });
+})(jQuery);
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index d9e9b49a9779..38cd0203ba3c 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -41,7 +41,6 @@ function statistics_help($path, $arg) {
   }
 }
 
-
 /**
  * Implements hook_exit().
  *
@@ -57,22 +56,6 @@ function statistics_exit() {
   // in which case we need to bootstrap to the session phase anyway.
   drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
 
-  if (variable_get('statistics_count_content_views', 0)) {
-    // We are counting content views.
-    if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == NULL) {
-      // 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)) {
     drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
 
@@ -115,6 +98,19 @@ function statistics_permission() {
  * Implements hook_node_view().
  */
 function statistics_node_view($node, $view_mode) {
+  if (!empty($node->nid) && $view_mode == 'full') {
+    $node->content['#attached']['js'] = array(
+      drupal_get_path('module', 'statistics') . '/statistics.js' => array(
+        'scope' => 'footer'
+      ),
+    );
+    $settings = array('nid' => $node->nid);
+    $node->content['#attached']['js'][] = array(
+      'data' => array('statistics' => $settings),
+      'type' => 'setting',
+    );
+  }
+
   if ($view_mode != 'rss') {
     if (user_access('view post access counter')) {
       $statistics = statistics_get($node->nid);
diff --git a/core/modules/statistics/statistics.php b/core/modules/statistics/statistics.php
new file mode 100644
index 000000000000..040dc19f8f0b
--- /dev/null
+++ b/core/modules/statistics/statistics.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Handles counts of node views via AJAX with minimal bootstrap.
+ */
+
+// Change the directory to the Drupal root.
+chdir('../../..');
+
+/**
+* Root directory of Drupal installation.
+*/
+define('DRUPAL_ROOT', getcwd());
+
+include_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
+drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
+if (variable_get('statistics_count_content_views', 0)) {
+  $nid = $_POST['nid'];
+  if (is_numeric($nid)) {
+    db_merge('node_counter')
+      ->key(array('nid' => $nid))
+      ->fields(array(
+        'daycount' => 1,
+        'totalcount' => 1,
+        'timestamp' => REQUEST_TIME,
+      ))
+      ->expression('daycount', 'daycount + 1')
+      ->expression('totalcount', 'totalcount + 1')
+      ->execute();
+  }
+}
+
diff --git a/core/modules/statistics/statistics.test b/core/modules/statistics/statistics.test
index d19fd92444a9..6f19e37f8bfe 100644
--- a/core/modules/statistics/statistics.test
+++ b/core/modules/statistics/statistics.test
@@ -104,6 +104,13 @@ class StatisticsLoggingTestCase extends DrupalWebTestCase {
 
     // Verify logging of an uncached page.
     $this->drupalGet($path);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $this->node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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', t('Testing an uncached page.'));
     $log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
     $this->assertTrue(is_array($log) && count($log) == 1, t('Page request was logged.'));
@@ -113,6 +120,8 @@ class StatisticsLoggingTestCase extends DrupalWebTestCase {
 
     // Verify logging of a cached page.
     $this->drupalGet($path);
+    // 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', t('Testing a cached page.'));
     $log = db_query('SELECT * FROM {accesslog}')->fetchAll(PDO::FETCH_ASSOC);
     $this->assertTrue(is_array($log) && count($log) == 2, t('Page request was logged.'));
@@ -123,6 +132,8 @@ class StatisticsLoggingTestCase extends DrupalWebTestCase {
     // Test logging from authenticated users
     $this->drupalLogin($this->auth_user);
     $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, t('Page request was logged.'));
@@ -219,6 +230,13 @@ class StatisticsReportsTestCase extends StatisticsTestCase {
     // Visit a node to have something show up in the block.
     $node = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->blocking_user->uid));
     $this->drupalGet('node/' . $node->nid);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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));
 
     // Configure and save the block.
     $block = block_load('statistics', 'popular');
@@ -353,6 +371,13 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
 
     // Hit the node.
     $this->drupalGet('node/' . $this->test_node->nid);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $this->test_node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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', t('Test node found.'));
@@ -360,9 +385,11 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
     // 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);
+    drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
     $this->assertText('1 view', t('Node is viewed once.'));
 
     $this->drupalGet('node/' . $this->test_node->nid);
+    drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
     $this->assertText('2 views', t('Node is viewed 2 times.'));
   }
 
@@ -373,6 +400,13 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
     variable_set('statistics_count_content_views', 1);
 
     $this->drupalGet('node/' . $this->test_node->nid);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $this->test_node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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));
 
     $result = db_select('node_counter', 'n')
       ->fields('n', array('nid'))
@@ -432,7 +466,15 @@ class StatisticsAdminTestCase extends DrupalWebTestCase {
     variable_set('statistics_flush_accesslog_timer', 1);
 
     $this->drupalGet('node/' . $this->test_node->nid);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $this->test_node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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('node/' . $this->test_node->nid);
+    drupal_http_request($stats_path, array('method' => 'POST', 'data' => $post, 'headers' => $headers, 'timeout' => 10000));
     $this->assertText('1 view', t('Node is viewed once.'));
 
     $this->drupalGet('admin/reports/pages');
@@ -481,6 +523,13 @@ class StatisticsTokenReplaceTestCase extends StatisticsTestCase {
 
     // Hit the node.
     $this->drupalGet('node/' . $node->nid);
+    // Manually calling statistics.php, simulating ajax behavior.
+    $nid = $node->nid;
+    $post = http_build_query(array('nid' => $nid));
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded');
+    global $base_url;
+    $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));
     $statistics = statistics_get($node->nid);
 
     // Generate and test tokens.
-- 
GitLab