Update composer/spdx-licenses to 1.4.0 and mediawiki/mediawiki-codesniffer to 21.0.0
[lhc/web/wiklou.git] / includes / libs / http / HttpAcceptParser.php
1 <?php
2
3 /**
4 * Utility for parsing a HTTP Accept header value into a weight map. May also be used with
5 * other, similar headers like Accept-Language, Accept-Encoding, etc.
6 *
7 * @license GPL-2.0-or-later
8 * @author Daniel Kinzler
9 */
10
11 namespace Wikimedia\Http;
12
13 class HttpAcceptParser {
14
15 /**
16 * Parses an HTTP header into a weight map, that is an associative array
17 * mapping values to their respective weights. Any header name preceding
18 * weight spec is ignored for convenience.
19 *
20 * This implementation is partially based on the code at
21 * http://www.thefutureoftheweb.com/blog/use-accept-language-header
22 *
23 * Note that type parameters and accept extension like the "level" parameter
24 * are not supported, weights are derived from "q" values only.
25 *
26 * @todo If additional type parameters are present, ignore them cleanly.
27 * At present, they often confuse the result.
28 *
29 * See HTTP/1.1 section 14 for details.
30 *
31 * @param string $rawHeader
32 *
33 * @return array
34 */
35 public function parseWeights( $rawHeader ) {
36 //FIXME: The code below was copied and adapted from WebRequest::getAcceptLang.
37 // Move this utility class into core for reuse!
38
39 // first, strip header name
40 $rawHeader = preg_replace( '/^[-\w]+:\s*/', '', $rawHeader );
41
42 // Return values in lower case
43 $rawHeader = strtolower( $rawHeader );
44
45 // Break up string into pieces (values and q factors)
46 $value_parse = null;
47 preg_match_all( '@([a-z\d*]+([-+/.][a-z\d*]+)*)\s*(;\s*q\s*=\s*(1(\.0{0,3})?|0(\.\d{0,3})?)?)?@',
48 $rawHeader, $value_parse );
49
50 if ( !count( $value_parse[1] ) ) {
51 return [];
52 }
53
54 $values = $value_parse[1];
55 $qvalues = $value_parse[4];
56 $indices = range( 0, count( $value_parse[1] ) - 1 );
57
58 // Set default q factor to 1
59 foreach ( $indices as $index ) {
60 if ( $qvalues[$index] === '' ) {
61 $qvalues[$index] = 1;
62 } elseif ( $qvalues[$index] == 0 ) {
63 unset( $values[$index], $qvalues[$index], $indices[$index] );
64 } else {
65 $qvalues[$index] = (float)$qvalues[$index];
66 }
67 }
68
69 // Sort list. First by $qvalues, then by order. Reorder $values the same way
70 array_multisort( $qvalues, SORT_DESC, SORT_NUMERIC, $indices, $values );
71
72 // Create a list like "en" => 0.8
73 $weights = array_combine( $values, $qvalues );
74
75 return $weights;
76 }
77
78 }