[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/willdurand/negotiation/src/Negotiation/ -> AbstractNegotiator.php (source)

   1  <?php
   2  
   3  namespace Negotiation;
   4  
   5  use Negotiation\Exception\InvalidArgument;
   6  use Negotiation\Exception\InvalidHeader;
   7  
   8  abstract class AbstractNegotiator
   9  {
  10      /**
  11       * @param string $header     A string containing an `Accept|Accept-*` header.
  12       * @param array  $priorities A set of server priorities.
  13       *
  14       * @return AcceptHeader|null best matching type
  15       */
  16      public function getBest($header, array $priorities, $strict = false)
  17      {
  18          if (empty($priorities)) {
  19              throw new InvalidArgument('A set of server priorities should be given.');
  20          }
  21  
  22          if (!$header) {
  23              throw new InvalidArgument('The header string should not be empty.');
  24          }
  25  
  26          // Once upon a time, two `array_map` calls were sitting there, but for
  27          // some reasons, they triggered `E_WARNING` time to time (because of
  28          // PHP bug [55416](https://bugs.php.net/bug.php?id=55416). Now, they
  29          // are gone.
  30          // See: https://github.com/willdurand/Negotiation/issues/81
  31          $acceptedHeaders = array();
  32          foreach ($this->parseHeader($header) as $h) {
  33              try {
  34                  $acceptedHeaders[] = $this->acceptFactory($h);
  35              } catch (Exception\Exception $e) {
  36                  if ($strict) {
  37                      throw $e;
  38                  }
  39              }
  40          }
  41          $acceptedPriorities = array();
  42          foreach ($priorities as $p) {
  43              $acceptedPriorities[] = $this->acceptFactory($p);
  44          }
  45          $matches         = $this->findMatches($acceptedHeaders, $acceptedPriorities);
  46          $specificMatches = array_reduce($matches, 'Negotiation\AcceptMatch::reduce', []);
  47  
  48          usort($specificMatches, 'Negotiation\AcceptMatch::compare');
  49  
  50          $match = array_shift($specificMatches);
  51  
  52          return null === $match ? null : $acceptedPriorities[$match->index];
  53      }
  54  
  55      /**
  56       * @param string $header A string containing an `Accept|Accept-*` header.
  57       *
  58       * @return AcceptHeader[] An ordered list of accept header elements
  59       */
  60      public function getOrderedElements($header)
  61      {
  62          if (!$header) {
  63              throw new InvalidArgument('The header string should not be empty.');
  64          }
  65  
  66          $elements = array();
  67          $orderKeys = array();
  68          foreach ($this->parseHeader($header) as $key => $h) {
  69              try {
  70                  $element = $this->acceptFactory($h);
  71                  $elements[] = $element;
  72                  $orderKeys[] = [$element->getQuality(), $key, $element->getValue()];
  73              } catch (Exception\Exception $e) {
  74                  // silently skip in case of invalid headers coming in from a client
  75              }
  76          }
  77  
  78          // sort based on quality and then original order. This is necessary as
  79          // to ensure that the first in the list for two items with the same
  80          // quality stays in that order in both PHP5 and PHP7.
  81          uasort($orderKeys, function ($a, $b) {
  82              $qA = $a[0];
  83              $qB = $b[0];
  84  
  85              if ($qA == $qB) {
  86                  return $a[1] <=> $b[1];
  87              }
  88  
  89              return ($qA > $qB) ? -1 : 1;
  90          });
  91  
  92          $orderedElements = [];
  93          foreach ($orderKeys as $key) {
  94              $orderedElements[] = $elements[$key[1]];
  95          }
  96  
  97          return $orderedElements;
  98      }
  99  
 100      /**
 101       * @param string $header accept header part or server priority
 102       *
 103       * @return AcceptHeader Parsed header object
 104       */
 105      abstract protected function acceptFactory($header);
 106  
 107      /**
 108       * @param AcceptHeader $header
 109       * @param AcceptHeader $priority
 110       * @param integer      $index
 111       *
 112       * @return AcceptMatch|null Headers matched
 113       */
 114      protected function match(AcceptHeader $header, AcceptHeader $priority, $index)
 115      {
 116          $ac = $header->getType();
 117          $pc = $priority->getType();
 118  
 119          $equal = !strcasecmp($ac, $pc);
 120  
 121          if ($equal || $ac === '*') {
 122              $score = 1 * $equal;
 123  
 124              return new AcceptMatch($header->getQuality() * $priority->getQuality(), $score, $index);
 125          }
 126  
 127          return null;
 128      }
 129  
 130      /**
 131       * @param string $header A string that contains an `Accept*` header.
 132       *
 133       * @return AcceptHeader[]
 134       */
 135      private function parseHeader($header)
 136      {
 137          $res = preg_match_all('/(?:[^,"]*+(?:"[^"]*+")?)+[^,"]*+/', $header, $matches);
 138  
 139          if (!$res) {
 140              throw new InvalidHeader(sprintf('Failed to parse accept header: "%s"', $header));
 141          }
 142  
 143          return array_values(array_filter(array_map('trim', $matches[0])));
 144      }
 145  
 146      /**
 147       * @param AcceptHeader[] $headerParts
 148       * @param Priority[]     $priorities  Configured priorities
 149       *
 150       * @return AcceptMatch[] Headers matched
 151       */
 152      private function findMatches(array $headerParts, array $priorities)
 153      {
 154          $matches = [];
 155          foreach ($priorities as $index => $p) {
 156              foreach ($headerParts as $h) {
 157                  if (null !== $match = $this->match($h, $p, $index)) {
 158                      $matches[] = $match;
 159                  }
 160              }
 161          }
 162  
 163          return $matches;
 164      }
 165  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer