drupalorg-1.0.x-dev/src/Utilities/ActiveInstalls.php

src/Utilities/ActiveInstalls.php
<?php

namespace Drupal\drupalorg\Utilities;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\node\Entity\Node;

/**
 * Utility functions to calculate and populate the active installs per branch.
 */
class ActiveInstalls {

  /**
   * Calculate and save new usage data for projects in a plain-text field.
   *
   * Temporary function as the modules managing this are not ported to D9. We
   * just migrate the data and then use it raw.
   *
   * Recommended to be used in cron as it could timeout due to the number of
   * projects (~15k) and their releases.
   *
   * @param int $timestamp
   *   Timestamp to check from, otherwise we'll take the most recent one.
   * @param bool $verbose
   *   Add verbosity to the logger.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public static function calculateNewActiveInstalls($timestamp = NULL, $verbose = FALSE) {
    $memory_cache = \Drupal::service('entity.memory_cache');
    $memory_cache_clear_counter = 0;
    $last_timestamp = $timestamp ?? self::weeklyUsageWeekTimestamps()[0] ?? FALSE;
    $verbose && \Drupal::logger('drupalorg')->info('(Active Installs) Last timestamp: @last_timestamp', [
      '@last_timestamp' => date('c', $last_timestamp),
    ]);
    if ($last_timestamp) {
      $last_timestamp_date = (new \DateTime())->setTimestamp($last_timestamp);
      $date_time_diff = (new DrupalDateTime())->diff($last_timestamp_date);
      // Difference older than a week.
      if ($date_time_diff->days > 7) {
        $results = \Drupal::database()
          ->select('project_usage_week_release', 'puwr')
          ->fields('puwr', ['project_id'])
          ->distinct()
          ->condition('timestamp', $last_timestamp, '>=')
          ->execute()
          ->fetchCol();

        $verbose && \Drupal::logger('drupalorg')->info('(Active Installs) Results: @results', [
          '@results' => count($results),
        ]);
        if (!empty($results)) {
          foreach ($results as $project_id) {
            $project = Node::load($project_id);
            $weekly_usage = self::weeklyUsagePerProject($project_id);
            $project_usage = array_shift($weekly_usage);
            $total = 0;
            foreach ($project_usage as $branch_usage) {
              $total += $branch_usage;
            }
            $verbose && \Drupal::logger('drupalorg')->info('(Active Installs) Project: @project // Total: @total // Usage: @usage', [
              '@project' => $project ? $project->label() : $project_id,
              '@total' => $total,
              '@usage' => Json::encode($project_usage),
            ]);
            if ($project) {
              $changed = FALSE;
              if ($project->hasField('field_active_installs')) {
                $changed = TRUE;
                $project->set('field_active_installs', Json::encode($project_usage));
              }
              if ($project->hasField('field_active_installs_total')) {
                $changed = TRUE;
                $project->set('field_active_installs_total', $total);
              }
              if ($changed) {
                $project->save();
              }
            }

            // Reset the cache in order to free memory as we progress.
            $memory_cache_clear_counter++;
            if ($memory_cache_clear_counter > 100) {
              $memory_cache->deleteAll();
              $memory_cache_clear_counter = 0;
            }
          }
        }
      }
    }
  }

  /**
   * Retrieves project usage information by project.
   *
   * Temporary function as the modules managing this are not ported to D9. We
   * just migrate the data and then use it raw.
   *
   * @param int $id
   *   Id of the project to check.
   * @param int $weeks_to_show
   *   Number of weeks to get stats from.
   *
   * @return array
   *   Usage information for the project organised by releases.
   */
  protected static function weeklyUsagePerProject($id, $weeks_to_show = 1) {
    // Limit weeks that can be retrieved.
    $weeks_to_show = ($weeks_to_show > 4) ? 4 : $weeks_to_show;

    $cache = \Drupal::cache();
    $cache_key = 'drupalorg:usage_per_project:' . $id . ':' . $weeks_to_show;
    if ($result = $cache->get($cache_key)) {
      return $result->data;
    }

    $weeks = self::weeklyUsageWeekTimestamps($weeks_to_show);
    $result = [];
    foreach ($weeks as $week) {
      $result[$week] = self::getUsageByReleasesPerProjectPerWeek($id, $week);
    }

    $cache->set($cache_key, $result, strtotime('+1 week'));
    return $result;
  }

  /**
   * Get array of timestamps used in the weekly tracking.
   *
   * Temporary function as the modules managing this are not ported to D9. We
   * just migrate the data and then use it raw.
   *
   * @param int $number_of_weekly_timestamps
   *   Number of weeks to get.
   *
   * @return array
   *   List of timestamps sorted by most recent.
   */
  protected static function weeklyUsageWeekTimestamps($number_of_weekly_timestamps = 1) {
    $number_of_weekly_timestamps = abs((int) $number_of_weekly_timestamps);

    $cache = \Drupal::cache();
    $cache_key = 'drupalorg:weekly_timestamps:' . $number_of_weekly_timestamps;
    $weeks = $cache->get($cache_key);
    if ($weeks && !empty($weeks->data)) {
      return $weeks->data;
    }

    $results = \Drupal::database()
      ->select('project_usage_week_release', 'puwr')
      ->fields('puwr', ['timestamp'])
      ->distinct()
      ->orderBy('timestamp', 'DESC')
      ->range(0, $number_of_weekly_timestamps)
      ->execute()
      ->fetchCol();
    $weeks = [];
    foreach ($results as $result) {
      $weeks[] = $result;
    }

    // Cache it but make it invalid in one week.
    $cache->set($cache_key, $weeks, strtotime('+1 week'));
    return $weeks;
  }

  /**
   * Retrieves usage data for a project and a week.
   *
   * @param int $id
   *   Id of the project.
   * @param int $week
   *   Week to fetch data from.
   *
   * @return array
   *   Releases active installs information for the given week and project.
   */
  protected static function getUsageByReleasesPerProjectPerWeek($id, $week) {
    /** @var \Drupal\drupalorg\ProjectService $project_service */
    $project_service = \Drupal::service('drupalorg.project_service');
    $project = Node::load($id);
    return ($project && $project_service->isProject($project)) ?
      $project_service->getWeeklyUsage($project, $week, TRUE) :
      [];
  }

}

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

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