Purifier   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 274
Duplicated Lines 0 %

Importance

Changes 13
Bugs 1 Features 1
Metric Value
eloc 94
c 13
b 1
f 1
dl 0
loc 274
rs 9.0399
wmc 42

9 Methods

Rating   Name   Duplication   Size   Complexity  
A addCustomElements() 0 14 4
A __construct() 0 6 1
B addCustomDefinition() 0 30 7
A clean() 0 25 6
B addCustomAttributes() 0 30 8
A setUp() 0 13 2
A getInstance() 0 3 1
A checkCacheDirectory() 0 7 3
C getConfig() 0 52 10

How to fix   Complexity   

Complex Class

Complex classes like Purifier often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Purifier, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Mews\Purifier;
4
5
/**
6
 * Laravel 5 HTMLPurifier package
7
 *
8
 * @copyright Copyright (c) 2015 MeWebStudio
9
 * @version   2.0.0
10
 * @author    Muharrem ERİN
11
 * @contact [email protected]
12
 * @web http://www.mewebstudio.com
13
 * @date      2014-04-02
14
 * @license   MIT
15
 */
16
17
use Exception;
18
use HTMLPurifier;
19
use HTMLPurifier_Config;
20
use HTMLPurifier_HTMLDefinition;
21
use Illuminate\Contracts\Config\Repository;
22
use Illuminate\Filesystem\Filesystem;
23
24
class Purifier
25
{
26
27
    /**
28
     * @var Filesystem
29
     */
30
    protected $files;
31
32
    /**
33
     * @var Repository
34
     */
35
    protected $config;
36
37
    /**
38
     * @var HTMLPurifier
39
     */
40
    protected $purifier;
41
42
    /**
43
     * Constructor
44
     *
45
     * @param Filesystem $files
46
     * @param Repository $config
47
     * @throws Exception
48
     */
49
    public function __construct(Filesystem $files, Repository $config)
50
    {
51
        $this->files = $files;
52
        $this->config = $config;
53
54
        $this->setUp();
55
    }
56
57
    /**
58
     * Setup
59
     *
60
     * @throws Exception
61
     */
62
    private function setUp()
63
    {
64
        if (!$this->config->has('purifier')) {
65
            throw new Exception('Configuration parameters not loaded!');
66
        }
67
68
        $this->checkCacheDirectory();
69
70
        // Create a new configuration object
71
        $config = $this->getConfig();
72
73
        // Create HTMLPurifier object
74
        $this->purifier = new HTMLPurifier($config);
75
    }
76
77
    /**
78
     * Add a custom definition
79
     *
80
     * @see http://htmlpurifier.org/docs/enduser-customize.html
81
     * @param array $definitionConfig
82
     * @param HTMLPurifier_Config $configObject Defaults to using default config
83
     *
84
     * @return HTMLPurifier_Config $configObject
85
     */
86
    private function addCustomDefinition(array $definitionConfig, HTMLPurifier_Config $configObject = null)
87
    {
88
        if (!$configObject) {
89
            $configObject = HTMLPurifier_Config::createDefault();
90
            $configObject->loadArray($this->getConfig());
0 ignored issues
show
Bug introduced by
$this->getConfig() of type HTMLPurifier_Config is incompatible with the type array expected by parameter $config_array of HTMLPurifier_Config::loadArray(). ( Ignorable by Annotation )

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

90
            $configObject->loadArray(/** @scrutinizer ignore-type */ $this->getConfig());
Loading history...
91
        }
92
93
        // Setup the custom definition
94
        $configObject->set('HTML.DefinitionID', $definitionConfig['id']);
95
        $configObject->set('HTML.DefinitionRev', $definitionConfig['rev']);
96
97
        // Enable debug mode
98
        if (!isset($definitionConfig['debug']) || $definitionConfig['debug']) {
99
            $configObject->set('Cache.DefinitionImpl', null);
100
        }
101
102
        // Start configuring the definition
103
        if ($def = $configObject->maybeGetRawHTMLDefinition()) {
104
            // Create the definition attributes
105
            if (!empty($definitionConfig['attributes'])) {
106
                $this->addCustomAttributes($definitionConfig['attributes'], $def);
107
            }
108
109
            // Create the definition elements
110
            if (!empty($definitionConfig['elements'])) {
111
                $this->addCustomElements($definitionConfig['elements'], $def);
112
            }
113
        }
114
115
        return $configObject;
116
    }
117
118
    /**
119
     * Add provided attributes to the provided definition
120
     *
121
     * @param array $attributes
122
     * @param HTMLPurifier_HTMLDefinition $definition
123
     *
124
     * @return HTMLPurifier_HTMLDefinition $definition
125
     */
126
    private function addCustomAttributes(array $attributes, HTMLPurifier_HTMLDefinition $definition)
127
    {
128
        foreach ($attributes as $attribute) {
129
            // Get configuration of attribute
130
            $required = !empty($attribute[3]) ? true : false;
131
            $onElement = $attribute[0];
132
            $attrName = $required ? $attribute[1] . '*' : $attribute[1];
133
            $validValues = $attribute[2];
134
135
            if ($onElement === '*') {
136
                $def = $validValues;
137
                if (is_string($validValues)) {
138
                    $def = new $validValues();
139
                }
140
141
                if ($def instanceof \HTMLPurifier_AttrDef) {
142
                    $definition->info_global_attr[$attrName] = $def;
143
                }
144
145
                continue;
146
	    }
147
148
	    if (class_exists($validValues)) {
149
		$validValues = new $validValues();
150
	    }
151
152
            $definition->addAttribute($onElement, $attrName, $validValues);
153
        }
154
155
        return $definition;
156
    }
157
158
    /**
159
     * Add provided elements to the provided definition
160
     *
161
     * @param array $elements
162
     * @param HTMLPurifier_HTMLDefinition $definition
163
     *
164
     * @return HTMLPurifier_HTMLDefinition $definition
165
     */
166
    private function addCustomElements(array $elements, HTMLPurifier_HTMLDefinition $definition)
167
    {
168
        foreach ($elements as $element) {
169
            // Get configuration of element
170
            $name = $element[0];
171
            $contentSet = $element[1];
172
            $allowedChildren = $element[2];
173
            $attributeCollection = $element[3];
174
            $attributes = isset($element[4]) ? $element[4] : null;
175
176
            if (!empty($attributes)) {
177
                $definition->addElement($name, $contentSet, $allowedChildren, $attributeCollection, $attributes);
178
            } else {
179
                $definition->addElement($name, $contentSet, $allowedChildren, $attributeCollection);
180
            }
181
        }
182
    }
183
184
    /**
185
     * Check/Create cache directory
186
     */
187
    private function checkCacheDirectory()
188
    {
189
        $cachePath = $this->config->get('purifier.cachePath');
190
191
        if ($cachePath) {
192
            if (!$this->files->isDirectory($cachePath)) {
193
                $this->files->makeDirectory($cachePath, $this->config->get('purifier.cacheFileMode', 0755),true);
194
            }
195
        }
196
    }
197
198
    /**
199
     * @param null $config
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $config is correct as it would always require null to be passed?
Loading history...
200
     *
201
     * @return mixed|null
202
     */
203
    protected function getConfig($config = null)
204
    {
205
        // Create a new configuration object
206
        $configObject = HTMLPurifier_Config::createDefault();
207
208
        // Allow configuration to be modified
209
        if (! $this->config->get('purifier.finalize')) {
210
            $configObject->autoFinalize = false;
211
        }
212
213
        // Set default config
214
        $defaultConfig = [];
215
        $defaultConfig['Core.Encoding'] = $this->config->get('purifier.encoding');
216
        $defaultConfig['Cache.SerializerPath'] = $this->config->get('purifier.cachePath');
217
        $defaultConfig['Cache.SerializerPermissions'] = $this->config->get('purifier.cacheFileMode', 0755);
218
219
        if (! $config) {
0 ignored issues
show
introduced by
$config is of type null, thus it always evaluated to false.
Loading history...
220
            $config = $this->config->get('purifier.settings.default');
221
        } elseif (is_string($config)) {
222
            $config = $this->config->get('purifier.settings.' . $config);
223
        }
224
225
        if (! is_array($config)) {
226
            $config = [];
227
        }
228
229
        // Merge configurations
230
        $config = $defaultConfig + $config;
231
232
        // Load to Purifier config
233
        $configObject->loadArray($config);
234
235
        // Load custom definition if set
236
        if ($definitionConfig = $this->config->get('purifier.settings.custom_definition')) {
237
            $this->addCustomDefinition($definitionConfig, $configObject);
238
        }
239
240
        // Load custom elements if set
241
        if ($elements = $this->config->get('purifier.settings.custom_elements')) {
242
            if ($def = $configObject->maybeGetRawHTMLDefinition()) {
243
                $this->addCustomElements($elements, $def);
244
            }
245
        }
246
247
        // Load custom attributes if set
248
        if ($attributes = $this->config->get('purifier.settings.custom_attributes')) {
249
            if ($def = $configObject->maybeGetRawHTMLDefinition()) {
250
                $this->addCustomAttributes($attributes, $def);
251
            }
252
        }
253
254
        return $configObject;
255
    }
256
257
    /**
258
     * @param      $dirty
259
     * @param null $config
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $config is correct as it would always require null to be passed?
Loading history...
260
     * @param \Closure|null $postCreateConfigHook
261
     * @return mixed
262
     */
263
    public function clean($dirty, $config = null, \Closure $postCreateConfigHook = null)
264
    {
265
        if (is_array($dirty)) {
266
            return array_map(function ($item) use ($config) {
267
                return $this->clean($item, $config);
268
            }, $dirty);
269
        }
270
271
        $configObject = null;
272
        if ($config !== null) {
0 ignored issues
show
introduced by
The condition $config !== null is always false.
Loading history...
273
            $configObject = $this->getConfig($config);
274
275
            if ($postCreateConfigHook !== null) {
276
                $postCreateConfigHook->call($this, $configObject);
277
            }
278
        }
279
280
        //If $dirty is not an explicit string, bypass purification assuming configuration allows this
281
        $ignoreNonStrings = $this->config->get('purifier.ignoreNonStrings', false);
282
        $stringTest = is_string($dirty);
283
        if($stringTest === false && $ignoreNonStrings === true) {
284
            return $dirty;
285
        }
286
287
        return $this->purifier->purify($dirty, $configObject);
288
    }
289
290
    /**
291
     * Get HTMLPurifier instance.
292
     *
293
     * @return \HTMLPurifier
294
     */
295
    public function getInstance()
296
    {
297
        return $this->purifier;
298
    }
299
}
300