Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
94.59% |
35 / 37 |
|
60.00% |
3 / 5 |
CRAP | |
0.00% |
0 / 1 |
PageBundleParserOutputConverter | |
94.59% |
35 / 37 |
|
60.00% |
3 / 5 |
8.01 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
parserOutputFromPageBundle | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
applyPageBundleDataToParserOutput | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
2 | |||
pageBundleFromParserOutput | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
2 | |||
hasPageBundle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Parser\Parsoid; |
4 | |
5 | use MediaWiki\Language\LanguageCode; |
6 | use MediaWiki\Parser\ParserOutput; |
7 | use Wikimedia\Parsoid\Core\PageBundle; |
8 | |
9 | /** |
10 | * Provides methods for conversion between PageBundle and ParserOutput |
11 | * TODO: Convert to a trait once we drop support for PHP < 8.2 since |
12 | * support for constants in traits was added in PHP 8.2 |
13 | * @since 1.40 |
14 | * @internal |
15 | */ |
16 | final class PageBundleParserOutputConverter { |
17 | /** |
18 | * @var string Key used to store parsoid page bundle data in ParserOutput |
19 | */ |
20 | public const PARSOID_PAGE_BUNDLE_KEY = 'parsoid-page-bundle'; |
21 | |
22 | /** |
23 | * We do not want instances of this class to be created |
24 | * @return void |
25 | */ |
26 | private function __construct() { |
27 | } |
28 | |
29 | /** |
30 | * Creates a ParserOutput object containing the relevant data from |
31 | * the given PageBundle object. |
32 | * |
33 | * We need to inject data-parsoid and other properties into the |
34 | * parser output object for caching, so we can use it for VE edits |
35 | * and transformations. |
36 | * |
37 | * @param PageBundle $pageBundle |
38 | * @param ?ParserOutput $originalParserOutput Any non-parsoid metadata |
39 | * from $originalParserOutput will be copied into the new ParserOutput object. |
40 | * |
41 | * @return ParserOutput |
42 | */ |
43 | public static function parserOutputFromPageBundle( |
44 | PageBundle $pageBundle, ?ParserOutput $originalParserOutput = null |
45 | ): ParserOutput { |
46 | $parserOutput = new ParserOutput( $pageBundle->html ); |
47 | if ( $originalParserOutput ) { |
48 | $parserOutput->mergeHtmlMetaDataFrom( $originalParserOutput ); |
49 | $parserOutput->mergeTrackingMetaDataFrom( $originalParserOutput ); |
50 | $parserOutput->mergeInternalMetaDataFrom( $originalParserOutput ); |
51 | } |
52 | self::applyPageBundleDataToParserOutput( $pageBundle, $parserOutput ); |
53 | return $parserOutput; |
54 | } |
55 | |
56 | /** |
57 | * Given an existing ParserOutput and a PageBundle, applies the PageBundle data to the ParserOutput. |
58 | * NOTE: it does NOT apply the text of said pageBundle - this should be done by the calling method, if desired. |
59 | * This way, we can modify a ParserOutput's associated bundle without creating a new ParserOutput, |
60 | * which makes it easier to deal with in the OutputTransformPipeline. |
61 | * @param PageBundle|\stdClass $pageBundle |
62 | * @param ParserOutput $parserOutput |
63 | * @internal |
64 | */ |
65 | public static function applyPageBundleDataToParserOutput( |
66 | $pageBundle, ParserOutput $parserOutput |
67 | ): void { |
68 | // Overwriting ExtensionData was deprecated in 1.38 but it's safe inside an OutputTransform pipeline, |
69 | // which is the only place where this should happen right now. |
70 | $parserOutput->setExtensionData( |
71 | self::PARSOID_PAGE_BUNDLE_KEY, |
72 | [ |
73 | 'parsoid' => $pageBundle->parsoid ?? null, |
74 | 'mw' => $pageBundle->mw ?? null, |
75 | 'version' => $pageBundle->version ?? null, |
76 | 'headers' => $pageBundle->headers ?? null, |
77 | 'contentmodel' => $pageBundle->contentmodel ?? null, |
78 | ] |
79 | ); |
80 | |
81 | if ( isset( $pageBundle->headers['content-language'] ) ) { |
82 | $lang = LanguageCode::normalizeNonstandardCodeAndWarn( |
83 | // @phan-suppress-next-line PhanTypeArraySuspiciousNullable |
84 | $pageBundle->headers['content-language'] |
85 | ); |
86 | $parserOutput->setLanguage( $lang ); |
87 | } |
88 | } |
89 | |
90 | /** |
91 | * Returns a Parsoid PageBundle equivalent to the given ParserOutput. |
92 | * |
93 | * @param ParserOutput $parserOutput |
94 | * |
95 | * @return PageBundle |
96 | */ |
97 | public static function pageBundleFromParserOutput( ParserOutput $parserOutput ): PageBundle { |
98 | $pageBundleData = $parserOutput->getExtensionData( self::PARSOID_PAGE_BUNDLE_KEY ); |
99 | $lang = $parserOutput->getLanguage(); |
100 | |
101 | $headers = $pageBundleData['headers'] ?? []; |
102 | |
103 | if ( $lang ) { |
104 | $headers['content-language'] = $lang->toBcp47Code(); |
105 | } |
106 | |
107 | return new PageBundle( |
108 | $parserOutput->getRawText(), |
109 | $pageBundleData['parsoid'] ?? [ 'ids' => [] ], |
110 | $pageBundleData['mw'] ?? null, |
111 | // It would be nice to have this be "null", but PageBundle::responseData() |
112 | // chocks on that: T325137. |
113 | $pageBundleData['version'] ?? '0.0.0', |
114 | $pageBundleData['headers'] ?? $headers, |
115 | $pageBundleData['contentmodel'] ?? null |
116 | ); |
117 | } |
118 | |
119 | public static function hasPageBundle( ParserOutput $parserOutput ) { |
120 | return $parserOutput->getExtensionData( self::PARSOID_PAGE_BUNDLE_KEY ) !== null; |
121 | } |
122 | } |