"Fossies" - the Fresh Open Source Software Archive

Member "grav/vendor/willdurand/negotiation/src/Negotiation/AbstractNegotiator.php" (19 Mar 2020, 3634 Bytes) of package /linux/www/grav-v1.6.23.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AbstractNegotiator.php" see the Fossies "Dox" file reference documentation.

    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)
   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                 // silently skip in case of invalid headers coming in from a client
   37             }
   38         }
   39         $acceptedPriorities = array();
   40         foreach ($priorities as $p) {
   41             $acceptedPriorities[] = $this->acceptFactory($p);
   42         }
   43         $matches         = $this->findMatches($acceptedHeaders, $acceptedPriorities);
   44         $specificMatches = array_reduce($matches, 'Negotiation\Match::reduce', []);
   45 
   46         usort($specificMatches, 'Negotiation\Match::compare');
   47 
   48         $match = array_shift($specificMatches);
   49 
   50         return null === $match ? null : $acceptedPriorities[$match->index];
   51     }
   52 
   53     /**
   54      * @param string $header accept header part or server priority
   55      *
   56      * @return AcceptHeader Parsed header object
   57      */
   58     abstract protected function acceptFactory($header);
   59 
   60     /**
   61      * @param AcceptHeader $header
   62      * @param AcceptHeader $priority
   63      * @param integer      $index
   64      *
   65      * @return Match|null Headers matched
   66      */
   67     protected function match(AcceptHeader $header, AcceptHeader $priority, $index)
   68     {
   69         $ac = $header->getType();
   70         $pc = $priority->getType();
   71 
   72         $equal = !strcasecmp($ac, $pc);
   73 
   74         if ($equal || $ac === '*') {
   75             $score = 1 * $equal;
   76 
   77             return new Match($header->getQuality() * $priority->getQuality(), $score, $index);
   78         }
   79 
   80         return null;
   81     }
   82 
   83     /**
   84      * @param string $header A string that contains an `Accept*` header.
   85      *
   86      * @return AcceptHeader[]
   87      */
   88     private function parseHeader($header)
   89     {
   90         $res = preg_match_all('/(?:[^,"]*+(?:"[^"]*+")?)+[^,"]*+/', $header, $matches);
   91 
   92         if (!$res) {
   93             throw new InvalidHeader(sprintf('Failed to parse accept header: "%s"', $header));
   94         }
   95 
   96         return array_values(array_filter(array_map('trim', $matches[0])));
   97     }
   98 
   99     /**
  100      * @param AcceptHeader[] $headerParts
  101      * @param Priority[]     $priorities  Configured priorities
  102      *
  103      * @return Match[] Headers matched
  104      */
  105     private function findMatches(array $headerParts, array $priorities)
  106     {
  107         $matches = [];
  108         foreach ($priorities as $index => $p) {
  109             foreach ($headerParts as $h) {
  110                 if (null !== $match = $this->match($h, $p, $index)) {
  111                     $matches[] = $match;
  112                 }
  113             }
  114         }
  115 
  116         return $matches;
  117     }
  118 }