Completed
Pull Request — master (#82)
by
unknown
10:19
created

PurifierConfigBuilder::addCustomDefinition()   C

Complexity

Conditions 7
Paths 20

Size

Total Lines 31
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 14
c 0
b 0
f 0
nc 20
nop 2
dl 0
loc 31
rs 6.7272
1
<?php
2
/**
3
 * Laravel 5 HTMLPurifier package
4
 *
5
 * @copyright Copyright (c) 2015 MeWebStudio
6
 * @version   2.0.0
7
 * @author    Muharrem ERİN
8
 * @contact [email protected]
9
 * @web http://www.mewebstudio.com
10
 * @date      2014-04-02
11
 * @license   MIT
12
 */
13
14
namespace Mews\Purifier;
15
16
use HTMLPurifier_Config;
17
use HTMLPurifier_HTMLDefinition;
18
use Illuminate\Contracts\Config\Repository;
19
20
class PurifierConfigBuilder
21
{
22
    /**
23
     * @var \Illuminate\Contracts\Config\Repository
24
     */
25
    private $config;
26
27
    /**
28
     * PurifierConfig constructor.
29
     *
30
     * @param \Illuminate\Contracts\Config\Repository $config
31
     */
32
    public function __construct(Repository $config)
33
    {
34
        $this->config = $config;
35
    }
36
37
    /**
38
     * @param null $config
39
     *
40
     * @return mixed|null
41
     */
42
    public function getConfig($config = null)
43
    {
44
        // Create a new configuration object
45
        $configObject = HTMLPurifier_Config::createDefault();
46
47
        // Allow configuration to be modified
48
        if (! $this->config->get('purifier.finalize')) {
49
            $configObject->autoFinalize = false;
50
        }
51
52
        // Set default config
53
        $defaultConfig = [];
54
        $defaultConfig['Core.Encoding'] = $this->config->get('purifier.encoding');
55
        $defaultConfig['Cache.SerializerPath'] = $this->config->get('purifier.cachePath');
56
        $defaultConfig['Cache.SerializerPermissions'] = $this->config->get('purifier.cacheFileMode', 0755);
57
58
        if (! $config) {
59
            $config = $this->config->get('purifier.settings.default');
60
        } elseif (is_string($config)) {
61
            $config = $this->config->get('purifier.settings.' . $config);
62
        }
63
64
        if (! is_array($config)) {
65
            $config = [];
66
        }
67
68
        // Merge configurations
69
        $config = $defaultConfig + $config;
70
71
        // Load to Purifier config
72
        $configObject->loadArray($config);
73
74
        // Load custom definition if set
75
        if ($definitionConfig = $this->config->get('purifier.settings.custom_definition')) {
76
            $this->addCustomDefinition($definitionConfig, $configObject);
77
        }
78
79
        // Load custom elements if set
80
        if ($elements = $this->config->get('purifier.settings.custom_elements')) {
81
            if ($def = $configObject->maybeGetRawHTMLDefinition()) {
82
                $this->addCustomElements($elements, $def, $configObject);
83
            }
84
        }
85
86
        // Load custom attributes if set
87
        if ($attributes = $this->config->get('purifier.settings.custom_attributes')) {
88
            if ($def = $configObject->maybeGetRawHTMLDefinition()) {
89
                $this->addCustomAttributes($attributes, $def);
90
            }
91
        }
92
93
        return $configObject;
94
    }
95
96
    /**
97
     * Add a custom definition
98
     *
99
     * @see http://htmlpurifier.org/docs/enduser-customize.html
100
     * @param array $definitionConfig
101
     * @param HTMLPurifier_Config $configObject Defaults to using default config
102
     *
103
     * @return HTMLPurifier_Config $configObject
104
     */
105
    private function addCustomDefinition(array $definitionConfig, $configObject = null)
106
    {
107
        if (! $configObject) {
108
            $configObject = HTMLPurifier_Config::createDefault();
109
            $configObject->loadArray($this->getConfig());
0 ignored issues
show
Documentation introduced by
$this->getConfig() is of type object<HTMLPurifier_Config>, 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...
110
        }
111
112
        // Setup the custom definition
113
        $configObject->set('HTML.DefinitionID', $definitionConfig['id']);
114
        $configObject->set('HTML.DefinitionRev', $definitionConfig['rev']);
115
116
        // Enable debug mode
117
        if (! isset($definitionConfig['debug']) || $definitionConfig['debug']) {
118
            $configObject->set('Cache.DefinitionImpl', null);
119
        }
120
121
        // Start configuring the definition
122
        if ($def = $configObject->maybeGetRawHTMLDefinition()) {
123
            // Create the definition attributes
124
            if (! empty($definitionConfig['attributes'])) {
125
                $this->addCustomAttributes($definitionConfig['attributes'], $def);
126
            }
127
128
            // Create the definition elements
129
            if (! empty($definitionConfig['elements'])) {
130
                $this->addCustomElements($definitionConfig['elements'], $def, $configObject);
131
            }
132
        }
133
134
        return $configObject;
135
    }
136
137
    /**
138
     * Add provided attributes to the provided definition
139
     *
140
     * @param array $attributes
141
     * @param HTMLPurifier_HTMLDefinition $definition
142
     *
143
     * @return HTMLPurifier_HTMLDefinition $definition
144
     */
145
    private function addCustomAttributes(array $attributes, $definition)
146
    {
147
        foreach ($attributes as $attribute) {
148
            // Get configuration of attribute
149
            $required = ! empty($attribute[3]) ? true : false;
150
            $onElement = $attribute[0];
151
            $attrName = $required ? $attribute[1] . '*' : $attribute[1];
152
            $validValues = $attribute[2];
153
154
            $definition->addAttribute($onElement, $attrName, $validValues);
155
        }
156
157
        return $definition;
158
    }
159
160
    /**
161
     * Add provided elements to the provided definition
162
     *
163
     * @param array $elements
164
     * @param HTMLPurifier_HTMLDefinition $definition
165
     * @param HTMLPurifier_Config $configObject
166
     *
167
     * @return HTMLPurifier_HTMLDefinition $definition
168
     */
169
    private function addCustomElements(array $elements, HTMLPurifier_HTMLDefinition $definition, HTMLPurifier_Config $configObject) {
170
        $customElements = [];
171
172
        foreach ($elements as $element) {
173
            // Get configuration of element
174
            $name = $element[0];
175
            $contentSet = $element[1];
176
            $allowedChildren = $element[2];
177
            $attributeCollection = $element[3];
178
            $attributes = isset($element[4]) ? $element[4] : null;
179
180
            $customElements[] = $name;
181
182
            if (! empty($attributes)) {
183
                $definition->addElement($name, $contentSet, $allowedChildren, $attributeCollection, $attributes);
184
            } else {
185
                $definition->addElement($name, $contentSet, $allowedChildren, $attributeCollection);
186
            }
187
        }
188
189
        // There is no custom elements to append to allowed - return
190
        if (empty($customElements)) {
191
            return;
192
        }
193
194
        // We must append custom elements to the list of allowed elements if it is provided
195
        if ($allowed = $this->getAllowedProperty($configObject)) {
196
            $allowed = $allowed . ',' . implode(',', $customElements);
197
198
            $this->setAllowedProperty($allowed, $configObject);
199
        }
200
    }
201
202
    /**
203
     * @param \HTMLPurifier_Config $configObject
204
     * @return mixed
205
     */
206
    private function getAllowedProperty(HTMLPurifier_Config $configObject)
207
    {
208
        if (null !== $configObject->get('HTML.Allowed')) {
209
            return $configObject->get('HTML.Allowed');
210
        }
211
212
        if (null !== $configObject->get('HTML.AllowedElements')) {
213
            $allowedArray = $configObject->get('HTML.AllowedElements');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $allowedArray is correct as $configObject->get('HTML.AllowedElements') (which targets HTMLPurifier_Config::get()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
214
215
            return implode(',', array_keys($allowedArray));
216
        }
217
218
        return;
219
    }
220
221
    /**
222
     * @param $allowed
223
     * @param \HTMLPurifier_Config $configObject
224
     * @return mixed
225
     */
226
    private function setAllowedProperty($allowed, HTMLPurifier_Config $configObject)
227
    {
228
        if (null !== $configObject->get('HTML.Allowed')) {
229
            $this->setPropertyDirectly('HTML.Allowed', $allowed, $configObject);
230
231
            return;
232
        }
233
234
        if (null !== $configObject->get('HTML.AllowedElements')) {
235
            $allowedArray = array_fill_keys(array_keys(array_flip(explode(',', $allowed))), true);
236
            $this->setPropertyDirectly('HTML.AllowedElements', $allowedArray, $configObject);
237
238
            return;
239
        }
240
241
        return;
242
    }
243
244
    /**
245
     * @param $name
246
     * @param $value
247
     * @param \HTMLPurifier_Config $configObject
248
     */
249
    private function setPropertyDirectly($name, $value, HTMLPurifier_Config $configObject)
250
    {
251
        // We can not use $configObject->set() because it resets definitions
252
        // when setting properties from HTML namespace
253
        // So we  use closure to access protected property and set modified value directly
254
        // Closure much faster than ReflectionProperty
255
        $plistClosure = \Closure::bind(function ($configObject) {
256
            return $configObject->plist;
257
        }, null, HTMLPurifier_Config::class);
258
259
        /** @var \HTMLPurifier_PropertyList $plist */
260
        $plist = $plistClosure($configObject);
261
262
        $plist->set($name, $value);
263
    }
264
}