gamify-1.1.x-dev/src/UserPointsLogService.php

src/UserPointsLogService.php
<?php

namespace Drupal\gamify;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\gamify\Traits\GamifyEntityLogTrait;
use Drupal\userpoints\Service\UserPointsService;
use Drupal\gamify\TypedData\Options\AbstractUserOptions as UserOpts;

/**
 * Helper class for RulesConditions and RulesActions by query userpoints log.
 *
 * With this class we can check log entries of prior userpoint assignments, and
 * form RulesConditions based on it.
 *
 * @ingroup gamify
 */
class UserPointsLogService {

  use GamifyEntityLogTrait;

  const DEFAULT_POINT_TYPE = 'advancement';

  /**
   * The current active database's master connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected Connection $database;

  /**
   * The current active database's master connection.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * Drupal\gamify\AbstractUserService definition.
   *
   * @var \Drupal\gamify\AbstractUserService
   */
  protected AbstractUserService $abstractUserService;

  /**
   * Drupal\userpoints\Service\UserPointsService definition.
   *
   * @var \Drupal\userpoints\Service\UserPointsService
   */
  protected UserPointsService $userpointsService;

  /**
   * Drupal\Component\Datetime\TimeInterface definition.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected TimeInterface $time;

  /**
   * Constructs a new EvaluatingService object.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, AbstractUserService $abstract_user_service, UserPointsService $userpoints_service, TimeInterface $time) {
    $this->entityTypeManager = $entity_type_manager;
    $this->database = $database;
    $this->abstractUserService = $abstract_user_service;
    $this->userpointsService = $userpoints_service;
    $this->time = $time;
  }

  /**
   * Add to or subtract points from an entity.
   *
   * @param float|int $quantity
   *   The number of points (can be negative to subtract).
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to check.
   * @param string $log
   *   Revision log messsage for the operation.
   */
  public function addPoints(float|int $quantity, EntityInterface $entity, string $log = ''): void {
    $this->userpointsService->addPoints($quantity, self::DEFAULT_POINT_TYPE, $entity, $log);
  }

  /**
   * Executes the Plugin.
   *
   * @param string $type
   *   Original value of an element which is being updated.
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity that should get an alias.
   * @param string $addressed_user
   *   The abstract user who will receive user points.
   * @param int $user_points
   *   Number of points to assign.
   */
  public function assign(string $type, EntityInterface $entity, string $addressed_user, int $user_points): void {
    $log_msg = "{$this->buildLogHash($type, $entity)} {$entity->label()}";
    foreach ($this->abstractUserService->getUsers($addressed_user, $entity, TRUE) as $user) {
      $this->addPoints($user_points, $user, $log_msg);
    }
  }

  /**
   * Returns number of repeats, user received points for executing same action.
   *
   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
   *   The entity to check for the provided field.
   * @param string $type
   *   Action type identifier (create, ...) used in the following action.
   *
   * @return ?int
   *   Returns number of repeats current number executes the operation. Returns NULL no user active.
   *
   * @throws \Exception
   */
  public function userActionRepeat(FieldableEntityInterface $entity, string $type, string $abstract_user = UserOpts::CURRENT_USER): ?int {
    $log_hash = $this->getLogHashSearchStr($type, $entity);
    foreach ($this->abstractUserService->getUsers($abstract_user, $entity, TRUE) as $user) {
      $query = $this->queryLog($log_hash, $user);
      return count($query);
    }
    return NULL;
  }

  /**
   * Gets time elapsed since the user previously performed same action.
   *
   * @param string $log_hash
   *   Action type identifier (create, ...) used in the following action.
   *   \Drupal\gamify\TypedData\Options\EntityOperationOptions
   *
   * @return mixed
   */
  public function getLastActionExecLog(string $log_hash): mixed {
    $users = $this->abstractUserService->getUsers(UserOpts::CURRENT_USER, NULL, TRUE);
    if ($user = reset($users)) {
      $results = $this->queryLog($log_hash, $user);
      $time = 0;
      $current = NULL;
      foreach ($results as $result) {
        if ($result->revision_timestamp >= $time) {
          $current = $result;
          $time = $result->revision_timestamp;
        }
      }
      return $current;
    }
    return NULL;
  }

  /**
   * Gets time elapsed since the user previously performed same action.
   *
   * @param null|object $log_entry
   *   A raw log entry as it returned from db query.
   *
   * @return int|null
   *   Returns time since user previously performed same action.
   */
  public function getActionExecLogTime(?object $log_entry = NULL): ?int {
    return $log_entry?->revision_timestamp;
  }

  /**
   * Gets time elapsed between given time and time the logged action was performed.
   *
   * @param null|object $log_entry
   *   A raw log entry as it returned from db query.
   * @param $time int|null
   *   Timestamp to build the relation. If time is not given, request time will be used.
   *
   * @return int|null
   *   Returns time since user previously performed same action.
   */
  public function getActionExecTimeDiff(?object $log_entry = NULL, int $time = NULL): ?int {
    if ($prev_log_time = $this->getActionExecLogTime($log_entry)) {
      $request_time = $time ?? $this->time->getRequestTime();
      return $request_time - $prev_log_time;
    }
    return NULL;
  }

  /**
   * Method reverts all userpoints given on a log id (or fragment of it).
   *
   * @param string $type
   *   Type of operation.
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The target entity.
   * @param string $abstract_user
   *   The abstract user or user group.
   * @param array $revert_operations
   *   The abstract user or user group.
   */
  public function revertUserPoints(string $type, EntityInterface $entity, string $abstract_user, array $revert_operations): void {
    try {
      $reverts = [];
      $users = $this->abstractUserService->getUsers($abstract_user, $entity, TRUE);
      $single_user = (count($users) && ($abstract_user !== UserOpts::INVOLVED_USERS)) ? reset($users) : NULL;

      foreach ($revert_operations as $operation) {
        $log_hash = $this->getLogHashSearchStr($operation, $entity);

        // Filter by user. Involved don't need a filter. Just taking all.
        $log_entries = $this->queryLog($log_hash, $single_user);

        // Search the query log and spread revert points to each user.
        foreach ($log_entries as $upr) {
          if ($upr->entity_type_id !== 'user') {
            continue;
          }
          if (!isset($reverts[$upr->entity_id])) {
            $reverts[$upr->entity_id] = 0;
          }
          $reverts[$upr->entity_id] += (int) $upr->points ?? 0;
        }
      }

      // Revert user points.
      foreach ($users as $user) {
        $log_id = $this->buildLogHash($type, $entity);
        if ($points = $reverts[$user->id()] ?? NULL) {
          $this->userpointsService->addPoints(-$points, self::DEFAULT_POINT_TYPE, $user, "$log_id Reverting points from prior actions.");
        }
      }
    }
    catch (\Exception $e) {
      $msg = "Try to revert user points for {$entity->getEntityTypeId()}:{$entity->id()}. ";
      \Drupal::logger('gamify')->error($msg. $e->getMessage());
    }
  }

}

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

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