Issues (37)

src/AppserverIo/Resources/SystemLocale.php (6 issues)

1
<?php
2
3
/**
4
 * AppserverIo\Resources\SystemLocale
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2018 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/resources
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Resources;
22
23
use AppserverIo\Lang\Object;
24
use AppserverIo\Lang\String;
25
use AppserverIo\Lang\NullPointerException;
26
use AppserverIo\Collections\ArrayList;
27
use AppserverIo\Collections\CollectionUtils;
28
use AppserverIo\Resources\Predicates\SystemLocaleExistsPredicate;
29
30
/**
31
 * A Locale object represents a specific geographical, political, or cultural
32
 * region. An operation that requires a Locale to perform its task is called
33
 * locale-sensitive and uses the Locale  to tailor information for the user.
34
 * For example, displaying a number is a locale-sensitive operation--the number
35
 * should be formatted according to the customs/conventions of the user's native
36
 * country, region, or culture.
37
 *
38
 * The language argument is a valid ISO Language Code. These codes are the
39
 * lower-case, two-letter codes as defined by ISO-639. You can find a full list
40
 * of these codes at a number of sites, such as:
41
 * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
42
 *
43
 * The country argument is a valid ISO Country Code. These codes are the
44
 * upper-case, two-letter codes as defined by ISO-3166. You can find a full list
45
 * of these codes at a number of sites, such as:
46
 * http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
47
 *
48
 * The variant argument is a vendor or browser-specific code. For example, use
49
 * WIN for Windows, MAC for Macintosh, and POSIX for POSIX. Where there are two
50
 * variants, separate them with an underscore, and put the most important one
51
 * first. For example, a Traditional Spanish collation might construct a locale
52
 * with parameters for language, country and variant as: "es", "ES",
53
 * "Traditional_WIN".
54
 *
55
 * Because a Locale object is just an identifier for a region, no validity check
56
 * is performed when you construct a Locale. If you want to see whether
57
 * particular resources are available for the Locale you construct, you must
58
 * query those resources. For example, ask the NumberFormat for the locales it
59
 * supports using its getAvailableLocales method.
60
 *
61
 * Note: When you ask for a resource for a particular locale, you get back the
62
 * best available match, not necessarily precisely what you asked for. For more
63
 * information, look at ResourceBundle.
64
 *
65
 * The Locale class provides a number of convenient constants that you can use
66
 * to create Locale objects for commonly used locales. For example, the
67
 * following creates a Locale object for the United States:
68
 *
69
 * SystemLocale::create(SystemLocale::US)
70
 *
71
 * Once you've created a Locale you can query it for information about itself.
72
 * Use getCountry to get the ISO Country Code and getLanguage to get the ISO
73
 * Language Code. You can use getDisplayCountry to get the name of the country
74
 * suitable for displaying to the user. Similarly, you can use
75
 * getDisplayLanguage to get the name of the language suitable for displaying
76
 * to the user. Interestingly, the getDisplayXXX methods are themselves
77
 * locale-sensitive and have two versions: one that uses the default locale and
78
 * one that uses the locale specified as an argument.
79
 *
80
 * @author    Tim Wagner <[email protected]>
81
 * @copyright 2018 TechDivision GmbH <[email protected]>
82
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
83
 * @link      https://github.com/appserver-io/resources
84
 * @link      http://www.appserver.io
85
 */
86
class SystemLocale extends Object
87
{
88
89
    /**
90
     * Holds the constant for the United States locale string.
91
     *
92
     * @var string
93
     */
94
    const US = 'en_US';
95
96
    /**
97
     * Holds the constant for the United Kingdom locale string.
98
     *
99
     * @var string
100
     */
101
    const UK = 'en_UK';
102
103
    /**
104
     * Holds the constant for the Germany locale string.
105
     *
106
     * @var string
107
     */
108
    const GERMANY = 'de_DE';
109
110
    /**
111
     * Holds the language.
112
     *
113
     * @var \AppserverIo\Lang\String
114
     */
115
    protected $language = null;
116
117
    /**
118
     * Holds the country.
119
     *
120
     * @var \AppserverIo\Lang\String
121
     */
122
    protected $country = null;
123
124
    /**
125
     * Holds the variant.
126
     *
127
     * @var \AppserverIo\Lang\String
128
     */
129
    protected $variant = null;
130
131
    /**
132
     * Construct a locale from language, country, variant. NOTE: ISO 639 is not
133
     * a stable standard; some of the language codes it defines (specifically
134
     * iw, ji, and in) have changed. This constructor accepts both the old codes
135
     * (iw, ji, and in) and the new codes (he, yi, and id), but all other API on
136
     * Locale will return only the OLD codes.
137
     *
138
     * @param \AppserverIo\Lang\String $language The lowercase two-letter ISO-639 code
139
     * @param \AppserverIo\Lang\String $country  The uppercase two-letter ISO-3166 code
140
     * @param \AppserverIo\Lang\String $variant  The vendor and browser specific code. See class description
141
     */
142
    public function __construct(String $language, String $country = null, String $variant = null)
143
    {
144
145
        // initialize the language
146
        $this->language = $language;
0 ignored issues
show
Documentation Bug introduced by
It seems like $language of type string is incompatible with the declared type AppserverIo\Lang\String of property $language.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
147
148
        // initialize the country and the variant with the passed values
149
        $this->country = new String($country);
150
        $this->variant = new String($variant);
151
152
        // initialize the country and check if at least a language
153
        // or a country is passed
154
        if ($this->language->length() == 0 &&
155
            $this->country->length() == 0) {
156
            throw new NullPointerException(
157
                'Either language or country must have a value'
158
            );
159
        }
160
    }
161
162
    /**
163
     * This method tries to create a new Locale instance from
164
     * the passed string value.
165
     *
166
     * The passed string must have the following format: language_country
167
     *
168
     * @param string $localeString Holds the locale string to create the locale from
169
     *
170
     * @return \AppserverIo\Resources\SystemLocale Holds the initialized locale object
171
     */
172
    public static function create($localeString)
173
    {
174
175
        // split the passed string
176
        $elements = new ArrayList(explode("_", $localeString));
177
178
        // if only the language was found
179
        if ($elements->size() == 1) {
0 ignored issues
show
The condition $elements->size() == 1 is always false.
Loading history...
180
            // initialize a new Locale
181
            return new SystemLocale(new String($elements->get(0)));
182
        }
183
184
        // if the language and the country was found
185
        if ($elements->size() == 2) {
0 ignored issues
show
The condition $elements->size() == 2 is always false.
Loading history...
186
            // initialize a new Locale
187
            return new SystemLocale(
188
                new String($elements->get(0)),
189
                new String($elements->get(1))
190
            );
191
        }
192
193
        // if the language, the country and the variant was found
194
        if ($elements->size() == 3) {
0 ignored issues
show
The condition $elements->size() == 3 is always false.
Loading history...
195
            // initialize a new Locale
196
            return new SystemLocale(
197
                new String($elements->get(0)),
198
                new String($elements->get(1)),
199
                new String($elements->get(2))
200
            );
201
        }
202
    }
203
204
    /**
205
     * This method returns an ArrayList with the installed system locales.
206
     *
207
     * @return \AppserverIo\Collections\ArrayList Holds an ArrayList with Locale instances installed  on the actual system
208
     */
209
    public static function getAvailableLocales()
210
    {
211
212
        // initialize the ArrayList for the system locales
213
        $locales = new ArrayList();
214
215
        // initialize the result array
216
        $result = array();
217
218
        // get the list with locales
219
        exec('locale -a', $result);
220
221
        // initialize the Locale instances and add them the ArrayList
222
        foreach ($result as $locale) {
223
            // initialize the array with the found locales
224
            $locales->add(SystemLocale::create(trim($locale)));
0 ignored issues
show
trim($locale) of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $localeString of AppserverIo\Resources\SystemLocale::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

224
            $locales->add(SystemLocale::create(/** @scrutinizer ignore-type */ trim($locale)));
Loading history...
225
        }
226
227
        // return the locales
228
        return $locales;
229
    }
230
231
    /**
232
     * Getter for the programmatic name of the entire locale, with the language, country and variant separated by underbars.
233
     *
234
     * @return \AppserverIo\Lang\String Holds the entire locale as String object
235
     * @see \AppserverIo\Resources\SystemLocale::__toString()
236
     */
237
    public function toString()
238
    {
239
        return new String($this->__toString());
240
    }
241
242
    /**
243
     * Getter for the programmatic name of the entire locale, with the language, country and variant separated by underbars.
244
     *
245
     * @return string Holds the entire locale as string
246
     * @see \AppserverIo\Resources\SystemLocale::toString()
247
     */
248
    public function __toString()
249
    {
250
        $string = '';
251
        if (!$this->language->length() == 0) {
252
            $string = $this->language->stringValue();
253
        }
254
        if (!$this->country->length() == 0) {
255
            $string .= "_" . $this->country->stringValue();
256
        }
257
        if (!$this->variant->length() == 0) {
258
            $string .= "_" . $this->variant->stringValue();
259
        }
260
        return $string;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $string returns the type string which is incompatible with the documented return type AppserverIo\Lang\String.
Loading history...
261
    }
262
263
    /**
264
     * Sets the default locale, but does not set the system locale.
265
     *
266
     * @param \AppserverIo\Resources\SystemLocale $newLocale Holds the new default system locale to use
267
     *
268
     * @return void
269
     * @throws \Exception Is thrown if the passed locale is not installed in the system
270
     */
271
    public static function setDefault(SystemLocale $newLocale)
272
    {
273
274
        // check if the passed locale is installed
275
        if (!CollectionUtils::exists(SystemLocale::getAvailableLocales(), new SystemLocaleExistsPredicate($newLocale))) {
276
            throw new \Exception('System locale ' . $newLocale . ' is not installed');
277
        }
278
279
        // set the default system locale
280
        if (!setlocale(LC_ALL, $newLocale)) {
281
            throw new \Exception('Default locale can\'t be set to ' . $newLocale);
282
        }
283
    }
284
285
    /**
286
     * Returns the default system locale.
287
     *
288
     * @return \AppserverIo\Resources\SystemLocale Holds the default system locale
289
     * @throws \Exception If no system locale is set
290
     */
291
    public static function getDefault()
292
    {
293
294
        // initialize the variables
295
        $language = new String();
296
        $country = new String();
297
        $variant = new String();
298
299
        // get the default system locale
300
        $systemLocale = setlocale(LC_ALL, "0");
301
302
        // explode the parts
303
        $list = new ArrayList(explode("_", $systemLocale));
304
305
        // initialize the language, the country and the variant
306
        if ($list->size() > 0) {
307
            if ($list->exists(0)) {
308
                $language = new String($list->get(0));
309
            }
310
            if ($list->exists(1)) {
311
                $country = new String($list->get(1));
312
            }
313
            if ($list->exists(2)) {
314
                $variant = new String($list->get(2));
315
            }
316
317
        } else {
318
            throw new \Exception("No system locale set");
319
        }
320
321
        // initialize and return the SystemLocale instance
322
        return new SystemLocale($language, $country, $variant);
323
    }
324
325
    /**
326
     * Returns the language.
327
     *
328
     * @return String Holds the language
329
     */
330
    public function getLanguage()
331
    {
332
        return $this->language;
333
    }
334
335
    /**
336
     * Returns the country.
337
     *
338
     * @return String Holds the country
339
     */
340
    public function getCountry()
341
    {
342
        return $this->country;
343
    }
344
345
    /**
346
     * Returns the variant.
347
     *
348
     * @return String Holds the variant
349
     */
350
    public function getVariant()
351
    {
352
        return $this->variant;
353
    }
354
355
    /**
356
     * Returns true if the passed value is equal.
357
     *
358
     * @param \AppserverIo\Lang\Object $val The value to check
359
     *
360
     * @return boolean TRUE if the passed object is equal, else FALSE
361
     */
362
    public function equals(Object $val)
363
    {
364
        return $this->__toString() == $val->__toString();
365
    }
366
}
367