Completed
Push — master ( ee2839...95eb94 )
by Michal
02:54
created

MoLoader::load_functions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/*
3
    Copyright (c) 2005 Steven Armstrong <sa at c-area dot ch>
4
    Copyright (c) 2009 Danilo Segan <[email protected]>
5
    Copyright (c) 2016 Michal Čihař <[email protected]>
6
7
    This file is part of MoTranslator.
8
9
    This program is free software; you can redistribute it and/or modify
10
    it under the terms of the GNU General Public License as published by
11
    the Free Software Foundation; either version 2 of the License, or
12
    (at your option) any later version.
13
14
    This program is distributed in the hope that it will be useful,
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
    GNU General Public License for more details.
18
19
    You should have received a copy of the GNU General Public License along
20
    with this program; if not, write to the Free Software Foundation, Inc.,
21
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
*/
23
24
namespace MoTranslator;
25
26
class MoLoader {
27
    /**
28
     * Loader instance
29
     *
30
     * @access private
31
     * @static
32
     * @var MoLoader
33
     */
34
    private static $_instance;
35
36
    /**
37
     * @var string Default gettext domain to use.
38
     */
39
    private $default_domain = '';
40
41
    /**
42
     * @var string Configured locale.
43
     */
44
    private $locale = '';
45
46
    /**
47
     * @var array Loaded domains
48
     */
49
    private $domains = array();
50
51
    /**
52
     * @var array Bound paths for domains
53
     */
54
    private $paths = array('' => './');
55
56
    /**
57
     * Returns the singleton Response object
58
     *
59
     * @return Response object
60
     */
61 3
    public static function getInstance()
62
    {
63 3
        if (empty(self::$_instance)) {
64 1
            self::$_instance = new MoLoader();
65 1
        }
66 3
        return self::$_instance;
67 1
    }
68
69
    /**
70
     * Loads global localizaton functions.
71
     *
72
     * @return void
73
     */
74 2
    public static function load_functions()
75
    {
76 2
        require_once __DIR__ . '/functions.php';
77 2
    }
78
79
    /**
80
     * Figure out all possible locale names and start with the most
81
     * specific ones.  I.e. for sr_CS.UTF-8@latin, look through all of
82
     * sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr.
83
     *
84
     * @param string $locale Locale code
85
     *
86
     * @return array list of locales to try for any POSIX-style locale specification.
87
     */
88 17
    static public function list_locales($locale) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
89 17
        $locale_names = array();
90
91 17
        $lang = NULL;
92 17
        $country = NULL;
93 17
        $charset = NULL;
94 17
        $modifier = NULL;
95
96 17
        if ($locale) {
97 16
            if (preg_match("/^(?P<lang>[a-z]{2,3})"              // language code
98
                ."(?:_(?P<country>[A-Z]{2}))?"           // country code
99 16
                ."(?:\.(?P<charset>[-A-Za-z0-9_]+))?"    // charset
100 16
                ."(?:@(?P<modifier>[-A-Za-z0-9_]+))?$/",  // @ modifier
101 16
                $locale, $matches)) {
102
103 15
                extract($matches);
104
105 15
                if ($modifier) {
106 4
                    if ($country) {
107 2
                        if ($charset) {
108 2
                            array_push($locale_names, "${lang}_$country.$charset@$modifier");
109 2
                        }
110 2
                        array_push($locale_names, "${lang}_$country@$modifier");
111 4
                    } elseif ($charset)
112
                        array_push($locale_names, "${lang}.$charset@$modifier");
113 4
                        array_push($locale_names, "$lang@$modifier");
114 4
                    }
115
                if ($country) {
116
                    if ($charset) {
117
                        array_push($locale_names, "${lang}_$country.$charset");
118
                    }
119
                    array_push($locale_names, "${lang}_$country");
120 15
                } elseif ($charset) {
121 1
                    array_push($locale_names, "${lang}.$charset");
122 1
                }
123 15
                array_push($locale_names, $lang);
124 15
            }
125
126
            // If the locale name doesn't match POSIX style, just include it as-is.
127 16
            if (!in_array($locale, $locale_names)) {
128 1
                array_push($locale_names, $locale);
129 1
            }
130 16
        }
131 17
        return $locale_names;
132
    }
133
134
    public function get_translator($domain='')
135
    {
136 9
        if (empty($domain)) {
137 6
            $domain = $this->default_domain;
138 6
        }
139
140 9
        if (!isset($this->domains[$domain])) {
141
142 7
            if (isset($this->paths[$domain])) {
143 5
                $base = $this->paths[$domain];
144 5
            } else {
145 2
                $base = './';
146
            }
147
148 7
            $locale_names = $this->list_locales($this->locale);
149
150 7
            foreach ($locale_names as $locale) {
151 7
                $full_path = "$base/$locale/LC_MESSAGES/$domain.mo";
152 7
                if (file_exists($full_path)) {
153 5
                    break;
154
                }
155 7
            }
156
157
            // We don't care about invalid path, we will get fallback
158
            // translator here
159 7
            $this->domains[$domain] = new MoTranslator($full_path);
0 ignored issues
show
Bug introduced by
The variable $full_path does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
160 7
        }
161
162 9
        return $this->domains[$domain];
163
    }
164
165
    public function bindtextdomain($domain, $path)
166
    {
167 9
        $this->paths[$domain] = $path;
168 9
    }
169
170
    public function textdomain($domain)
171
    {
172 9
        $this->default_domain = $domain;
173 9
    }
174
175
    public function setlocale($locale)
176
    {
177 9
        if (!empty($locale)) {
178 9
            $this->locale = $locale;
179
            // Set system locales as well
180 9
            if (function_exists('setlocale')) {
181 9
                setlocale(LC_MESSAGES, $locale);
182 9
            }
183 9
        }
184 9
        return $this->locale;
185
    }
186
}
187