Passed
Push — master ( bee645...5a9b46 )
by Bekh-Ivanov
02:05
created

HtmlMatcher::escapeScriptTagContents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace WMDE\HamcrestHtml;
4
5
use Hamcrest\Description;
6
use Hamcrest\DiagnosingMatcher;
7
use Hamcrest\Matcher;
8
9
class HtmlMatcher extends DiagnosingMatcher
10
{
11
12
	/**
13
     * @link http://www.xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
14
     * @link https://github.com/Chronic-Dev/libxml2/blob/683f296a905710ff285c28b8644ef3a3d8be9486/include/libxml/xmlerror.h#L257
15
     */
16
    const XML_UNKNOWN_TAG_ERROR_CODE = 801;
17
18
    /**
19
     * @var Matcher
20
     */
21
    private $elementMatcher;
22
23
    /**
24
     * @param Matcher $elementMatcher
25
     *
26
     * @return HtmlMatcher
27
     */
28 65
    public static function htmlPiece(Matcher $elementMatcher = null)
29
    {
30 65
        return new static($elementMatcher);
31
    }
32
33 65
    private function __construct(Matcher $elementMatcher = null)
34
    {
35 65
        $this->elementMatcher = $elementMatcher;
36 65
    }
37
38 15
    public function describeTo(Description $description)
39
    {
40 15
        $description->appendText('valid html piece ');
41 15
        if ($this->elementMatcher) {
42 14
            $description->appendDescriptionOf($this->elementMatcher);
43 14
        }
44 15
    }
45
46 65
    protected function matchesWithDiagnosticDescription($html, Description $mismatchDescription)
47
    {
48 65
        $internalErrors = libxml_use_internal_errors(true);
49 65
        $document = new \DOMDocument();
50
51 65
        $html = $this->escapeScriptTagContents($html);
52
53 65
        if ([email protected]$document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'))) {
54
            $mismatchDescription->appendText('there was some parsing error');
55
            return false;
56
        }
57
58 65
        $errors = libxml_get_errors();
59 65
        libxml_clear_errors();
60 65
        libxml_use_internal_errors($internalErrors);
61
62 65
        $result = true;
63
        /** @var \LibXMLError $error */
64 65
        foreach ($errors as $error) {
65 32
            if ($this->isUnknownTagError($error)) {
66 31
                continue;
67
            }
68
69 1
            $mismatchDescription->appendText('there was parsing error: ')
70 1
                ->appendText(trim($error->message))
71 1
                ->appendText(' on line ')
72 1
                ->appendText($error->line);
73 1
            $result = false;
74 65
        }
75
76 65
        if ($result === false) {
77 1
            return $result;
78
        }
79 64
        $mismatchDescription->appendText('valid html piece ');
80
81 64
        if ($this->elementMatcher) {
82 30
            $result = $this->elementMatcher->matches($document);
83 30
            $this->elementMatcher->describeMismatch($document, $mismatchDescription);
84 30
        }
85
86 64
        $mismatchDescription->appendText("\nActual html:\n")->appendText($html);
87
88 64
        return $result;
89
    }
90
91 32
    private function isUnknownTagError(\LibXMLError $error)
92
    {
93 32
        return $error->code === self::XML_UNKNOWN_TAG_ERROR_CODE;
94
    }
95
96
    /**
97
     * @param string $html
98
     *
99
     * @return string HTML
100
     */
101
    private function escapeScriptTagContents($html)
102
    {
103 65
        return preg_replace_callback('#(<script.*>)(.*)(</script>)#isU', function ($matches) {
104 3
            return $matches[1] . str_replace('</', '<\/', $matches[2]) . $matches[3];
105 65
        }, $html);
106
    }
107
108
}
109