Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
65.52% covered (warning)
65.52%
19 / 29
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
TemplateHelper
65.52% covered (warning)
65.52%
19 / 29
50.00% covered (danger)
50.00%
2 / 4
15.96
0.00% covered (danger)
0.00%
0 / 1
 removeFromHtml
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
5
 getTemplateName
50.00% covered (danger)
50.00%
2 / 4
0.00% covered (danger)
0.00%
0 / 1
2.50
 removeAboutNodes
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 extractTemplates
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Flow\Import;
4
5use DOMDocument;
6use DOMElement;
7use DOMXPath;
8use Flow\Conversion\Utils;
9use MediaWiki\Title\Title;
10
11class TemplateHelper {
12
13    /**
14     * @param string $htmlContent
15     * @param string $templateName
16     * @return string
17     * @throws \Flow\Exception\WikitextException
18     */
19    public static function removeFromHtml( $htmlContent, $templateName ) {
20        $dom = Utils::createDOM( $htmlContent );
21        $xpath = new DOMXPath( $dom );
22        $templateNodes = $xpath->query( '//*[@typeof="mw:Transclusion"]' );
23
24        foreach ( $templateNodes as $templateNode ) {
25            /** @var DOMElement $templateNode */
26            if ( $templateNode->hasAttribute( 'data-mw' ) ) {
27                $name = self::getTemplateName( $templateNode->getAttribute( 'data-mw' ) );
28                if ( $name === $templateName ) {
29                    $templateNode->parentNode->removeChild( $templateNode );
30                    if ( $templateNode->hasAttribute( 'about' ) ) {
31                        $about = $templateNode->getAttribute( 'about' );
32                        self::removeAboutNodes( $dom, $about );
33                    }
34                }
35            }
36        }
37
38        $body = $xpath->query( '/html/body' )->item( 0 );
39        return $dom->saveHTML( $body );
40    }
41
42    /**
43     * @param string $dataMW
44     * @return string|null
45     */
46    private static function getTemplateName( $dataMW ) {
47        try {
48            $mwAttr = json_decode( $dataMW );
49            // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
50            return @$mwAttr->parts[0]->template->target->wt;
51        } catch ( \Throwable $e ) {
52            return null;
53        }
54    }
55
56    /**
57     * @param DOMDocument $dom
58     * @param string $about
59     */
60    private static function removeAboutNodes( DOMDocument $dom, $about ) {
61        $xpath = new DOMXPath( $dom );
62        $aboutNodes = $xpath->query( '//*[@about="' . $about . '"]' );
63        foreach ( $aboutNodes as $aboutNode ) {
64            $aboutNode->parentNode->removeChild( $aboutNode );
65        }
66    }
67
68    /**
69     * Extract templates from wikitext content.
70     * Requires Parsoid to reliably extract templates.
71     *
72     * @param string $wtContent
73     * @param Title $title
74     * @return string
75     */
76    public static function extractTemplates( $wtContent, Title $title ) {
77        $content = Utils::convert( 'wikitext', 'html', $wtContent, $title );
78        $dom = Utils::createDOM( $content );
79        $xpath = new \DOMXPath( $dom );
80        $templates = $xpath->query( '//*[@typeof="mw:Transclusion"]' );
81
82        $content = '';
83        foreach ( $templates as $template ) {
84            $content .= $dom->saveHTML( $template ) . "\n";
85        }
86
87        return Utils::convert( 'html', 'wikitext', $content, $title );
88    }
89
90}