Completed
Push — master ( 39ec1b...93bdb4 )
by Michal
04:12
created

Loader::detectlocale()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.0342

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 13
ccs 8
cts 9
cp 0.8889
rs 8.8571
cc 5
eloc 10
nc 5
nop 0
crap 5.0342
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 Loader {
27
    /**
28
     * Loader instance
29
     *
30
     * @access private
31
     * @static
32
     * @var Loader
33
     */
34
    private static $_instance;
35
36
    /**
37
     * Default gettext domain to use.
38
     *
39
     * @var string
40
     */
41
    private $default_domain = '';
42
43
    /**
44
     * Configured locale.
45
     *
46
     * @var string
47
     */
48
    private $locale = '';
49
50
    /**
51
     * Loaded domains
52
     *
53
     * @var array
54
     */
55
    private $domains = array();
56
57
    /**
58
     * Bound paths for domains
59
     *
60
     * @var array
61
     */
62
    private $paths = array('' => './');
63
64
    /**
65
     * Returns the singleton Loader object
66
     *
67
     * @return Loader object
68
     */
69 4
    public static function getInstance()
70
    {
71 4
        if (empty(self::$_instance)) {
72 1
            self::$_instance = new Loader();
73 1
        }
74 4
        return self::$_instance;
75 1
    }
76
77
    /**
78
     * Loads global localizaton functions.
79
     *
80
     * @return void
81
     */
82 2
    public static function load_functions()
83
    {
84 2
        require_once __DIR__ . '/functions.php';
85 2
    }
86
87
    /**
88
     * Figure out all possible locale names and start with the most
89
     * specific ones.  I.e. for sr_CS.UTF-8@latin, look through all of
90
     * sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr.
91
     *
92
     * @param string $locale Locale code
93
     *
94
     * @return array list of locales to try for any POSIX-style locale specification.
95
     */
96 18
    public static function list_locales($locale) {
97 18
        $locale_names = array();
98
99 18
        $lang = NULL;
100 18
        $country = NULL;
101 18
        $charset = NULL;
102 18
        $modifier = NULL;
103
104 18
        if ($locale) {
105 17
            if (preg_match("/^(?P<lang>[a-z]{2,3})"      // language code
106
                ."(?:_(?P<country>[A-Z]{2}))?"           // country code
107 17
                ."(?:\.(?P<charset>[-A-Za-z0-9_]+))?"    // charset
108 17
                ."(?:@(?P<modifier>[-A-Za-z0-9_]+))?$/", // @ modifier
109 17
                $locale, $matches)) {
110
111 16
                extract($matches);
112
113 16
                if ($modifier) {
114 5 View Code Duplication
                    if ($country) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115 2
                        if ($charset) {
116 2
                            array_push($locale_names, "${lang}_$country.$charset@$modifier");
117 2
                        }
118 2
                        array_push($locale_names, "${lang}_$country@$modifier");
119 5
                    } elseif ($charset) {
120 1
                        array_push($locale_names, "${lang}.$charset@$modifier");
121 1
                    }
122 5
                    array_push($locale_names, "$lang@$modifier");
123 5
                }
124 View Code Duplication
                if ($country) {
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
                    if ($charset) {
126
                        array_push($locale_names, "${lang}_$country.$charset");
127
                    }
128
                    array_push($locale_names, "${lang}_$country");
129 16
                } elseif ($charset) {
130 2
                    array_push($locale_names, "${lang}.$charset");
131 2
                }
132 16
                array_push($locale_names, $lang);
133 16
            }
134
135
            // If the locale name doesn't match POSIX style, just include it as-is.
136 17
            if (!in_array($locale, $locale_names)) {
137 1
                array_push($locale_names, $locale);
138 1
            }
139 17
        }
140 18
        return $locale_names;
141
    }
142
143
    /**
144
     * Returns Translator object for domain or for default domain
145
     *
146
     * @param string $domain Translation domain
147
     *
148
     * @return Translator
149
     */
150
    public function get_translator($domain = '')
151
    {
152 9
        if (empty($domain)) {
153 6
            $domain = $this->default_domain;
154 6
        }
155
156 9
        if (!isset($this->domains[$domain])) {
157
158 7
            if (isset($this->paths[$domain])) {
159 5
                $base = $this->paths[$domain];
160 5
            } else {
161 2
                $base = './';
162
            }
163
164 7
            $locale_names = $this->list_locales($this->locale);
165
166 7
            $filename = '';
167 7
            foreach ($locale_names as $locale) {
168 7
                $filename = "$base/$locale/LC_MESSAGES/$domain.mo";
169 7
                if (file_exists($filename)) {
170 5
                    break;
171
                }
172 7
            }
173
174
            // We don't care about invalid path, we will get fallback
175
            // translator here
176 7
            $this->domains[$domain] = new Translator($filename);
177 7
        }
178
179 9
        return $this->domains[$domain];
180
    }
181
182
    /**
183
     * Sets the path for a domain.
184
     *
185
     * @param string $domain Domain name
186
     * @param string $path   Path where to find locales
187
     *
188
     * @return void
189
     */
190
    public function bindtextdomain($domain, $path)
191
    {
192 9
        $this->paths[$domain] = $path;
193 9
    }
194
195
    /**
196
     * Sets the default domain.
197
     *
198
     * @param string $domain Domain name
199
     *
200
     * @return void
201
     */
202
    public function textdomain($domain)
203
    {
204 9
        $this->default_domain = $domain;
205 9
    }
206
207
    /**
208
     * Sets a requested locale
209
     *
210
     * @param string $locale Locale name
211
     *
212
     * @return string Set or current locale
213
     */
214
    public function setlocale($locale)
215
    {
216 9
        if (!empty($locale)) {
217 9
            $this->locale = $locale;
218
            // Set system locales as well
219 9
            if (function_exists('setlocale')) {
220 9
                setlocale(0, $locale);
221 9
            }
222 9
        }
223 9
        return $this->locale;
224
    }
225
226
    /**
227
     * Detects currently configured locale
228
     *
229
     * It checks:
230
     *
231
     * - global lang variable
232
     * - environment for LC_ALL, LC_MESSAGES and LANG
233
     *
234
     * @return string with locale name
235
     */
236
    public function detectlocale()
1 ignored issue
show
Coding Style introduced by
detectlocale uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
237
    {
238 1
        if (isset($GLOBALS['lang'])) {
239 1
            return $GLOBALS['lang'];
240 1
        } elseif (getenv('LC_ALL')) {
241 1
            return getenv('LC_ALL');
242 1
        } elseif (getenv('LC_MESSAGES')) {
243 1
            return getenv('LC_MESSAGES');
244 1
        } elseif (getenv('LANG')) {
245 1
            return getenv('LANG');
246
        }
247
        return 'en';
248
    }
249
}
250