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_HTMLDefinition::setupConfigStuff()   F
last analyzed

Complexity

Conditions 43
Paths 2160

Size

Total Lines 187
Code Lines 114

Duplication

Lines 29
Ratio 15.51 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 43
eloc 114
c 1
b 0
f 0
nc 2160
nop 1
dl 29
loc 187
rs 2

How to fix   Long Method    Complexity   

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
/**
4
 * Definition of the purified HTML that describes allowed children,
5
 * attributes, and many other things.
6
 *
7
 * Conventions:
8
 *
9
 * All member variables that are prefixed with info
10
 * (including the main $info array) are used by HTML Purifier internals
11
 * and should not be directly edited when customizing the HTMLDefinition.
12
 * They can usually be set via configuration directives or custom
13
 * modules.
14
 *
15
 * On the other hand, member variables without the info prefix are used
16
 * internally by the HTMLDefinition and MUST NOT be used by other HTML
17
 * Purifier internals. Many of them, however, are public, and may be
18
 * edited by userspace code to tweak the behavior of HTMLDefinition.
19
 *
20
 * @note This class is inspected by Printer_HTMLDefinition; please
21
 *       update that class if things here change.
22
 *
23
 * @warning Directives that change this object's structure must be in
24
 *          the HTML or Attr namespace!
25
 */
26
class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
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...
27
{
28
29
    // FULLY-PUBLIC VARIABLES ---------------------------------------------
30
31
    /**
32
     * Associative array of element names to HTMLPurifier_ElementDef.
33
     * @type HTMLPurifier_ElementDef[]
34
     */
35
    public $info = array();
36
37
    /**
38
     * Associative array of global attribute name to attribute definition.
39
     * @type array
40
     */
41
    public $info_global_attr = array();
42
43
    /**
44
     * String name of parent element HTML will be going into.
45
     * @type string
46
     */
47
    public $info_parent = 'div';
48
49
    /**
50
     * Definition for parent element, allows parent element to be a
51
     * tag that's not allowed inside the HTML fragment.
52
     * @type HTMLPurifier_ElementDef
53
     */
54
    public $info_parent_def;
55
56
    /**
57
     * String name of element used to wrap inline elements in block context.
58
     * @type string
59
     * @note This is rarely used except for BLOCKQUOTEs in strict mode
60
     */
61
    public $info_block_wrapper = 'p';
62
63
    /**
64
     * Associative array of deprecated tag name to HTMLPurifier_TagTransform.
65
     * @type array
66
     */
67
    public $info_tag_transform = array();
68
69
    /**
70
     * Indexed list of HTMLPurifier_AttrTransform to be performed before validation.
71
     * @type HTMLPurifier_AttrTransform[]
72
     */
73
    public $info_attr_transform_pre = array();
74
75
    /**
76
     * Indexed list of HTMLPurifier_AttrTransform to be performed after validation.
77
     * @type HTMLPurifier_AttrTransform[]
78
     */
79
    public $info_attr_transform_post = array();
80
81
    /**
82
     * Nested lookup array of content set name (Block, Inline) to
83
     * element name to whether or not it belongs in that content set.
84
     * @type array
85
     */
86
    public $info_content_sets = array();
87
88
    /**
89
     * Indexed list of HTMLPurifier_Injector to be used.
90
     * @type HTMLPurifier_Injector[]
91
     */
92
    public $info_injector = array();
93
94
    /**
95
     * Doctype object
96
     * @type HTMLPurifier_Doctype
97
     */
98
    public $doctype;
99
100
101
102
    // RAW CUSTOMIZATION STUFF --------------------------------------------
103
104
    /**
105
     * Adds a custom attribute to a pre-existing element
106
     * @note This is strictly convenience, and does not have a corresponding
107
     *       method in HTMLPurifier_HTMLModule
108
     * @param string $element_name Element name to add attribute to
109
     * @param string $attr_name Name of attribute
110
     * @param mixed $def Attribute definition, can be string or object, see
111
     *             HTMLPurifier_AttrTypes for details
112
     */
113
    public function addAttribute($element_name, $attr_name, $def)
114
    {
115
        $module = $this->getAnonymousModule();
116
        if (!isset($module->info[$element_name])) {
117
            $element = $module->addBlankElement($element_name);
118
        } else {
119
            $element = $module->info[$element_name];
120
        }
121
        $element->attr[$attr_name] = $def;
122
    }
123
124
    /**
125
     * Adds a custom element to your HTML definition
126
     * @see HTMLPurifier_HTMLModule::addElement() for detailed
127
     *       parameter and return value descriptions.
128
     */
129
    public function addElement($element_name, $type, $contents, $attr_collections, $attributes = array())
130
    {
131
        $module = $this->getAnonymousModule();
132
        // assume that if the user is calling this, the element
133
        // is safe. This may not be a good idea
134
        $element = $module->addElement($element_name, $type, $contents, $attr_collections, $attributes);
135
        return $element;
136
    }
137
138
    /**
139
     * Adds a blank element to your HTML definition, for overriding
140
     * existing behavior
141
     * @param string $element_name
142
     * @return HTMLPurifier_ElementDef
143
     * @see HTMLPurifier_HTMLModule::addBlankElement() for detailed
144
     *       parameter and return value descriptions.
145
     */
146
    public function addBlankElement($element_name)
147
    {
148
        $module  = $this->getAnonymousModule();
149
        $element = $module->addBlankElement($element_name);
150
        return $element;
151
    }
152
153
    /**
154
     * Retrieves a reference to the anonymous module, so you can
155
     * bust out advanced features without having to make your own
156
     * module.
157
     * @return HTMLPurifier_HTMLModule
158
     */
159
    public function getAnonymousModule()
160
    {
161
        if (!$this->_anonModule) {
162
            $this->_anonModule = new HTMLPurifier_HTMLModule();
163
            $this->_anonModule->name = 'Anonymous';
164
        }
165
        return $this->_anonModule;
166
    }
167
168
    private $_anonModule = null;
169
170
    // PUBLIC BUT INTERNAL VARIABLES --------------------------------------
171
172
    /**
173
     * @type string
174
     */
175
    public $type = 'HTML';
176
177
    /**
178
     * @type HTMLPurifier_HTMLModuleManager
179
     */
180
    public $manager;
181
182
    /**
183
     * Performs low-cost, preliminary initialization.
184
     */
185
    public function __construct()
186
    {
187
        $this->manager = new HTMLPurifier_HTMLModuleManager();
188
    }
189
190
    /**
191
     * @param HTMLPurifier_Config $config
192
     */
193
    protected function doSetup($config)
194
    {
195
        $this->processModules($config);
196
        $this->setupConfigStuff($config);
197
        unset($this->manager);
198
199
        // cleanup some of the element definitions
200
        foreach ($this->info as $k => $v) {
201
            unset($this->info[$k]->content_model);
202
            unset($this->info[$k]->content_model_type);
203
        }
204
    }
205
206
    /**
207
     * Extract out the information from the manager
208
     * @param HTMLPurifier_Config $config
209
     */
210
    protected function processModules($config)
211
    {
212
        if ($this->_anonModule) {
213
            // for user specific changes
214
            // this is late-loaded so we don't have to deal with PHP4
215
            // reference wonky-ness
216
            $this->manager->addModule($this->_anonModule);
217
            unset($this->_anonModule);
218
        }
219
220
        $this->manager->setup($config);
221
        $this->doctype = $this->manager->doctype;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->manager->doctype of type string is incompatible with the declared type object<HTMLPurifier_Doctype> of property $doctype.

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...
222
223
        foreach ($this->manager->modules as $module) {
224 View Code Duplication
            foreach ($module->info_tag_transform as $k => $v) {
0 ignored issues
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...
225
                if ($v === false) {
226
                    unset($this->info_tag_transform[$k]);
227
                } else {
228
                    $this->info_tag_transform[$k] = $v;
229
                }
230
            }
231 View Code Duplication
            foreach ($module->info_attr_transform_pre as $k => $v) {
0 ignored issues
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...
232
                if ($v === false) {
233
                    unset($this->info_attr_transform_pre[$k]);
234
                } else {
235
                    $this->info_attr_transform_pre[$k] = $v;
236
                }
237
            }
238 View Code Duplication
            foreach ($module->info_attr_transform_post as $k => $v) {
0 ignored issues
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...
239
                if ($v === false) {
240
                    unset($this->info_attr_transform_post[$k]);
241
                } else {
242
                    $this->info_attr_transform_post[$k] = $v;
243
                }
244
            }
245 View Code Duplication
            foreach ($module->info_injector as $k => $v) {
0 ignored issues
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...
246
                if ($v === false) {
247
                    unset($this->info_injector[$k]);
248
                } else {
249
                    $this->info_injector[$k] = $v;
250
                }
251
            }
252
        }
253
        $this->info = $this->manager->getElements();
254
        $this->info_content_sets = $this->manager->contentSets->lookup;
255
    }
256
257
    /**
258
     * Sets up stuff based on config. We need a better way of doing this.
259
     * @param HTMLPurifier_Config $config
260
     */
261
    protected function setupConfigStuff($config)
262
    {
263
        $block_wrapper = $config->get('HTML.BlockWrapper');
264
        if (isset($this->info_content_sets['Block'][$block_wrapper])) {
265
            $this->info_block_wrapper = $block_wrapper;
266
        } else {
267
            trigger_error(
268
                'Cannot use non-block element as block wrapper',
269
                E_USER_ERROR
270
            );
271
        }
272
273
        $parent = $config->get('HTML.Parent');
274
        $def = $this->manager->getElement($parent, true);
275
        if ($def) {
276
            $this->info_parent = $parent;
277
            $this->info_parent_def = $def;
278
        } else {
279
            trigger_error(
280
                'Cannot use unrecognized element as parent',
281
                E_USER_ERROR
282
            );
283
            $this->info_parent_def = $this->manager->getElement($this->info_parent, true);
284
        }
285
286
        // support template text
287
        $support = "(for information on implementing this, see the support forums) ";
288
289
        // setup allowed elements -----------------------------------------
290
291
        $allowed_elements = $config->get('HTML.AllowedElements');
292
        $allowed_attributes = $config->get('HTML.AllowedAttributes'); // retrieve early
293
294
        if (!is_array($allowed_elements) && !is_array($allowed_attributes)) {
295
            $allowed = $config->get('HTML.Allowed');
296
            if (is_string($allowed)) {
297
                list($allowed_elements, $allowed_attributes) = $this->parseTinyMCEAllowedList($allowed);
0 ignored issues
show
Documentation introduced by
$allowed is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
298
            }
299
        }
300
301 View Code Duplication
        if (is_array($allowed_elements)) {
0 ignored issues
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...
302
            foreach ($this->info as $name => $d) {
303
                if (!isset($allowed_elements[$name])) {
304
                    unset($this->info[$name]);
305
                }
306
                unset($allowed_elements[$name]);
307
            }
308
            // emit errors
309
            foreach ($allowed_elements as $element => $d) {
310
                $element = htmlspecialchars($element); // PHP doesn't escape errors, be careful!
311
                trigger_error("Element '$element' is not supported $support", E_USER_WARNING);
312
            }
313
        }
314
315
        // setup allowed attributes ---------------------------------------
316
317
        $allowed_attributes_mutable = $allowed_attributes; // by copy!
318
        if (is_array($allowed_attributes)) {
319
            // This actually doesn't do anything, since we went away from
320
            // global attributes. It's possible that userland code uses
321
            // it, but HTMLModuleManager doesn't!
322
            foreach ($this->info_global_attr as $attr => $x) {
323
                $keys = array($attr, "*@$attr", "*.$attr");
324
                $delete = true;
325 View Code Duplication
                foreach ($keys as $key) {
0 ignored issues
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...
326
                    if ($delete && isset($allowed_attributes[$key])) {
327
                        $delete = false;
328
                    }
329
                    if (isset($allowed_attributes_mutable[$key])) {
330
                        unset($allowed_attributes_mutable[$key]);
331
                    }
332
                }
333
                if ($delete) {
334
                    unset($this->info_global_attr[$attr]);
335
                }
336
            }
337
338
            foreach ($this->info as $tag => $info) {
339
                foreach ($info->attr as $attr => $x) {
340
                    $keys = array("$tag@$attr", $attr, "*@$attr", "$tag.$attr", "*.$attr");
341
                    $delete = true;
342 View Code Duplication
                    foreach ($keys as $key) {
0 ignored issues
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...
343
                        if ($delete && isset($allowed_attributes[$key])) {
344
                            $delete = false;
345
                        }
346
                        if (isset($allowed_attributes_mutable[$key])) {
347
                            unset($allowed_attributes_mutable[$key]);
348
                        }
349
                    }
350
                    if ($delete) {
351
                        if ($this->info[$tag]->attr[$attr]->required) {
352
                            trigger_error(
353
                                "Required attribute '$attr' in element '$tag' " .
354
                                "was not allowed, which means '$tag' will not be allowed either",
355
                                E_USER_WARNING
356
                            );
357
                        }
358
                        unset($this->info[$tag]->attr[$attr]);
359
                    }
360
                }
361
            }
362
            // emit errors
363
            foreach ($allowed_attributes_mutable as $elattr => $d) {
364
                $bits = preg_split('/[.@]/', $elattr, 2);
365
                $c = count($bits);
366
                switch ($c) {
367
                    case 2:
368
                        if ($bits[0] !== '*') {
369
                            $element = htmlspecialchars($bits[0]);
370
                            $attribute = htmlspecialchars($bits[1]);
371
                            if (!isset($this->info[$element])) {
372
                                trigger_error(
373
                                    "Cannot allow attribute '$attribute' if element " .
374
                                    "'$element' is not allowed/supported $support"
375
                                );
376
                            } else {
377
                                trigger_error(
378
                                    "Attribute '$attribute' in element '$element' not supported $support",
379
                                    E_USER_WARNING
380
                                );
381
                            }
382
                            break;
383
                        }
384
                        // otherwise fall through
385
                    case 1:
386
                        $attribute = htmlspecialchars($bits[0]);
387
                        trigger_error(
388
                            "Global attribute '$attribute' is not ".
389
                            "supported in any elements $support",
390
                            E_USER_WARNING
391
                        );
392
                        break;
393
                }
394
            }
395
        }
396
397
        // setup forbidden elements ---------------------------------------
398
399
        $forbidden_elements   = $config->get('HTML.ForbiddenElements');
400
        $forbidden_attributes = $config->get('HTML.ForbiddenAttributes');
401
402
        foreach ($this->info as $tag => $info) {
403
            if (isset($forbidden_elements[$tag])) {
404
                unset($this->info[$tag]);
405
                continue;
406
            }
407
            foreach ($info->attr as $attr => $x) {
408
                if (isset($forbidden_attributes["$tag@$attr"]) ||
409
                    isset($forbidden_attributes["*@$attr"]) ||
410
                    isset($forbidden_attributes[$attr])
411
                ) {
412
                    unset($this->info[$tag]->attr[$attr]);
413
                    continue;
414
                } elseif (isset($forbidden_attributes["$tag.$attr"])) { // this segment might get removed eventually
415
                    // $tag.$attr are not user supplied, so no worries!
416
                    trigger_error(
417
                        "Error with $tag.$attr: tag.attr syntax not supported for " .
418
                        "HTML.ForbiddenAttributes; use tag@attr instead",
419
                        E_USER_WARNING
420
                    );
421
                }
422
            }
423
        }
424
        foreach ($forbidden_attributes as $key => $v) {
425
            if (strlen($key) < 2) {
426
                continue;
427
            }
428
            if ($key[0] != '*') {
429
                continue;
430
            }
431
            if ($key[1] == '.') {
432
                trigger_error(
433
                    "Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead",
434
                    E_USER_WARNING
435
                );
436
            }
437
        }
438
439
        // setup injectors -----------------------------------------------------
440
        foreach ($this->info_injector as $i => $injector) {
441
            if ($injector->checkNeeded($config) !== false) {
442
                // remove injector that does not have it's required
443
                // elements/attributes present, and is thus not needed.
444
                unset($this->info_injector[$i]);
445
            }
446
        }
447
    }
448
449
    /**
450
     * Parses a TinyMCE-flavored Allowed Elements and Attributes list into
451
     * separate lists for processing. Format is element[attr1|attr2],element2...
452
     * @warning Although it's largely drawn from TinyMCE's implementation,
453
     *      it is different, and you'll probably have to modify your lists
454
     * @param array $list String list to parse
455
     * @return array
456
     * @todo Give this its own class, probably static interface
457
     */
458
    public function parseTinyMCEAllowedList($list)
459
    {
460
        $list = str_replace(array(' ', "\t"), '', $list);
461
462
        $elements = array();
463
        $attributes = array();
464
465
        $chunks = preg_split('/(,|[\n\r]+)/', $list);
466
        foreach ($chunks as $chunk) {
467
            if (empty($chunk)) {
468
                continue;
469
            }
470
            // remove TinyMCE element control characters
471
            if (!strpos($chunk, '[')) {
472
                $element = $chunk;
473
                $attr = false;
474
            } else {
475
                list($element, $attr) = explode('[', $chunk);
476
            }
477
            if ($element !== '*') {
478
                $elements[$element] = true;
479
            }
480
            if (!$attr) {
481
                continue;
482
            }
483
            $attr = substr($attr, 0, strlen($attr) - 1); // remove trailing ]
484
            $attr = explode('|', $attr);
485
            foreach ($attr as $key) {
486
                $attributes["$element.$key"] = true;
487
            }
488
        }
489
        return array($elements, $attributes);
490
    }
491
}
492
493
// vim: et sw=4 sts=4
494