LanguageStringParser   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 130
ccs 51
cts 51
cp 1
rs 10
c 0
b 0
f 0
wmc 26

10 Methods

Rating   Name   Duplication   Size   Complexity  
B _compare_languages_by_wildcard() 0 21 5
C _compare_languages_by_variant() 0 25 7
A create_from_string() 0 5 1
A __construct() 0 2 1
A _compare_languages_by_weight_only() 0 4 1
B _compare_languages() 0 24 4
A create_empty_parser() 0 3 1
A create_from_array() 0 15 4
A get_languages() 0 3 1
A get_languages_ordered() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Vendi\HttpLanguageHelper;
6
7
final class LanguageStringParser
8
{
9
    private $languages = [];
10
11 3
    public function get_languages() : array
12
    {
13 3
        return $this->languages;
14
    }
15
16 13
    private function __construct()
17
    {
18
        //NOOP
19 13
    }
20
21 12
    public static function create_empty_parser() : self
22
    {
23 12
        return new self();
24
    }
25
26 3
    public static function create_from_string(string $languages) : self
27
    {
28 3
        $parts = explode(',', $languages);
29
30 3
        return self::create_from_array($parts);
31
    }
32
33 3
    public static function create_from_array(array $languages) : self
34
    {
35 3
        $obj = new self();
36
37 3
        foreach ($languages as $part) {
38 3
            $string = trim($part);
39 3
            if ($string) {
40 3
                $lang = (new Language)->with_string($string);
41 3
                if (!$lang->get_last_error()) {
42 3
                    $obj->languages[] = $lang;
43
                }
44
            }
45
        }
46
47 3
        return $obj;
48
    }
49
50 1
    public function get_languages_ordered() : array
51
    {
52 1
        $ret = $this->get_languages();
53 1
        usort($ret, [ $this, '_compare_languages' ]);
54 1
        return $ret;
55
    }
56
57 8
    public function _compare_languages(Language $a, Language $b) : int
58
    {
59
        //Priorities always win unless they are the same
60 8
        $weight_result = $this->_compare_languages_by_weight_only($a, $b);
61 8
        if (0 !== $weight_result) {
62 2
            return $weight_result;
63
        }
64
65
        //Wildcards are the least-specific. If they exist they should
66
        //always be sorted lowest.
67 6
        $wildcard_result = $this->_compare_languages_by_wildcard($a, $b);
68 6
        if (0 !== $wildcard_result) {
69 3
            return $wildcard_result;
70
        }
71
72
        //Lastly, look at variants. The presence of means that they
73
        //are more specific.
74 3
        $variant_result = $this->_compare_languages_by_variant($a, $b);
75 3
        if (0 !== $variant_result) {
76 2
            return $variant_result;
77
        }
78
79
        //As far as we can tell they are the same
80 1
        return 0;
81
    }
82
83 9
    public function _compare_languages_by_weight_only(Language $a, Language $b) : int
84
    {
85
        //Reverse directions because higher numbers sort lower
86 9
        return $b->get_weight() <=> $a->get_weight();
87
    }
88
89 7
    public function _compare_languages_by_wildcard(Language $a, Language $b) : int
90
    {
91
        //I know this can be simplified but I prefer to break them out.
92
93
        //Both wildcard. Weird. Whatever.
94 7
        if ('*' === $a->get_language() && '*' === $b->get_language()) {
95 1
            return 0;
96
        }
97
98
        //If A is a wildcard then B is more specific and should be preferred
99 7
        if ('*' === $a->get_language()) {
100 3
            return 1;
101
        }
102
103
        //If B is a wildcard then A is more specific and should be preferred
104 5
        if ('*' === $b->get_language()) {
105 2
            return -1;
106
        }
107
108
        //Both have languages and we can't tell further, same
109 4
        return 0;
110
    }
111
112 4
    public function _compare_languages_by_variant(Language $a, Language $b) : int
113
    {
114
        //Neither has a variant, same.
115
        //en and en
116 4
        if (!$a->get_variant() && !$b->get_variant()) {
117 1
            return 0;
118
        }
119
120
        //A has a variant but B doesn't, A wins
121
        //en-US and en
122 4
        if ($a->get_variant() && !$b->get_variant()) {
123 2
            return -1;
124
        }
125
126
        //B has a variant but A doesn't, B wins
127
        //en and en-US
128 3
        if (!$a->get_variant() && $b->get_variant()) {
129 2
            return 1;
130
        }
131
132
        //String comparison isn't done on variants unless someone has local-only
133
        //rules. For this, if they both have a variant then regardless of the
134
        //value they are considered the same. So en-US and en-GB are weighted
135
        //the same.
136 2
        return 0;
137
    }
138
}
139