vendor/friendsofsymfony/http-cache/src/CacheInvalidator.php line 301

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the FOSHttpCache package.
  4.  *
  5.  * (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\HttpCache;
  11. use FOS\HttpCache\Exception\ExceptionCollection;
  12. use FOS\HttpCache\Exception\InvalidArgumentException;
  13. use FOS\HttpCache\Exception\ProxyResponseException;
  14. use FOS\HttpCache\Exception\ProxyUnreachableException;
  15. use FOS\HttpCache\Exception\UnsupportedProxyOperationException;
  16. use FOS\HttpCache\ProxyClient\Invalidation\BanCapable;
  17. use FOS\HttpCache\ProxyClient\Invalidation\ClearCapable;
  18. use FOS\HttpCache\ProxyClient\Invalidation\PurgeCapable;
  19. use FOS\HttpCache\ProxyClient\Invalidation\RefreshCapable;
  20. use FOS\HttpCache\ProxyClient\Invalidation\TagCapable;
  21. use FOS\HttpCache\ProxyClient\ProxyClient;
  22. use FOS\HttpCache\ProxyClient\Symfony;
  23. use Symfony\Component\EventDispatcher\EventDispatcher;
  24. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  25. use Toflar\Psr6HttpCacheStore\Psr6Store;
  26. /**
  27.  * Manages HTTP cache invalidation.
  28.  *
  29.  * @author David de Boer <david@driebit.nl>
  30.  * @author David Buchmann <mail@davidbu.ch>
  31.  * @author André Rømcke <ar@ez.no>
  32.  */
  33. class CacheInvalidator
  34. {
  35.     /**
  36.      * Value to check support of invalidatePath operation.
  37.      */
  38.     public const PATH 'path';
  39.     /**
  40.      * Value to check support of refreshPath operation.
  41.      */
  42.     public const REFRESH 'refresh';
  43.     /**
  44.      * Value to check support of invalidate and invalidateRegex operations.
  45.      */
  46.     public const INVALIDATE 'invalidate';
  47.     /**
  48.      * Value to check support of invalidateTags operation.
  49.      */
  50.     public const TAGS 'tags';
  51.     /**
  52.      * Value to check support of clearCache operation.
  53.      */
  54.     public const CLEAR 'clear';
  55.     /**
  56.      * @var ProxyClient
  57.      */
  58.     private $cache;
  59.     /**
  60.      * @var EventDispatcherInterface
  61.      */
  62.     private $eventDispatcher;
  63.     /**
  64.      * Constructor.
  65.      *
  66.      * @param ProxyClient $cache HTTP cache
  67.      */
  68.     public function __construct(ProxyClient $cache)
  69.     {
  70.         $this->cache $cache;
  71.     }
  72.     /**
  73.      * Check whether this invalidator instance supports the specified
  74.      * operation.
  75.      *
  76.      * Support for PATH means invalidatePath will work, REFRESH means
  77.      * refreshPath works, TAGS means that invalidateTags works and
  78.      * INVALIDATE is for the invalidate and invalidateRegex methods.
  79.      *
  80.      * @param string $operation one of the class constants
  81.      *
  82.      * @return bool
  83.      *
  84.      * @throws InvalidArgumentException
  85.      */
  86.     public function supports($operation)
  87.     {
  88.         switch ($operation) {
  89.             case self::PATH:
  90.                 return $this->cache instanceof PurgeCapable;
  91.             case self::REFRESH:
  92.                 return $this->cache instanceof RefreshCapable;
  93.             case self::INVALIDATE:
  94.                 return $this->cache instanceof BanCapable;
  95.             case self::TAGS:
  96.                 $supports $this->cache instanceof TagCapable;
  97.                 if ($supports && $this->cache instanceof Symfony) {
  98.                     return class_exists(Psr6Store::class);
  99.                 }
  100.                 return $supports;
  101.             case self::CLEAR:
  102.                 return $this->cache instanceof ClearCapable;
  103.             default:
  104.                 throw new InvalidArgumentException('Unknown operation '.$operation);
  105.         }
  106.     }
  107.     /**
  108.      * Set event dispatcher - may only be called once.
  109.      *
  110.      * @throws \Exception when trying to override the event dispatcher
  111.      */
  112.     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
  113.     {
  114.         if ($this->eventDispatcher) {
  115.             // if you want to set a custom event dispatcher, do so right after instantiating
  116.             // the invalidator.
  117.             throw new \Exception('You may not change the event dispatcher once it is set.');
  118.         }
  119.         $this->eventDispatcher $eventDispatcher;
  120.     }
  121.     /**
  122.      * Get the event dispatcher used by the cache invalidator.
  123.      *
  124.      * @return EventDispatcherInterface
  125.      */
  126.     public function getEventDispatcher()
  127.     {
  128.         if (!$this->eventDispatcher) {
  129.             $this->eventDispatcher = new EventDispatcher();
  130.         }
  131.         return $this->eventDispatcher;
  132.     }
  133.     /**
  134.      * Invalidate a path or URL.
  135.      *
  136.      * @param string $path    Path or URL
  137.      * @param array  $headers HTTP headers (optional)
  138.      *
  139.      * @return $this
  140.      *
  141.      * @throws UnsupportedProxyOperationException
  142.      */
  143.     public function invalidatePath($path, array $headers = [])
  144.     {
  145.         if (!$this->cache instanceof PurgeCapable) {
  146.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('PURGE');
  147.         }
  148.         $this->cache->purge($path$headers);
  149.         return $this;
  150.     }
  151.     /**
  152.      * Refresh a path or URL.
  153.      *
  154.      * @param string $path    Path or URL
  155.      * @param array  $headers HTTP headers (optional)
  156.      *
  157.      * @see RefreshCapable::refresh()
  158.      *
  159.      * @return $this
  160.      *
  161.      * @throws UnsupportedProxyOperationException
  162.      */
  163.     public function refreshPath($path, array $headers = [])
  164.     {
  165.         if (!$this->cache instanceof RefreshCapable) {
  166.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('REFRESH');
  167.         }
  168.         $this->cache->refresh($path$headers);
  169.         return $this;
  170.     }
  171.     /**
  172.      * Invalidate all cached objects matching the provided HTTP headers.
  173.      *
  174.      * Each header is a a POSIX regular expression, for example
  175.      * ['X-Host' => '^(www\.)?(this|that)\.com$']
  176.      *
  177.      * @see BanCapable::ban()
  178.      *
  179.      * @param array $headers HTTP headers that path must match to be banned
  180.      *
  181.      * @return $this
  182.      *
  183.      * @throws UnsupportedProxyOperationException If HTTP cache does not support BAN requests
  184.      */
  185.     public function invalidate(array $headers)
  186.     {
  187.         if (!$this->cache instanceof BanCapable) {
  188.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('BAN');
  189.         }
  190.         $this->cache->ban($headers);
  191.         return $this;
  192.     }
  193.     /**
  194.      * Remove/Expire cache objects based on cache tags.
  195.      *
  196.      * @see TagCapable::tags()
  197.      *
  198.      * @param array $tags Tags that should be removed/expired from the cache
  199.      *
  200.      * @return $this
  201.      *
  202.      * @throws UnsupportedProxyOperationException If HTTP cache does not support Tags invalidation
  203.      */
  204.     public function invalidateTags(array $tags)
  205.     {
  206.         if (!$this->cache instanceof TagCapable) {
  207.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('Tags');
  208.         }
  209.         $this->cache->invalidateTags($tags);
  210.         return $this;
  211.     }
  212.     /**
  213.      * Invalidate URLs based on a regular expression for the URI, an optional
  214.      * content type and optional limit to certain hosts.
  215.      *
  216.      * The hosts parameter can either be a regular expression, e.g.
  217.      * '^(www\.)?(this|that)\.com$' or an array of exact host names, e.g.
  218.      * ['example.com', 'other.net']. If the parameter is empty, all hosts
  219.      * are matched.
  220.      *
  221.      * @see BanCapable::banPath()
  222.      *
  223.      * @param string       $path        Regular expression pattern for URI to
  224.      *                                  invalidate
  225.      * @param string       $contentType Regular expression pattern for the content
  226.      *                                  type to limit banning, for instance 'text'
  227.      * @param array|string $hosts       Regular expression of a host name or list of
  228.      *                                  exact host names to limit banning
  229.      *
  230.      * @return $this
  231.      *
  232.      * @throws UnsupportedProxyOperationException If HTTP cache does not support BAN requests
  233.      */
  234.     public function invalidateRegex($path$contentType null$hosts null)
  235.     {
  236.         if (!$this->cache instanceof BanCapable) {
  237.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('BAN');
  238.         }
  239.         $this->cache->banPath($path$contentType$hosts);
  240.         return $this;
  241.     }
  242.     /**
  243.      * Clear the cache completely.
  244.      *
  245.      * @return $this
  246.      *
  247.      * @throws UnsupportedProxyOperationException if HTTP cache does not support clearing the cache completely
  248.      */
  249.     public function clearCache()
  250.     {
  251.         if (!$this->cache instanceof ClearCapable) {
  252.             throw UnsupportedProxyOperationException::cacheDoesNotImplement('CLEAR');
  253.         }
  254.         $this->cache->clear();
  255.         return $this;
  256.     }
  257.     /**
  258.      * Send all pending invalidation requests.
  259.      *
  260.      * @return int the number of cache invalidations performed per caching server
  261.      *
  262.      * @throws ExceptionCollection if any errors occurred during flush
  263.      */
  264.     public function flush()
  265.     {
  266.         try {
  267.             return $this->cache->flush();
  268.         } catch (ExceptionCollection $exceptions) {
  269.             foreach ($exceptions as $exception) {
  270.                 $event = new Event();
  271.                 $event->setException($exception);
  272.                 if ($exception instanceof ProxyResponseException) {
  273.                     $this->getEventDispatcher()->dispatch($eventEvents::PROXY_RESPONSE_ERROR);
  274.                 } elseif ($exception instanceof ProxyUnreachableException) {
  275.                     $this->getEventDispatcher()->dispatch($eventEvents::PROXY_UNREACHABLE_ERROR);
  276.                 }
  277.             }
  278.             throw $exceptions;
  279.         }
  280.     }
  281. }