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.
Test Failed
Pull Request — master (#12)
by no
03:40
created
src/TagNameMatcher.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -8,39 +8,39 @@
 block discarded – undo
8 8
 
9 9
 class TagNameMatcher extends TagMatcher {
10 10
 
11
-	/**
12
-	 * @var Matcher
13
-	 */
14
-	private $tagNameMatcher;
15
-
16
-	public static function withTagName( $tagName ) {
17
-		return new static( Util::wrapValueWithIsEqual( $tagName ) );
18
-	}
19
-
20
-	public function __construct( Matcher $tagNameMatcher ) {
21
-		parent::__construct();
22
-		$this->tagNameMatcher = $tagNameMatcher;
23
-	}
24
-
25
-	public function describeTo( Description $description ) {
26
-		$description->appendText( 'with tag name ' )
27
-			->appendDescriptionOf( $this->tagNameMatcher );
28
-	}
29
-
30
-	/**
31
-	 * @param \DOMElement $item
32
-	 * @param Description $mismatchDescription
33
-	 *
34
-	 * @return bool
35
-	 */
36
-	protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
37
-		if ( $this->tagNameMatcher->matches( $item->tagName ) ) {
38
-			return true;
39
-		}
40
-
41
-		$mismatchDescription->appendText( 'tag name ' );
42
-		$this->tagNameMatcher->describeMismatch( $item->tagName, $mismatchDescription );
43
-		return false;
44
-	}
11
+    /**
12
+     * @var Matcher
13
+     */
14
+    private $tagNameMatcher;
15
+
16
+    public static function withTagName( $tagName ) {
17
+        return new static( Util::wrapValueWithIsEqual( $tagName ) );
18
+    }
19
+
20
+    public function __construct( Matcher $tagNameMatcher ) {
21
+        parent::__construct();
22
+        $this->tagNameMatcher = $tagNameMatcher;
23
+    }
24
+
25
+    public function describeTo( Description $description ) {
26
+        $description->appendText( 'with tag name ' )
27
+            ->appendDescriptionOf( $this->tagNameMatcher );
28
+    }
29
+
30
+    /**
31
+     * @param \DOMElement $item
32
+     * @param Description $mismatchDescription
33
+     *
34
+     * @return bool
35
+     */
36
+    protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
37
+        if ( $this->tagNameMatcher->matches( $item->tagName ) ) {
38
+            return true;
39
+        }
40
+
41
+        $mismatchDescription->appendText( 'tag name ' );
42
+        $this->tagNameMatcher->describeMismatch( $item->tagName, $mismatchDescription );
43
+        return false;
44
+    }
45 45
 
46 46
 }
Please login to merge, or discard this patch.
src/HtmlMatcher.php 1 patch
Indentation   +89 added lines, -89 removed lines patch added patch discarded remove patch
@@ -8,94 +8,94 @@
 block discarded – undo
8 8
 
9 9
 class HtmlMatcher extends DiagnosingMatcher {
10 10
 
11
-	/**
12
-	 * @link http://www.xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
13
-	 * @link https://github.com/Chronic-Dev/libxml2/blob/683f296a905710ff285c28b8644ef3a3d8be9486/include/libxml/xmlerror.h#L257
14
-	 */
15
-	const XML_UNKNOWN_TAG_ERROR_CODE = 801;
16
-
17
-	/**
18
-	 * @var Matcher
19
-	 */
20
-	private $elementMatcher;
21
-
22
-	/**
23
-	 * @param Matcher $elementMatcher
24
-	 *
25
-	 * @return HtmlMatcher
26
-	 */
27
-	public static function htmlPiece( Matcher $elementMatcher = null ) {
28
-		return new static( $elementMatcher );
29
-	}
30
-
31
-	private function __construct( Matcher $elementMatcher = null ) {
32
-		$this->elementMatcher = $elementMatcher;
33
-	}
34
-
35
-	public function describeTo( Description $description ) {
36
-		$description->appendText( 'valid html piece ' );
37
-		if ( $this->elementMatcher ) {
38
-			$description->appendDescriptionOf( $this->elementMatcher );
39
-		}
40
-	}
41
-
42
-	protected function matchesWithDiagnosticDescription( $html, Description $mismatchDescription ) {
43
-		$internalErrors = libxml_use_internal_errors( true );
44
-		$document = new \DOMDocument();
45
-
46
-		$html = $this->escapeScriptTagContents( $html );
47
-
48
-		if ( !@$document->loadHTML( mb_convert_encoding( $html, 'HTML-ENTITIES', 'UTF-8' ) ) ) {
49
-			$mismatchDescription->appendText( 'there was some parsing error' );
50
-			return false;
51
-		}
52
-
53
-		$errors = libxml_get_errors();
54
-		libxml_clear_errors();
55
-		libxml_use_internal_errors( $internalErrors );
56
-
57
-		$result = true;
58
-		/** @var \LibXMLError $error */
59
-		foreach ( $errors as $error ) {
60
-			if ( $this->isUnknownTagError( $error ) ) {
61
-				continue;
62
-			}
63
-
64
-			$mismatchDescription->appendText( 'there was parsing error: ' )
65
-				->appendText( trim( $error->message ) )
66
-				->appendText( ' on line ' )
67
-				->appendText( $error->line );
68
-			$result = false;
69
-		}
70
-
71
-		if ( !$result ) {
72
-			return false;
73
-		}
74
-		$mismatchDescription->appendText( 'valid html piece ' );
75
-
76
-		if ( $this->elementMatcher ) {
77
-			$result = $this->elementMatcher->matches( $document );
78
-			$this->elementMatcher->describeMismatch( $document, $mismatchDescription );
79
-		}
80
-
81
-		$mismatchDescription->appendText( "\nActual html:\n" )->appendText( $html );
82
-
83
-		return $result;
84
-	}
85
-
86
-	private function isUnknownTagError( \LibXMLError $error ) {
87
-		return $error->code === self::XML_UNKNOWN_TAG_ERROR_CODE;
88
-	}
89
-
90
-	/**
91
-	 * @param string $html
92
-	 *
93
-	 * @return string HTML
94
-	 */
95
-	private function escapeScriptTagContents( $html ) {
96
-		return preg_replace_callback( '#(<script.*>)(.*)(</script>)#isU', function ( $matches ) {
97
-			return $matches[1] . str_replace( '</', '<\/', $matches[2] ) . $matches[3];
98
-		}, $html );
99
-	}
11
+    /**
12
+     * @link http://www.xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
13
+     * @link https://github.com/Chronic-Dev/libxml2/blob/683f296a905710ff285c28b8644ef3a3d8be9486/include/libxml/xmlerror.h#L257
14
+     */
15
+    const XML_UNKNOWN_TAG_ERROR_CODE = 801;
16
+
17
+    /**
18
+     * @var Matcher
19
+     */
20
+    private $elementMatcher;
21
+
22
+    /**
23
+     * @param Matcher $elementMatcher
24
+     *
25
+     * @return HtmlMatcher
26
+     */
27
+    public static function htmlPiece( Matcher $elementMatcher = null ) {
28
+        return new static( $elementMatcher );
29
+    }
30
+
31
+    private function __construct( Matcher $elementMatcher = null ) {
32
+        $this->elementMatcher = $elementMatcher;
33
+    }
34
+
35
+    public function describeTo( Description $description ) {
36
+        $description->appendText( 'valid html piece ' );
37
+        if ( $this->elementMatcher ) {
38
+            $description->appendDescriptionOf( $this->elementMatcher );
39
+        }
40
+    }
41
+
42
+    protected function matchesWithDiagnosticDescription( $html, Description $mismatchDescription ) {
43
+        $internalErrors = libxml_use_internal_errors( true );
44
+        $document = new \DOMDocument();
45
+
46
+        $html = $this->escapeScriptTagContents( $html );
47
+
48
+        if ( !@$document->loadHTML( mb_convert_encoding( $html, 'HTML-ENTITIES', 'UTF-8' ) ) ) {
49
+            $mismatchDescription->appendText( 'there was some parsing error' );
50
+            return false;
51
+        }
52
+
53
+        $errors = libxml_get_errors();
54
+        libxml_clear_errors();
55
+        libxml_use_internal_errors( $internalErrors );
56
+
57
+        $result = true;
58
+        /** @var \LibXMLError $error */
59
+        foreach ( $errors as $error ) {
60
+            if ( $this->isUnknownTagError( $error ) ) {
61
+                continue;
62
+            }
63
+
64
+            $mismatchDescription->appendText( 'there was parsing error: ' )
65
+                ->appendText( trim( $error->message ) )
66
+                ->appendText( ' on line ' )
67
+                ->appendText( $error->line );
68
+            $result = false;
69
+        }
70
+
71
+        if ( !$result ) {
72
+            return false;
73
+        }
74
+        $mismatchDescription->appendText( 'valid html piece ' );
75
+
76
+        if ( $this->elementMatcher ) {
77
+            $result = $this->elementMatcher->matches( $document );
78
+            $this->elementMatcher->describeMismatch( $document, $mismatchDescription );
79
+        }
80
+
81
+        $mismatchDescription->appendText( "\nActual html:\n" )->appendText( $html );
82
+
83
+        return $result;
84
+    }
85
+
86
+    private function isUnknownTagError( \LibXMLError $error ) {
87
+        return $error->code === self::XML_UNKNOWN_TAG_ERROR_CODE;
88
+    }
89
+
90
+    /**
91
+     * @param string $html
92
+     *
93
+     * @return string HTML
94
+     */
95
+    private function escapeScriptTagContents( $html ) {
96
+        return preg_replace_callback( '#(<script.*>)(.*)(</script>)#isU', function ( $matches ) {
97
+            return $matches[1] . str_replace( '</', '<\/', $matches[2] ) . $matches[3];
98
+        }, $html );
99
+    }
100 100
 
101 101
 }
Please login to merge, or discard this patch.
src/RootElementMatcher.php 1 patch
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -8,60 +8,60 @@
 block discarded – undo
8 8
 
9 9
 class RootElementMatcher extends TypeSafeDiagnosingMatcher {
10 10
 
11
-	/**
12
-	 * @var Matcher
13
-	 */
14
-	private $tagMatcher;
11
+    /**
12
+     * @var Matcher
13
+     */
14
+    private $tagMatcher;
15 15
 
16
-	/**
17
-	 * @param Matcher|null $tagMatcher
18
-	 *
19
-	 * @return static
20
-	 */
21
-	public static function havingRootElement( Matcher $tagMatcher = null ) {
22
-		return new static( $tagMatcher );
23
-	}
16
+    /**
17
+     * @param Matcher|null $tagMatcher
18
+     *
19
+     * @return static
20
+     */
21
+    public static function havingRootElement( Matcher $tagMatcher = null ) {
22
+        return new static( $tagMatcher );
23
+    }
24 24
 
25
-	public function __construct( Matcher $tagMatcher = null ) {
26
-		parent::__construct( self::TYPE_OBJECT, \DOMDocument::class );
27
-		$this->tagMatcher = $tagMatcher;
28
-	}
25
+    public function __construct( Matcher $tagMatcher = null ) {
26
+        parent::__construct( self::TYPE_OBJECT, \DOMDocument::class );
27
+        $this->tagMatcher = $tagMatcher;
28
+    }
29 29
 
30
-	public function describeTo( Description $description ) {
31
-		$description->appendText( 'having root element ' );
32
-		if ( $this->tagMatcher ) {
33
-			$description->appendDescriptionOf( $this->tagMatcher );
34
-		}
35
-	}
30
+    public function describeTo( Description $description ) {
31
+        $description->appendText( 'having root element ' );
32
+        if ( $this->tagMatcher ) {
33
+            $description->appendDescriptionOf( $this->tagMatcher );
34
+        }
35
+    }
36 36
 
37
-	/**
38
-	 * @param \DOMDocument $item
39
-	 * @param Description $mismatchDescription
40
-	 *
41
-	 * @return bool
42
-	 */
43
-	protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
44
-		$DOMNodeList = $item->documentElement->childNodes->item( 0 )->childNodes;
45
-		if ( $DOMNodeList->length > 1 ) {
46
-			// TODO Test this description
47
-			$mismatchDescription->appendText( 'having ' . $DOMNodeList->length . ' root elements ' );
48
-			return false;
49
-		}
37
+    /**
38
+     * @param \DOMDocument $item
39
+     * @param Description $mismatchDescription
40
+     *
41
+     * @return bool
42
+     */
43
+    protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
44
+        $DOMNodeList = $item->documentElement->childNodes->item( 0 )->childNodes;
45
+        if ( $DOMNodeList->length > 1 ) {
46
+            // TODO Test this description
47
+            $mismatchDescription->appendText( 'having ' . $DOMNodeList->length . ' root elements ' );
48
+            return false;
49
+        }
50 50
 
51
-		$target = $DOMNodeList->item( 0 );
52
-		if ( !$target ) {
53
-			// TODO Reproduce?
54
-			$mismatchDescription->appendText( 'having no root elements ' );
55
-			return false;
56
-		}
51
+        $target = $DOMNodeList->item( 0 );
52
+        if ( !$target ) {
53
+            // TODO Reproduce?
54
+            $mismatchDescription->appendText( 'having no root elements ' );
55
+            return false;
56
+        }
57 57
 
58
-		if ( $this->tagMatcher ) {
59
-			$mismatchDescription->appendText( 'root element ' );
60
-			$this->tagMatcher->describeMismatch( $target, $mismatchDescription );
61
-			return $this->tagMatcher->matches( $target );
62
-		}
58
+        if ( $this->tagMatcher ) {
59
+            $mismatchDescription->appendText( 'root element ' );
60
+            $this->tagMatcher->describeMismatch( $target, $mismatchDescription );
61
+            return $this->tagMatcher->matches( $target );
62
+        }
63 63
 
64
-		return true;
65
-	}
64
+        return true;
65
+    }
66 66
 
67 67
 }
Please login to merge, or discard this patch.
src/DirectChildElementMatcher.php 1 patch
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -8,61 +8,61 @@
 block discarded – undo
8 8
 
9 9
 class DirectChildElementMatcher extends TypeSafeDiagnosingMatcher {
10 10
 
11
-	/**
12
-	 * @var Matcher
13
-	 */
14
-	private $matcher;
15
-
16
-	public static function havingDirectChild( Matcher $elementMatcher = null ) {
17
-		return new static( $elementMatcher );
18
-	}
19
-
20
-	public function __construct( Matcher $matcher = null ) {
21
-		parent::__construct( \DOMNode::class );
22
-		$this->matcher = $matcher;
23
-	}
24
-
25
-	public function describeTo( Description $description ) {
26
-		$description->appendText( 'having direct child ' );
27
-		if ( $this->matcher ) {
28
-			$description->appendDescriptionOf( $this->matcher );
29
-		}
30
-	}
31
-
32
-	/**
33
-	 * @param \DOMDocument|\DOMNode $item
34
-	 * @param Description $mismatchDescription
35
-	 *
36
-	 * @return bool
37
-	 */
38
-	protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
39
-		if ( $item instanceof \DOMDocument ) {
40
-			$item = $item->documentElement->childNodes->item( 0 );
41
-		}
42
-		$directChildren = $item->childNodes;
43
-
44
-		if ( $directChildren->length === 0 ) {
45
-			$mismatchDescription->appendText( 'with no direct children' );
46
-			return false;
47
-		}
48
-
49
-		$childWord = $directChildren->length === 1 ? 'child' : 'children';
50
-
51
-		$mismatchDescription->appendText( "with direct {$childWord} " );
52
-
53
-		if ( !$this->matcher ) {
54
-			return $directChildren->length !== 0;
55
-		}
56
-
57
-		foreach ( $directChildren as $child ) {
58
-			if ( $this->matcher->matches( $child ) ) {
59
-				return true;
60
-			}
61
-		}
62
-
63
-		$this->matcher->describeMismatch( $child, $mismatchDescription );
64
-
65
-		return false;
66
-	}
11
+    /**
12
+     * @var Matcher
13
+     */
14
+    private $matcher;
15
+
16
+    public static function havingDirectChild( Matcher $elementMatcher = null ) {
17
+        return new static( $elementMatcher );
18
+    }
19
+
20
+    public function __construct( Matcher $matcher = null ) {
21
+        parent::__construct( \DOMNode::class );
22
+        $this->matcher = $matcher;
23
+    }
24
+
25
+    public function describeTo( Description $description ) {
26
+        $description->appendText( 'having direct child ' );
27
+        if ( $this->matcher ) {
28
+            $description->appendDescriptionOf( $this->matcher );
29
+        }
30
+    }
31
+
32
+    /**
33
+     * @param \DOMDocument|\DOMNode $item
34
+     * @param Description $mismatchDescription
35
+     *
36
+     * @return bool
37
+     */
38
+    protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
39
+        if ( $item instanceof \DOMDocument ) {
40
+            $item = $item->documentElement->childNodes->item( 0 );
41
+        }
42
+        $directChildren = $item->childNodes;
43
+
44
+        if ( $directChildren->length === 0 ) {
45
+            $mismatchDescription->appendText( 'with no direct children' );
46
+            return false;
47
+        }
48
+
49
+        $childWord = $directChildren->length === 1 ? 'child' : 'children';
50
+
51
+        $mismatchDescription->appendText( "with direct {$childWord} " );
52
+
53
+        if ( !$this->matcher ) {
54
+            return $directChildren->length !== 0;
55
+        }
56
+
57
+        foreach ( $directChildren as $child ) {
58
+            if ( $this->matcher->matches( $child ) ) {
59
+                return true;
60
+            }
61
+        }
62
+
63
+        $this->matcher->describeMismatch( $child, $mismatchDescription );
64
+
65
+        return false;
66
+    }
67 67
 
68 68
 }
Please login to merge, or discard this patch.
src/ChildElementMatcher.php 1 patch
Indentation   +44 added lines, -44 removed lines patch added patch discarded remove patch
@@ -8,57 +8,57 @@
 block discarded – undo
8 8
 
9 9
 class ChildElementMatcher extends TypeSafeDiagnosingMatcher {
10 10
 
11
-	/**
12
-	 * @var Matcher|null
13
-	 */
14
-	private $matcher;
11
+    /**
12
+     * @var Matcher|null
13
+     */
14
+    private $matcher;
15 15
 
16
-	public static function havingChild( Matcher $elementMatcher = null ) {
17
-		return new static( $elementMatcher );
18
-	}
16
+    public static function havingChild( Matcher $elementMatcher = null ) {
17
+        return new static( $elementMatcher );
18
+    }
19 19
 
20
-	public function __construct( Matcher $matcher = null ) {
21
-		parent::__construct( \DOMNode::class );
22
-		$this->matcher = $matcher;
23
-	}
20
+    public function __construct( Matcher $matcher = null ) {
21
+        parent::__construct( \DOMNode::class );
22
+        $this->matcher = $matcher;
23
+    }
24 24
 
25
-	public function describeTo( Description $description ) {
26
-		$description->appendText( 'having child ' );
27
-		if ( $this->matcher ) {
28
-			$description->appendDescriptionOf( $this->matcher );
29
-		}
30
-	}
25
+    public function describeTo( Description $description ) {
26
+        $description->appendText( 'having child ' );
27
+        if ( $this->matcher ) {
28
+            $description->appendDescriptionOf( $this->matcher );
29
+        }
30
+    }
31 31
 
32
-	/**
33
-	 * @param \DOMDocument|\DOMNode $item
34
-	 * @param Description $mismatchDescription
35
-	 *
36
-	 * @return bool
37
-	 */
38
-	protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
39
-		if ( $item instanceof \DOMDocument ) {
40
-			$directChildren = $item->documentElement->childNodes->item( 0 )->childNodes;
41
-		} else {
42
-			$directChildren = $item->childNodes;
43
-		}
32
+    /**
33
+     * @param \DOMDocument|\DOMNode $item
34
+     * @param Description $mismatchDescription
35
+     *
36
+     * @return bool
37
+     */
38
+    protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
39
+        if ( $item instanceof \DOMDocument ) {
40
+            $directChildren = $item->documentElement->childNodes->item( 0 )->childNodes;
41
+        } else {
42
+            $directChildren = $item->childNodes;
43
+        }
44 44
 
45
-		if ( $directChildren->length === 0 ) {
46
-			$mismatchDescription->appendText( 'having no children' );
47
-			return false;
48
-		}
45
+        if ( $directChildren->length === 0 ) {
46
+            $mismatchDescription->appendText( 'having no children' );
47
+            return false;
48
+        }
49 49
 
50
-		if ( !$this->matcher ) {
51
-			return $directChildren->length > 0;
52
-		}
50
+        if ( !$this->matcher ) {
51
+            return $directChildren->length > 0;
52
+        }
53 53
 
54
-		foreach ( new XmlNodeRecursiveIterator( $directChildren ) as $child ) {
55
-			if ( $this->matcher->matches( $child ) ) {
56
-				return true;
57
-			}
58
-		}
54
+        foreach ( new XmlNodeRecursiveIterator( $directChildren ) as $child ) {
55
+            if ( $this->matcher->matches( $child ) ) {
56
+                return true;
57
+            }
58
+        }
59 59
 
60
-		$mismatchDescription->appendText( 'having no children ' )->appendDescriptionOf( $this->matcher );
61
-		return false;
62
-	}
60
+        $mismatchDescription->appendText( 'having no children ' )->appendDescriptionOf( $this->matcher );
61
+        return false;
62
+    }
63 63
 
64 64
 }
Please login to merge, or discard this patch.
src/ComplexTagMatcher.php 1 patch
Indentation   +182 added lines, -182 removed lines patch added patch discarded remove patch
@@ -10,187 +10,187 @@
 block discarded – undo
10 10
 
11 11
 class ComplexTagMatcher extends TagMatcher {
12 12
 
13
-	/**
14
-	 * @link http://www.xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
15
-	 * @link https://github.com/Chronic-Dev/libxml2/blob/683f296a905710ff285c28b8644ef3a3d8be9486/include/libxml/xmlerror.h#L257
16
-	 */
17
-	const XML_UNKNOWN_TAG_ERROR_CODE = 801;
18
-
19
-	/**
20
-	 * @var string
21
-	 */
22
-	private $tagHtmlOutline;
23
-
24
-	/**
25
-	 * @var Matcher
26
-	 */
27
-	private $matcher;
28
-
29
-	/**
30
-	 * @param string $htmlOutline
31
-	 * @return self
32
-	 */
33
-	public static function tagMatchingOutline( $htmlOutline ) {
34
-		return new self( $htmlOutline );
35
-	}
36
-
37
-	public function __construct( $tagHtmlRepresentation ) {
38
-		parent::__construct();
39
-
40
-		$this->tagHtmlOutline = $tagHtmlRepresentation;
41
-		$this->matcher = $this->createMatcherFromHtml( $tagHtmlRepresentation );
42
-	}
43
-
44
-	public function describeTo( Description $description ) {
45
-		$description->appendText( 'tag matching outline `' )
46
-			->appendText( $this->tagHtmlOutline )
47
-			->appendText( '` ' );
48
-	}
49
-
50
-	/**
51
-	 * @param \DOMElement $item
52
-	 * @param Description $mismatchDescription
53
-	 *
54
-	 * @return bool
55
-	 */
56
-	protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
57
-		if ( $this->matcher->matches( $item ) ) {
58
-			return true;
59
-		}
60
-
61
-		$mismatchDescription->appendText( 'was `' )
62
-			->appendText( $this->elementToString( $item ) )
63
-			->appendText( '`' );
64
-		return false;
65
-	}
66
-
67
-	private function createMatcherFromHtml( $htmlOutline ) {
68
-		$document = $this->parseHtml( $htmlOutline );
69
-		$targetTag = $this->getSingleTagFromThe( $document );
70
-
71
-		$this->assertTagDoesNotContainChildren( $targetTag );
72
-
73
-		$attributeMatchers = $this->createAttributeMatchers( $htmlOutline, $targetTag );
74
-		$classMatchers = $this->createClassMatchers( $targetTag );
75
-
76
-		return AllOf::allOf(
77
-			new TagNameMatcher( IsEqual::equalTo( $targetTag->tagName ) ),
78
-			call_user_func_array( [ AllOf::class, 'allOf' ], $attributeMatchers ),
79
-			call_user_func_array( [ AllOf::class, 'allOf' ], $classMatchers )
80
-		);
81
-	}
82
-
83
-	private function isUnknownTagError( \LibXMLError $error ) {
84
-		return $error->code === self::XML_UNKNOWN_TAG_ERROR_CODE;
85
-	}
86
-
87
-	private function isBooleanAttribute( $inputHtml, $attributeName ) {
88
-		$quotedName = preg_quote( $attributeName, '/' );
89
-
90
-		$attributeHasValueAssigned = preg_match( "/\b{$quotedName}\s*=/ui", $inputHtml );
91
-		return !$attributeHasValueAssigned;
92
-	}
93
-
94
-	/**
95
-	 * @param $html
96
-	 *
97
-	 * @return \DOMDocument
98
-	 * @throws \InvalidArgumentException
99
-	 */
100
-	private function parseHtml( $html ) {
101
-		$internalErrors = libxml_use_internal_errors( true );
102
-		$document = new \DOMDocument();
103
-
104
-		if ( !@$document->loadHTML( $html ) ) {
105
-			throw new \InvalidArgumentException( "There was some parsing error of `$html`" );
106
-		}
107
-
108
-		$errors = libxml_get_errors();
109
-		libxml_clear_errors();
110
-		libxml_use_internal_errors( $internalErrors );
111
-
112
-		/** @var \LibXMLError $error */
113
-		foreach ( $errors as $error ) {
114
-			if ( $this->isUnknownTagError( $error ) ) {
115
-				continue;
116
-			}
117
-
118
-			throw new \InvalidArgumentException(
119
-				'There was parsing error: ' . trim( $error->message ) . ' on line ' . $error->line
120
-			);
121
-		}
122
-
123
-		return $document;
124
-	}
125
-
126
-	/**
127
-	 * @param \DOMDocument $document
128
-	 *
129
-	 * @return \DOMElement
130
-	 * @throws \InvalidArgumentException
131
-	 */
132
-	private function getSingleTagFromThe( \DOMDocument $document ) {
133
-		$directChildren = $document->documentElement->childNodes->item( 0 )->childNodes;
134
-
135
-		if ( $directChildren->length !== 1 ) {
136
-			throw new InvalidArgumentException(
137
-				'Expected exactly 1 tag description, got ' . $directChildren->length
138
-			);
139
-		}
140
-
141
-		return $directChildren[0];
142
-	}
143
-
144
-	private function assertTagDoesNotContainChildren( \DOMElement $targetTag ) {
145
-		if ( $targetTag->childNodes->length > 0 ) {
146
-			throw new InvalidArgumentException( 'Nested elements are not allowed' );
147
-		}
148
-	}
149
-
150
-	/**
151
-	 * @param string $inputHtml
152
-	 * @param $targetTag
153
-	 * @return AttributeMatcher[]
154
-	 */
155
-	private function createAttributeMatchers( $inputHtml, \DOMElement $targetTag ) {
156
-		$attributeMatchers = [];
157
-		/** @var \DOMAttr $attribute */
158
-		foreach ( $targetTag->attributes as $attribute ) {
159
-			if ( $attribute->name === 'class' ) {
160
-				continue;
161
-			}
162
-
163
-			$attributeMatcher = new AttributeMatcher( IsEqual::equalTo( $attribute->name ) );
164
-			if ( !$this->isBooleanAttribute( $inputHtml, $attribute->name ) ) {
165
-				$attributeMatcher = $attributeMatcher->havingValue( IsEqual::equalTo( $attribute->value ) );
166
-			}
167
-
168
-			$attributeMatchers[] = $attributeMatcher;
169
-		}
170
-		return $attributeMatchers;
171
-	}
172
-
173
-	/**
174
-	 * @param \DOMElement $targetTag
175
-	 * @return ClassMatcher[]
176
-	 */
177
-	private function createClassMatchers( $targetTag ) {
178
-		$classMatchers = [];
179
-		$classValue = $targetTag->getAttribute( 'class' );
180
-		foreach ( explode( ' ', $classValue ) as $expectedClass ) {
181
-			if ( $expectedClass === '' ) {
182
-				continue;
183
-			}
184
-			$classMatchers[] = new ClassMatcher( IsEqual::equalTo( $expectedClass ) );
185
-		}
186
-		return $classMatchers;
187
-	}
188
-
189
-	private function elementToString( \DOMElement $element ) {
190
-		$newDocument = new \DOMDocument();
191
-		$cloned = $element->cloneNode( true );
192
-		$newDocument->appendChild( $newDocument->importNode( $cloned, true ) );
193
-		return trim( $newDocument->saveHTML() );
194
-	}
13
+    /**
14
+     * @link http://www.xmlsoft.org/html/libxml-xmlerror.html#xmlParserErrors
15
+     * @link https://github.com/Chronic-Dev/libxml2/blob/683f296a905710ff285c28b8644ef3a3d8be9486/include/libxml/xmlerror.h#L257
16
+     */
17
+    const XML_UNKNOWN_TAG_ERROR_CODE = 801;
18
+
19
+    /**
20
+     * @var string
21
+     */
22
+    private $tagHtmlOutline;
23
+
24
+    /**
25
+     * @var Matcher
26
+     */
27
+    private $matcher;
28
+
29
+    /**
30
+     * @param string $htmlOutline
31
+     * @return self
32
+     */
33
+    public static function tagMatchingOutline( $htmlOutline ) {
34
+        return new self( $htmlOutline );
35
+    }
36
+
37
+    public function __construct( $tagHtmlRepresentation ) {
38
+        parent::__construct();
39
+
40
+        $this->tagHtmlOutline = $tagHtmlRepresentation;
41
+        $this->matcher = $this->createMatcherFromHtml( $tagHtmlRepresentation );
42
+    }
43
+
44
+    public function describeTo( Description $description ) {
45
+        $description->appendText( 'tag matching outline `' )
46
+            ->appendText( $this->tagHtmlOutline )
47
+            ->appendText( '` ' );
48
+    }
49
+
50
+    /**
51
+     * @param \DOMElement $item
52
+     * @param Description $mismatchDescription
53
+     *
54
+     * @return bool
55
+     */
56
+    protected function matchesSafelyWithDiagnosticDescription( $item, Description $mismatchDescription ) {
57
+        if ( $this->matcher->matches( $item ) ) {
58
+            return true;
59
+        }
60
+
61
+        $mismatchDescription->appendText( 'was `' )
62
+            ->appendText( $this->elementToString( $item ) )
63
+            ->appendText( '`' );
64
+        return false;
65
+    }
66
+
67
+    private function createMatcherFromHtml( $htmlOutline ) {
68
+        $document = $this->parseHtml( $htmlOutline );
69
+        $targetTag = $this->getSingleTagFromThe( $document );
70
+
71
+        $this->assertTagDoesNotContainChildren( $targetTag );
72
+
73
+        $attributeMatchers = $this->createAttributeMatchers( $htmlOutline, $targetTag );
74
+        $classMatchers = $this->createClassMatchers( $targetTag );
75
+
76
+        return AllOf::allOf(
77
+            new TagNameMatcher( IsEqual::equalTo( $targetTag->tagName ) ),
78
+            call_user_func_array( [ AllOf::class, 'allOf' ], $attributeMatchers ),
79
+            call_user_func_array( [ AllOf::class, 'allOf' ], $classMatchers )
80
+        );
81
+    }
82
+
83
+    private function isUnknownTagError( \LibXMLError $error ) {
84
+        return $error->code === self::XML_UNKNOWN_TAG_ERROR_CODE;
85
+    }
86
+
87
+    private function isBooleanAttribute( $inputHtml, $attributeName ) {
88
+        $quotedName = preg_quote( $attributeName, '/' );
89
+
90
+        $attributeHasValueAssigned = preg_match( "/\b{$quotedName}\s*=/ui", $inputHtml );
91
+        return !$attributeHasValueAssigned;
92
+    }
93
+
94
+    /**
95
+     * @param $html
96
+     *
97
+     * @return \DOMDocument
98
+     * @throws \InvalidArgumentException
99
+     */
100
+    private function parseHtml( $html ) {
101
+        $internalErrors = libxml_use_internal_errors( true );
102
+        $document = new \DOMDocument();
103
+
104
+        if ( !@$document->loadHTML( $html ) ) {
105
+            throw new \InvalidArgumentException( "There was some parsing error of `$html`" );
106
+        }
107
+
108
+        $errors = libxml_get_errors();
109
+        libxml_clear_errors();
110
+        libxml_use_internal_errors( $internalErrors );
111
+
112
+        /** @var \LibXMLError $error */
113
+        foreach ( $errors as $error ) {
114
+            if ( $this->isUnknownTagError( $error ) ) {
115
+                continue;
116
+            }
117
+
118
+            throw new \InvalidArgumentException(
119
+                'There was parsing error: ' . trim( $error->message ) . ' on line ' . $error->line
120
+            );
121
+        }
122
+
123
+        return $document;
124
+    }
125
+
126
+    /**
127
+     * @param \DOMDocument $document
128
+     *
129
+     * @return \DOMElement
130
+     * @throws \InvalidArgumentException
131
+     */
132
+    private function getSingleTagFromThe( \DOMDocument $document ) {
133
+        $directChildren = $document->documentElement->childNodes->item( 0 )->childNodes;
134
+
135
+        if ( $directChildren->length !== 1 ) {
136
+            throw new InvalidArgumentException(
137
+                'Expected exactly 1 tag description, got ' . $directChildren->length
138
+            );
139
+        }
140
+
141
+        return $directChildren[0];
142
+    }
143
+
144
+    private function assertTagDoesNotContainChildren( \DOMElement $targetTag ) {
145
+        if ( $targetTag->childNodes->length > 0 ) {
146
+            throw new InvalidArgumentException( 'Nested elements are not allowed' );
147
+        }
148
+    }
149
+
150
+    /**
151
+     * @param string $inputHtml
152
+     * @param $targetTag
153
+     * @return AttributeMatcher[]
154
+     */
155
+    private function createAttributeMatchers( $inputHtml, \DOMElement $targetTag ) {
156
+        $attributeMatchers = [];
157
+        /** @var \DOMAttr $attribute */
158
+        foreach ( $targetTag->attributes as $attribute ) {
159
+            if ( $attribute->name === 'class' ) {
160
+                continue;
161
+            }
162
+
163
+            $attributeMatcher = new AttributeMatcher( IsEqual::equalTo( $attribute->name ) );
164
+            if ( !$this->isBooleanAttribute( $inputHtml, $attribute->name ) ) {
165
+                $attributeMatcher = $attributeMatcher->havingValue( IsEqual::equalTo( $attribute->value ) );
166
+            }
167
+
168
+            $attributeMatchers[] = $attributeMatcher;
169
+        }
170
+        return $attributeMatchers;
171
+    }
172
+
173
+    /**
174
+     * @param \DOMElement $targetTag
175
+     * @return ClassMatcher[]
176
+     */
177
+    private function createClassMatchers( $targetTag ) {
178
+        $classMatchers = [];
179
+        $classValue = $targetTag->getAttribute( 'class' );
180
+        foreach ( explode( ' ', $classValue ) as $expectedClass ) {
181
+            if ( $expectedClass === '' ) {
182
+                continue;
183
+            }
184
+            $classMatchers[] = new ClassMatcher( IsEqual::equalTo( $expectedClass ) );
185
+        }
186
+        return $classMatchers;
187
+    }
188
+
189
+    private function elementToString( \DOMElement $element ) {
190
+        $newDocument = new \DOMDocument();
191
+        $cloned = $element->cloneNode( true );
192
+        $newDocument->appendChild( $newDocument->importNode( $cloned, true ) );
193
+        return trim( $newDocument->saveHTML() );
194
+    }
195 195
 
196 196
 }
Please login to merge, or discard this patch.