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