Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ParserHook
0.00% covered (danger)
0.00%
0 / 101
0.00% covered (danger)
0.00%
0 / 4
380
0.00% covered (danger)
0.00%
0 / 1
 sourceToDom
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
132
 processAttributeEmbeddedHTML
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 domToWikitext
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 getConfig
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\ParserTests;
5
6use Closure;
7use Error;
8use Wikimedia\Parsoid\DOM\DocumentFragment;
9use Wikimedia\Parsoid\DOM\Element;
10use Wikimedia\Parsoid\Ext\ExtensionModule;
11use Wikimedia\Parsoid\Ext\ExtensionTagHandler;
12use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
13use Wikimedia\Parsoid\Utils\DOMCompat;
14use Wikimedia\Parsoid\Utils\DOMDataUtils;
15use Wikimedia\Parsoid\Utils\WTUtils;
16
17/**
18 * See tests/parser/ParserTestParserHook.php in core.
19 */
20class ParserHook extends ExtensionTagHandler implements ExtensionModule {
21
22    /** @inheritDoc */
23    public function sourceToDom(
24        ParsoidExtensionAPI $extApi, string $content, array $args
25    ): DocumentFragment {
26        $extName = $extApi->extTag->getName();
27        if ( $extApi->extTag->isSelfClosed() ) {
28            $content = null;
29        }
30        switch ( $extName ) {
31            case 'tag':
32            case 'tåg':
33                return $extApi->htmlToDom(
34                    "<pre>\n" .
35                        var_export( $content, true ) . "\n" .
36                        var_export( $extApi->extArgsToArray( $args ), true ) . "\n" .
37                    "</pre>"
38                );
39
40            case 'statictag':
41                // FIXME: Choose a better DOM representation that doesn't mess with
42                // newline constraints.
43                return $extApi->htmlToDom( '<span />' );
44
45            case 'asidetag':
46                // T278565
47                return $extApi->htmlToDom( '<aside>Some aside content</aside>' );
48
49            case 'pwraptest':
50                return $extApi->htmlToDom( '<!--CMT--><style>p{}</style>' );
51
52            case 'spantag':
53                // "Transparent" tag which wraps wikitext in a <span>;
54                // useful in testing various parsoid wrapping scenarios
55                // (we used to use <ref> for this)
56                // NOTE: This tag disables p-wrapping and indent-pre transforms.
57                return $extApi->extTagToDOM( $args, $content, [
58                    'wrapperTag' => 'span',
59                    'parseOpts' => [
60                        'extTag' => $extName,
61                        'context' => 'inline',
62                    ],
63                ] );
64
65            case 'embedtag':
66                $dataMw = $extApi->extTag->getDefaultDataMw();
67                $domFragment = $extApi->extTagToDOM( $args, $content, [
68                    'parseOpts' => [
69                        'extTag' => $extName,
70                        'context' => 'inline',
71                    ],
72                ] );
73                $dataMw->body = (object)[
74                    'html' => $extApi->domToHtml( $domFragment, true )
75                ];
76                $span = $domFragment->ownerDocument->createElement( 'span' );
77                DOMDataUtils::setDataMw( $span, $dataMw );
78                DOMCompat::replaceChildren( $domFragment, $span );
79                return $domFragment;
80
81            case 'sealtag':
82                return $extApi->htmlToDom( '<span />' );
83
84            default:
85                throw new Error( "Unexpected tag name: $extName in ParserHook" );
86        }
87    }
88
89    /** @inheritDoc */
90    public function processAttributeEmbeddedHTML(
91        ParsoidExtensionAPI $extApi, Element $elt, Closure $proc
92    ): void {
93        $dataMw = DOMDataUtils::getDataMw( $elt );
94        if ( isset( $dataMw->body->html ) ) {
95            $dataMw->body->html = $proc( $dataMw->body->html );
96        }
97    }
98
99    /** @inheritDoc */
100    public function domToWikitext(
101        ParsoidExtensionAPI $extApi, Element $node, bool $wrapperUnmodified
102    ) {
103        $dataMw = DOMDataUtils::getDataMw( $node );
104        $extName = WTUtils::getExtTagName( $node ) ?? $dataMw->name;
105        if ( !in_array( $extName, [ 'spantag', 'embedtag' ], true ) ) {
106            return false; // use default serialization
107        }
108        $html2wtOpts = [
109            'extName' => $extName,
110            // FIXME: One-off PHP parser state leak. This needs a better solution.
111            'inPHPBlock' => true
112        ];
113        $src = '';
114        if ( $wrapperUnmodified && isset( $dataMw->body->extsrc ) ) {
115            $src = $dataMw->body->extsrc;
116        } elseif ( $extName === 'embedtag' ) {
117            // First look for the extension's content in data-mw.body.html
118            $src = $extApi->htmlToWikitext( $html2wtOpts, $dataMw->body->html );
119        } else {
120            $src = $extApi->htmlToWikitext( $html2wtOpts, DOMCompat::getInnerHTML( $node ) );
121        }
122        return "<$extName>" . $src . "</$extName>";
123    }
124
125    /** @inheritDoc */
126    public function getConfig(): array {
127        return [
128            'name' => 'ParserHook',
129            'tags' => [
130                [ 'name' => 'tag', 'handler' => self::class ],
131                [ 'name' => 'tåg', 'handler' => self::class ],
132                [ 'name' => 'statictag', 'handler' => self::class ],
133                [ 'name' => 'asidetag', 'handler' => self::class ],
134                [ 'name' => 'pwraptest', 'handler' => self::class ],
135                [
136                    'name' => 'spantag',
137                    'handler' => self::class,
138                    'options' => [
139                        'outputHasCoreMwDomSpecMarkup' => true,
140                    ],
141                ],
142                [
143                    'name' => 'embedtag',
144                    'handler' => self::class,
145                    'options' => [
146                        'wt2html' => [
147                            'embedsHTMLInAttributes' => true,
148                            'customizesDataMw' => true,
149                        ],
150                        'outputHasCoreMwDomSpecMarkup' => true,
151                    ],
152                ],
153                [
154                    'name' => 'sealtag',
155                    'handler' => self::class,
156                    'options' => [
157                        'wt2html' => [
158                            'unpackOutput' => false,
159                        ],
160                    ],
161                ],
162            ],
163            'domProcessors' => [
164                ParserHookProcessor::class
165            ]
166        ];
167    }
168}