Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 61
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
OnlyInclude
0.00% covered (danger)
0.00%
0 / 61
0.00% covered (danger)
0.00%
0 / 5
600
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 onAny
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 onTag
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
12
 onOnlyInclude
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 onAnyInclude
0.00% covered (danger)
0.00%
0 / 40
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\NodeData\DataParsoid;
7use Wikimedia\Parsoid\Tokens\EndTagTk;
8use Wikimedia\Parsoid\Tokens\KV;
9use Wikimedia\Parsoid\Tokens\SelfclosingTagTk;
10use Wikimedia\Parsoid\Tokens\Token;
11use Wikimedia\Parsoid\Utils\TokenUtils;
12use Wikimedia\Parsoid\Wt2Html\TokenTransformManager;
13
14/**
15 * OnlyInclude sadly forces synchronous template processing, as it needs to
16 * hold onto all tokens in case an onlyinclude block is encountered later.
17 * This can fortunately be worked around by caching the tokens after
18 * onlyinclude processing (which is a good idea anyway).
19 */
20class OnlyInclude extends TokenHandler {
21    /** @var array */
22    private $accum = [];
23
24    /** @var bool */
25    private $inOnlyInclude = false;
26
27    /** @var bool */
28    private $foundOnlyInclude = false;
29
30    /**
31     * @param TokenTransformManager $manager manager environment
32     * @param array $options options
33     */
34    public function __construct( TokenTransformManager $manager, array $options ) {
35        parent::__construct( $manager, $options );
36        if ( empty( $this->options['isInclude'] ) ) {
37            $this->accum = [];
38            $this->inOnlyInclude = false;
39            $this->foundOnlyInclude = false;
40        }
41    }
42
43    /**
44     * @inheritDoc
45     */
46    public function onAny( $token ): ?TokenHandlerResult {
47        return !empty( $this->options['isInclude'] ) ? $this->onAnyInclude( $token ) : null;
48    }
49
50    /**
51     * @inheritDoc
52     */
53    public function onTag( Token $token ): ?TokenHandlerResult {
54        return empty( $this->options['isInclude'] ) && $token->getName() === 'onlyinclude' ?
55            $this->onOnlyInclude( $token ) : null;
56    }
57
58    private function onOnlyInclude( Token $token ): TokenHandlerResult {
59        $tsr = $token->dataParsoid->tsr;
60        $src = !$this->options['inTemplate']
61            ? $token->getWTSource( $this->manager->getFrame() )
62            : null;
63        $attribs = [
64            new KV( 'typeof', 'mw:Includes/OnlyInclude' .
65                ( ( $token instanceof EndTagTk ) ? '/End' : '' ) )
66        ];
67        $dp = new DataParsoid;
68        $dp->tsr = $tsr;
69        $dp->src = $src;
70        $meta = new SelfclosingTagTk( 'meta', $attribs, $dp );
71        return new TokenHandlerResult( [ $meta ] );
72    }
73
74    /**
75     * @param Token|array $token
76     * @return TokenHandlerResult|null
77     */
78    private function onAnyInclude( $token ): ?TokenHandlerResult {
79        $tagName = null;
80        $isTag = null;
81        $meta = null;
82
83        $tc = TokenUtils::getTokenType( $token );
84        if ( $tc === 'EOFTk' ) {
85            $this->inOnlyInclude = false;
86            if ( count( $this->accum ) && !$this->foundOnlyInclude ) {
87                $res = $this->accum;
88                $res[] = $token;
89                $this->accum = [];
90                return new TokenHandlerResult( $res );
91            } else {
92                $this->foundOnlyInclude = false;
93                $this->accum = [];
94                return null;
95            }
96        }
97
98        $isTag = $tc === 'TagTk' || $tc === 'EndTagTk' || $tc === 'SelfclosingTagTk';
99        if ( $isTag ) {
100            switch ( $token->getName() ) {
101                case 'onlyinclude':
102                    $tagName = 'mw:Includes/OnlyInclude';
103                    break;
104                case 'includeonly':
105                    $tagName = 'mw:Includes/IncludeOnly';
106                    break;
107                case 'noinclude':
108                    $tagName = 'mw:Includes/NoInclude';
109                    break;
110            }
111        }
112
113        if ( $isTag && $token->getName() === 'onlyinclude' ) {
114            if ( !$this->inOnlyInclude ) {
115                $this->foundOnlyInclude = true;
116                $this->inOnlyInclude = true;
117                // wrap collected tokens into meta tag for round-tripping
118                $meta = TokenCollector::buildMetaToken( $this->manager, $tagName,
119                    $tc === 'EndTagTk', $token->dataParsoid->tsr ?? null, '' );
120            } else {
121                $this->inOnlyInclude = false;
122                $meta = TokenCollector::buildMetaToken( $this->manager, $tagName,
123                    $tc === 'EndTagTk', $token->dataParsoid->tsr ?? null, '' );
124            }
125            return new TokenHandlerResult( [ $meta ] );
126        } else {
127            if ( $this->inOnlyInclude ) {
128                return null;
129            } else {
130                $this->accum[] = $token;
131                return new TokenHandlerResult( [] );
132            }
133        }
134    }
135}