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.
Completed
Push — develop ( d80144...902697 )
by gyeong-won
12:23
created

HTMLPurifier_HTMLModuleManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 69
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 47
nc 1
nop 0
dl 0
loc 69
rs 9.2083
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class HTMLPurifier_HTMLModuleManager
4
{
5
6
    /**
7
     * Instance of HTMLPurifier_DoctypeRegistry
8
     */
9
    public $doctypes;
10
11
    /**
12
     * Instance of current doctype
13
     */
14
    public $doctype;
15
16
    /**
17
     * Instance of HTMLPurifier_AttrTypes
18
     */
19
    public $attrTypes;
20
21
    /**
22
     * Active instances of modules for the specified doctype are
23
     * indexed, by name, in this array.
24
     */
25
    public $modules = array();
26
27
    /**
28
     * Array of recognized HTMLPurifier_Module instances, indexed by
29
     * module's class name. This array is usually lazy loaded, but a
30
     * user can overload a module by pre-emptively registering it.
31
     */
32
    public $registeredModules = array();
33
34
    /**
35
     * List of extra modules that were added by the user using addModule().
36
     * These get unconditionally merged into the current doctype, whatever
37
     * it may be.
38
     */
39
    public $userModules = array();
40
41
    /**
42
     * Associative array of element name to list of modules that have
43
     * definitions for the element; this array is dynamically filled.
44
     */
45
    public $elementLookup = array();
46
47
    /** List of prefixes we should use for registering small names */
48
    public $prefixes = array('HTMLPurifier_HTMLModule_');
49
50
    public $contentSets;     /**< Instance of HTMLPurifier_ContentSets */
51
    public $attrCollections; /**< Instance of HTMLPurifier_AttrCollections */
52
53
    /** If set to true, unsafe elements and attributes will be allowed */
54
    public $trusted = false;
55
56
    public function __construct() {
57
58
        // editable internal objects
59
        $this->attrTypes = new HTMLPurifier_AttrTypes();
60
        $this->doctypes  = new HTMLPurifier_DoctypeRegistry();
61
62
        // setup basic modules
63
        $common = array(
64
            'CommonAttributes', 'Text', 'Hypertext', 'List',
65
            'Presentation', 'Edit', 'Bdo', 'Tables', 'Image',
66
            'StyleAttribute',
67
            // Unsafe:
68
            'Scripting', 'Object', 'Forms',
69
            // Sorta legacy, but present in strict:
70
            'Name',
71
        );
72
        $transitional = array('Legacy', 'Target', 'Iframe');
73
        $xml = array('XMLCommonAttributes');
74
        $non_xml = array('NonXMLCommonAttributes');
75
76
        // setup basic doctypes
77
        $this->doctypes->register(
78
            'HTML 4.01 Transitional', false,
79
            array_merge($common, $transitional, $non_xml),
80
            array('Tidy_Transitional', 'Tidy_Proprietary'),
81
            array(),
82
            '-//W3C//DTD HTML 4.01 Transitional//EN',
83
            'http://www.w3.org/TR/html4/loose.dtd'
84
        );
85
86
        $this->doctypes->register(
87
            'HTML 4.01 Strict', false,
88
            array_merge($common, $non_xml),
89
            array('Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'),
90
            array(),
91
            '-//W3C//DTD HTML 4.01//EN',
92
            'http://www.w3.org/TR/html4/strict.dtd'
93
        );
94
95
        $this->doctypes->register(
96
            'XHTML 1.0 Transitional', true,
97
            array_merge($common, $transitional, $xml, $non_xml),
98
            array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Name'),
99
            array(),
100
            '-//W3C//DTD XHTML 1.0 Transitional//EN',
101
            'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
102
        );
103
104
        $this->doctypes->register(
105
            'XHTML 1.0 Strict', true,
106
            array_merge($common, $xml, $non_xml),
107
            array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'),
108
            array(),
109
            '-//W3C//DTD XHTML 1.0 Strict//EN',
110
            'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
111
        );
112
113
        $this->doctypes->register(
114
            'XHTML 1.1', true,
115
            // Iframe is a real XHTML 1.1 module, despite being
116
            // "transitional"!
117
            array_merge($common, $xml, array('Ruby', 'Iframe')),
118
            array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Strict', 'Tidy_Name'), // Tidy_XHTML1_1
119
            array(),
120
            '-//W3C//DTD XHTML 1.1//EN',
121
            'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'
122
        );
123
124
    }
125
126
    /**
127
     * Registers a module to the recognized module list, useful for
128
     * overloading pre-existing modules.
129
     * @param $module Mixed: string module name, with or without
130
     *                HTMLPurifier_HTMLModule prefix, or instance of
131
     *                subclass of HTMLPurifier_HTMLModule.
132
     * @param $overload Boolean whether or not to overload previous modules.
133
     *                  If this is not set, and you do overload a module,
134
     *                  HTML Purifier will complain with a warning.
135
     * @note This function will not call autoload, you must instantiate
136
     *       (and thus invoke) autoload outside the method.
137
     * @note If a string is passed as a module name, different variants
138
     *       will be tested in this order:
139
     *          - Check for HTMLPurifier_HTMLModule_$name
140
     *          - Check all prefixes with $name in order they were added
141
     *          - Check for literal object name
142
     *          - Throw fatal error
143
     *       If your object name collides with an internal class, specify
144
     *       your module manually. All modules must have been included
145
     *       externally: registerModule will not perform inclusions for you!
146
     */
147
    public function registerModule($module, $overload = false) {
148
        if (is_string($module)) {
149
            // attempt to load the module
150
            $original_module = $module;
151
            $ok = false;
152
            foreach ($this->prefixes as $prefix) {
153
                $module = $prefix . $original_module;
154
                if (class_exists($module)) {
155
                    $ok = true;
156
                    break;
157
                }
158
            }
159
            if (!$ok) {
160
                $module = $original_module;
161
                if (!class_exists($module)) {
162
                    trigger_error($original_module . ' module does not exist',
163
                        E_USER_ERROR);
164
                    return;
165
                }
166
            }
167
            $module = new $module();
168
        }
169
        if (empty($module->name)) {
170
            trigger_error('Module instance of ' . get_class($module) . ' must have name');
171
            return;
172
        }
173
        if (!$overload && isset($this->registeredModules[$module->name])) {
174
            trigger_error('Overloading ' . $module->name . ' without explicit overload parameter', E_USER_WARNING);
175
        }
176
        $this->registeredModules[$module->name] = $module;
177
    }
178
179
    /**
180
     * Adds a module to the current doctype by first registering it,
181
     * and then tacking it on to the active doctype
182
     */
183
    public function addModule($module) {
184
        $this->registerModule($module);
185
        if (is_object($module)) $module = $module->name;
186
        $this->userModules[] = $module;
187
    }
188
189
    /**
190
     * Adds a class prefix that registerModule() will use to resolve a
191
     * string name to a concrete class
192
     */
193
    public function addPrefix($prefix) {
194
        $this->prefixes[] = $prefix;
195
    }
196
197
    /**
198
     * Performs processing on modules, after being called you may
199
     * use getElement() and getElements()
200
     * @param $config Instance of HTMLPurifier_Config
201
     */
202
    public function setup($config) {
203
204
        $this->trusted = $config->get('HTML.Trusted');
205
206
        // generate
207
        $this->doctype = $this->doctypes->make($config);
208
        $modules = $this->doctype->modules;
209
210
        // take out the default modules that aren't allowed
211
        $lookup = $config->get('HTML.AllowedModules');
212
        $special_cases = $config->get('HTML.CoreModules');
213
214
        if (is_array($lookup)) {
215
            foreach ($modules as $k => $m) {
216
                if (isset($special_cases[$m])) continue;
217
                if (!isset($lookup[$m])) unset($modules[$k]);
218
            }
219
        }
220
221
        // custom modules
222
        if ($config->get('HTML.Proprietary')) {
223
            $modules[] = 'Proprietary';
224
        }
225
        if ($config->get('HTML.SafeObject')) {
226
            $modules[] = 'SafeObject';
227
        }
228
        if ($config->get('HTML.SafeEmbed')) {
229
            $modules[] = 'SafeEmbed';
230
        }
231
        if ($config->get('HTML.Nofollow')) {
232
            $modules[] = 'Nofollow';
233
        }
234
        if ($config->get('HTML.TargetBlank')) {
235
            $modules[] = 'TargetBlank';
236
        }
237
238
        // merge in custom modules
239
        $modules = array_merge($modules, $this->userModules);
240
241
        foreach ($modules as $module) {
242
            $this->processModule($module);
243
            $this->modules[$module]->setup($config);
244
        }
245
246
        foreach ($this->doctype->tidyModules as $module) {
247
            $this->processModule($module);
248
            $this->modules[$module]->setup($config);
249
        }
250
251
        // prepare any injectors
252
        foreach ($this->modules as $module) {
253
            $n = array();
254
            foreach ($module->info_injector as $i => $injector) {
255
                if (!is_object($injector)) {
256
                    $class = "HTMLPurifier_Injector_$injector";
257
                    $injector = new $class;
258
                }
259
                $n[$injector->name] = $injector;
260
            }
261
            $module->info_injector = $n;
262
        }
263
264
        // setup lookup table based on all valid modules
265
        foreach ($this->modules as $module) {
266
            foreach ($module->info as $name => $def) {
267
                if (!isset($this->elementLookup[$name])) {
268
                    $this->elementLookup[$name] = array();
269
                }
270
                $this->elementLookup[$name][] = $module->name;
271
            }
272
        }
273
274
        // note the different choice
275
        $this->contentSets = new HTMLPurifier_ContentSets(
276
            // content set assembly deals with all possible modules,
277
            // not just ones deemed to be "safe"
278
            $this->modules
279
        );
280
        $this->attrCollections = new HTMLPurifier_AttrCollections(
281
            $this->attrTypes,
282
            // there is no way to directly disable a global attribute,
283
            // but using AllowedAttributes or simply not including
284
            // the module in your custom doctype should be sufficient
285
            $this->modules
286
        );
287
    }
288
289
    /**
290
     * Takes a module and adds it to the active module collection,
291
     * registering it if necessary.
292
     */
293
    public function processModule($module) {
294
        if (!isset($this->registeredModules[$module]) || is_object($module)) {
295
            $this->registerModule($module);
296
        }
297
        $this->modules[$module] = $this->registeredModules[$module];
298
    }
299
300
    /**
301
     * Retrieves merged element definitions.
302
     * @return Array of HTMLPurifier_ElementDef
303
     */
304
    public function getElements() {
305
306
        $elements = array();
307
        foreach ($this->modules as $module) {
308
            if (!$this->trusted && !$module->safe) continue;
309
            foreach ($module->info as $name => $v) {
310
                if (isset($elements[$name])) continue;
311
                $elements[$name] = $this->getElement($name);
312
            }
313
        }
314
315
        // remove dud elements, this happens when an element that
316
        // appeared to be safe actually wasn't
317
        foreach ($elements as $n => $v) {
318
            if ($v === false) unset($elements[$n]);
319
        }
320
321
        return $elements;
322
323
    }
324
325
    /**
326
     * Retrieves a single merged element definition
327
     * @param $name Name of element
328
     * @param $trusted Boolean trusted overriding parameter: set to true
329
     *                 if you want the full version of an element
330
     * @return Merged HTMLPurifier_ElementDef
331
     * @note You may notice that modules are getting iterated over twice (once
332
     *       in getElements() and once here). This
333
     *       is because
334
     */
335
    public function getElement($name, $trusted = null) {
336
337
        if (!isset($this->elementLookup[$name])) {
338
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by HTMLPurifier_HTMLModuleManager::getElement of type Merged.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
339
        }
340
341
        // setup global state variables
342
        $def = false;
343
        if ($trusted === null) $trusted = $this->trusted;
344
345
        // iterate through each module that has registered itself to this
346
        // element
347
        foreach($this->elementLookup[$name] as $module_name) {
348
349
            $module = $this->modules[$module_name];
350
351
            // refuse to create/merge from a module that is deemed unsafe--
352
            // pretend the module doesn't exist--when trusted mode is not on.
353
            if (!$trusted && !$module->safe) {
354
                continue;
355
            }
356
357
            // clone is used because, ideally speaking, the original
358
            // definition should not be modified. Usually, this will
359
            // make no difference, but for consistency's sake
360
            $new_def = clone $module->info[$name];
361
362
            if (!$def && $new_def->standalone) {
363
                $def = $new_def;
364
            } elseif ($def) {
365
                // This will occur even if $new_def is standalone. In practice,
366
                // this will usually result in a full replacement.
367
                $def->mergeIn($new_def);
368
            } else {
369
                // :TODO:
370
                // non-standalone definitions that don't have a standalone
371
                // to merge into could be deferred to the end
372
                // HOWEVER, it is perfectly valid for a non-standalone
373
                // definition to lack a standalone definition, even
374
                // after all processing: this allows us to safely
375
                // specify extra attributes for elements that may not be
376
                // enabled all in one place.  In particular, this might
377
                // be the case for trusted elements.  WARNING: care must
378
                // be taken that the /extra/ definitions are all safe.
379
                continue;
380
            }
381
382
            // attribute value expansions
383
            $this->attrCollections->performInclusions($def->attr);
384
            $this->attrCollections->expandIdentifiers($def->attr, $this->attrTypes);
385
386
            // descendants_are_inline, for ChildDef_Chameleon
387
            if (is_string($def->content_model) &&
388
                strpos($def->content_model, 'Inline') !== false) {
389
                if ($name != 'del' && $name != 'ins') {
390
                    // this is for you, ins/del
391
                    $def->descendants_are_inline = true;
392
                }
393
            }
394
395
            $this->contentSets->generateChildDef($def, $module);
396
        }
397
398
        // This can occur if there is a blank definition, but no base to
399
        // mix it in with
400
        if (!$def) return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by HTMLPurifier_HTMLModuleManager::getElement of type Merged.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
401
402
        // add information on required attributes
403
        foreach ($def->attr as $attr_name => $attr_def) {
404
            if ($attr_def->required) {
405
                $def->required_attr[] = $attr_name;
406
            }
407
        }
408
409
        return $def;
410
411
    }
412
413
}
414
415
// vim: et sw=4 sts=4
416