Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
TokenHandler
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 10
600
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 setPipelineId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 resetState
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isDisabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onEnd
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onNewline
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onTag
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onAny
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isModified
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 process
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
210
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Wt2Html\TT;
5
6use Wikimedia\Parsoid\Config\Env;
7use Wikimedia\Parsoid\Tokens\EOFTk;
8use Wikimedia\Parsoid\Tokens\NlTk;
9use Wikimedia\Parsoid\Tokens\Token;
10use Wikimedia\Parsoid\Utils\PHPUtils;
11use Wikimedia\Parsoid\Wt2Html\TokenTransformManager;
12
13abstract class TokenHandler {
14    /** @var Env */
15    protected $env;
16    /** @var TokenTransformManager */
17    protected $manager;
18    /** @var int|null */
19    protected $pipelineId;
20    /** @var array */
21    protected $options;
22    /** This is set if the token handler is disabled for the entire pipeline. */
23    protected bool $disabled = false;
24    /**
25     * This is set/reset by the token handlers at various points in the token stream based on what
26     * is encountered. This only enables/disables the onAny handler.
27     */
28    protected bool $onAnyEnabled = true;
29    /** @var bool */
30    protected $atTopLevel = false;
31
32    /**
33     * @param TokenTransformManager $manager The manager for this stage of the parse.
34     * @param array $options Any options for the expander.
35     */
36    public function __construct( TokenTransformManager $manager, array $options ) {
37        $this->manager = $manager;
38        $this->env = $manager->getEnv();
39        $this->options = $options;
40    }
41
42    public function setPipelineId( int $id ): void {
43        $this->pipelineId = $id;
44    }
45
46    /**
47     * Resets any internal state for this token handler.
48     *
49     * @param array $options
50     */
51    public function resetState( array $options ): void {
52        $this->atTopLevel = $options['toplevel'] ?? false;
53    }
54
55    /**
56     * Is this transformer disabled?
57     * @return bool
58     */
59    public function isDisabled(): bool {
60        return $this->disabled;
61    }
62
63    /**
64     * This handler is called for EOF tokens only
65     * @param EOFTk $token EOF token to be processed
66     * @return TokenHandlerResult|null A TokenHandlerResult, or null to efficiently
67     *   indicate that the input token is unchanged.
68     */
69    public function onEnd( EOFTk $token ): ?TokenHandlerResult {
70        return null;
71    }
72
73    /**
74     * This handler is called for newline tokens only
75     * @param NlTk $token Newline token to be processed
76     * @return TokenHandlerResult|null A TokenHandlerResult, or null to efficiently
77     *   indicate that the input token is unchanged.
78     */
79    public function onNewline( NlTk $token ): ?TokenHandlerResult {
80        return null;
81    }
82
83    /**
84     * This handler is called for tokens that are not EOFTk or NLTk tokens.
85     * The handler may choose to process only specific kinds of tokens.
86     * For example, a list handler may only process 'listitem' TagTk tokens.
87     *
88     * @param Token $token Token to be processed
89     * @return TokenHandlerResult|null A TokenHandlerResult, or null to efficiently
90     *   indicate that the input token is unchanged.
91     */
92    public function onTag( Token $token ): ?TokenHandlerResult {
93        return null;
94    }
95
96    /**
97     * This handler is called for *all* tokens in the token stream except if
98     * (a) The more specific handlers above modified the token
99     * (b) the more specific handlers (onTag, onEnd, onNewline) have set
100     *     the skip flag in their return values.
101     * (c) this handlers 'active' flag is set to false (can be set by any
102     *     of the handlers).
103     *
104     * @param Token|string $token Token to be processed
105     * @return TokenHandlerResult|null A TokenHandlerResult, or null to efficiently
106     *   indicate that the input token is unchanged.
107     */
108    public function onAny( $token ): ?TokenHandlerResult {
109        return null;
110    }
111
112    /**
113     * @param mixed $token
114     * @param TokenHandlerResult $res
115     * @return bool
116     */
117    private function isModified( $token, $res ): bool {
118        return $res->tokens !== null
119            && $res->tokens !== [ $token ];
120    }
121
122    /**
123     * Push an input array of tokens through the transformer
124     * and return the transformed tokens
125     * @param array $tokens
126     * @return array
127     */
128    public function process( $tokens ): array {
129        $accum = [];
130        foreach ( $tokens as $token ) {
131            $res = null;
132            $resTokens = null; // Not needed but helpful for code comprehension
133            if ( $token instanceof NlTk ) {
134                $res = $this->onNewline( $token );
135            } elseif ( $token instanceof EOFTk ) {
136                $res = $this->onEnd( $token );
137            } elseif ( !is_string( $token ) ) {
138                $res = $this->onTag( $token );
139            } else {
140                $res = null;
141            }
142
143            $modified = $res && $this->isModified( $token, $res );
144            if ( $modified ) {
145                $resTokens = $res->tokens;
146            } elseif ( $this->onAnyEnabled && ( !$res || !$res->skipOnAny ) ) {
147                $res = $this->onAny( $token );
148                $modified = $res && $this->isModified( $token, $res );
149                if ( $modified ) {
150                    $resTokens = $res->tokens;
151                }
152            }
153
154            if ( !$modified ) {
155                $accum[] = $token;
156            } elseif ( $resTokens ) {
157                // Avoid array_merge() -- see https://w.wiki/3zvE
158                PHPUtils::pushArray( $accum, $resTokens );
159            }
160        }
161
162        return $accum;
163    }
164}