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.

HTMLPurifier_LanguageFactory::getFallbackFor()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 9.4285
1
<?php
2
3
/**
4
 * Class responsible for generating HTMLPurifier_Language objects, managing
5
 * caching and fallbacks.
6
 * @note Thanks to MediaWiki for the general logic, although this version
7
 *       has been entirely rewritten
8
 * @todo Serialized cache for languages
9
 */
10
class HTMLPurifier_LanguageFactory
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
11
{
12
13
    /**
14
     * Cache of language code information used to load HTMLPurifier_Language objects.
15
     * Structure is: $factory->cache[$language_code][$key] = $value
16
     * @type array
17
     */
18
    public $cache;
19
20
    /**
21
     * Valid keys in the HTMLPurifier_Language object. Designates which
22
     * variables to slurp out of a message file.
23
     * @type array
24
     */
25
    public $keys = array('fallback', 'messages', 'errorNames');
26
27
    /**
28
     * Instance to validate language codes.
29
     * @type HTMLPurifier_AttrDef_Lang
30
     *
31
     */
32
    protected $validator;
33
34
    /**
35
     * Cached copy of dirname(__FILE__), directory of current file without
36
     * trailing slash.
37
     * @type string
38
     */
39
    protected $dir;
40
41
    /**
42
     * Keys whose contents are a hash map and can be merged.
43
     * @type array
44
     */
45
    protected $mergeable_keys_map = array('messages' => true, 'errorNames' => true);
46
47
    /**
48
     * Keys whose contents are a list and can be merged.
49
     * @value array lookup
50
     */
51
    protected $mergeable_keys_list = array();
52
53
    /**
54
     * Retrieve sole instance of the factory.
55
     * @param HTMLPurifier_LanguageFactory $prototype Optional prototype to overload sole instance with,
56
     *                   or bool true to reset to default factory.
57
     * @return HTMLPurifier_LanguageFactory
58
     */
59 View Code Duplication
    public static function instance($prototype = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
60
    {
61
        static $instance = null;
62
        if ($prototype !== null) {
63
            $instance = $prototype;
64
        } elseif ($instance === null || $prototype == true) {
65
            $instance = new HTMLPurifier_LanguageFactory();
66
            $instance->setup();
67
        }
68
        return $instance;
69
    }
70
71
    /**
72
     * Sets up the singleton, much like a constructor
73
     * @note Prevents people from getting this outside of the singleton
74
     */
75
    public function setup()
76
    {
77
        $this->validator = new HTMLPurifier_AttrDef_Lang();
78
        $this->dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier';
79
    }
80
81
    /**
82
     * Creates a language object, handles class fallbacks
83
     * @param HTMLPurifier_Config $config
84
     * @param HTMLPurifier_Context $context
85
     * @param bool|string $code Code to override configuration with. Private parameter.
86
     * @return HTMLPurifier_Language
87
     */
88
    public function create($config, $context, $code = false)
89
    {
90
        // validate language code
91
        if ($code === false) {
92
            $code = $this->validator->validate(
93
                $config->get('Core.Language'),
94
                $config,
95
                $context
96
            );
97
        } else {
98
            $code = $this->validator->validate($code, $config, $context);
0 ignored issues
show
Bug introduced by
It seems like $code defined by $this->validator->valida...ode, $config, $context) on line 98 can also be of type boolean; however, HTMLPurifier_AttrDef_Lang::validate() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
99
        }
100
        if ($code === false) {
101
            $code = 'en'; // malformed code becomes English
102
        }
103
104
        $pcode = str_replace('-', '_', $code); // make valid PHP classname
105
        static $depth = 0; // recursion protection
106
107
        if ($code == 'en') {
108
            $lang = new HTMLPurifier_Language($config, $context);
109
        } else {
110
            $class = 'HTMLPurifier_Language_' . $pcode;
111
            $file  = $this->dir . '/Language/classes/' . $code . '.php';
112
            if (file_exists($file) || class_exists($class, false)) {
113
                $lang = new $class($config, $context);
114
            } else {
115
                // Go fallback
116
                $raw_fallback = $this->getFallbackFor($code);
0 ignored issues
show
Bug introduced by
It seems like $code can also be of type boolean; however, HTMLPurifier_LanguageFactory::getFallbackFor() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
117
                $fallback = $raw_fallback ? $raw_fallback : 'en';
118
                $depth++;
119
                $lang = $this->create($config, $context, $fallback);
120
                if (!$raw_fallback) {
121
                    $lang->error = true;
122
                }
123
                $depth--;
124
            }
125
        }
126
        $lang->code = $code;
127
        return $lang;
128
    }
129
130
    /**
131
     * Returns the fallback language for language
132
     * @note Loads the original language into cache
133
     * @param string $code language code
134
     * @return string|bool
135
     */
136
    public function getFallbackFor($code)
137
    {
138
        $this->loadLanguage($code);
139
        return $this->cache[$code]['fallback'];
140
    }
141
142
    /**
143
     * Loads language into the cache, handles message file and fallbacks
144
     * @param string $code language code
145
     */
146
    public function loadLanguage($code)
147
    {
148
        static $languages_seen = array(); // recursion guard
149
150
        // abort if we've already loaded it
151
        if (isset($this->cache[$code])) {
152
            return;
153
        }
154
155
        // generate filename
156
        $filename = $this->dir . '/Language/messages/' . $code . '.php';
157
158
        // default fallback : may be overwritten by the ensuing include
159
        $fallback = ($code != 'en') ? 'en' : false;
160
161
        // load primary localisation
162
        if (!file_exists($filename)) {
163
            // skip the include: will rely solely on fallback
164
            $filename = $this->dir . '/Language/messages/en.php';
0 ignored issues
show
Unused Code introduced by
$filename is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
165
            $cache = array();
166
        } else {
167
            include $filename;
168
            $cache = compact($this->keys);
169
        }
170
171
        // load fallback localisation
172
        if (!empty($fallback)) {
173
174
            // infinite recursion guard
175
            if (isset($languages_seen[$code])) {
176
                trigger_error(
177
                    'Circular fallback reference in language ' .
178
                    $code,
179
                    E_USER_ERROR
180
                );
181
                $fallback = 'en';
182
            }
183
            $language_seen[$code] = true;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$language_seen was never initialized. Although not strictly required by PHP, it is generally a good practice to add $language_seen = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
184
185
            // load the fallback recursively
186
            $this->loadLanguage($fallback);
187
            $fallback_cache = $this->cache[$fallback];
188
189
            // merge fallback with current language
190
            foreach ($this->keys as $key) {
191
                if (isset($cache[$key]) && isset($fallback_cache[$key])) {
192
                    if (isset($this->mergeable_keys_map[$key])) {
193
                        $cache[$key] = $cache[$key] + $fallback_cache[$key];
194
                    } elseif (isset($this->mergeable_keys_list[$key])) {
195
                        $cache[$key] = array_merge($fallback_cache[$key], $cache[$key]);
196
                    }
197
                } else {
198
                    $cache[$key] = $fallback_cache[$key];
199
                }
200
            }
201
        }
202
203
        // save to cache for later retrieval
204
        $this->cache[$code] = $cache;
205
        return;
206
    }
207
}
208
209
// vim: et sw=4 sts=4
210