<?php

/**
 * @file
 * Cache class for gathering heuristics.
 */

use Drupal\Core\Cache\CacheBackendInterface;

/**
 * Safe cache backend that replicates operations across multiple cache backends.
 */
abstract class AutoslaveCacheSafe implements CacheBackendInterface {
  private $backends = [];
  protected $bin;

  /**
   * Constructor.
   * Initialize bin and prefetch data
   */
  public function __construct($bin) {
    $this->bin = $bin;

    // Let our parent do his work.
    $classes = variable_get('autoslave_safe_cache_class_' . $bin);
    if (!isset($classes)) {
      $classes = variable_get('autoslave_safe_cache_default_class', ['DrupalDatabaseCache']);
    }
    if (!is_array($classes)) {
      $classes = [$classes];
    }
    foreach ($classes as $class) {
      $this->backends[] = new $class($bin);
    }
  }

  /**
   * Implements DrupalCacheInterface::clear().
   */
  public function clear($cid = NULL, $wildcard = FALSE) {
    foreach ($this->backends as $backend) {
      $backend->clear($cid, $wildcard);
    }
  }

  /**
   * Implements DrupalCacheInterface::get().
   */
  public function get($cid, $allow_invalid = FALSE) {
    foreach ($this->backends as $index => $backend) {
      if (($return = $backend->get($cid)) !== FALSE) {
        return $return;
      }
    }

    return FALSE;
  }

  /**
   * Implements DrupalCacheInterface::getMultiple().
   */
  public function getMultiple(&$cids, $allow_invalid = FALSE) {
    $return = [];

    foreach ($this->backends as $index => $backend) {
      $items = $backend->getMultiple($cids);

      // Append the values to the previously retrieved ones.
      $return += $items;

      if (empty($cids)) {
        // No need to go further if we don't have any cid to fetch left.
        break;
      }
    }
    return $return;
  }

  /**
   * Implements DrupalCacheInterface::set().
   */
  public function set($cid, $data, $expire = CACHE_PERMANENT, array $tags = []) {
    foreach ($this->backends as $backend) {
      $backend->set($cid, $data, $expire);
    }
  }

  /**
   * Implements DrupalCacheInterface::isEmpty().
   */
  public function isEmpty() {
    foreach ($this->backends as $backend) {
      if (!$backend->isEmpty()) {
        return FALSE;
      }
    }

    return TRUE;
  }

}
