[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |