vendor/symfony/cache/Adapter/ChainAdapter.php line 87

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Cache\Adapter;
  11. use Psr\Cache\CacheItemInterface;
  12. use Psr\Cache\CacheItemPoolInterface;
  13. use Symfony\Component\Cache\CacheItem;
  14. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  15. use Symfony\Component\Cache\PruneableInterface;
  16. use Symfony\Component\Cache\ResettableInterface;
  17. /**
  18.  * Chains several adapters together.
  19.  *
  20.  * Cached items are fetched from the first adapter having them in its data store.
  21.  * They are saved and deleted in all adapters at once.
  22.  *
  23.  * @author Kévin Dunglas <dunglas@gmail.com>
  24.  */
  25. class ChainAdapter implements AdapterInterfacePruneableInterfaceResettableInterface
  26. {
  27.     private $adapters = [];
  28.     private $adapterCount;
  29.     private $syncItem;
  30.     /**
  31.      * @param CacheItemPoolInterface[] $adapters        The ordered list of adapters used to fetch cached items
  32.      * @param int                      $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones
  33.      */
  34.     public function __construct(array $adapters$defaultLifetime 0)
  35.     {
  36.         if (!$adapters) {
  37.             throw new InvalidArgumentException('At least one adapter must be specified.');
  38.         }
  39.         foreach ($adapters as $adapter) {
  40.             if (!$adapter instanceof CacheItemPoolInterface) {
  41.                 throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class));
  42.             }
  43.             if ($adapter instanceof AdapterInterface) {
  44.                 $this->adapters[] = $adapter;
  45.             } else {
  46.                 $this->adapters[] = new ProxyAdapter($adapter);
  47.             }
  48.         }
  49.         $this->adapterCount = \count($this->adapters);
  50.         $this->syncItem = \Closure::bind(
  51.             static function ($sourceItem$item) use ($defaultLifetime) {
  52.                 $item->value $sourceItem->value;
  53.                 $item->expiry $sourceItem->expiry;
  54.                 $item->isHit $sourceItem->isHit;
  55.                 if ($sourceItem->defaultLifetime && $sourceItem->defaultLifetime $defaultLifetime) {
  56.                     $defaultLifetime $sourceItem->defaultLifetime;
  57.                 }
  58.                 if ($defaultLifetime && ($item->defaultLifetime <= || $defaultLifetime $item->defaultLifetime)) {
  59.                     $item->defaultLifetime $defaultLifetime;
  60.                 }
  61.                 return $item;
  62.             },
  63.             null,
  64.             CacheItem::class
  65.         );
  66.     }
  67.     /**
  68.      * {@inheritdoc}
  69.      */
  70.     public function getItem($key)
  71.     {
  72.         $syncItem $this->syncItem;
  73.         $misses = [];
  74.         foreach ($this->adapters as $i => $adapter) {
  75.             $item $adapter->getItem($key);
  76.             if ($item->isHit()) {
  77.                 while (<= --$i) {
  78.                     $this->adapters[$i]->save($syncItem($item$misses[$i]));
  79.                 }
  80.                 return $item;
  81.             }
  82.             $misses[$i] = $item;
  83.         }
  84.         return $item;
  85.     }
  86.     /**
  87.      * {@inheritdoc}
  88.      */
  89.     public function getItems(array $keys = [])
  90.     {
  91.         return $this->generateItems($this->adapters[0]->getItems($keys), 0);
  92.     }
  93.     private function generateItems($items$adapterIndex)
  94.     {
  95.         $missing = [];
  96.         $misses = [];
  97.         $nextAdapterIndex $adapterIndex 1;
  98.         $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null;
  99.         foreach ($items as $k => $item) {
  100.             if (!$nextAdapter || $item->isHit()) {
  101.                 yield $k => $item;
  102.             } else {
  103.                 $missing[] = $k;
  104.                 $misses[$k] = $item;
  105.             }
  106.         }
  107.         if ($missing) {
  108.             $syncItem $this->syncItem;
  109.             $adapter $this->adapters[$adapterIndex];
  110.             $items $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex);
  111.             foreach ($items as $k => $item) {
  112.                 if ($item->isHit()) {
  113.                     $adapter->save($syncItem($item$misses[$k]));
  114.                 }
  115.                 yield $k => $item;
  116.             }
  117.         }
  118.     }
  119.     /**
  120.      * {@inheritdoc}
  121.      */
  122.     public function hasItem($key)
  123.     {
  124.         foreach ($this->adapters as $adapter) {
  125.             if ($adapter->hasItem($key)) {
  126.                 return true;
  127.             }
  128.         }
  129.         return false;
  130.     }
  131.     /**
  132.      * {@inheritdoc}
  133.      */
  134.     public function clear()
  135.     {
  136.         $cleared true;
  137.         $i $this->adapterCount;
  138.         while ($i--) {
  139.             $cleared $this->adapters[$i]->clear() && $cleared;
  140.         }
  141.         return $cleared;
  142.     }
  143.     /**
  144.      * {@inheritdoc}
  145.      */
  146.     public function deleteItem($key)
  147.     {
  148.         $deleted true;
  149.         $i $this->adapterCount;
  150.         while ($i--) {
  151.             $deleted $this->adapters[$i]->deleteItem($key) && $deleted;
  152.         }
  153.         return $deleted;
  154.     }
  155.     /**
  156.      * {@inheritdoc}
  157.      */
  158.     public function deleteItems(array $keys)
  159.     {
  160.         $deleted true;
  161.         $i $this->adapterCount;
  162.         while ($i--) {
  163.             $deleted $this->adapters[$i]->deleteItems($keys) && $deleted;
  164.         }
  165.         return $deleted;
  166.     }
  167.     /**
  168.      * {@inheritdoc}
  169.      */
  170.     public function save(CacheItemInterface $item)
  171.     {
  172.         $saved true;
  173.         $i $this->adapterCount;
  174.         while ($i--) {
  175.             $saved $this->adapters[$i]->save($item) && $saved;
  176.         }
  177.         return $saved;
  178.     }
  179.     /**
  180.      * {@inheritdoc}
  181.      */
  182.     public function saveDeferred(CacheItemInterface $item)
  183.     {
  184.         $saved true;
  185.         $i $this->adapterCount;
  186.         while ($i--) {
  187.             $saved $this->adapters[$i]->saveDeferred($item) && $saved;
  188.         }
  189.         return $saved;
  190.     }
  191.     /**
  192.      * {@inheritdoc}
  193.      */
  194.     public function commit()
  195.     {
  196.         $committed true;
  197.         $i $this->adapterCount;
  198.         while ($i--) {
  199.             $committed $this->adapters[$i]->commit() && $committed;
  200.         }
  201.         return $committed;
  202.     }
  203.     /**
  204.      * {@inheritdoc}
  205.      */
  206.     public function prune()
  207.     {
  208.         $pruned true;
  209.         foreach ($this->adapters as $adapter) {
  210.             if ($adapter instanceof PruneableInterface) {
  211.                 $pruned $adapter->prune() && $pruned;
  212.             }
  213.         }
  214.         return $pruned;
  215.     }
  216.     /**
  217.      * {@inheritdoc}
  218.      */
  219.     public function reset()
  220.     {
  221.         foreach ($this->adapters as $adapter) {
  222.             if ($adapter instanceof ResettableInterface) {
  223.                 $adapter->reset();
  224.             }
  225.         }
  226.     }
  227. }