vendor/friendsofsymfony/http-cache/src/ProxyClient/HttpProxyClient.php line 63

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\ProxyClient;
  11. use Http\Discovery\MessageFactoryDiscovery;
  12. use Http\Message\RequestFactory;
  13. use Psr\Http\Message\StreamInterface;
  14. use Psr\Http\Message\UriInterface;
  15. use Symfony\Component\OptionsResolver\OptionsResolver;
  16. /**
  17.  * Base class for HTTP based caching proxy client.
  18.  *
  19.  * @author David de Boer <david@driebit.nl>
  20.  */
  21. abstract class HttpProxyClient implements ProxyClient
  22. {
  23.     /**
  24.      * Dispatcher for invalidation HTTP requests.
  25.      *
  26.      * @var HttpDispatcher
  27.      */
  28.     private $httpDispatcher;
  29.     /**
  30.      * @var RequestFactory
  31.      */
  32.     private $requestFactory;
  33.     /**
  34.      * The options configured in the constructor argument or default values.
  35.      *
  36.      * @var array The resolved options
  37.      */
  38.     protected $options;
  39.     /**
  40.      * Constructor.
  41.      *
  42.      * The base class has no options.
  43.      *
  44.      * @param Dispatcher          $httpDispatcher Helper to send HTTP requests to caching proxy
  45.      * @param array               $options        Options for this client
  46.      * @param RequestFactory|null $messageFactory Factory for PSR-7 messages. If none supplied,
  47.      *                                            a default one is created
  48.      */
  49.     public function __construct(
  50.         Dispatcher $httpDispatcher,
  51.         array $options = [],
  52.         ?RequestFactory $messageFactory null
  53.     ) {
  54.         $this->httpDispatcher $httpDispatcher;
  55.         $this->options $this->configureOptions()->resolve($options);
  56.         $this->requestFactory $messageFactory ?: MessageFactoryDiscovery::find();
  57.     }
  58.     public function flush()
  59.     {
  60.         return $this->httpDispatcher->flush();
  61.     }
  62.     /**
  63.      * Get options resolver with default settings.
  64.      *
  65.      * @return OptionsResolver
  66.      */
  67.     protected function configureOptions()
  68.     {
  69.         return new OptionsResolver();
  70.     }
  71.     /**
  72.      * Create a request and queue it with the HTTP dispatcher.
  73.      *
  74.      * @param string                               $method
  75.      * @param string|UriInterface                  $url
  76.      * @param bool                                 $validateHost see Dispatcher::invalidate
  77.      * @param resource|string|StreamInterface|null $body
  78.      */
  79.     protected function queueRequest($method$url, array $headers$validateHost true$body null)
  80.     {
  81.         $this->httpDispatcher->invalidate(
  82.             $this->requestFactory->createRequest($method$url$headers$body),
  83.             $validateHost
  84.         );
  85.     }
  86.     /**
  87.      * Make sure that the tags are valid.
  88.      *
  89.      * Reusable function for proxy clients.
  90.      * Escapes `,` and `\n` (newline) characters.
  91.      *
  92.      * Note: This is not a safe escaping function, it can lead to collisions,
  93.      * e.g. between "foo,bar" and "foo_bar". But from the nature of the data,
  94.      * such collisions are unlikely, and from the function of cache tagging,
  95.      * collisions would in the worst case lead to unintended invalidations,
  96.      * which is not a bug.
  97.      *
  98.      * @param array $tags The tags to escape
  99.      *
  100.      * @return array Sane tags
  101.      */
  102.     protected function escapeTags(array $tags)
  103.     {
  104.         array_walk($tags, function (&$tag) {
  105.             // WARNING: changing the list of characters that are escaped is a BC break for existing installations,
  106.             // as existing tags on the cache would not be invalidated anymore if they contain a character that is
  107.             // newly escaped
  108.             $tag str_replace([','"\n"], '_'$tag);
  109.         });
  110.         return $tags;
  111.     }
  112.     /**
  113.      * Calculate how many tags fit into the header.
  114.      *
  115.      * This assumes that the tags are separated by one character.
  116.      *
  117.      * @param string[] $escapedTags
  118.      * @param string   $glue        The concatenation string to use
  119.      *
  120.      * @return int Number of tags per tag invalidation request
  121.      */
  122.     protected function determineTagsPerHeader($escapedTags$glue)
  123.     {
  124.         if (mb_strlen(implode($glue$escapedTags)) < $this->options['header_length']) {
  125.             return count($escapedTags);
  126.         }
  127.         /*
  128.          * estimate the amount of tags to invalidate by dividing the max
  129.          * header length by the largest tag (minus the glue length)
  130.          */
  131.         $tagsize max(array_map('mb_strlen'$escapedTags));
  132.         return floor($this->options['header_length'] / ($tagsize strlen($glue))) ?: 1;
  133.     }
  134. }