Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.76% covered (warning)
75.76%
25 / 33
33.33% covered (danger)
33.33%
2 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
PageBundleParserOutputConverter
75.76% covered (warning)
75.76%
25 / 33
33.33% covered (danger)
33.33%
2 / 6
11.42
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 parserOutputFromPageBundle
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
 pageBundleFromParserOutput
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 htmlPageBundleFromParserOutput
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 basePageBundleFromParserOutput
61.54% covered (warning)
61.54%
8 / 13
0.00% covered (danger)
0.00%
0 / 1
3.51
 hasPageBundle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Parser\Parsoid;
5
6use MediaWiki\Language\LanguageCode;
7use MediaWiki\Parser\ContentHolder;
8use MediaWiki\Parser\ParserOutput;
9use Wikimedia\Parsoid\Core\BasePageBundle;
10use Wikimedia\Parsoid\Core\HtmlPageBundle;
11
12/**
13 * Provides methods for conversion between HtmlPageBundle and ParserOutput
14 * TODO: Convert to a trait once we drop support for PHP < 8.2 since
15 * support for constants in traits was added in PHP 8.2
16 * @since 1.40
17 * @internal
18 */
19final class PageBundleParserOutputConverter {
20    /**
21     * @var string Key used to store parsoid page bundle data in ParserOutput
22     * @deprecated since 1.45; use ParserOutput::PARSOID_PAGE_BUNDLE_KEY
23     */
24    public const PARSOID_PAGE_BUNDLE_KEY = ParserOutput::PARSOID_PAGE_BUNDLE_KEY;
25
26    /**
27     * We do not want instances of this class to be created
28     * @return void
29     */
30    private function __construct() {
31    }
32
33    /**
34     * Creates a ParserOutput object containing the relevant data from
35     * the given HtmlPageBundle object.
36     *
37     * We need to inject data-parsoid and other properties into the
38     * parser output object for caching, so we can use it for VE edits
39     * and transformations.
40     *
41     * @param HtmlPageBundle $pageBundle
42     * @param ?ParserOutput $originalParserOutput Any non-parsoid metadata
43     *  from $originalParserOutput will be copied into the new ParserOutput object.
44     *
45     * @return ParserOutput
46     */
47    public static function parserOutputFromPageBundle(
48        HtmlPageBundle $pageBundle, ?ParserOutput $originalParserOutput = null
49    ): ParserOutput {
50        $parserOutput = new ParserOutput();
51        $parserOutput->setContentHolder(
52            ContentHolder::createFromParsoidPageBundle( $pageBundle )
53        );
54        if ( $originalParserOutput ) {
55            // Merging metadata from the original parser output will also
56            // potentially transfer fragments from
57            // $originalParserOutput->getContentHolder() to
58            // $parserOutput->getContentHolder()
59            $parserOutput->mergeHtmlMetaDataFrom( $originalParserOutput );
60            $parserOutput->mergeTrackingMetaDataFrom( $originalParserOutput );
61            $parserOutput->mergeInternalMetaDataFrom( $originalParserOutput );
62        }
63        if ( isset( $pageBundle->headers['content-language'] ) ) {
64            $lang = LanguageCode::normalizeNonstandardCodeAndWarn(
65            // @phan-suppress-next-line PhanTypeArraySuspiciousNullable
66                $pageBundle->headers['content-language']
67            );
68            $parserOutput->setLanguage( $lang );
69        }
70        return $parserOutput;
71    }
72
73    /**
74     * Returns a Parsoid HtmlPageBundle equivalent to the given ParserOutput.
75     * @param ParserOutput $parserOutput
76     *
77     * @return HtmlPageBundle
78     * @deprecated Use ::htmlPageBundleFromParserOutput
79     */
80    public static function pageBundleFromParserOutput( ParserOutput $parserOutput ): HtmlPageBundle {
81        return self::htmlPageBundleFromParserOutput( $parserOutput );
82    }
83
84    /**
85     * Returns a Parsoid HtmlPageBundle equivalent to the given ParserOutput.
86     * @param ParserOutput $parserOutput
87     *
88     * @return HtmlPageBundle
89     */
90    public static function htmlPageBundleFromParserOutput( ParserOutput $parserOutput ): HtmlPageBundle {
91        $bpb = self::basePageBundleFromParserOutput( $parserOutput );
92        $pb = $bpb->withHtml( $parserOutput->getContentHolderText() );
93        // NOTE that the fragments from the ContentHolder are missing
94        // from this page bundle.  It is assumed that the fragments
95        // are referenced from other parts of the ParserOutput; aka that
96        // they are loaded/saved as part of ParserOuput::$mIndicators
97        return $pb;
98    }
99
100    private static function basePageBundleFromParserOutput( ParserOutput $parserOutput ): BasePageBundle {
101        $contentHolder = $parserOutput->getContentHolder();
102        $basePageBundle = $contentHolder->isParsoidContent() ?
103            $contentHolder->getBasePageBundle() :
104            new BasePageBundle(
105                parsoid: [ 'ids' => [] ],
106                headers: [],
107                // It would be nice to have this be "null", but
108                // ParsoidFormatHelper chokes on that: T325137.
109                version: '0.0.0',
110            );
111        $lang = $parserOutput->getLanguage();
112
113        if ( $lang ) {
114            $basePageBundle->headers ??= [];
115            $basePageBundle->headers['content-language'] = $lang->toBcp47Code();
116        }
117        return $basePageBundle;
118    }
119
120    public static function hasPageBundle( ParserOutput $parserOutput ): bool {
121        return $parserOutput->getContentHolder()->isParsoidContent();
122    }
123}