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