Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 45 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
| Hooks | |
0.00% |
0 / 45 |
|
0.00% |
0 / 8 |
380 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
| onParserFirstCallInit | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| onParserAfterParse | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
| onParserTestGlobals | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| onRegistration | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
12 | |||
| onOutputTransformFirstStage | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| onOutputTransformLastStage | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| traverseJson | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
72 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * @license MIT |
| 4 | * @file |
| 5 | * |
| 6 | * @author Yuri Astrakhan |
| 7 | */ |
| 8 | |
| 9 | namespace Kartographer; |
| 10 | |
| 11 | use Kartographer\Tag\LegacyMapFrame; |
| 12 | use Kartographer\Tag\LegacyMapLink; |
| 13 | use Kartographer\Tag\LegacyTagHandler; |
| 14 | use MediaWiki\Config\Config; |
| 15 | use MediaWiki\Hook\ParserTestGlobalsHook; |
| 16 | use MediaWiki\Language\LanguageNameUtils; |
| 17 | use MediaWiki\OutputTransform\Hook\OutputTransformFirstStageHook; |
| 18 | use MediaWiki\OutputTransform\Hook\OutputTransformLastStageHook; |
| 19 | use MediaWiki\Parser\Hook\ParserAfterParseHook; |
| 20 | use MediaWiki\Parser\Hook\ParserFirstCallInitHook; |
| 21 | use MediaWiki\Parser\Parser; |
| 22 | use MediaWiki\Parser\ParserOptions; |
| 23 | use MediaWiki\Parser\ParserOutput; |
| 24 | use MediaWiki\Parser\StripState; |
| 25 | use MediaWiki\Settings\SettingsBuilder; |
| 26 | use MediaWiki\Title\TitleFormatter; |
| 27 | |
| 28 | /** |
| 29 | * @license MIT |
| 30 | */ |
| 31 | class Hooks implements |
| 32 | ParserFirstCallInitHook, |
| 33 | ParserAfterParseHook, |
| 34 | ParserTestGlobalsHook, |
| 35 | OutputTransformFirstStageHook, |
| 36 | OutputTransformLastStageHook |
| 37 | { |
| 38 | private readonly LegacyMapLink $legacyMapLink; |
| 39 | private readonly LegacyMapFrame $legacyMapFrame; |
| 40 | |
| 41 | public function __construct( |
| 42 | Config $config, |
| 43 | LanguageNameUtils $languageCodeValidator, |
| 44 | TitleFormatter $titleFormatter |
| 45 | ) { |
| 46 | $this->legacyMapLink = new LegacyMapLink( |
| 47 | $config, |
| 48 | $languageCodeValidator, |
| 49 | $titleFormatter |
| 50 | ); |
| 51 | $this->legacyMapFrame = new LegacyMapFrame( |
| 52 | $config, |
| 53 | $languageCodeValidator, |
| 54 | $titleFormatter |
| 55 | ); |
| 56 | } |
| 57 | |
| 58 | /** |
| 59 | * ParserFirstCallInit hook handler |
| 60 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit |
| 61 | * @param Parser $parser |
| 62 | */ |
| 63 | public function onParserFirstCallInit( $parser ) { |
| 64 | $parser->setHook( LegacyMapLink::TAG, $this->legacyMapLink->handle( ... ) ); |
| 65 | $parser->setHook( LegacyMapFrame::TAG, $this->legacyMapFrame->handle( ... ) ); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * ParserAfterParse hook handler |
| 70 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserAfterParse |
| 71 | * @param Parser $parser |
| 72 | * @param string &$text Text being parsed |
| 73 | * @param StripState $stripState StripState used |
| 74 | */ |
| 75 | public function onParserAfterParse( $parser, &$text, $stripState ) { |
| 76 | $output = $parser->getOutput(); |
| 77 | $state = State::getState( $output ); |
| 78 | |
| 79 | if ( $state ) { |
| 80 | $options = $parser->getOptions(); |
| 81 | $isPreview = $options->getIsPreview() || $options->getIsSectionPreview(); |
| 82 | $tracker = new ParserFunctionTracker( $parser ); |
| 83 | LegacyTagHandler::finalParseStep( $state, $output, $isPreview, $tracker ); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | /** |
| 88 | * @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserTestGlobals |
| 89 | * @param array &$globals Array with all the globals which should be set for parser tests. |
| 90 | * The arrays keys serve as the globals' names, its values are the globals' values. |
| 91 | * @return bool|void True or no return value to continue or false to abort |
| 92 | */ |
| 93 | public function onParserTestGlobals( &$globals ) { |
| 94 | $globals['wgKartographerMapServer'] = 'https://maps.wikimedia.org'; |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * Sets $wgKartographerMapServer in integration test/CI setup |
| 99 | * This is needed by parserTests that define articles containing Kartographer content - parsing them when |
| 100 | * inserting them in the test DB requires $wgKartographerMapServer to be defined early. |
| 101 | */ |
| 102 | public static function onRegistration( array $extInfo, SettingsBuilder $settings ) { |
| 103 | if ( defined( 'MW_PHPUNIT_TEST' ) || defined( 'MW_QUIBBLE_CI' ) ) { |
| 104 | $settings->overrideConfigValue( 'KartographerMapServer', 'https://maps.wikimedia.org' ); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | public function onOutputTransformFirstStage( ParserOutput &$parserOutput, ParserOptions $parserOptions ): void { |
| 109 | $data = $parserOutput->getExtensionData( 'kartographer' )['data'] ?? []; |
| 110 | $path = 'kartographer:'; |
| 111 | $traversal = static function ( ParserOutput $po, $json, string $prop, string $path ) { |
| 112 | $po->getContentHolder()->setAsHtmlString( $path, $json->properties->$prop ); |
| 113 | }; |
| 114 | $this->traverseJson( $parserOutput, $data, $path, $traversal ); |
| 115 | } |
| 116 | |
| 117 | public function onOutputTransformLastStage( ParserOutput &$parserOutput, ParserOptions $parserOptions ): void { |
| 118 | // Note: this works because $wgKartographerLiveData in jsConfigVars is referencing this same array |
| 119 | $data = $parserOutput->getExtensionData( 'kartographer' )['data'] ?? []; |
| 120 | $path = 'kartographer:'; |
| 121 | $traversal = static function ( ParserOutput $po, $json, string $prop, string $path ) { |
| 122 | $json->properties->$prop = $po->getContentHolder()->getAsHtmlString( $path ) ?? ''; |
| 123 | // clean up the contentholder to avoid extraneous serialization |
| 124 | $po->getContentHolder()->setAsHtmlString( $path, null ); |
| 125 | }; |
| 126 | $this->traverseJson( $parserOutput, $data, $path, $traversal ); |
| 127 | } |
| 128 | |
| 129 | private function traverseJson( ParserOutput $po, mixed &$json, string $path, callable $callable ): void { |
| 130 | if ( is_array( $json ) ) { |
| 131 | foreach ( $json as $k => &$element ) { |
| 132 | $this->traverseJson( $po, $element, $path . "$k/", $callable ); |
| 133 | } |
| 134 | } elseif ( is_object( $json ) ) { |
| 135 | if ( isset( $json->properties ) && is_object( $json->properties ) ) { |
| 136 | foreach ( SimpleStyleParser::WIKITEXT_PROPERTIES as $prop ) { |
| 137 | if ( !property_exists( $json->properties, $prop ) ) { |
| 138 | continue; |
| 139 | } |
| 140 | $path .= $prop; |
| 141 | $callable( $po, $json, $prop, $path ); |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | } |