Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.31% covered (success)
92.31%
24 / 26
88.89% covered (warning)
88.89%
16 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
TreeMutationTracer
92.31% covered (success)
92.31%
24 / 26
88.89% covered (warning)
88.89%
16 / 18
20.18
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
 traceEvent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 handleMutation
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 handleSimple
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 before
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 after
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 startDocument
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 endDocument
100.00% covered (success)
100.00%
1 / 1
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
 insertElement
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
 error
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 mergeAttributes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 removeNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 reparentChildren
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;
6
7/**
8 * This is a debugging helper class which calls the supplied callback function
9 * each time there is a TreeHandler event, giving a descriptive message. It
10 * then forwards the event through to the supplied handler.
11 */
12class TreeMutationTracer implements TreeHandler {
13    /** @var TreeHandler */
14    private $handler;
15
16    /** @var callable */
17    private $callback;
18
19    /** @var int */
20    private $verbosity;
21
22    /**
23     * Constructor.
24     *
25     * @param TreeHandler $handler The next pipeline stage
26     * @param callable $callback The message output function
27     * @param int $verbosity Set to non-zero to call dump() on the handler
28     *   before and after each event.
29     */
30    public function __construct( TreeHandler $handler, callable $callback, $verbosity = 0 ) {
31        $this->handler = $handler;
32        $this->callback = $callback;
33        $this->verbosity = $verbosity;
34    }
35
36    /**
37     * Send a message
38     *
39     * @param string $msg
40     */
41    private function trace( $msg ) {
42        call_user_func( $this->callback, "[Tree] $msg" );
43    }
44
45    /**
46     * Send a message for an event
47     *
48     * @param string $funcName
49     * @param array $args
50     */
51    private function traceEvent( $funcName, $args ) {
52        $this->trace( call_user_func_array( [ TraceFormatter::class, $funcName ], $args ) );
53    }
54
55    private function handleMutation( $funcName, $args ) {
56        $this->traceEvent( $funcName, $args );
57        $this->before();
58        call_user_func_array( [ $this->handler, $funcName ], $args );
59        $this->after();
60    }
61
62    private function handleSimple( $funcName, $args ) {
63        $this->traceEvent( $funcName, $args );
64        call_user_func_array( [ $this->handler, $funcName ], $args );
65    }
66
67    /**
68     * A helper called before the underlying handler is called.
69     */
70    private function before() {
71        if ( $this->verbosity > 0 ) {
72            // @phan-suppress-next-line PhanUndeclaredMethod
73            $this->trace( "Before: " . $this->handler->dump() . "\n" );
74        }
75    }
76
77    /**
78     * A helper called after the underlying handler is called.
79     */
80    private function after() {
81        if ( $this->verbosity > 0 ) {
82            // @phan-suppress-next-line PhanUndeclaredMethod
83            $this->trace( "After:  " . $this->handler->dump() . "\n" );
84        }
85    }
86
87    /**
88     * @inheritDoc
89     */
90    public function startDocument( $fns, $fn ) {
91        $this->handleSimple( __FUNCTION__, func_get_args() );
92    }
93
94    /**
95     * @inheritDoc
96     */
97    public function endDocument( $pos ) {
98        $this->handleSimple( __FUNCTION__, func_get_args() );
99    }
100
101    /**
102     * @inheritDoc
103     */
104    public function characters( $preposition, $refNode, $text, $start, $length,
105        $sourceStart, $sourceLength
106    ) {
107        $this->handleMutation( __FUNCTION__, func_get_args() );
108    }
109
110    /**
111     * @inheritDoc
112     */
113    public function insertElement( $preposition, $refNode, Element $element, $void,
114        $sourceStart, $sourceLength
115    ) {
116        $this->handleMutation( __FUNCTION__, func_get_args() );
117    }
118
119    /**
120     * @inheritDoc
121     */
122    public function endTag( Element $element, $sourceStart, $sourceLength ) {
123        $this->handleMutation( __FUNCTION__, func_get_args() );
124    }
125
126    /**
127     * @inheritDoc
128     */
129    public function doctype( $name, $public, $system, $quirks, $sourceStart, $sourceLength ) {
130        $this->handleMutation( __FUNCTION__, func_get_args() );
131    }
132
133    /**
134     * @inheritDoc
135     */
136    public function comment( $preposition, $refNode, $text, $sourceStart, $sourceLength ) {
137        $this->handleMutation( __FUNCTION__, func_get_args() );
138    }
139
140    /**
141     * @inheritDoc
142     */
143    public function error( $text, $pos ) {
144        $this->handleSimple( __FUNCTION__, func_get_args() );
145    }
146
147    /**
148     * @inheritDoc
149     */
150    public function mergeAttributes( Element $element, Attributes $attrs, $sourceStart ) {
151        $this->handleMutation( __FUNCTION__, func_get_args() );
152    }
153
154    /**
155     * @inheritDoc
156     */
157    public function removeNode( Element $element, $sourceStart ) {
158        $this->handleMutation( __FUNCTION__, func_get_args() );
159    }
160
161    /**
162     * @inheritDoc
163     */
164    public function reparentChildren( Element $element, Element $newParent, $sourceStart ) {
165        $this->handleMutation( __FUNCTION__, func_get_args() );
166    }
167}