Completed
Push — master ( 0f8e30...cf8497 )
by Ivan
01:53
created

BrowserLocale::filterLocaleInfo()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.2
cc 4
eloc 6
nc 3
nop 1
crap 4
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
        if ( ! in_array($property, $this->filters)) {
52 3
            return $this->locales;
53
        }
54
55 6
        return $this->filterLocaleInfo($property);
56
    }
57
58
    /**
59
     * Parse all HTTP Accept Languages.
60
     *
61
     * @param string $httpAcceptLanguages
62
     *
63
     * @return void
64
     */
65 9
    protected function parseHttpAcceptLanguages($httpAcceptLanguages)
66
    {
67 9
        $locales = $this->split($httpAcceptLanguages, ',');
68
69 9
        foreach ($locales as $httpAcceptLanguage) {
70 9
            $this->makeLocale($httpAcceptLanguage);
71
        }
72
73 9
        $this->sortLocales();
74 9
    }
75
76
    /**
77
     * Convert the given HTTP Accept Language to a Locale object.
78
     *
79
     * @param string $httpAcceptLanguage
80
     *
81
     * @return void
82
     */
83 9
    protected function makeLocale($httpAcceptLanguage)
84
    {
85 9
        $parts = $this->split($httpAcceptLanguage, ';');
86
87 9
        $locale = $parts[0];
88 9
        $weight = $parts[1] ?? null;
89
90 9
        if (empty($locale)) {
91 2
            return;
92
        }
93
94 7
        $this->locales[] = new Locale(
95 7
            $locale,
96 7
            $this->getLanguage($locale),
97 7
            $this->getCountry($locale),
98 7
            $this->getWeight($weight)
99
        );
100 7
    }
101
102
    /**
103
     * Split the given string by the delimiter.
104
     *
105
     * @param string $string
106
     * @param string $delimiter
107
     *
108
     * @return array
109
     */
110 9
    protected function split($string, $delimiter)
111
    {
112 9
        return explode($delimiter, trim($string)) ?: [];
113
    }
114
115
    /**
116
     * Get the 2-letter language code from the locale.
117
     *
118
     * @param string $locale
119
     *
120
     * @return string
121
     */
122 7
    protected function getLanguage($locale)
123
    {
124 7
        return substr($locale, 0, 2) ?: '';
125
    }
126
127
    /**
128
     * Get the 2-letter country code from the locale.
129
     *
130
     * @param string $locale
131
     *
132
     * @return string
133
     */
134 7
    protected function getCountry($locale)
135
    {
136 7
        return substr($locale, 3, 2) ?: '';
137
    }
138
139
    /**
140
     * Parse the relative quality factor and return its value.
141
     *
142
     * @param string $q
143
     *
144
     * @return float
145
     */
146 7
    protected function getWeight($q)
147
    {
148 7
        $parts = $this->split($q, '=');
149
150 7
        $weight = $parts[1] ?? 1.0;
151
152 7
        return (float) $weight;
153
    }
154
155
    /**
156
     * Sort the array of locales in descending order of preference.
157
     *
158
     * @return void
159
     */
160
    protected function sortLocales()
161
    {
162 9
        usort($this->locales, function ($a, $b) {
163 7
            if ($a->weight === $b->weight) {
164 1
                return 0;
165
            }
166
167 7
            return ($a->weight > $b->weight) ? -1 : 1;
168 9
        });
169 9
    }
170
171
    /**
172
     * Get a flattened array of locale information,
173
     * containing only the requested property values.
174
     *
175
     * @param string $property
176
     *
177
     * @return array
178
     */
179 6
    protected function filterLocaleInfo($property)
180
    {
181 6
        $filtered = [];
182
183 6
        foreach ($this->locales as $locale) {
184 4
            if ($locale->$property && ! in_array($locale->$property, $filtered)) {
185 4
                $filtered[] = $locale->$property;
186
            }
187
        }
188
189 6
        return $filtered;
190
    }
191
}
192