Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateTemplateOutput
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
72
0.00% covered (danger)
0.00%
0 / 1
 run
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Wt2Html\DOM\Processors;
5
6use Wikimedia\Parsoid\Config\Env;
7use Wikimedia\Parsoid\DOM\DocumentFragment;
8use Wikimedia\Parsoid\DOM\Element;
9use Wikimedia\Parsoid\DOM\Node;
10use Wikimedia\Parsoid\Utils\DOMCompat;
11use Wikimedia\Parsoid\Utils\DOMDataUtils;
12use Wikimedia\Parsoid\Utils\DOMUtils;
13use Wikimedia\Parsoid\Utils\PipelineUtils;
14use Wikimedia\Parsoid\Wt2Html\Wt2HtmlDOMProcessor;
15
16class UpdateTemplateOutput implements Wt2HtmlDOMProcessor {
17    /**
18     * FIXME:
19     * -- mwt-id counter may need to be reset!
20     * -- We have hardcoded check for Template: in English
21     * -- We aren't checking for other instances (ex: template args)
22     * -- We aren't checking for indirect dependencies (ex: nested templates)
23     * -- In the core repo, we also need to figure out what OutputTransformPipeline
24     *    stages need to run in this case.
25     *
26     * @inheritDoc
27     */
28    public function run(
29        Env $env, Node $root, array $options = [], bool $atTopLevel = false
30    ): void {
31        '@phan-var Element|DocumentFragment $root';  // @var Element|DocumentFragment $root
32
33        $selparData = $options['selparData'] ?? null;
34        if ( !$selparData ) {
35            error_log( "Missing selpar data" );
36            return;
37        }
38
39        // FIXME: Hardcoded for English
40        $tplTitle = "./Template:" . $selparData->templateTitle;
41        // FIXME: Insufficient - missing check for template args, indirect dependencies
42        $tplNodes = DOMCompat::querySelectorAll( $root, '[typeof~="mw:Transclusion"]' );
43        foreach ( $tplNodes as $tplNode ) {
44            $dataMw = DOMDataUtils::getDataMW( $tplNode );
45            $ti = $dataMw->parts[0] ?? null;
46            if ( !is_string( $ti ) && $ti->href === $tplTitle ) {
47                $dp = DOMDataUtils::getDataParsoid( $tplNode );
48                $wt = $dp->dsr->substr( $selparData->revText );
49                $opts = [
50                    'pipelineType' => 'selective-update-fragment-wikitext-to-dom',
51                    'sol' => false, // FIXME: Not strictly correct
52                    'srcText' => $selparData->revText,
53                    'pipelineOpts' => [],
54                    'srcOffsets' => $dp->dsr,
55                ];
56
57                // Process template string in new pipeline
58                $frag = PipelineUtils::processContentInPipeline(
59                    $env, $options['frame'], $wt, $opts
60                );
61
62                // Pull out only the transclusion marked portion of $frag & strip p-wrapper
63                $newContent = $frag->firstChild;
64                if (
65                    DOMCompat::nodeName( $tplNode ) !== 'p' &&
66                    DOMCompat::nodeName( $newContent ) === 'p'
67                ) {
68                    $newContent = $newContent->firstChild;
69                }
70                DOMDataUtils::getDataParsoid( $newContent )->dsr = $dp->dsr;
71
72                // Delete template from DOM + add new content to DOM
73                // Note that $tplNode and $frag may have more than one child in the general case
74                $tplParent = $tplNode->parentNode;
75                $about = DOMCompat::getAttribute( $tplNode, 'about' );
76                do {
77                    $next = $tplNode->nextSibling;
78                    $tplParent->removeChild( $tplNode );
79                    $tplNode = $next;
80                } while (
81                    $tplNode instanceof Element &&
82                    DOMCompat::getAttribute( $tplNode, 'about' ) === $about
83                );
84
85                DOMUtils::migrateChildren( $newContent->parentNode, $tplParent, $tplNode );
86            }
87        }
88    }
89}