Commit 1b67ae53 authored by Gaurav Kapoor's avatar Gaurav Kapoor Committed by Gaurav Kapoor
Browse files

Issue #3264628 by gaurav.kapoor: Add a counter service with all the utility methods

parent 54601e16
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@
 * The counter module used for displaying Site Counter.
 */

use DeviceDetector\DeviceDetector;
use Drupal\Core\Routing\RouteMatchInterface;

/**
@@ -20,37 +19,3 @@ function counter_help($route_name, RouteMatchInterface $route_match) {
      return $output;
  }
}

/**
 * To find out browser type and return browser info.
 */
function counter_get_browser() {
  // Using device detector library to get user agent information.
  $user_agent = \Drupal::request()->server->get('HTTP_USER_AGENT');
  $device_detector = new DeviceDetector($user_agent);
  $device_detector->parse();

  $browser_name    = 'Unknown';
  $browser_version = '';
  $platform        = 'Unknown';

  // Return unknown in case user is a bot.
  if ($device_detector->isBot()) {
    return [
      'browser_name'    => $browser_name,
      'browser_version' => $browser_version,
      'platform'        => $platform,
    ];
  }

  // Fetching required information using helper functions.
  $browser_name = $device_detector->getClient('name');
  $browser_version = $device_detector->getClient('version');
  $platform = $device_detector->getOs()['name'];

  return [
    'browser_name'    => $browser_name,
    'browser_version' => $browser_version,
    'platform'        => $platform,
  ];
}
+9 −2
Original line number Diff line number Diff line
services:
  counter_event_subscriber:
  counter.device_detector:
    class: 'DeviceDetector\DeviceDetector'

  counter.counter_utility:
    class: '\Drupal\counter\CounterUtility'
    arguments: ['@database', '@request_stack', '@counter.device_detector']

  counter.counter_event_subscriber:
    class: '\Drupal\counter\EventSubscriber\CounterEventsSubscriber'
    arguments: ['@database', '@config.factory', '@current_user']
    arguments: ['@config.factory', '@current_user', '@counter.counter_utility']
    tags:
      - { name: 'event_subscriber' }

src/CounterUtility.php

0 → 100644
+138 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\counter;

use DeviceDetector\DeviceDetector;
use Drupal\Core\Database\Connection;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Class that provides utility functions for the counter module.
 *
 * @package Drupal\counter
 */
class CounterUtility {
  /**
   * The database connection.
   *
   * @var Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The request stack.
   *
   * @var Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The device detector.
   *
   * @var \DeviceDetector\DeviceDetector\DeviceDetector
   */
  protected $deviceDetector;

  /**
   * Constructs an event subscriber.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection variable for executing queries.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack for accessing request information.
   * @param \DeviceDetector\DeviceDetector $device_detector
   *   The device detector for getting accessing device details.
   */
  public function __construct(Connection $database, RequestStack $request_stack, DeviceDetector $device_detector) {
    $this->database = $database;
    $this->requestStack = $request_stack;
    $this->deviceDetector = $device_detector;

    // Setting up user agent based on current request.
    $this->deviceDetector->setUserAgent($this->requestStack->getCurrentRequest()->server->get('HTTP_USER_AGENT'));
    $this->deviceDetector->parse();
  }

  /**
   * Retrieves counter last date from database.
   */
  public function getCounterLastDate() {
    $query = $this->database->select('counter', 'c');
    $query->condition('c.created', 0, '<>');
    $query->fields('c', ['created']);
    $query->orderBy('created', 'DESC');
    $query->range(0, 1);
    $result = $query->execute();

    return $result->fetchField();
  }

  /**
   * Fetches browser and platform information.
   */
  public function getBrowserInformation() {
    $browser_name = 'Unknown';
    $browser_version = '';
    $platform = 'Unknown';

    // Return unknown in case user is a bot.
    if ($this->deviceDetector->isBot()) {
      return [
        'browser_name' => $browser_name,
        'browser_version' => $browser_version,
        'platform' => $platform,
      ];
    }

    // Fetching required information using helper functions.
    $browser_name = $this->deviceDetector->getClient('name');
    $browser_version = $this->deviceDetector->getClient('version');
    $platform = $this->deviceDetector->getOs()['name'];

    return [
      'browser_name' => $browser_name,
      'browser_version' => $browser_version,
      'platform' => $platform,
    ];
  }

  /**
   * Inserts counter data to database.
   */
  public function insertCounterData(array $data) {
    $this->database->insert('counter')
      ->fields([
        'ip' => $data['ip'],
        'created' => time(),
        'url' => $data['url'],
        'uid' => $data['uid'],
        'nid' => $data['nid'],
        'type' => $data['type'],
        'browser_name' => $data['browser_name'],
        'browser_version' => $data['browser_version'],
        'platform' => $data['platform'],
      ])
      ->execute();
  }

  /**
   * Update counter data table with correct values.
   */
  public function updateCounterDataTable() {
    $query = $this->database->select('counter_data', 'c');
    $query->condition('c.counter_name', 'site_counter');
    $query->fields('c', ['counter_value']);
    $result = $query->execute();
    $site_counter = $result->fetchField();

    $new_site_counter = $site_counter + 1;

    $this->database->update('counter_data')
      ->fields([
        'counter_value' => $new_site_counter,
      ])
      ->condition('counter_name', 'site_counter')
      ->execute();
  }

}
+33 −68
Original line number Diff line number Diff line
@@ -2,9 +2,10 @@

namespace Drupal\counter\EventSubscriber;

use Drupal\counter\CounterUtility;
use Drupal\node\NodeInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
@@ -17,13 +18,6 @@ use Symfony\Component\HttpKernel\KernelEvents;
 */
class CounterEventsSubscriber implements EventSubscriberInterface {

  /**
   * The database connection.
   *
   * @var Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The config factory.
   *
@@ -38,20 +32,27 @@ class CounterEventsSubscriber implements EventSubscriberInterface {
   */
  protected $account;

  /**
   * The counter utility variable for accessing helper functions.
   *
   * @var Drupal\counter\CounterUtility
   */
  protected $counterUtility;

  /**
   * Constructs an event subscriber.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection variable for executing queries.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory for the form.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The account interface for accessing current user.
   * @param \Drupal\counter\CounterUtility $counter_utility
   *   The counter utility variable to access helper functions.
   */
  public function __construct(Connection $database, ConfigFactoryInterface $config_factory, AccountInterface $account) {
    $this->database = $database;
  public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $account, CounterUtility $counter_utility) {
    $this->configFactory = $config_factory;
    $this->account = $account;
    $this->counterUtility = $counter_utility;
  }

  /**
@@ -74,84 +75,48 @@ class CounterEventsSubscriber implements EventSubscriberInterface {
   */
  public function counterInsert(RequestEvent $event) {
    $request = $event->getRequest();
    $ip = $request->getClientIp();
    $created = \time();
    $url = Html::escape($request->getRequestUri());
    $data['ip'] = $request->getClientIp();
    $data['url'] = Html::escape($request->getRequestUri());
    $data['uid'] = $this->account->id();

    $config = $this->configFactory->get('counter.settings');
    $counter_insert_delay = $config->get('counter_insert_delay');
    $counter_skip_admin = $config->get('counter_skip_admin');

    // Fetch last created value from database.
    $db_types = $this->database->driver();
    switch ($db_types) {
      case 'mssql':
        $sql = " SELECT TOP 1 created FROM {counter} WHERE created<>0 ORDER BY created DESC";
        break;

      case 'oracle':
        $sql = " SELECT created FROM {counter} WHERE ROWNUM=1 AND created<>0 ORDER BY created DESC";
        break;

      default:
        $sql = " SELECT created FROM {counter} WHERE created<>0 ORDER BY created DESC LIMIT 1";
    }
    $counter_lastdate = $this->database->query($sql)->fetchField();
    $counter_lastdate = $this->counterUtility->getCounterLastDate();

    // Check if permitted to insert data.
    $interval = \time() - $counter_lastdate;
    $interval = time() - $counter_lastdate;
    $data_insert = ($interval >= $counter_insert_delay ? 1 : 0);

    // Uid, nid, type, browser name, browser version, platform.
    // Get UID, NID, content type, browser name, browser version and platform.
    $node = $request->attributes->get('node');
    $nid = 0;
    $type = '';
    $account = $this->account;
    $path_args = \explode('/', $request->getRequestUri());
    if ($path_args[0] == 'node' && is_numeric($path_args[1])) {
      $nid  = $node->nid;
      $type = $node->type;
    $data['nid'] = 0;
    $data['type'] = '';
    if ($node instanceof NodeInterface) {
      $data['nid'] = $node->id();
      $data['type'] = $node->bundle();
    }
    $browser = counter_get_browser();
    $browser_name = $browser['browser_name'];
    $browser_version = $browser['browser_version'];
    $platform = $browser['platform'];
    $browser = $this->counterUtility->getBrowserInformation();
    $data['browser_name'] = $browser['browser_name'];
    $data['browser_version'] = $browser['browser_version'];
    $data['platform'] = $browser['platform'];

    $sql = " INSERT INTO {counter} (ip,created,url, uid, nid, type, browser_name, browser_version, platform)" .
    " VALUES (:ip, :created, :url, :uid, :nid, :type, :browser_name, :browser_version, :platform)";
    $counter_exec = FALSE;

    if ($data_insert && ($account->id() <> 1)) {
    if ($data_insert && $data['uid'] != 1) {
      $counter_exec = TRUE;
    }
    else {
      if ($data_insert && ($account->id() == 1) && !$counter_skip_admin) {

    if ($data_insert && $data['uid'] == 1 && !$counter_skip_admin) {
      $counter_exec = TRUE;
    }
    }

    if ($counter_exec) {
      $this->database->query($sql, [
        ':ip' => $ip,
        ':created' => $created,
        ':url' => $url,
        ':uid' => $account->id(),
        ':nid' => $nid,
        ':type' => $type,
        ':browser_name' => $browser_name,
        ':browser_version' => $browser_version,
        ':platform' => $platform,
      ]);
      $this->counterUtility->insertCounterData($data);
      $this->counterUtility->updateCounterDataTable();
    }

    // Update counter data table.
    $sql_site_counter = "SELECT counter_value FROM {counter_data} WHERE counter_name='site_counter'";
    $site_counter = $this->database->query($sql_site_counter)->fetchField();

    $new_site_counter = $site_counter + 1;

    $sql = " UPDATE {counter_data} SET counter_value = :counter_value WHERE counter_name='site_counter'";
    $this->database->query($sql, [':counter_value' => $new_site_counter]);
  }

}