GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (3647)

symphony/lib/toolkit/class.lang.php (34 issues)

1
<?php
2
/**
3
* @package toolkit
4
*/
5
6
/**
7
 * The Lang class loads and manages languages
8
 */
9
class Lang
10
{
11
    /**
12
     * Array of transliterations
13
     * @var array
14
     */
15
    private static $_transliterations;
16
17
    /**
18
     * Code of active language
19
     * @var string
20
     */
21
    private static $_lang;
22
23
    /**
24
     * Context information of all available languages
25
     * @var array
26
     */
27
    private static $_languages;
28
29
    /**
30
     * Array of localized strings
31
     * @var array
32
     */
33
    private static $_dictionary;
34
35
    /**
36
     * Array of localized date and time strings
37
     * @var array
38
     */
39
    private static $_datetime_dictionary;
40
41
    /**
42
     * Get the current dictionary
43
     *
44
     * @return array
45
     *  Return the dictionary
46
     */
47
    public static function Dictionary()
48
    {
49
        return self::$_dictionary;
50
    }
51
52
    /**
53
     * Get a list of either enabled or disabled languages. Example:
54
     *
55
     *      array(
56
     *          [...]
57
     *
58
     *          'en' => array(
59
     *              'name' => 'English',
60
     *              'handle' => 'english',
61
     *              'extensions' => array()
62
     *          ),
63
     *
64
     *          'it' => array(
65
     *              'name' => 'Italiano',
66
     *              'handle' => 'italian',
67
     *              'extensions' => array(
68
     *                  [...]
69
     *              )
70
     *          ),
71
     *
72
     *          [...]
73
     *      )
74
     *
75
     * @see toolkit.Lang#createLanguage()
76
     * @since Symphony 2.3
77
     * @return array
78
     *  Return an array of languages (both enabled and disabled)
79
     */
80
    public static function Languages()
81
    {
82
        return self::$_languages;
83
    }
84
85
    /**
86
     * Get transliterations
87
     *
88
     * @return array
89
     *  Returns the transliterations array
90
     */
91
    public static function Transliterations()
92
    {
93
        return self::$_transliterations;
94
    }
95
96
    /**
97
     * Initialize transliterations, datetime dictionary and languages array.
98
     */
99
    public static function initialize()
100
    {
101
        self::$_dictionary = array();
102
103
        // Load default datetime strings
104
        if (empty(self::$_datetime_dictionary)) {
105
            self::$_datetime_dictionary = include LANG . '/datetime.php';
0 ignored issues
show
The constant LANG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
106
        }
107
108
        // Load default transliterations
109
        if (empty(self::$_transliterations)) {
110
            self::$_transliterations = include LANG . '/transliterations.php';
111
        }
112
113
        // Load default English language
114
        if (empty(self::$_languages)) {
115
            self::$_languages = self::createLanguage('en', 'English', 'english');
116
        }
117
118
        // Fetch all available languages
119
        self::fetch();
120
    }
121
122
    /**
123
     * Create an array of Language information for internal use.
124
     *
125
     * @since Symphony 2.3
126
     * @param string $code
127
     *  Language code, e. g. 'en' or 'pt-br'
128
     * @param string $name
129
     *  Language name
130
     * @param string $handle (optional)
131
     *  Handle for the given language, used to build a valid 'lang_$handle' extension's handle.
132
     *  Defaults to null.
133
     * @param array $extensions (optional)
134
     *  An array of extensions that support the given language.
135
     * @return array
136
     *  An array of Language information.
137
     */
138
    private static function createLanguage($code, $name, $handle = null, array $extensions = array())
0 ignored issues
show
Incorrect spacing between argument "$handle" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$handle"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$extensions" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$extensions"; expected 0 but found 1
Loading history...
139
    {
140
        return array(
141
            $code => array(
142
                'name' => $name,
143
                'handle' => $handle,
144
                'extensions' => $extensions
145
            )
146
        );
147
    }
148
149
    /**
150
     * Fetch all languages available in the core language folder and the language extensions.
151
     * The function stores all language information in the private variable `$_languages`.
152
     * It contains an array with the name and handle of each language and an array of all
153
     * extensions available in that language.
154
     *
155
     * @throws UnexpectedValueException
156
     * @throws RuntimeException
157
     */
158
    private static function fetch()
159
    {
160
        if (!@is_readable(EXTENSIONS)) {
0 ignored issues
show
The constant EXTENSIONS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
161
            return;
162
        }
163
164
        // Fetch extensions
165
        $extensions = new FilesystemIterator(EXTENSIONS);
166
167
        // Language extensions
168
        foreach ($extensions as $extension) {
169
            if ($extension->isFile()) {
170
                continue;
171
            }
172
173
            // Core translations
174
            $core_handle = (strpos($extension->getFilename(), 'lang_') !== false)
175
                ? str_replace('lang_', '', $extension->getFilename())
0 ignored issues
show
Inline shorthand IF statement must be declared on a single line
Loading history...
176
                : null;
177
178
            // Loop over the `/lang` directory of this `$extension` searching for language
179
            // files. If `/lang` isn't a directory, `UnexpectedValueException` will be
180
            // thrown.
181
            try {
182
                $path = $extension->getPathname() . '/lang';
183
                if (!is_dir($path)) {
184
                    continue;
185
                }
186
187
                $directory = new GlobIterator($path . '/lang.*.php');
188
                foreach ($directory as $file) {
189
                    include($file->getPathname());
190
191
                    // Get language code (chars between lang. and .php)
192
                    $code = substr($file->getFilename(), 5, -4);
193
                    $lang = null;
194
                    $handle = null;
195
                    $extensions = array();
196
197
                    // Set lang, handle and extensions if defined.
198
                    if (isset(self::$_languages[$code])) {
199
                        $lang = self::$_languages[$code];
200
                        $handle = $lang['handle'];
201
                        $extensions = $lang['extensions'];
202
                    }
203
204
                    // Core translations
205
                    if ($core_handle) {
206
                        $handle = $core_handle;
207
208
                        // Extension translations
209
                    } else {
210
                        $extensions = array_merge(array($extension->getFilename()), $extensions);
211
                    }
212
213
                    // Merge languages ($about is declared inside the included $file)
214
                    $temp = self::createLanguage($code, $about['name'], $handle, $extensions);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $about seems to be never defined.
Loading history...
215
216
                    if (isset($lang)) {
217
                        foreach ($lang as $key => $value) {
218
                            // Prevent missing or nulled values overwriting existing values
219
                            // which can occur if a translation file is not correct.
220
                            if (!isset($temp[$code][$key]) || empty($temp[$code][$key])) {
221
                                continue;
222
                            }
223
224
                            self::$_languages[$code][$key] = $temp[$code][$key];
225
                        }
226
                    } else {
227
                        self::$_languages[$code] = $temp[$code];
228
                    }
229
                }
230
            } catch (Exception $ex) {
231
                continue;
232
            }
233
        }
234
    }
235
236
    /**
237
     * Set system language, load translations for core and extensions. If the specified language
238
     * cannot be found, Symphony will default to English.
239
     *
240
     * Note: Beginning with Symphony 2.2 translations bundled with extensions will only be loaded
241
     * when the core dictionary of the specific language is available.
242
     *
243
     * @param string $code
244
     *  Language code, e. g. 'en' or 'pt-br'
245
     * @param boolean $checkStatus (optional)
246
     *  If false, set the language even if it's not enabled. Defaults to true.
247
     */
248
    public static function set($code, $checkStatus = true)
0 ignored issues
show
Incorrect spacing between argument "$checkStatus" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$checkStatus"; expected 0 but found 1
Loading history...
249
    {
250
        if (!$code || $code == self::get()) {
251
            return;
252
        }
253
254
        // Language file available
255
        if ($code !== 'en' && (self::isLanguageEnabled($code) || $checkStatus === false)) {
256
            // Store desired language code
257
            self::$_lang = $code;
258
259
            // Clear dictionary
260
            self::$_dictionary = array();
261
262
            // Load core translations
263
            self::load(vsprintf('%s/lang_%s/lang/lang.%s.php', array(
264
                EXTENSIONS, self::$_languages[$code]['handle'], $code
0 ignored issues
show
The constant EXTENSIONS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
265
            )));
266
267
            // Load extension translations
268
            if (is_array(self::$_languages[$code]['extensions'])) {
269
                foreach (self::$_languages[$code]['extensions'] as $extension) {
270
                    self::load(vsprintf('%s/%s/lang/lang.%s.php', array(
271
                        EXTENSIONS, $extension, $code
272
                    )));
273
                }
274
            }
275
276
            // Language file unavailable, use default language
277
        } else {
278
            self::$_lang = 'en';
279
280
            // Log error, if possible
281
            if ($code !== 'en' && class_exists('Symphony', false) && Symphony::Log() instanceof Log) {
282
                Symphony::Log()->pushToLog(
283
                    __('The selected language, %s, could not be found. Using default English dictionary instead.', array($code)),
284
                    E_ERROR,
285
                    true
286
                );
287
            }
288
        }
289
    }
290
291
    /**
292
     * Given a valid language code, this function checks if the language is enabled.
293
     *
294
     * @since Symphony 2.3
295
     * @param string $code
296
     *  Language code, e. g. 'en' or 'pt-br'
297
     * @return boolean
298
     *  If true, the language is enabled.
299
     */
300
    public static function isLanguageEnabled($code)
301
    {
302
        if ($code == 'en') {
303
            return true;
304
        }
305
306
        $handle = (isset(self::$_languages[$code])) ? self::$_languages[$code]['handle'] : '';
307
        $enabled_extensions = array();
308
309
        // Fetch list of active extensions
310
        if (class_exists('Symphony', false) && (!is_null(Symphony::ExtensionManager()))) {
311
            $enabled_extensions = Symphony::ExtensionManager()->listInstalledHandles();
312
        }
313
314
        return in_array('lang_' . $handle, $enabled_extensions);
315
    }
316
317
    /**
318
     * Load language file. Each language file contains three arrays:
319
     * about, dictionary and transliterations.
320
     *
321
     * @param string $path
322
     *  Path of the language file that should be loaded
323
     */
324
    private static function load($path)
325
    {
326
        // Load language file
327
        if (file_exists($path)) {
328
            require($path);
329
        }
330
331
        // Populate dictionary ($dictionary is declared inside $path)
332
        if (isset($dictionary) && is_array($dictionary)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dictionary seems to never exist and therefore isset should always be false.
Loading history...
333
            self::$_dictionary = array_merge(self::$_dictionary, $dictionary);
334
        }
335
336
        // Populate transliterations ($transliterations is declared inside $path)
337
        if (isset($transliterations) && is_array($transliterations)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $transliterations seems to never exist and therefore isset should always be false.
Loading history...
338
            self::$_transliterations = array_merge(self::$_transliterations, $transliterations);
339
        }
340
    }
341
342
    /**
343
     * Get current language
344
     *
345
     * @return string
346
     */
347
    public static function get()
348
    {
349
        return self::$_lang;
350
    }
351
352
    /**
353
     * This function is an internal alias for `__()`.
354
     *
355
     * @since Symphony 2.3
356
     * @see toolkit.__()
357
     * @param string $string
358
     *  The string that should be translated
359
     * @param array $inserts (optional)
360
     *  Optional array used to replace translation placeholders, defaults to NULL
361
     * @param string $namespace (optional)
362
     *  Optional string used to define the namespace, defaults to NULL.
363
     * @return string
364
     *  Returns the translated string
365
     */
366
    public static function translate($string, array $inserts = null, $namespace = null)
0 ignored issues
show
Incorrect spacing between argument "$inserts" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$inserts"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$namespace" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$namespace"; expected 0 but found 1
Loading history...
367
    {
368
        if (is_null($namespace) && class_exists('Symphony', false)) {
369
            $namespace = Symphony::getPageNamespace();
370
        }
371
372
        if (isset($namespace, self::$_dictionary[$namespace][$string])) {
373
            $translated = self::$_dictionary[$namespace][$string];
374
        } elseif (isset(self::$_dictionary[$string])) {
375
            $translated = self::$_dictionary[$string];
376
        } else {
377
            $translated = $string;
378
        }
379
380
        $translated = empty($translated) ? $string : $translated;
381
382
        // Replace translation placeholders
383
        if (is_array($inserts) && !empty($inserts)) {
384
            $translated = vsprintf($translated, $inserts);
385
        }
386
387
        return $translated;
388
    }
389
390
    /**
391
     * Get an array of the codes and names of all languages that are available system wide.
392
     *
393
     * Note: Beginning with Symphony 2.2 language files are only available
394
     * when the language extension is explicitly enabled.
395
     *
396
     * @param boolean $checkStatus (optional)
397
     *  If false, retrieves a list a languages that support core translation.
398
     * @return array
399
     *  Returns an associative array of language codes and names, e. g. 'en' => 'English'
400
     */
401
    public static function getAvailableLanguages($checkStatus = true)
0 ignored issues
show
Incorrect spacing between argument "$checkStatus" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$checkStatus"; expected 0 but found 1
Loading history...
402
    {
403
        $languages = array();
404
405
        // Get available languages
406
        foreach (self::$_languages as $key => $language) {
407
            if (self::isLanguageEnabled($key) || ($checkStatus === false && isset($language['handle']))) {
408
                $languages[$key] = $language['name'];
409
            }
410
        }
411
412
        // Return languages codes
413
        return $languages;
414
    }
415
416
    /**
417
     * Check if Symphony is localised.
418
     *
419
     * @return boolean
420
     *  Returns true for localized system, false for English system
421
     */
422
    public static function isLocalized()
423
    {
424
        return (self::get() !== 'en');
425
    }
426
427
    /**
428
     * Localize dates.
429
     *
430
     * @param string $string
431
     *  Standard date that should be localized
432
     * @return string
433
     *  Return the given date with translated month and day names
434
     */
435
    public static function localizeDate($string)
436
    {
437
        // Only translate dates in localized environments
438
        if (self::isLocalized()) {
439
            foreach (self::$_datetime_dictionary as $value) {
440
                $string = preg_replace('/\b' . $value . '\b/i', self::translate($value), $string);
441
            }
442
        }
443
444
        return $string;
445
    }
446
447
    /**
448
     * Standardize dates.
449
     *
450
     * @param string $string
451
     *  Localized date that should be standardized
452
     * @return string
453
     *  Returns the given date with English month and day names
454
     */
455
    public static function standardizeDate($string)
456
    {
457
        // Only standardize dates in localized environments
458
        if (self::isLocalized()) {
0 ignored issues
show
Blank line found at start of control structure
Loading history...
459
460
            // Translate names to English
461
            foreach (self::$_datetime_dictionary as $values) {
462
                $string = preg_replace('/\b' . self::translate($values) . '\b/i' . (self::isUnicodeCompiled() === true ? 'u' : null), $values, $string);
0 ignored issues
show
Inline shorthand IF statement requires brackets around comparison
Loading history...
463
            }
464
465
            // Replace custom date and time separator with space:
466
            // This is important, otherwise the `DateTime` constructor may break
467
            // @todo Test if this separator is still required. It's a hidden setting
468
            // and users are only aware of it if they go digging/pointed in the right direction
469
            $separator = Symphony::Configuration()->get('datetime_separator', 'region');
470
            if ($separator !== ' ') {
471
                $string = str_replace($separator, ' ', $string);
472
            }
473
        }
474
475
        return $string;
476
    }
477
478
    /**
479
     * Given a string, this will clean it for use as a Symphony handle. Preserves multi-byte characters.
480
     *
481
     * @param string $string
482
     *  String to be cleaned up
483
     * @param integer $max_length
484
     *  The maximum number of characters in the handle
485
     * @param string $delim
486
     *  All non-valid characters will be replaced with this
487
     * @param boolean $uriencode
488
     *  Force the resultant string to be uri encoded making it safe for URLs
489
     * @param boolean $apply_transliteration
490
     *  If true, this will run the string through an array of substitution characters
491
     * @param array $additional_rule_set
492
     *  An array of REGEX patterns that should be applied to the `$string`. This
493
     *  occurs after the string has been trimmed and joined with the `$delim`
494
     * @return string
495
     *  Returns resultant handle
496
     */
497
    public static function createHandle($string, $max_length = 255, $delim = '-', $uriencode = false, $apply_transliteration = true, $additional_rule_set = null)
0 ignored issues
show
Incorrect spacing between argument "$max_length" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$max_length"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$delim" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$delim"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$uriencode" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$uriencode"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$apply_transliteration" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$apply_transliteration"; expected 0 but found 1
Loading history...
Incorrect spacing between argument "$additional_rule_set" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$additional_rule_set"; expected 0 but found 1
Loading history...
498
    {
499
        // Use the transliteration table if provided
500
        if ($apply_transliteration === true) {
501
            $string = self::applyTransliterations($string);
502
        }
503
504
        return General::createHandle($string, $max_length, $delim, $uriencode, $additional_rule_set);
505
    }
506
507
    /**
508
     * Given a string, this will clean it for use as a filename. Preserves multi-byte characters.
509
     *
510
     * @param string $string
511
     *  String to be cleaned up
512
     * @param string $delim
513
     *  Replacement for invalid characters
514
     * @param boolean $apply_transliteration
515
     *  If true, umlauts and special characters will be substituted
516
     * @return string
517
     *  Returns created filename
518
     */
519
    public static function createFilename($string, $delim='-', $apply_transliteration = true)
0 ignored issues
show
Incorrect spacing between argument "$apply_transliteration" and equals sign; expected 0 but found 1
Loading history...
Incorrect spacing between default value and equals sign for argument "$apply_transliteration"; expected 0 but found 1
Loading history...
520
    {
521
        // Use the transliteration table if provided
522
        if ($apply_transliteration === true) {
523
            $file = pathinfo($string);
524
            $string = self::applyTransliterations($file['filename']) . '.' . $file['extension'];
525
        }
526
527
        return General::createFilename($string, $delim);
528
    }
529
530
    /**
531
     * This function replaces special characters according to the values stored inside
532
     * `$_transliterations`.
533
     *
534
     * @since Symphony 2.3
535
     * @param string $string
536
     *  The string that should be cleaned-up
537
     * @return mixed
538
     *  Returns the transliterated string
539
     */
540
    private static function applyTransliterations($string)
541
    {
542
        // Apply the straight transliterations with strtr as it's much faster
543
        $string = strtr($string, self::$_transliterations['straight']);
544
545
        // Apply the regex rules over the resulting $string
546
        return preg_replace(
547
            array_keys(self::$_transliterations['regexp']),
548
            array_values(self::$_transliterations['regexp']),
549
            $string
550
        );
551
    }
552
553
    /**
554
     * Returns boolean if PHP has been compiled with unicode support. This is
555
     * useful to determine if unicode modifier's can be used in regular expression's
556
     *
557
     * @link http://stackoverflow.com/questions/4509576/detect-if-pcre-was-built-without-the-enable-unicode-properties-or-enable-utf8
558
     * @since Symphony 2.2.2
559
     * @return boolean
560
     */
561
    public static function isUnicodeCompiled()
562
    {
563
        return (@preg_match('/\pL/u', 'a') == 1 ? true : false);
0 ignored issues
show
Inline shorthand IF statement requires brackets around comparison
Loading history...
564
    }
565
}
566