Passed
Push — master ( 3968a7...b87f75 )
by Rougin
02:18
created

HtmlMinifier::childbearing()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
nc 3
nop 1
dl 0
loc 14
ccs 10
cts 10
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Staticka\Filter;
4
5
/**
6
 * HTML Minifier
7
 *
8
 * @package Staticka
9
 * @author  Rougin Gutib <[email protected]>
10
 */
11
class HtmlMinifier implements FilterInterface
12
{
13
    /**
14
     * @var array
15
     */
16
    protected $data = array();
17
18
    /**
19
     * Filters the specified code.
20
     *
21
     * @param  string $code
22
     * @return string
23
     */
24 6
    public function filter($code)
25
    {
26 6
        if (strpos($code, '<html') === false)
27 4
        {
28 3
            return $this->minify($code);
29
        }
30
31 3
        $utf8 = (string) '<?xml encoding="UTF-8">';
32
33 3
        $dom = new \DOMDocument;
34
35 3
        @$dom->loadHTML((string) $utf8 . $code);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for loadHTML(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

35
        /** @scrutinizer ignore-unhandled */ @$dom->loadHTML((string) $utf8 . $code);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
36
37 3
        $elements = $dom->getElementsByTagName('*');
38
39 3
        $this->remove($elements);
40
41 3
        $html = $this->minify($dom->saveHTML());
42
43 3
        return $this->restore((string) $html);
44
    }
45
46
    /**
47
     * Checks if a specified node has children.
48
     *
49
     * @param  \DOMNode $node
50
     * @return boolean
51
     */
52 3
    protected function childbearing(\DOMNode $node)
53
    {
54 3
        if ($node->hasChildNodes())
55 2
        {
56 3
            foreach ($node->childNodes as $child)
57
            {
58 3
                if ($child->nodeType === XML_ELEMENT_NODE)
59 2
                {
60 3
                    return true;
61
                }
62 2
            }
63 2
        }
64
65 3
        return false;
66
    }
67
68
    /**
69
     * Minifies the specified HTML.
70
     *
71
     * @param  string $html
72
     * @return string
73
     */
74 6
    protected function minify($html)
75
    {
76 6
        $html = str_replace('<?xml encoding="UTF-8">', '', $html);
77
78 6
        $html = trim(preg_replace('/\s+/', ' ', $html));
79
80 6
        $html = str_replace('> <', '><', $html);
81
82 6
        return str_replace(array(' />', '/>'), '>', $html);
83
    }
84
85
    /**
86
     * Removes the content of single elements.
87
     *
88
     * @param  \DOMNodeList $elements
89
     * @return void
90
     */
91 3
    protected function remove(\DOMNodeList $elements)
92
    {
93 3
        $encoded = array('textarea', 'code');
94
95 3
        foreach ($elements as $element)
96
        {
97 3
            if ($this->childbearing($element))
98 2
            {
99 3
                continue;
100
            }
101
102 3
            $output = (string) $element->nodeValue;
103
104 3
            if (in_array($element->nodeName, $encoded))
105 2
            {
106 3
                $output = htmlentities($element->nodeValue);
107 2
            }
108
109 3
            array_push($this->data, (string) $output);
110
111 3
            $current = count($this->data) - 1;
112
113 3
            $element->nodeValue = '$' . $current . '$';
114 2
        }
115 3
    }
116
117
    /**
118
     * Restores the data into the minified HTML.
119
     *
120
     * @param  string $html
121
     * @return string
122
     */
123 3
    protected function restore($html)
124
    {
125 3
        foreach ($this->data as $index => $item)
126
        {
127 3
            $key = (string) '$' . $index . '$';
128
129 3
            $html = str_replace($key, $item, $html);
130 2
        }
131
132 3
        return (string) $html;
133
    }
134
}
135