gamify-1.1.x-dev/src/Traits/GamifyEntityLogTrait.php

src/Traits/GamifyEntityLogTrait.php
<?php

namespace Drupal\gamify\Traits;

use Drupal\Core\Entity\EntityInterface;
use Drupal\user\UserInterface;

/**
 * Trait for using Gamify entity log.
 *
 * @ingroup gamify
 */
trait GamifyEntityLogTrait {

  /**
   * Query user points revisions for given user and log_id.
   *
   * @param string $log_id
   *   The queried log_id.
   * @param \Drupal\user\UserInterface|null $user
   *   The user receiving user points on log_id (Must not be the current user).
   * @param bool $normalize
   *   Normalize entries to be used with log inquiries.
   *
   * @return array
   *   Return assoc array of user points revisions keyed by version id.
   */
  protected function queryLog(string $log_id, UserInterface $user = NULL, bool $normalize = FALSE): array {
    $query = $this->database
      ->select('userpoints_revision', 't')
      ->fields('t')
      ->condition('revision_log', "%{$this->database->escapeLike($log_id)}%", 'LIKE')
      ->orderBy('vid');
    if ($user) {
      $query->condition('entity_type_id', 'user')
        ->condition('entity_id', $user->id());
    }
    $results = $query
      ->execute()
      ->fetchAllAssoc('vid');

    if ($normalize) {
      $results = $this->normalizeUpEntry($results);
    }
    return $results;
  }

  /**
   * Transforms query result in a normalized array, equal to watchdog results.
   *
   * @param array $results
   *   Results as StdClass with db-log keys.
   *
   * @return array
   *   Normalized array of arrays with default keys.
   */
  private function normalizeUpEntry(array $results): array {
    foreach ($results as $key => $result) {
      $results[$key] = [
        'src' => 'userpoints_log',
        'log_id' => $result->vid,
        'uid' => ($result->entity_type_id == 'user') ? $result->entity_id : 0,
        'log_hash' => $result->revision_log,
        'timestamp' => (int) $result->revision_timestamp,
        'quantity' => (int) $result->quantity,
        'points' => (int) $result->points,
      ];
    }
    return $results;
  }

  /**
   * Build operation hash as content for the log entry.
   *
   * @param string $type
   *   Operation name (create, update or delete).
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The root entity on that the operation is done.
   * @param bool $deep_context
   *   If TRUE method returns complete chain of dependent entity context,
   *   if FALSE returns only entry for this entity (e.g. for db searching).
   *
   * @return string
   *   Returns the action id with entity suffix.
   */
  public function buildLogHash(string $type, EntityInterface $entity, bool $deep_context = TRUE): string {
    $operation = [$type];
    $context = $this->getLogHashContext($entity, $deep_context);
    $frags = array_merge($operation, $context);
    $str = implode('][', $frags);
    return "[$str]";
  }

  /**
   * Receive context identifier from invoke hook.
   *
   * For entities in a nested entity structure you may want to include more
   * context variables. E.g. if it is a vote or paragraph entity, you want
   * to know the parent entity [paragraph:12][node:4].
   * This is to be more flexible in building rules conditions and actions.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity context is requested for.
   * @param bool $deep_context
   *   If TRUE method returns complete chain of dependent entity context,
   *   if FALSE it returns just context for this entity.
   *
   * @return array
   *   The optional context of an entity e.g. parent entity.
   *
   * @see hook_gamify_log_hash_ENTITY_TYPE_context()
   */
  protected function getLogHashContext(EntityInterface $entity, bool $deep_context): array {
    $entity_type = $entity->getEntityTypeId();
    $params = [
      'entity' => $entity,
      'deep_context' => $deep_context,
    ];
    return \Drupal::moduleHandler()
      ->invokeAll("gamify_log_hash_{$entity_type}_context", $params);
    /* @todo It is an open problem, to call the hook with invokeAll, because
     *   there should be only one hook for each entity type. If there are
     *   multiple hooks the system becomes confused. But we don't know what
     *   entity comes in and where the hook for this type lives.
     */
  }

  /**
   * Extract operation from event name.
   *
   * @param string $event_name
   *   The full event name, e.g. 'rules_entity_delete:node'.
   *
   * @return string|null
   *   The operation type <insert|update|delete>
   */
  public function getOperationFromEventName(string $event_name): ?string {
    if (str_starts_with($event_name, 'gamify.')) {
      return substr($event_name, 7);
    }
    return NULL;
  }

  /**
   * Returns valid search string for operation and entity slug.
   *
   * Context properties may change on updates, so we have to reduce search
   * strings to Operation an entity slug.
   *
   * Examples:
   * - $log_hash = [update][node:42 bundle='rule'][term:4 bundle='section']
   *   returns '[update][node:42 '
   * - $log_hash = [update][node:42][term:4 bundle='section']
   *   returns '[update][node:42]'
   *
   * @param string $type
   *   Operation name (create, update or delete).
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The root entity on that the operation is done.
   *
   * @return string
   *   The pure entity operation.
   *
   * @throws \Exception
   */
  public function getLogHashSearchStr(string $type, EntityInterface $entity): string {
    $log_hash = $this->buildLogHash($type, $entity, FALSE);
    // Return context string to array.
    $frags = explode('][', substr($log_hash, 1, -1));
    $return_frags = [];
    if (count($frags) >= 2) {
      // Remove context properties.
      $return_frags[] = $frags[0];
      $entity_frags = explode(' ', $frags[1]);
      // Trailing char required to not find 'node:42' when searching 'node:4'.
      $trailing_char = ($entity_frags >= 2) ? ' ' : ']';
      $return_frags[] = $entity_frags[0] . $trailing_char;
    }
    if (count($return_frags) < 2) {
      $entity_type = $entity->getEntityTypeId();
      throw new \Exception("Failed to build log hash '$type' for entity type '$entity_type'.");
    }
    return "[" . implode('][', $return_frags);
  }

}

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

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