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

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.     /**
  59.      * {@inheritdoc}
  60.      */
  61.     public function flush()
  62.     {
  63.         return $this->httpDispatcher->flush();
  64.     }
  65.     /**
  66.      * Get options resolver with default settings.
  67.      *
  68.      * @return OptionsResolver
  69.      */
  70.     protected function configureOptions()
  71.     {
  72.         return new OptionsResolver();
  73.     }
  74.     /**
  75.      * Create a request and queue it with the HTTP dispatcher.
  76.      *
  77.      * @param string                               $method
  78.      * @param string|UriInterface                  $url
  79.      * @param bool                                 $validateHost see Dispatcher::invalidate
  80.      * @param resource|string|StreamInterface|null $body
  81.      */
  82.     protected function queueRequest($method$url, array $headers$validateHost true$body null)
  83.     {
  84.         $this->httpDispatcher->invalidate(
  85.             $this->requestFactory->createRequest($method$url$headers$body),
  86.             $validateHost
  87.         );
  88.     }
  89.     /**
  90.      * Make sure that the tags are valid.
  91.      *
  92.      * Reusable function for proxy clients.
  93.      * Escapes `,` and `\n` (newline) characters.
  94.      *
  95.      * Note: This is not a safe escaping function, it can lead to collisions,
  96.      * e.g. between "foo,bar" and "foo_bar". But from the nature of the data,
  97.      * such collisions are unlikely, and from the function of cache tagging,
  98.      * collisions would in the worst case lead to unintended invalidations,
  99.      * which is not a bug.
  100.      *
  101.      * @param array $tags The tags to escape
  102.      *
  103.      * @return array Sane tags
  104.      */
  105.     protected function escapeTags(array $tags)
  106.     {
  107.         array_walk($tags, function (&$tag) {
  108.             // WARNING: changing the list of characters that are escaped is a BC break for existing installations,
  109.             // as existing tags on the cache would not be invalidated anymore if they contain a character that is
  110.             // newly escaped
  111.             $tag str_replace([','"\n"], '_'$tag);
  112.         });
  113.         return $tags;
  114.     }
  115.     /**
  116.      * Calculate how many tags fit into the header.
  117.      *
  118.      * This assumes that the tags are separated by one character.
  119.      *
  120.      * @param string[] $escapedTags
  121.      * @param string   $glue        The concatenation string to use
  122.      *
  123.      * @return int Number of tags per tag invalidation request
  124.      */
  125.     protected function determineTagsPerHeader($escapedTags$glue)
  126.     {
  127.         if (mb_strlen(implode($glue$escapedTags)) < $this->options['header_length']) {
  128.             return count($escapedTags);
  129.         }
  130.         /*
  131.          * estimate the amount of tags to invalidate by dividing the max
  132.          * header length by the largest tag (minus the glue length)
  133.          */
  134.         $tagsize max(array_map('mb_strlen'$escapedTags));
  135.         return floor($this->options['header_length'] / ($tagsize strlen($glue))) ?: 1;
  136.     }
  137. }