Completed
Push — master ( 4b4318...02813d )
by Ivan
01:55
created

BrowserLocale::splitAcceptLanguage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace CodeZero\BrowserLocale;
4
5
class BrowserLocale
6
{
7
    /**
8
     * Array of \CodeZero\BrowserLocale\Locale instances.
9
     *
10
     * @var array
11
     */
12
    protected $locales = [];
13
14
    /**
15
     * Supported filters for getLocales().
16
     *
17
     * @var array
18
     */
19
    protected $filters = ['locale', 'language', 'country', 'weight'];
20
21
    /**
22
     * Create a new BrowserLocale instance.
23
     *
24
     * @param string $httpAcceptLanguages
25
     */
26 9
    public function __construct($httpAcceptLanguages)
27
    {
28 9
        $this->parseHttpAcceptLanguages($httpAcceptLanguages);
29 9
    }
30
31
    /**
32
     * Get the most preferred locale.
33
     *
34
     * @return \CodeZero\BrowserLocale\Locale|null
35
     */
36 4
    public function getLocale()
37
    {
38 4
        return $this->locales[0] ?? null;
39
    }
40
41
    /**
42
     * Get an array of Locale objects in descending order of preference.
43
     * Specify a Locale property to get a flattened array of values of that property.
44
     *
45
     * @param string $property
46
     *
47
     * @return array
48
     */
49 7
    public function getLocales($property = null)
50
    {
51 7
        return $this->filterLocaleInfo($property);
52
    }
53
54
    /**
55
     * Parse all HTTP Accept Languages.
56
     *
57
     * @param string $httpAcceptLanguages
58
     *
59
     * @return void
60
     */
61 9
    protected function parseHttpAcceptLanguages($httpAcceptLanguages)
62
    {
63 9
        $locales = $this->split($httpAcceptLanguages, ',');
64
65 9
        foreach ($locales as $httpAcceptLanguage) {
66 9
            $this->makeLocale($httpAcceptLanguage);
67
        }
68
69 9
        $this->sortLocales();
70 9
    }
71
72
    /**
73
     * Convert the given HTTP Accept Language to a Locale object.
74
     *
75
     * @param string $httpAcceptLanguage
76
     *
77
     * @return void
78
     */
79 9
    protected function makeLocale($httpAcceptLanguage)
80
    {
81 9
        $parts = $this->split($httpAcceptLanguage, ';');
82
83 9
        $locale = $parts[0];
84 9
        $weight = $parts[1] ?? null;
85
86 9
        if (empty($locale)) {
87 2
            return;
88
        }
89
90 7
        $this->locales[] = new Locale(
91 7
            $locale,
92 7
            $this->getLanguage($locale),
93 7
            $this->getCountry($locale),
94 7
            $this->getWeight($weight)
95
        );
96 7
    }
97
98
    /**
99
     * Split the given string by the delimiter.
100
     *
101
     * @param string $string
102
     * @param string $delimiter
103
     *
104
     * @return array
105
     */
106 9
    protected function split($string, $delimiter)
107
    {
108 9
        return explode($delimiter, trim($string)) ?: [];
109
    }
110
111
    /**
112
     * Get the 2-letter language code from the locale.
113
     *
114
     * @param string $locale
115
     *
116
     * @return string
117
     */
118 7
    protected function getLanguage($locale)
119
    {
120 7
        return substr($locale, 0, 2) ?: '';
121
    }
122
123
    /**
124
     * Get the 2-letter country code from the locale.
125
     *
126
     * @param string $locale
127
     *
128
     * @return string
129
     */
130 7
    protected function getCountry($locale)
131
    {
132 7
        return substr($locale, 3, 2) ?: '';
133
    }
134
135
    /**
136
     * Parse the relative quality factor and return its value.
137
     *
138
     * @param string $q
139
     *
140
     * @return float
141
     */
142 7
    protected function getWeight($q)
143
    {
144 7
        $parts = $this->split($q, '=');
145
146 7
        $weight = $parts[1] ?? 1.0;
147
148 7
        return (float) $weight;
149
    }
150
151
    /**
152
     * Sort the array of locales in descending order of preference.
153
     *
154
     * @return void
155
     */
156
    protected function sortLocales()
157
    {
158 9
        usort($this->locales, function ($a, $b) {
159 7
            if ($a->weight === $b->weight) {
160 1
                return 0;
161
            }
162
163 7
            return ($a->weight > $b->weight) ? -1 : 1;
164 9
        });
165 9
    }
166
167
    /**
168
     * Get a flattened array of locale information,
169
     * containing only the requested property values.
170
     *
171
     * @param string $property
172
     *
173
     * @return array
174
     */
175 7
    protected function filterLocaleInfo($property)
176
    {
177 7
        $locales = $this->locales;
178
179 7
        if ( ! in_array($property, $this->filters)) {
180 3
            return $locales;
181
        }
182
183 6
        $filtered = [];
184
185 6
        foreach ($locales as $locale) {
186 4
            if ($locale->$property && ! in_array($locale->$property, $filtered)) {
187 4
                $filtered[] = $locale->$property;
188
            }
189
        }
190
191 6
        return $filtered;
192
    }
193
}
194