187 $this->getMain()->setCacheMode(
'anon-public-user-private' );
190 $params = $this->extractRequestParams();
194 $this->requireMaxOneParameter( $params,
'page',
'pageid',
'oldid',
'text' );
195 $this->requireMaxOneParameter( $params,
'page',
'pageid',
'oldid',
'title' );
196 $this->requireMaxOneParameter( $params,
'page',
'pageid',
'oldid',
'revid' );
198 $text = $params[
'text'];
199 $title = $params[
'title'];
201 $titleProvided =
false;
205 $titleProvided =
true;
208 $page = $params[
'page'];
209 $pageid = $params[
'pageid'];
210 $oldid = $params[
'oldid'];
212 $prop = array_fill_keys( $params[
'prop'],
true );
214 if ( isset( $params[
'section'] ) ) {
215 $this->section = $params[
'section'];
216 if ( !preg_match(
'/^((T-)?\d+|new)$/', $this->section ) ) {
217 $this->dieWithError(
'apierror-invalidsection' );
220 $this->section =
false;
231 $needContent = isset( $prop[
'wikitext'] ) ||
232 isset( $prop[
'parsetree'] ) || $params[
'generatexml'];
235 $result = $this->getResult();
237 if ( $oldid !==
null || $pageid !==
null || $page !==
null ) {
238 if ( $this->section ===
'new' ) {
239 $this->dieWithError(
'apierror-invalidparammix-parse-new-section',
'invalidparammix' );
241 if ( $oldid !==
null ) {
243 $rev = $this->revisionLookup->getRevisionById( $oldid );
245 $this->dieWithError( [
'apierror-nosuchrevid', $oldid ] );
248 $this->checkTitleUserPermissions( $rev->getPage(),
'read' );
250 if ( !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() ) ) {
252 [
'apierror-permissiondenied', $this->msg(
'action-deletedtext' ) ]
256 $revLinkTarget = $rev->getPageAsLinkTarget();
257 $titleObj = Title::newFromLinkTarget( $revLinkTarget );
259 $pageObj = $this->wikiPageFactory->newFromTitle( $titleObj );
260 [ $popts, $reset, $suppressCache ] = $this->makeParserOptions( $pageObj, $params );
261 $p_result = $this->getParsedContent(
262 $pageObj, $popts, $suppressCache, $pageid, $rev, $needContent
265 if ( $params[
'redirects'] ) {
270 if ( $pageid !==
null ) {
271 $reqParams[
'pageids'] = $pageid;
272 $pageParams[
'pageid'] = $pageid;
274 $reqParams[
'titles'] = $page;
275 $pageParams[
'title'] = $page;
281 $redirValues = $pageSet->getRedirectTitlesAsResult( $this->getResult() );
283 foreach ( $pageSet->getRedirectTitles() as
$title ) {
284 $pageParams = [
'title' =>
$title->getFullText() ];
286 } elseif ( $pageid !==
null ) {
287 $pageParams = [
'pageid' => $pageid ];
289 $pageParams = [
'title' => $page ];
292 $pageObj = $this->getTitleOrPageId( $pageParams,
'fromdb' );
294 if ( !$titleObj->exists() ) {
295 $this->dieWithError(
'apierror-missingtitle' );
298 $this->checkTitleUserPermissions( $titleObj,
'read' );
301 if ( isset( $prop[
'revid'] ) ) {
305 [ $popts, $reset, $suppressCache ] = $this->makeParserOptions( $pageObj, $params );
306 $p_result = $this->getParsedContent(
307 $pageObj, $popts, $suppressCache, $pageid,
null, $needContent
311 $model = $params[
'contentmodel'];
312 $format = $params[
'contentformat'];
314 $titleObj = Title::newFromText(
$title );
315 if ( !$titleObj || $titleObj->isExternal() ) {
318 $revid = $params[
'revid'];
319 if ( $revid !==
null ) {
320 $rev = $this->revisionLookup->getRevisionById( $revid );
322 $this->dieWithError( [
'apierror-nosuchrevid', $revid ] );
324 $pTitleObj = $titleObj;
325 $titleObj = Title::newFromLinkTarget( $rev->getPageAsLinkTarget() );
326 if ( $titleProvided ) {
327 if ( !$titleObj->equals( $pTitleObj ) ) {
328 $this->addWarning( [
'apierror-revwrongpage', $rev->getId(),
334 $titleProvided =
true;
338 if ( $titleObj->canExist() ) {
339 $pageObj = $this->wikiPageFactory->newFromTitle( $titleObj );
340 [ $popts, $reset ] = $this->makeParserOptions( $pageObj, $params );
344 $popts = ParserOptions::newFromContext( $this->
getContext() );
345 [ $popts, $reset ] = $this->tweakParserOptions( $popts, $titleObj, $params );
348 $textProvided = $text !==
null;
350 if ( !$textProvided ) {
351 if ( $titleProvided && ( $prop || $params[
'generatexml'] ) ) {
352 if ( $revid !==
null ) {
353 $this->addWarning(
'apiwarn-parse-revidwithouttext' );
355 $this->addWarning(
'apiwarn-parse-titlewithouttext' );
364 if ( $textProvided && !$titleProvided && $model ===
null ) {
366 $this->addWarning( [
'apiwarn-parse-nocontentmodel', $model ] );
367 } elseif ( $model ===
null ) {
368 $model = $titleObj->getContentModel();
371 $contentHandler = $this->contentHandlerFactory->getContentHandler( $model );
373 if ( $format && !$contentHandler->isSupportedFormat( $format ) ) {
374 $this->dieWithError( [
'apierror-badformat-generic', $format, $model ] );
378 $this->content = $contentHandler->unserializeContent( $text, $format );
380 $this->dieWithException( $ex, [
381 'wrap' => ApiMessage::create(
'apierror-contentserializationexception',
'parseerror' )
385 if ( $this->section !==
false ) {
386 if ( $this->section ===
'new' ) {
388 if ( $params[
'sectiontitle'] !==
null ) {
389 $this->content = $this->content->addSectionHeader( $params[
'sectiontitle'] );
392 $this->content = $this->getSectionContent( $this->content, $titleObj->getPrefixedText() );
396 if ( $params[
'pst'] || $params[
'onlypst'] ) {
397 $this->pstContent = $this->contentTransformer->preSaveTransform(
404 if ( $params[
'onlypst'] ) {
407 $result_array[
'text'] = $this->pstContent->serialize( $format );
408 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'text';
409 if ( isset( $prop[
'wikitext'] ) ) {
410 $result_array[
'wikitext'] = $this->content->serialize( $format );
411 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'wikitext';
413 if ( $params[
'summary'] !==
null ||
414 ( $params[
'sectiontitle'] !==
null && $this->section ===
'new' )
416 $result_array[
'parsedsummary'] = $this->formatSummary( $titleObj, $params );
417 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'parsedsummary';
420 $result->addValue(
null, $this->getModuleName(), $result_array );
426 if ( $params[
'pst'] ) {
427 $p_result = $this->getContentParserOutput( $this->pstContent, $titleObj, $revid, $popts );
429 $p_result = $this->getContentParserOutput( $this->content, $titleObj, $revid, $popts );
435 $result_array[
'title'] = $titleObj->getPrefixedText();
436 $result_array[
'pageid'] = $pageid ?: $titleObj->getArticleID();
437 if ( $this->contentIsDeleted ) {
438 $result_array[
'textdeleted'] =
true;
440 if ( $this->contentIsSuppressed ) {
441 $result_array[
'textsuppressed'] =
true;
444 if ( isset( $params[
'useskin'] ) ) {
453 $skin || isset( $prop[
'subtitle'] ) || isset( $prop[
'headhtml'] ) || isset( $prop[
'categorieshtml'] ) ||
454 isset( $params[
'mobileformat'] )
471 $context->setTitle( $titleObj );
474 $context->setWikiPage( $pageObj );
478 $context->setRequest(
new FauxRequest( [
'action' =>
'view' ] ) );
482 $context->setSkin( $skin );
484 $skin = $context->getSkin();
489 $context->setSkin( $context->getSkin() );
494 $outputPage->setArticleFlag(
true );
496 $outputPage->addParserOutputMetadata( $p_result );
497 if ( $this->content ) {
498 $outputPage->addContentOverride( $titleObj, $this->content );
500 $context->setOutput( $outputPage );
504 $outputPage->loadSkinModules( $skin );
507 $this->getHookRunner()->onApiParseMakeOutputPage( $this, $outputPage );
510 if ( $oldid !==
null ) {
511 $result_array[
'revid'] = (int)$oldid;
514 if ( $params[
'redirects'] && $redirValues !==
null ) {
515 $result_array[
'redirects'] = $redirValues;
518 if ( isset( $prop[
'text'] ) ) {
519 $skin = $context ? $context->getSkin() :
null;
520 $skinOptions = $skin ? $skin->getOptions() : [
523 $result_array[
'text'] = $p_result->getText( [
524 'allowTOC' => !$params[
'disabletoc'],
525 'injectTOC' => $skinOptions[
'toc'],
526 'enableSectionEditLinks' => !$params[
'disableeditsection'],
527 'wrapperDivClass' => $params[
'wrapoutputclass'],
528 'deduplicateStyles' => !$params[
'disablestylededuplication'],
529 'userLang' => $context ? $context->getLanguage() :
null,
531 'includeDebugInfo' => !$params[
'disablepp'] && !$params[
'disablelimitreport']
533 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'text';
535 $this->getHookRunner()->onOutputPageBeforeHTML( $context->getOutput(), $result_array[
'text'] );
539 if ( $params[
'summary'] !==
null ||
540 ( $params[
'sectiontitle'] !==
null && $this->section ===
'new' )
542 $result_array[
'parsedsummary'] = $this->formatSummary( $titleObj, $params );
543 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'parsedsummary';
546 if ( isset( $prop[
'langlinks'] ) ) {
548 $langlinks = $outputPage->getLanguageLinks();
550 $langlinks = $p_result->getLanguageLinks();
554 if ( $params[
'effectivelanglinks'] ) {
556 $this->getHookRunner()->onLanguageLinks( $titleObj, $langlinks, $linkFlags );
560 $result_array[
'langlinks'] = $this->formatLangLinks( $langlinks );
562 if ( isset( $prop[
'categories'] ) ) {
563 $result_array[
'categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
565 if ( isset( $prop[
'categorieshtml'] ) ) {
566 $result_array[
'categorieshtml'] = $outputPage->getSkin()->getCategories();
567 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'categorieshtml';
569 if ( isset( $prop[
'links'] ) ) {
570 $result_array[
'links'] = $this->formatLinks( $p_result->getLinks() );
572 if ( isset( $prop[
'templates'] ) ) {
573 $result_array[
'templates'] = $this->formatLinks( $p_result->getTemplates() );
575 if ( isset( $prop[
'images'] ) ) {
576 $result_array[
'images'] = array_keys( $p_result->getImages() );
578 if ( isset( $prop[
'externallinks'] ) ) {
579 $result_array[
'externallinks'] = array_keys( $p_result->getExternalLinks() );
581 if ( isset( $prop[
'sections'] ) ) {
582 $result_array[
'sections'] = $p_result->getSections();
583 $result_array[
'showtoc'] = $p_result->getOutputFlag( ParserOutputFlags::SHOW_TOC );
585 if ( isset( $prop[
'parsewarnings'] ) ) {
586 $result_array[
'parsewarnings'] = $p_result->getWarnings();
588 if ( isset( $prop[
'parsewarningshtml'] ) ) {
589 $warnings = $p_result->getWarnings();
590 $warningsHtml = array_map(
static function ( $warning ) {
591 return (
new RawMessage(
'$1', [ $warning ] ) )->parse();
593 $result_array[
'parsewarningshtml'] = $warningsHtml;
596 if ( isset( $prop[
'displaytitle'] ) ) {
597 $result_array[
'displaytitle'] = $p_result->getDisplayTitle() !==
false
598 ? $p_result->getDisplayTitle()
599 : htmlspecialchars( $titleObj->getPrefixedText(), ENT_NOQUOTES );
602 if ( isset( $prop[
'subtitle'] ) ) {
604 $result_array[
'subtitle'] = $context->getSkin()->prepareSubtitle(
false );
607 if ( isset( $prop[
'headitems'] ) ) {
609 $result_array[
'headitems'] = $this->formatHeadItems( $outputPage->getHeadItemsArray() );
611 $result_array[
'headitems'] = $this->formatHeadItems( $p_result->getHeadItems() );
615 if ( isset( $prop[
'headhtml'] ) ) {
616 $result_array[
'headhtml'] = $outputPage->headElement( $context->getSkin() );
617 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'headhtml';
620 if ( isset( $prop[
'modules'] ) ) {
622 $result_array[
'modules'] = $outputPage->getModules();
624 $result_array[
'modulescripts'] = [];
625 $result_array[
'modulestyles'] = $outputPage->getModuleStyles();
627 $result_array[
'modules'] = array_values( array_unique( $p_result->getModules() ) );
629 $result_array[
'modulescripts'] = [];
630 $result_array[
'modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) );
634 if ( isset( $prop[
'jsconfigvars'] ) ) {
635 $showStrategyKeys = (bool)( $params[
'showstrategykeys'] );
636 $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars( $showStrategyKeys );
637 $result_array[
'jsconfigvars'] = ApiResult::addMetadataToResultVars( $jsconfigvars );
640 if ( isset( $prop[
'encodedjsconfigvars'] ) ) {
641 $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars();
642 $result_array[
'encodedjsconfigvars'] = FormatJson::encode(
647 $result_array[ApiResult::META_SUBELEMENTS][] =
'encodedjsconfigvars';
650 if ( isset( $prop[
'modules'] ) &&
651 !isset( $prop[
'jsconfigvars'] ) && !isset( $prop[
'encodedjsconfigvars'] ) ) {
652 $this->addWarning(
'apiwarn-moduleswithoutvars' );
655 if ( isset( $prop[
'indicators'] ) ) {
657 $result_array[
'indicators'] = (array)$outputPage->getIndicators();
659 $result_array[
'indicators'] = (array)$p_result->getIndicators();
661 ApiResult::setArrayType( $result_array[
'indicators'],
'BCkvp',
'name' );
664 if ( isset( $prop[
'iwlinks'] ) ) {
665 $result_array[
'iwlinks'] = $this->formatIWLinks( $p_result->getInterwikiLinks() );
668 if ( isset( $prop[
'wikitext'] ) ) {
669 $result_array[
'wikitext'] = $this->content->serialize( $format );
670 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'wikitext';
672 if ( $this->pstContent !==
null ) {
673 $result_array[
'psttext'] = $this->pstContent->serialize( $format );
674 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'psttext';
677 if ( isset( $prop[
'properties'] ) ) {
678 $result_array[
'properties'] = $p_result->getPageProperties();
679 ApiResult::setArrayType( $result_array[
'properties'],
'BCkvp',
'name' );
682 if ( isset( $prop[
'limitreportdata'] ) ) {
683 $result_array[
'limitreportdata'] =
684 $this->formatLimitReportData( $p_result->getLimitReportData() );
686 if ( isset( $prop[
'limitreporthtml'] ) ) {
687 $result_array[
'limitreporthtml'] = EditPage::getPreviewLimitReport( $p_result );
688 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'limitreporthtml';
691 if ( isset( $prop[
'parsetree'] ) || $params[
'generatexml'] ) {
693 $this->dieWithError(
'apierror-parsetree-notwikitext',
'notwikitext' );
698 $xml = $this->parser->preprocessToDom( $this->content->getText() )->__toString();
699 $result_array[
'parsetree'] = $xml;
700 $result_array[ApiResult::META_BC_SUBELEMENTS][] =
'parsetree';
706 'categories' =>
'cl',
710 'externallinks' =>
'el',
715 'indicators' =>
'ind',
716 'modulescripts' =>
'm',
717 'modulestyles' =>
'm',
718 'properties' =>
'pp',
719 'limitreportdata' =>
'lr',
720 'parsewarnings' =>
'pw',
721 'parsewarningshtml' =>
'pw',
723 $this->setIndexedTagNames( $result_array, $result_mapping );
724 $result->addValue(
null, $this->getModuleName(), $result_array );