graphql_compose-1.0.0-beta20/modules/graphql_compose_edges/src/Wrappers/Cursor.php

modules/graphql_compose_edges/src/Wrappers/Cursor.php
<?php

declare(strict_types=1);

namespace Drupal\graphql_compose_edges\Wrappers;

use Drupal\Component\Serialization\Json;

/**
 * GraphQL cursor for pagination.
 *
 * The cursor is used to find the current position in the connection result
 * set.
 *
 * A critical feature of the cursor is that you can continue to paginate even
 * if the node that you grabbed the cursor from ceases to exist (or is
 * modified), so effectively it details the "value" it's sorted by.
 */
class Cursor {

  /**
   * Create a new GraphQL cursor.
   *
   * A cursor should provide a stable point in pagination results, even if the
   * type that backs it is removed or altered.
   *
   * @param string $backingType
   *   The internal type of the object the cursor is for.
   * @param int $backingId
   *   The internal ID of the object the cursor is for. Must be unique for the
   *   backingType as it may be used for stable sorting when there are
   *   duplicates in the value for the sort field.
   * @param string|null $sortKey
   *   The key to sort by. How this maps to object values is determined by the
   *   connection responsible for the edge.
   * @param mixed $sortValue
   *   The value to sort by.
   * @param array $filters
   *   An array of filters to apply to the cursor.
   */
  public function __construct(
    protected string $backingType,
    protected int $backingId,
    protected ?string $sortKey,
    protected mixed $sortValue,
    protected array $filters = [],
  ) {}

  /**
   * Magic method to stringify this object.
   *
   * @return string
   *   The string that can be returned in GraphQL responses.
   *
   * @see toCursorString()
   */
  public function __toString(): string {
    return $this->toCursorString();
  }

  /**
   * Convert the Cursor to a string.
   *
   * Classes overwriting this method should also overwrite fromCursorString
   * since the transformation between cursor class and string is considered to
   * be an implementation detail.
   *
   * @return string
   *   The string that can be returned in GraphQL responses.
   */
  public function toCursorString(): string {
    $cursor = [
      'backingType' => $this->backingType,
      'backingId' => $this->backingId,
      'sortKey' => $this->sortKey,
      'sortValue' => $this->sortValue,
      'filters' => $this->filters,
    ];

    $cursor = array_filter($cursor, fn ($value) => !is_null($value));

    return base64_encode(Json::encode($cursor));
  }

  /**
   * Hydrate a cursor into a queryable object.
   *
   * Classes overwriting this method should also overwrite toCursorString
   * since the transformation between cursor class and string is considered to
   * be an implementation detail.
   *
   * @param string $cursor
   *   The cursor string as returned by self::toCursorString().
   *
   * @return static|null
   *   An instance of the cursor class or null in case of an invalid cursor.
   */
  public static function fromCursorString(string $cursor): ?static {
    $encoded_object = base64_decode($cursor, TRUE);
    if ($encoded_object === FALSE) {
      return NULL;
    }

    $args = Json::decode($encoded_object);

    return new static(
      $args['backingType'],
      (int) $args['backingId'],
      $args['sortKey'] ?? NULL,
      $args['sortValue'] ?? NULL,
      $args['filters'] ?? [],
    );
  }

  /**
   * Get the backing ID for this cursor.
   *
   * @return int
   *   The internal identifier for the object that created this cursor.
   */
  public function getBackingId(): int {
    return $this->backingId;
  }

  /**
   * Get the sort value for this cursor.
   *
   * @return mixed
   *   The sort value for this cursor.
   */
  public function getSortValue() {
    return $this->sortValue;
  }

  /**
   * Set a filter on the cursor.
   *
   * @return static
   *   The cursor instance.
   */
  public function setFilter($key, $value) {
    $this->filters[$key] = $value;

    return $this;
  }

  /**
   * Get a filter from the cursor.
   *
   * @return mixed|null
   *   The filter value or NULL if the filter is not set.
   */
  public function getFilter($key) {
    return $this->filters[$key] ?? NULL;
  }

  /**
   * Whether the cursor is valid for the specified key and type.
   *
   * @param string|null $backing_type
   *   The connection entity type.
   * @param string|null $sort_key
   *   The sort key that this cursor should be for.
   * @param array $filters
   *   If provided will require the filter keys to match.
   *
   * @return bool
   *   Whether this cursor is valid for the provided arguments.
   */
  public function validate(?string $backing_type, ?string $sort_key, array $filters): bool {

    $key_match = $this->sortKey === $sort_key;
    $backing_match = $this->backingType === $backing_type;

    $filters_match = array_diff_key($this->filters, $filters) ? FALSE : TRUE;

    return $key_match && $backing_match && $filters_match;
  }

}

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

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