media_mpx-8.x-1.x-dev/src/SimpleCacheBackendAdapter.php

src/SimpleCacheBackendAdapter.php
<?php

namespace Drupal\media_mpx;

use Cache\TagInterop\TaggableCacheItemPoolInterface;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Psr\SimpleCache\CacheInterface;

/**
 * Adapter to use PSR-16 cache backends as a Drupal backend cache.
 *
 * While it is not part of a PSR, it is recommended that the adapted cache
 * implements \Cache\TagInterop\TaggableCacheItemPoolInterface. Otherwise,
 * each cache read will cause a database query to check to see if any tags have
 * been invalidated.
 *
 * @todo This class should be split out into it's own project.
 *
 * @see \Drupal\Core\Cache\ApcuBackend::prepareItem
 */
class SimpleCacheBackendAdapter implements CacheBackendInterface, CacheTagsInvalidatorInterface {

  /**
   * The adapted cache.
   *
   * @var \Psr\SimpleCache\CacheInterface
   */
  protected $cache;

  /**
   * The service used to get the time.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $time;

  /**
   * The checksum provider to implement tags support.
   *
   * @var \Drupal\Core\Cache\CacheTagsChecksumInterface
   */
  protected $checksumProvider;

  /**
   * SimpleCacheBackendAdapter constructor.
   *
   * @param \Psr\SimpleCache\CacheInterface $cache
   *   The adapted cache.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The service used to get the time.
   * @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksumProvider
   *   The checksum provider to implement tags support.
   */
  public function __construct(CacheInterface $cache, TimeInterface $time, CacheTagsChecksumInterface $checksumProvider) {
    $this->cache = $cache;
    $this->time = $time;
    $this->checksumProvider = $checksumProvider;
  }

  /**
   * {@inheritdoc}
   */
  public function get($cid, $allow_invalid = FALSE) {
    $key = $this->keyFromCid($cid);
    return $this->prepareItem($this->cache->get($key), $allow_invalid);
  }

  /**
   * {@inheritdoc}
   */
  public function getMultiple(&$cids, $allow_invalid = FALSE) {
    $keys = $this->keysFromCids($cids);
    $items = $this->cache->getMultiple($keys);

    // $items can be an iterable and not just an array, so we can't use array_*
    // functions here.
    $ret = $this->prepareGetMultiple($items, $allow_invalid);

    $cids = array_diff($cids, array_keys($ret));

    return $ret;
  }

  /**
   * {@inheritdoc}
   */
  public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
    $cache = $this->createCacheItem($cid, $data, $expire, $tags);

    $key = $this->keyFromCid($cid);
    $expire = $this->expireAsRelative($expire);
    $this->cache->set($key, $cache, $expire);
  }

  /**
   * {@inheritdoc}
   */
  public function setMultiple(array $items) {
    foreach ($items as $cid => $item) {
      // setMultiple() only supports a single TTL for all items so we have to do
      // individual sets.
      $tags = isset($item['tags']) ? $item['tags'] : [];
      $this->set($cid, $item['data'], $item['expire'], $tags);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function delete($cid) {
    $key = $this->keyFromCid($cid);
    $this->cache->delete($key);
  }

  /**
   * {@inheritdoc}
   */
  public function deleteMultiple(array $cids) {
    $keys = $this->keysFromCids($cids);
    $this->cache->deleteMultiple($keys);
  }

  /**
   * {@inheritdoc}
   */
  public function deleteAll() {
    $this->cache->clear();
  }

  /**
   * {@inheritdoc}
   */
  public function invalidate($cid) {
    $this->invalidateMultiple([$cid]);
  }

  /**
   * {@inheritdoc}
   */
  public function invalidateMultiple(array $cids) {
    foreach ($this->getMultiple($cids) as $cache) {
      $this->set($cache->cid, $cache, $this->time->getRequestTime() - 1);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function invalidateAll() {
    // Handle invalidateAll() including backends that don't support listing all
    // keys.
    // @see \Drupal\memcache\MemcacheBackend::invalidateAll
    $this->invalidateTags(["simple_cache_adapter"]);
  }

  /**
   * {@inheritdoc}
   */
  public function garbageCollection() {
    // PSR-16 does not have an interface for garbage collection.
  }

  /**
   * {@inheritdoc}
   */
  public function removeBin() {
    // PSR-16 does not have an interface to delete a bin, but we can at least
    // clear the cache.
    $this->cache->clear();
  }

  /**
   * Marks cache items with any of the specified tags as invalid.
   *
   * @param string[] $tags
   *   The list of tags for which to invalidate cache items.
   */
  public function invalidateTags(array $tags) {
    if ($this->cache instanceof TaggableCacheItemPoolInterface) {
      $this->cache->invalidateTags($tags);
    }
  }

  /**
   * Prepares a cached item.
   *
   * Checks that the item is either permanent or did not expire.
   *
   * @param object $cache
   *   An item loaded from cache_get() or cache_get_multiple().
   * @param bool $allow_invalid
   *   If TRUE, a cache item may be returned even if it is expired or has been
   *   invalidated. See ::get().
   *
   * @return mixed
   *   The cache item or FALSE if the item expired.
   */
  private function prepareItem(\stdClass $cache, bool $allow_invalid) {
    if (!isset($cache->data)) {
      return FALSE;
    }

    $cache->tags = $cache->tags ? explode(' ', $cache->tags) : [];

    // Check if invalidateTags() has been called with any of the entry's tags.
    if (!$this->cache instanceof TaggableCacheItemPoolInterface) {
      if (!$this->checksumProvider->isValid($cache->checksum, $cache->tags) && !$allow_invalid) {
        return FALSE;
      }
    }

    return $cache;
  }

  /**
   * Create a Drupal \stdClass cache item.
   *
   * @param string $cid
   *   The Drupal cache ID.
   * @param mixed $data
   *   The data to cache.
   * @param int $expire
   *   The absolute expiry of the cache item.
   * @param string[] $tags
   *   An array of cache tags.
   *
   * @return object
   *   The cache item.
   */
  private function createCacheItem($cid, $data, $expire, array $tags): \stdClass {
    // Additional tag to support invalidateAll().
    $tags[] = 'simple_cache_adapter';
    $tags = array_unique($tags);
    // Sort the cache tags so that they are stored consistently in the database.
    sort($tags);

    $cache = new \stdClass();
    $cache->cid = $cid;
    $cache->created = round(microtime(TRUE), 3);
    $cache->expire = $expire;
    $cache->tags = implode(' ', $tags);

    // By default, the database provider is used by Drupal, so save a query if
    // the adapted cache supports tags directly.
    if (!$this->cache instanceof TaggableCacheItemPoolInterface) {
      $cache->checksum = $this->checksumProvider->getCurrentChecksum($tags);
    }

    $cache->data = $data;
    return $cache;
  }

  /**
   * Convert an absolute expiry to a relative time from now.
   *
   * @param int $expire
   *   The absolute timestamp.
   *
   * @return int|null
   *   A relative time if $expire is a timestamp, or NULL if it is
   *   Cache::PERMANENT.
   */
  private function expireAsRelative(int $expire): ?int {
    if ($expire == Cache::PERMANENT) {
      $expire = NULL;
    }
    else {
      $expire = $expire - $this->time->getCurrentTime();
    }

    return $expire;
  }

  /**
   * Hash a cache ID so it is a valid PSR-6 / PSR-16 key.
   *
   * @param string $cid
   *   The Drupal cache ID.
   *
   * @see http://www.php-cache.com/en/latest/introduction/#cache-keys
   *
   * @return string
   *   A safe cache ID.
   */
  private function keyFromCid(string $cid): string {
    return sha1($cid);
  }

  /**
   * Hash multiple cache IDs.
   *
   * @param string[] $cids
   *   An array of Drupal cache IDs.
   *
   * @return array
   *   An array of safe cache IDS.
   */
  private function keysFromCids(array $cids): array {
    $keys = [];
    foreach ($cids as $cid) {
      $keys[] = $this->keyFromCid($cid);
    }
    return $keys;
  }

  /**
   * Generate the array of returns suitable for getMultiple().
   *
   * @param iterable $items
   *   The iterable of cache items, including cache misses.
   * @param bool $allow_invalid
   *   Allow invalid items to be returned.
   *
   * @return \stdClass[]
   *   An array of Drupal cache items.
   */
  private function prepareGetMultiple(iterable $items, $allow_invalid): array {
    $ret = [];
    foreach ($items as $item) {
      // $item is null if it could not be found, but it's an iterable so we
      // can't use array_filter().
      if ($item && $item = $this->prepareItem($item, $allow_invalid)) {
        $ret[$item->cid] = $item;
      }
    }
    return $ret;
  }

}

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

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