podcast_publisher-1.0.0-alpha3/modules/podcast_publisher_analytics/src/Cron/RehashCronHandler.php

modules/podcast_publisher_analytics/src/Cron/RehashCronHandler.php
<?php

namespace Drupal\podcast_publisher_analytics\Cron;

use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\State\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Cron handler to anonymize download intents.
 */
class RehashCronHandler implements ContainerInjectionInterface {

  const STATE_ID = 'podcast_publisher_analytics.last_cron_run';

  /**
   * The state.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected $state;

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

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Database\Connection $database
   *   The database.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state.
   */
  public function __construct(Connection $database, StateInterface $state) {
    $this->database = $database;
    $this->state = $state;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('database'),
      $container->get('state')
    );
  }

  /**
   * Anonymize all download intents that are older than 24 hours.
   */
  public function process() {
    $today = new \DateTime();
    $today->setTime(0, 0);

    $last_cron_run_timestamp = $this->state->get(static::STATE_ID) ?? 0;
    $last_cron_run = new \DateTime();
    $last_cron_run->setTimestamp($last_cron_run_timestamp);
    $last_cron_run->setTime(0, 0);

    // Let this cron handler only run once per day.
    if ($today <= $last_cron_run) {
      return;
    }
    $yesterday = clone $today;
    $yesterday->sub(new \DateInterval('P1D'));
    $this->updateDownloadIntents($yesterday->getTimestamp());

    // Set last cron run timestamp to now.
    $this->state->set(static::STATE_ID, $today->getTimestamp());
  }

  /**
   * Update all unprocessed requester_id values.
   *
   * @param int $timestamp
   *   The timestamp that marks the latest intent that should be processed.
   */
  protected function updateDownloadIntents($timestamp) {
    // Get unprocessed rows of original requests.
    $query = $this->database->select('podcast_download_intent', 'pdi');
    $statement = $query->fields('pdi', ['id', 'requester_id'])
      ->condition('pdi.processed', TRUE, '<>')
      ->condition('pdi.timestamp', $timestamp, '<')
      ->isNull('original_intent')
      ->execute();

    while ($row = $statement->fetch()) {
      // Update requester id of original and subsequent requests.
      $old_requester_id = $row->requester_id;
      $new_hash = $this->computeNewHash($old_requester_id);

      $query = $this->database->update('podcast_download_intent');
      $condition_group = $query->orConditionGroup()
        ->condition('id', $row->id)
        ->condition('original_intent', $row->id);

      $query->fields([
        'requester_id' => $new_hash,
        'processed' => TRUE,
      ])
        ->condition('timestamp', $timestamp, '<')
        ->condition('processed', TRUE, '<>')
        ->condition('requester_id', $old_requester_id)
        ->condition($condition_group)
        ->execute();
    }
  }

  /**
   * Computes new requester hash that makes it impossible to extract IP address.
   *
   * @param string $old_hash
   *   The old hash.
   *
   * @return string
   *   The new hash.
   */
  protected function computeNewHash($old_hash) {
    $salt = random_bytes(12);
    if (function_exists('openssl_digest')) {
      return openssl_digest($old_hash . $salt, 'sha256');
    }
    elseif (function_exists('crypt')) {
      return crypt($old_hash, $salt);
    }
    return sha1($old_hash . $salt);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc