Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.37% covered (success)
97.37%
37 / 38
92.31% covered (success)
92.31%
12 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
DispatchTracer
97.37% covered (success)
97.37%
37 / 38
92.31% covered (success)
92.31%
12 / 13
20
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 trace
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 excerpt
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 wrap
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 getHandlerName
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 startDocument
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 endDocument
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 error
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 characters
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 startTag
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 endTag
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 doctype
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 comment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Wikimedia\RemexHtml\TreeBuilder;
4
5use Wikimedia\RemexHtml\Tokenizer\Attributes;
6use Wikimedia\RemexHtml\Tokenizer\TokenHandler;
7use Wikimedia\RemexHtml\Tokenizer\Tokenizer;
8
9/**
10 * This is a debugging helper class which calls a callback function with a
11 * descriptive message each time a token event comes from the Tokenizer. The
12 * messages include information about the current state and transitions of the
13 * Dispatcher which is the next stage in the pipeline.
14 */
15class DispatchTracer implements TokenHandler {
16    private $input;
17    private $dispatcher;
18    private $callback;
19
20    public function __construct( $input, Dispatcher $dispatcher, callable $callback ) {
21        $this->input = $input;
22        $this->dispatcher = $dispatcher;
23        $this->callback = $callback;
24    }
25
26    private function trace( $msg ) {
27        call_user_func( $this->callback, "[Dispatch] $msg" );
28    }
29
30    private function excerpt( $text ) {
31        if ( strlen( $text ) > 20 ) {
32            $text = substr( $text, 0, 20 ) . '...';
33        }
34        return str_replace( "\n", "\\n", $text );
35    }
36
37    private function wrap( $funcName, $sourceStart, $sourceLength, $args ) {
38        $prevHandler = $this->getHandlerName();
39        $excerpt = $this->excerpt( substr( $this->input, $sourceStart, $sourceLength ) );
40        $msg = "$funcName $prevHandler \"$excerpt\"";
41        $this->trace( $msg );
42        call_user_func_array( [ $this->dispatcher, $funcName ], $args );
43        $handler = $this->getHandlerName();
44        if ( $prevHandler !== $handler ) {
45            $this->trace( "$prevHandler -> $handler" );
46        }
47    }
48
49    private function getHandlerName() {
50        $handler = $this->dispatcher->getHandler();
51        $name = $handler ? get_class( $handler ) : 'NULL';
52        $slashPos = strrpos( $name, '\\' );
53        if ( $slashPos === false ) {
54            return $name;
55        } else {
56            return substr( $name, $slashPos + 1 );
57        }
58    }
59
60    public function startDocument( Tokenizer $tokenizer, $ns, $name ) {
61        $prevHandler = $this->getHandlerName();
62        $nsMsg = $ns === null ? 'NULL' : $ns;
63        $nameMsg = $name === null ? 'NULL' : $name;
64        $this->trace( "startDocument $prevHandler $nsMsg $nameMsg" );
65        $this->dispatcher->startDocument( $tokenizer, $ns, $name );
66        $handler = $this->getHandlerName();
67        if ( $prevHandler !== $handler ) {
68            $this->trace( "$prevHandler -> $handler" );
69        }
70    }
71
72    public function endDocument( $pos ) {
73        $this->wrap( __FUNCTION__, $pos, 0, func_get_args() );
74    }
75
76    public function error( $text, $pos ) {
77        $handler = $this->getHandlerName();
78        $this->trace( "error $handler \"$text\"" );
79        $this->dispatcher->error( $text, $pos );
80    }
81
82    public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
83        $this->wrap( __FUNCTION__, $sourceStart, $sourceLength, func_get_args() );
84    }
85
86    public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
87        $this->wrap( __FUNCTION__, $sourceStart, $sourceLength, func_get_args() );
88    }
89
90    public function endTag( $name, $sourceStart, $sourceLength ) {
91        $this->wrap( __FUNCTION__, $sourceStart, $sourceLength, func_get_args() );
92    }
93
94    public function doctype( $name, $public, $system, $quirks, $sourceStart, $sourceLength ) {
95        $this->wrap( __FUNCTION__, $sourceStart, $sourceLength, func_get_args() );
96    }
97
98    public function comment( $text, $sourceStart, $sourceLength ) {
99        $this->wrap( __FUNCTION__, $sourceStart, $sourceLength, func_get_args() );
100    }
101}