You are here

download_count.module in Download Count 8

Tracks file downloads for files stored in the drupal files table.

Using the private files setting or custom private filefield.

File

download_count.module
View source
<?php

/**
 * @file
 * Tracks file downloads for files stored in the drupal files table.
 *
 * Using the private files setting or custom private filefield.
 */
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\EntityStorageInterface;

/**
 * Implements hook_help().
 */
function download_count_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'admin/help#download_count':
      return '<p>' . t('Counts file downloads for private core file fields and
      logs a message to the watchdog table.') . '</p>';
  }
}

/**
 * Implements hook_file_access().
 */
function download_count_file_access($entity, $operation, $account) {
  if ($operation == 'download') {
    $flood = Drupal::flood();
    $config = Drupal::config('download_count.settings');
    $flood_window = $config
      ->get('download_count_flood_window');
    $time = REQUEST_TIME;

    // If ($account->hasPermission('skip download counts')){
    // return;
    // }
    // check flood control.
    $flood_limit = $config
      ->get('download_count_flood_limit');
    if ($flood_limit > 0) {
      if (!$flood
        ->isAllowed('download_count-fid_' . $entity
        ->id(), $flood_limit, $flood_window)) {
        return;
      }
    }

    // Validate file has extension that should be counted, if not return.
    $extensions = explode(' ', Unicode::strtolower(trim($config
      ->get('download_count_excluded_file_extensions'))));
    if (count($extensions)) {
      $extension = Unicode::strtolower(pathinfo($entity
        ->getFilename(), PATHINFO_EXTENSION));
      if (in_array($extension, $extensions)) {
        return;
      }
    }

    // Count the download.
    $ip = Drupal::request()
      ->getClientIp();
    $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : t('Direct download');

    // Echo "<pre>";print_R($entity);exit;
    $references = file_get_file_references($entity, NULL, EntityStorageInterface::FIELD_LOAD_REVISION, NULL);
    foreach ($references as $entity_map) {
      foreach ($entity_map as $referencing_entities) {
        foreach ($referencing_entities as $referencing_entity) {
          $entity_type = $referencing_entity
            ->getEntityTypeId();
          $entity_id = $referencing_entity
            ->id();
        }
      }
    }
    $connection = Database::getConnection();
    $connection
      ->insert('download_count')
      ->fields([
      'fid' => $entity
        ->id(),
      'uid' => $account
        ->id(),
      'type' => $entity_type,
      'id' => $entity_id,
      'ip_address' => $ip,
      'referrer' => $referrer,
      'timestamp' => $time,
    ])
      ->execute();
    $flood
      ->register('download_count-fid_' . $entity
      ->id(), $flood_window);
    Drupal::logger('download_count')
      ->notice('%file was downloaded by user #%uid from %ip', [
      '%file' => $entity
        ->getFilename(),
      '%uid' => $account
        ->id(),
      '%ip' => $ip,
    ]);
    if (Drupal::moduleHandler()
      ->moduleExists('rules')) {
      $host_entity = Drupal::entityTypeManager()
        ->getStorage($entity_type)
        ->load($entity_id);
      if (function_exists('rules_invoke_event')) {
        rules_invoke_event('download_count_file_download', $entity, $account, $host_entity);
      }
    }
  }
}

/**
 * Implements hook_cron().
 *
 * Daily file download counts are cached for convenience.
 */
function download_count_cron() {
  $count = 0;
  $last_cron = Drupal::config('download_count.settings')
    ->get('download_count_last_cron');
  $connection = Database::getConnection();
  $query = $connection
    ->select('download_count', 'd');
  $query
    ->addExpression('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(timestamp)))', 'date');
  $query
    ->addExpression('COUNT(dcid)', 'count');
  $query
    ->fields('d', [
    'fid',
    'type',
    'id',
  ]);
  $query
    ->condition('d.timestamp', $last_cron, '>');
  $query
    ->groupBy('d.type');
  $query
    ->groupBy('d.id');
  $query
    ->groupBy('d.fid');
  $query
    ->groupBy('date');
  $result = $query
    ->execute()
    ->fetchAll();
  $queue = Drupal::queue('download_count');
  foreach ($result as $record) {
    $queue
      ->createItem($record);
    $count++;
  }
  if ($count > 0) {
    Drupal::logger('download_count')
      ->notice('Download count queued {$count} new entries for caching.');
  }
  Drupal::service('config.factory')
    ->getEditable('download_count.settings')
    ->set('download_count_last_cron', REQUEST_TIME)
    ->save();
}

/**
 * Implements hook_theme().
 */
function download_count_theme() {
  $theme = [
    'download_count_file_field_formatter' => [
      'variables' => [
        'file' => NULL,
        'url' => NULL,
        'classes' => NULL,
        'count' => NULL,
      ],
    ],
  ];
  return $theme;
}

Functions

Namesort descending Description
download_count_cron Implements hook_cron().
download_count_file_access Implements hook_file_access().
download_count_help Implements hook_help().
download_count_theme Implements hook_theme().