MediaWiki  master
ApiParse.php
Go to the documentation of this file.
1 <?php
31 
35 class ApiParse extends ApiBase {
36 
38  private $section = null;
39 
41  private $content = null;
42 
44  private $pstContent = null;
45 
47  private $contentIsDeleted = false, $contentIsSuppressed = false;
48 
50  private $revisionLookup;
51 
53  private $skinFactory;
54 
57 
60 
62  private $linkCache;
63 
66 
68  private $parser;
69 
72 
75 
89  public function __construct(
90  ApiMain $main,
91  $action,
101  ) {
102  parent::__construct( $main, $action );
103  $this->revisionLookup = $revisionLookup;
104  $this->skinFactory = $skinFactory;
105  $this->languageNameUtils = $languageNameUtils;
106  $this->linkBatchFactory = $linkBatchFactory;
107  $this->linkCache = $linkCache;
108  $this->contentHandlerFactory = $contentHandlerFactory;
109  $this->parser = $parser;
110  $this->wikiPageFactory = $wikiPageFactory;
111  $this->contentTransformer = $contentTransformer;
112  }
113 
114  private function getPoolKey(): string {
115  $poolKey = WikiMap::getCurrentWikiDbDomain() . ':ApiParse:';
116  if ( !$this->getUser()->isRegistered() ) {
117  $poolKey .= 'a:' . $this->getUser()->getName();
118  } else {
119  $poolKey .= 'u:' . $this->getUser()->getId();
120  }
121  return $poolKey;
122  }
123 
124  private function getContentParserOutput(
126  Title $title,
127  $revId,
128  ParserOptions $popts
129  ) {
130  $worker = new PoolCounterWorkViaCallback( 'ApiParser', $this->getPoolKey(),
131  [
132  'doWork' => static function () use ( $content, $title, $revId, $popts ) {
133  return $content->getParserOutput( $title, $revId, $popts );
134  },
135  'error' => function () {
136  $this->dieWithError( 'apierror-concurrency-limit' );
137  },
138  ]
139  );
140  return $worker->execute();
141  }
142 
143  private function getPageParserOutput(
144  WikiPage $page,
145  $revId,
146  ParserOptions $popts,
147  bool $suppressCache
148  ) {
149  $worker = new PoolCounterWorkViaCallback( 'ApiParser', $this->getPoolKey(),
150  [
151  'doWork' => static function () use ( $page, $revId, $popts, $suppressCache ) {
152  return $page->getParserOutput( $popts, $revId, $suppressCache );
153  },
154  'error' => function () {
155  $this->dieWithError( 'apierror-concurrency-limit' );
156  },
157  ]
158  );
159  return $worker->execute();
160  }
161 
162  public function execute() {
163  // The data is hot but user-dependent, like page views, so we set vary cookies
164  $this->getMain()->setCacheMode( 'anon-public-user-private' );
165 
166  // Get parameters
167  $params = $this->extractRequestParams();
168 
169  // No easy way to say that text and title or revid are allowed together
170  // while the rest aren't, so just do it in three calls.
171  $this->requireMaxOneParameter( $params, 'page', 'pageid', 'oldid', 'text' );
172  $this->requireMaxOneParameter( $params, 'page', 'pageid', 'oldid', 'title' );
173  $this->requireMaxOneParameter( $params, 'page', 'pageid', 'oldid', 'revid' );
174 
175  $text = $params['text'];
176  $title = $params['title'];
177  if ( $title === null ) {
178  $titleProvided = false;
179  // A title is needed for parsing, so arbitrarily choose one
180  $title = 'API';
181  } else {
182  $titleProvided = true;
183  }
184 
185  $page = $params['page'];
186  $pageid = $params['pageid'];
187  $oldid = $params['oldid'];
188 
189  $model = $params['contentmodel'];
190  $format = $params['contentformat'];
191 
192  $prop = array_fill_keys( $params['prop'], true );
193 
194  if ( isset( $params['section'] ) ) {
195  $this->section = $params['section'];
196  if ( !preg_match( '/^((T-)?\d+|new)$/', $this->section ) ) {
197  $this->dieWithError( 'apierror-invalidsection' );
198  }
199  } else {
200  $this->section = false;
201  }
202 
203  // The parser needs $wgTitle to be set, apparently the
204  // $title parameter in Parser::parse isn't enough *sigh*
205  // TODO: Does this still need $wgTitle?
206  global $wgTitle;
207 
208  $redirValues = null;
209 
210  $needContent = isset( $prop['wikitext'] ) ||
211  isset( $prop['parsetree'] ) || $params['generatexml'];
212 
213  // Return result
214  $result = $this->getResult();
215 
216  if ( $oldid !== null || $pageid !== null || $page !== null ) {
217  if ( $this->section === 'new' ) {
218  $this->dieWithError( 'apierror-invalidparammix-parse-new-section', 'invalidparammix' );
219  }
220  if ( $oldid !== null ) {
221  // Don't use the parser cache
222  $rev = $this->revisionLookup->getRevisionById( $oldid );
223  if ( !$rev ) {
224  $this->dieWithError( [ 'apierror-nosuchrevid', $oldid ] );
225  }
226 
227  $this->checkTitleUserPermissions( $rev->getPage(), 'read' );
228 
229  if ( !$rev->userCan( RevisionRecord::DELETED_TEXT, $this->getAuthority() ) ) {
230  $this->dieWithError(
231  [ 'apierror-permissiondenied', $this->msg( 'action-deletedtext' ) ]
232  );
233  }
234 
235  $revLinkTarget = $rev->getPageAsLinkTarget();
236  $titleObj = Title::newFromLinkTarget( $revLinkTarget );
237  $wgTitle = $titleObj;
238  $pageObj = $this->wikiPageFactory->newFromTitle( $titleObj );
239  list( $popts, $reset, $suppressCache ) = $this->makeParserOptions( $pageObj, $params );
240  $p_result = $this->getParsedContent(
241  $pageObj, $popts, $suppressCache, $pageid, $rev, $needContent
242  );
243  } else { // Not $oldid, but $pageid or $page
244  if ( $params['redirects'] ) {
245  $reqParams = [
246  'redirects' => '',
247  ];
248  $pageParams = [];
249  if ( $pageid !== null ) {
250  $reqParams['pageids'] = $pageid;
251  $pageParams['pageid'] = $pageid;
252  } else { // $page
253  $reqParams['titles'] = $page;
254  $pageParams['title'] = $page;
255  }
256  $req = new FauxRequest( $reqParams );
257  $main = new ApiMain( $req );
258  $pageSet = new ApiPageSet( $main );
259  $pageSet->execute();
260  $redirValues = $pageSet->getRedirectTitlesAsResult( $this->getResult() );
261 
262  foreach ( $pageSet->getRedirectTitles() as $title ) {
263  $pageParams = [ 'title' => $title->getFullText() ];
264  }
265  } elseif ( $pageid !== null ) {
266  $pageParams = [ 'pageid' => $pageid ];
267  } else { // $page
268  $pageParams = [ 'title' => $page ];
269  }
270 
271  $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' );
272  $titleObj = $pageObj->getTitle();
273  if ( !$titleObj->exists() ) {
274  $this->dieWithError( 'apierror-missingtitle' );
275  }
276 
277  $this->checkTitleUserPermissions( $titleObj, 'read' );
278  $wgTitle = $titleObj;
279 
280  if ( isset( $prop['revid'] ) ) {
281  $oldid = $pageObj->getLatest();
282  }
283 
284  list( $popts, $reset, $suppressCache ) = $this->makeParserOptions( $pageObj, $params );
285  $p_result = $this->getParsedContent(
286  $pageObj, $popts, $suppressCache, $pageid, null, $needContent
287  );
288  }
289  } else { // Not $oldid, $pageid, $page. Hence based on $text
290  $titleObj = Title::newFromText( $title );
291  if ( !$titleObj || $titleObj->isExternal() ) {
292  $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $title ) ] );
293  }
294  $revid = $params['revid'];
295  if ( $revid !== null ) {
296  $rev = $this->revisionLookup->getRevisionById( $revid );
297  if ( !$rev ) {
298  $this->dieWithError( [ 'apierror-nosuchrevid', $revid ] );
299  }
300  $pTitleObj = $titleObj;
301  $titleObj = Title::newFromLinkTarget( $rev->getPageAsLinkTarget() );
302  if ( $titleProvided ) {
303  if ( !$titleObj->equals( $pTitleObj ) ) {
304  $this->addWarning( [ 'apierror-revwrongpage', $rev->getId(),
305  wfEscapeWikiText( $pTitleObj->getPrefixedText() ) ] );
306  }
307  } else {
308  // Consider the title derived from the revid as having
309  // been provided.
310  $titleProvided = true;
311  }
312  }
313  $wgTitle = $titleObj;
314  if ( $titleObj->canExist() ) {
315  $pageObj = $this->wikiPageFactory->newFromTitle( $titleObj );
316  list( $popts, $reset ) = $this->makeParserOptions( $pageObj, $params );
317  } else { // A special page, presumably
318  // XXX: Why is this needed at all? Can't we just fail?
319  $pageObj = null;
320  $popts = ParserOptions::newCanonical( $this->getContext() );
321  list( $popts, $reset ) = $this->tweakParserOptions( $popts, $titleObj, $params );
322  }
323 
324  $textProvided = $text !== null;
325 
326  if ( !$textProvided ) {
327  if ( $titleProvided && ( $prop || $params['generatexml'] ) ) {
328  if ( $revid !== null ) {
329  $this->addWarning( 'apiwarn-parse-revidwithouttext' );
330  } else {
331  $this->addWarning( 'apiwarn-parse-titlewithouttext' );
332  }
333  }
334  // Prevent warning from ContentHandler::makeContent()
335  $text = '';
336  }
337 
338  // If we are parsing text, do not use the content model of the default
339  // API title, but default to wikitext to keep BC.
340  if ( $textProvided && !$titleProvided && $model === null ) {
341  $model = CONTENT_MODEL_WIKITEXT;
342  $this->addWarning( [ 'apiwarn-parse-nocontentmodel', $model ] );
343  }
344 
345  try {
346  $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
347  } catch ( MWContentSerializationException $ex ) {
348  $this->dieWithException( $ex, [
349  'wrap' => ApiMessage::create( 'apierror-contentserializationexception', 'parseerror' )
350  ] );
351  }
352 
353  if ( $this->section !== false ) {
354  if ( $this->section === 'new' ) {
355  // Insert the section title above the content.
356  if ( $params['sectiontitle'] !== null && $params['sectiontitle'] !== '' ) {
357  $this->content = $this->content->addSectionHeader( $params['sectiontitle'] );
358  }
359  } else {
360  $this->content = $this->getSectionContent( $this->content, $titleObj->getPrefixedText() );
361  }
362  }
363 
364  if ( $params['pst'] || $params['onlypst'] ) {
365  $this->pstContent = $this->contentTransformer->preSaveTransform(
366  $this->content,
367  $titleObj,
368  $this->getUser(),
369  $popts
370  );
371  }
372  if ( $params['onlypst'] ) {
373  // Build a result and bail out
374  $result_array = [];
375  $result_array['text'] = $this->pstContent->serialize( $format );
376  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text';
377  if ( isset( $prop['wikitext'] ) ) {
378  $result_array['wikitext'] = $this->content->serialize( $format );
379  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext';
380  }
381  if ( $params['summary'] !== null ||
382  ( $params['sectiontitle'] !== null && $this->section === 'new' )
383  ) {
384  $result_array['parsedsummary'] = $this->formatSummary( $titleObj, $params );
385  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary';
386  }
387 
388  $result->addValue( null, $this->getModuleName(), $result_array );
389 
390  return;
391  }
392 
393  // Not cached (save or load)
394  if ( $params['pst'] ) {
395  $p_result = $this->getContentParserOutput( $this->pstContent, $titleObj, $revid, $popts );
396  } else {
397  $p_result = $this->getContentParserOutput( $this->content, $titleObj, $revid, $popts );
398  }
399  }
400 
401  $result_array = [];
402 
403  $result_array['title'] = $titleObj->getPrefixedText();
404  $result_array['pageid'] = $pageid ?: $titleObj->getArticleID();
405  if ( $this->contentIsDeleted ) {
406  $result_array['textdeleted'] = true;
407  }
408  if ( $this->contentIsSuppressed ) {
409  $result_array['textsuppressed'] = true;
410  }
411 
412  if ( isset( $params['useskin'] ) ) {
413  $skin = $this->skinFactory->makeSkin( Skin::normalizeKey( $params['useskin'] ) );
414  } else {
415  $skin = null;
416  }
417 
418  $outputPage = null;
419  $context = null;
420  if ( $skin || isset( $prop['subtitle'] ) || isset( $prop['headhtml'] ) || isset( $prop['categorieshtml'] ) ) {
421  // Enabling the skin via 'useskin', 'subtitle', 'headhtml', or 'categorieshtml'
422  // gets OutputPage and Skin involved, which (among others) applies
423  // these hooks:
424  // - ParserOutputHooks
425  // - Hook: LanguageLinks
426  // - Hook: SkinSubPageSubtitle
427  // - Hook: OutputPageParserOutput
428  // - Hook: OutputPageMakeCategoryLinks
429  // - Hook: OutputPageBeforeHTML
430  $context = new DerivativeContext( $this->getContext() );
431  $context->setTitle( $titleObj );
432 
433  if ( $pageObj ) {
434  $context->setWikiPage( $pageObj );
435  }
436  // Some hooks only apply to pages when action=view, which this API
437  // call is simulating.
438  $context->setRequest( new FauxRequest( [ 'action' => 'view' ] ) );
439 
440  if ( $skin ) {
441  // Use the skin specified by 'useskin'
442  $context->setSkin( $skin );
443  // Context clones the skin, refetch to stay in sync. (T166022)
444  $skin = $context->getSkin();
445  } else {
446  // Make sure the context's skin refers to the context. Without this,
447  // $outputPage->getSkin()->getOutput() !== $outputPage which
448  // confuses some of the output.
449  $context->setSkin( $context->getSkin() );
450  }
451 
452  $outputPage = new OutputPage( $context );
453  // Required for subtitle to appear
454  $outputPage->setArticleFlag( true );
455 
456  $outputPage->addParserOutputMetadata( $p_result );
457  if ( $this->content ) {
458  $outputPage->addContentOverride( $titleObj, $this->content );
459  }
460  $context->setOutput( $outputPage );
461 
462  if ( $skin ) {
463  // Based on OutputPage::output()
464  $outputPage->loadSkinModules( $skin );
465  }
466 
467  $this->getHookRunner()->onApiParseMakeOutputPage( $this, $outputPage );
468  }
469 
470  if ( $oldid !== null ) {
471  $result_array['revid'] = (int)$oldid;
472  }
473 
474  if ( $params['redirects'] && $redirValues !== null ) {
475  $result_array['redirects'] = $redirValues;
476  }
477 
478  if ( isset( $prop['text'] ) ) {
479  $result_array['text'] = $p_result->getText( [
480  'allowTOC' => !$params['disabletoc'],
481  'enableSectionEditLinks' => !$params['disableeditsection'],
482  'wrapperDivClass' => $params['wrapoutputclass'],
483  'deduplicateStyles' => !$params['disablestylededuplication'],
484  'skin' => $context ? $context->getSkin() : null,
485  ] );
486  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text';
487  if ( $context ) {
488  $this->getHookRunner()->onOutputPageBeforeHTML( $context->getOutput(), $result_array['text'] );
489  }
490  }
491 
492  if ( $params['summary'] !== null ||
493  ( $params['sectiontitle'] !== null && $this->section === 'new' )
494  ) {
495  $result_array['parsedsummary'] = $this->formatSummary( $titleObj, $params );
496  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary';
497  }
498 
499  if ( isset( $prop['langlinks'] ) ) {
500  if ( $skin ) {
501  $langlinks = $outputPage->getLanguageLinks();
502  } else {
503  $langlinks = $p_result->getLanguageLinks();
504  // The deprecated 'effectivelanglinks' option depredates OutputPage
505  // support via 'useskin'. If not already applied, then run just this
506  // one hook of OutputPage::addParserOutputMetadata here.
507  if ( $params['effectivelanglinks'] ) {
508  $linkFlags = [];
509  $this->getHookRunner()->onLanguageLinks( $titleObj, $langlinks, $linkFlags );
510  }
511  }
512 
513  $result_array['langlinks'] = $this->formatLangLinks( $langlinks );
514  }
515  if ( isset( $prop['categories'] ) ) {
516  $result_array['categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
517  }
518  if ( isset( $prop['categorieshtml'] ) ) {
519  $result_array['categorieshtml'] = $outputPage->getSkin()->getCategories();
520  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'categorieshtml';
521  }
522  if ( isset( $prop['links'] ) ) {
523  $result_array['links'] = $this->formatLinks( $p_result->getLinks() );
524  }
525  if ( isset( $prop['templates'] ) ) {
526  $result_array['templates'] = $this->formatLinks( $p_result->getTemplates() );
527  }
528  if ( isset( $prop['images'] ) ) {
529  $result_array['images'] = array_keys( $p_result->getImages() );
530  }
531  if ( isset( $prop['externallinks'] ) ) {
532  $result_array['externallinks'] = array_keys( $p_result->getExternalLinks() );
533  }
534  if ( isset( $prop['sections'] ) ) {
535  $result_array['sections'] = $p_result->getSections();
536  }
537  if ( isset( $prop['parsewarnings'] ) ) {
538  $result_array['parsewarnings'] = $p_result->getWarnings();
539  }
540  if ( isset( $prop['parsewarningshtml'] ) ) {
541  $warnings = $p_result->getWarnings();
542  $warningsHtml = array_map( static function ( $warning ) {
543  return ( new RawMessage( '$1', [ $warning ] ) )->parse();
544  }, $warnings );
545  $result_array['parsewarningshtml'] = $warningsHtml;
546  }
547 
548  if ( isset( $prop['displaytitle'] ) ) {
549  $result_array['displaytitle'] = $p_result->getDisplayTitle() !== false
550  ? $p_result->getDisplayTitle() : $titleObj->getPrefixedText();
551  }
552 
553  if ( isset( $prop['subtitle'] ) ) {
554  $result_array['subtitle'] = $context->getSkin()->prepareSubtitle();
555  }
556 
557  if ( isset( $prop['headitems'] ) ) {
558  if ( $skin ) {
559  $result_array['headitems'] = $this->formatHeadItems( $outputPage->getHeadItemsArray() );
560  } else {
561  $result_array['headitems'] = $this->formatHeadItems( $p_result->getHeadItems() );
562  }
563  }
564 
565  if ( isset( $prop['headhtml'] ) ) {
566  $result_array['headhtml'] = $outputPage->headElement( $context->getSkin() );
567  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'headhtml';
568  }
569 
570  if ( isset( $prop['modules'] ) ) {
571  if ( $skin ) {
572  $result_array['modules'] = $outputPage->getModules();
573  // Deprecated since 1.32 (T188689)
574  $result_array['modulescripts'] = [];
575  $result_array['modulestyles'] = $outputPage->getModuleStyles();
576  } else {
577  $result_array['modules'] = array_values( array_unique( $p_result->getModules() ) );
578  // Deprecated since 1.32 (T188689)
579  $result_array['modulescripts'] = [];
580  $result_array['modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) );
581  }
582  }
583 
584  if ( isset( $prop['jsconfigvars'] ) ) {
585  $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars();
586  $result_array['jsconfigvars'] = ApiResult::addMetadataToResultVars( $jsconfigvars );
587  }
588 
589  if ( isset( $prop['encodedjsconfigvars'] ) ) {
590  $jsconfigvars = $skin ? $outputPage->getJsConfigVars() : $p_result->getJsConfigVars();
591  $result_array['encodedjsconfigvars'] = FormatJson::encode(
592  $jsconfigvars,
593  false,
595  );
596  $result_array[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
597  }
598 
599  if ( isset( $prop['modules'] ) &&
600  !isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
601  $this->addWarning( 'apiwarn-moduleswithoutvars' );
602  }
603 
604  if ( isset( $prop['indicators'] ) ) {
605  if ( $skin ) {
606  $result_array['indicators'] = (array)$outputPage->getIndicators();
607  } else {
608  $result_array['indicators'] = (array)$p_result->getIndicators();
609  }
610  ApiResult::setArrayType( $result_array['indicators'], 'BCkvp', 'name' );
611  }
612 
613  if ( isset( $prop['iwlinks'] ) ) {
614  $result_array['iwlinks'] = $this->formatIWLinks( $p_result->getInterwikiLinks() );
615  }
616 
617  if ( isset( $prop['wikitext'] ) ) {
618  $result_array['wikitext'] = $this->content->serialize( $format );
619  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext';
620  // @phan-suppress-next-line PhanImpossibleTypeComparison
621  if ( $this->pstContent !== null ) {
622  $result_array['psttext'] = $this->pstContent->serialize( $format );
623  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'psttext';
624  }
625  }
626  if ( isset( $prop['properties'] ) ) {
627  $result_array['properties'] = (array)$p_result->getProperties();
628  ApiResult::setArrayType( $result_array['properties'], 'BCkvp', 'name' );
629  }
630 
631  if ( isset( $prop['limitreportdata'] ) ) {
632  $result_array['limitreportdata'] =
633  $this->formatLimitReportData( $p_result->getLimitReportData() );
634  }
635  if ( isset( $prop['limitreporthtml'] ) ) {
636  $result_array['limitreporthtml'] = EditPage::getPreviewLimitReport( $p_result );
637  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'limitreporthtml';
638  }
639 
640  if ( isset( $prop['parsetree'] ) || $params['generatexml'] ) {
641  if ( $this->content->getModel() != CONTENT_MODEL_WIKITEXT ) {
642  $this->dieWithError( 'apierror-parsetree-notwikitext', 'notwikitext' );
643  }
644 
645  $this->parser->startExternalParse( $titleObj, $popts, Parser::OT_PREPROCESS );
646  // @phan-suppress-next-line PhanUndeclaredMethod
647  $xml = $this->parser->preprocessToDom( $this->content->getText() )->__toString();
648  $result_array['parsetree'] = $xml;
649  $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsetree';
650  }
651 
652  $result_mapping = [
653  'redirects' => 'r',
654  'langlinks' => 'll',
655  'categories' => 'cl',
656  'links' => 'pl',
657  'templates' => 'tl',
658  'images' => 'img',
659  'externallinks' => 'el',
660  'iwlinks' => 'iw',
661  'sections' => 's',
662  'headitems' => 'hi',
663  'modules' => 'm',
664  'indicators' => 'ind',
665  'modulescripts' => 'm',
666  'modulestyles' => 'm',
667  'properties' => 'pp',
668  'limitreportdata' => 'lr',
669  'parsewarnings' => 'pw',
670  'parsewarningshtml' => 'pw',
671  ];
672  $this->setIndexedTagNames( $result_array, $result_mapping );
673  $result->addValue( null, $this->getModuleName(), $result_array );
674  }
675 
684  private function makeParserOptions( WikiPage $pageObj, array $params ) {
685  $popts = $pageObj->makeParserOptions( $this->getContext() );
686  return $this->tweakParserOptions( $popts, $pageObj->getTitle(), $params );
687  }
688 
698  private function tweakParserOptions( ParserOptions $popts, Title $title, array $params ) {
699  $popts->enableLimitReport( !$params['disablepp'] && !$params['disablelimitreport'] );
700  $popts->setIsPreview( $params['preview'] || $params['sectionpreview'] );
701  $popts->setIsSectionPreview( $params['sectionpreview'] );
702 
703  if ( $params['wrapoutputclass'] !== '' ) {
704  $popts->setWrapOutputClass( $params['wrapoutputclass'] );
705  }
706 
707  $reset = null;
708  $suppressCache = false;
709  $this->getHookRunner()->onApiMakeParserOptions( $popts, $title,
710  $params, $this, $reset, $suppressCache );
711 
712  return [ $popts, $reset, $suppressCache ];
713  }
714 
724  private function getParsedContent(
725  WikiPage $page, $popts, $suppressCache, $pageId, $rev, $getContent
726  ) {
727  $revId = $rev ? $rev->getId() : null;
728  $isDeleted = $rev && $rev->isDeleted( RevisionRecord::DELETED_TEXT );
729 
730  if ( $getContent || $this->section !== false || $isDeleted ) {
731  if ( $rev ) {
732  $this->content = $rev->getContent(
733  SlotRecord::MAIN, RevisionRecord::FOR_THIS_USER, $this->getUser()
734  );
735  if ( !$this->content ) {
736  $this->dieWithError( [ 'apierror-missingcontent-revid', $revId ] );
737  }
738  } else {
739  $this->content = $page->getContent( RevisionRecord::FOR_THIS_USER, $this->getUser() );
740  if ( !$this->content ) {
741  $this->dieWithError( [ 'apierror-missingcontent-pageid', $page->getId() ] );
742  }
743  }
744  $this->contentIsDeleted = $isDeleted;
745  $this->contentIsSuppressed = $rev &&
746  $rev->isDeleted( RevisionRecord::DELETED_TEXT | RevisionRecord::DELETED_RESTRICTED );
747  }
748 
749  if ( $this->section !== false ) {
750  $this->content = $this->getSectionContent(
751  $this->content,
752  $pageId === null ? $page->getTitle()->getPrefixedText() : $this->msg( 'pageid', $pageId )
753  );
754  return $this->getContentParserOutput( $this->content, $page->getTitle(), $revId, $popts );
755  }
756 
757  if ( $isDeleted ) {
758  // getParserOutput can't do revdeled revisions
759 
760  $pout = $this->getContentParserOutput( $this->content, $page->getTitle(), $revId, $popts );
761  } else {
762  // getParserOutput will save to Parser cache if able
763  $pout = $this->getPageParserOutput( $page, $revId, $popts, $suppressCache );
764  }
765  if ( !$pout ) {
766  // @codeCoverageIgnoreStart
767  $this->dieWithError( [ 'apierror-nosuchrevid', $revId ?: $page->getLatest() ] );
768  // @codeCoverageIgnoreEnd
769  }
770 
771  return $pout;
772  }
773 
781  private function getSectionContent( Content $content, $what ) {
782  // Not cached (save or load)
783  $section = $content->getSection( $this->section );
784  if ( $section === false ) {
785  $this->dieWithError( [ 'apierror-nosuchsection-what', $this->section, $what ], 'nosuchsection' );
786  }
787  if ( $section === null ) {
788  $this->dieWithError( [ 'apierror-sectionsnotsupported-what', $what ], 'nosuchsection' );
789  }
790 
791  return $section;
792  }
793 
801  private function formatSummary( $title, $params ) {
802  $summary = $params['summary'] ?? '';
803  $sectionTitle = $params['sectiontitle'] ?? '';
804 
805  if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
806  if ( $sectionTitle !== '' ) {
807  $summary = $params['sectiontitle'];
808  }
809  if ( $summary !== '' ) {
810  $summary = wfMessage( 'newsectionsummary' )
811  ->rawParams( $this->parser->stripSectionName( $summary ) )
812  ->inContentLanguage()->text();
813  }
814  }
815  return Linker::formatComment( $summary, $title, $this->section === 'new' );
816  }
817 
818  private function formatLangLinks( $links ) {
819  $result = [];
820  foreach ( $links as $link ) {
821  $entry = [];
822  $bits = explode( ':', $link, 2 );
823  $title = Title::newFromText( $link );
824 
825  $entry['lang'] = $bits[0];
826  if ( $title ) {
827  $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
828  // localised language name in 'uselang' language
829  $entry['langname'] = $this->languageNameUtils->getLanguageName(
830  $title->getInterwiki(),
831  $this->getLanguage()->getCode()
832  );
833 
834  // native language name
835  $entry['autonym'] = $this->languageNameUtils->getLanguageName( $title->getInterwiki() );
836  }
837  ApiResult::setContentValue( $entry, 'title', $bits[1] );
838  $result[] = $entry;
839  }
840 
841  return $result;
842  }
843 
844  private function formatCategoryLinks( $links ) {
845  $result = [];
846 
847  if ( !$links ) {
848  return $result;
849  }
850 
851  // Fetch hiddencat property
852  $lb = $this->linkBatchFactory->newLinkBatch();
853  $lb->setArray( [ NS_CATEGORY => $links ] );
854  $db = $this->getDB();
855  $res = $db->select( [ 'page', 'page_props' ],
856  [ 'page_title', 'pp_propname' ],
857  $lb->constructSet( 'page', $db ),
858  __METHOD__,
859  [],
860  [ 'page_props' => [
861  'LEFT JOIN', [ 'pp_propname' => 'hiddencat', 'pp_page = page_id' ]
862  ] ]
863  );
864  $hiddencats = [];
865  foreach ( $res as $row ) {
866  $hiddencats[$row->page_title] = isset( $row->pp_propname );
867  }
868 
869  foreach ( $links as $link => $sortkey ) {
870  $entry = [];
871  $entry['sortkey'] = $sortkey;
872  // array keys will cast numeric category names to ints, so cast back to string
873  ApiResult::setContentValue( $entry, 'category', (string)$link );
874  if ( !isset( $hiddencats[$link] ) ) {
875  $entry['missing'] = true;
876 
877  // We already know the link doesn't exist in the database, so
878  // tell LinkCache that before calling $title->isKnown().
879  $title = Title::makeTitle( NS_CATEGORY, $link );
880  $this->linkCache->addBadLinkObj( $title );
881  if ( $title->isKnown() ) {
882  $entry['known'] = true;
883  }
884  } elseif ( $hiddencats[$link] ) {
885  $entry['hidden'] = true;
886  }
887  $result[] = $entry;
888  }
889 
890  return $result;
891  }
892 
893  private function formatLinks( $links ) {
894  $result = [];
895  foreach ( $links as $ns => $nslinks ) {
896  foreach ( $nslinks as $title => $id ) {
897  $entry = [];
898  $entry['ns'] = $ns;
899  ApiResult::setContentValue( $entry, 'title', Title::makeTitle( $ns, $title )->getFullText() );
900  $entry['exists'] = $id != 0;
901  $result[] = $entry;
902  }
903  }
904 
905  return $result;
906  }
907 
908  private function formatIWLinks( $iw ) {
909  $result = [];
910  foreach ( $iw as $prefix => $titles ) {
911  foreach ( array_keys( $titles ) as $title ) {
912  $entry = [];
913  $entry['prefix'] = $prefix;
914 
915  $title = Title::newFromText( "{$prefix}:{$title}" );
916  if ( $title ) {
917  $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
918  }
919 
920  ApiResult::setContentValue( $entry, 'title', $title->getFullText() );
921  $result[] = $entry;
922  }
923  }
924 
925  return $result;
926  }
927 
928  private function formatHeadItems( $headItems ) {
929  $result = [];
930  foreach ( $headItems as $tag => $content ) {
931  $entry = [];
932  $entry['tag'] = $tag;
933  ApiResult::setContentValue( $entry, 'content', $content );
934  $result[] = $entry;
935  }
936 
937  return $result;
938  }
939 
940  private function formatLimitReportData( $limitReportData ) {
941  $result = [];
942 
943  foreach ( $limitReportData as $name => $value ) {
944  $entry = [];
945  $entry['name'] = $name;
946  if ( !is_array( $value ) ) {
947  $value = [ $value ];
948  }
949  ApiResult::setIndexedTagNameRecursive( $value, 'param' );
950  $entry = array_merge( $entry, $value );
951  $result[] = $entry;
952  }
953 
954  return $result;
955  }
956 
957  private function setIndexedTagNames( &$array, $mapping ) {
958  foreach ( $mapping as $key => $name ) {
959  if ( isset( $array[$key] ) ) {
960  ApiResult::setIndexedTagName( $array[$key], $name );
961  }
962  }
963  }
964 
965  public function getAllowedParams() {
966  return [
967  'title' => null,
968  'text' => [
969  ApiBase::PARAM_TYPE => 'text',
970  ],
971  'revid' => [
972  ApiBase::PARAM_TYPE => 'integer',
973  ],
974  'summary' => null,
975  'page' => null,
976  'pageid' => [
977  ApiBase::PARAM_TYPE => 'integer',
978  ],
979  'redirects' => false,
980  'oldid' => [
981  ApiBase::PARAM_TYPE => 'integer',
982  ],
983  'prop' => [
984  ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|' .
985  'images|externallinks|sections|revid|displaytitle|iwlinks|' .
986  'properties|parsewarnings',
987  ApiBase::PARAM_ISMULTI => true,
989  'text',
990  'langlinks',
991  'categories',
992  'categorieshtml',
993  'links',
994  'templates',
995  'images',
996  'externallinks',
997  'sections',
998  'revid',
999  'displaytitle',
1000  'subtitle',
1001  'headhtml',
1002  'modules',
1003  'jsconfigvars',
1004  'encodedjsconfigvars',
1005  'indicators',
1006  'iwlinks',
1007  'wikitext',
1008  'properties',
1009  'limitreportdata',
1010  'limitreporthtml',
1011  'parsetree',
1012  'parsewarnings',
1013  'parsewarningshtml',
1014  'headitems',
1015  ],
1017  'parsetree' => [ 'apihelp-parse-paramvalue-prop-parsetree', CONTENT_MODEL_WIKITEXT ],
1018  ],
1020  'headitems' => 'apiwarn-deprecation-parse-headitems',
1021  ],
1022  ],
1023  'wrapoutputclass' => 'mw-parser-output',
1024  'pst' => false,
1025  'onlypst' => false,
1026  'effectivelanglinks' => [
1027  ApiBase::PARAM_DFLT => false,
1028  ApiBase::PARAM_DEPRECATED => true,
1029  ],
1030  'section' => null,
1031  'sectiontitle' => [
1032  ApiBase::PARAM_TYPE => 'string',
1033  ],
1034  'disablepp' => [
1035  ApiBase::PARAM_DFLT => false,
1036  ApiBase::PARAM_DEPRECATED => true,
1037  ],
1038  'disablelimitreport' => false,
1039  'disableeditsection' => false,
1040  'disablestylededuplication' => false,
1041  'generatexml' => [
1042  ApiBase::PARAM_DFLT => false,
1044  'apihelp-parse-param-generatexml', CONTENT_MODEL_WIKITEXT
1045  ],
1046  ApiBase::PARAM_DEPRECATED => true,
1047  ],
1048  'preview' => false,
1049  'sectionpreview' => false,
1050  'disabletoc' => false,
1051  'useskin' => [
1052  // T237856; We use all installed skins here to allow hidden (but usable) skins
1053  // to continue working correctly with some features such as Live Preview
1054  ApiBase::PARAM_TYPE => array_keys( $this->skinFactory->getInstalledSkins() ),
1055  ],
1056  'contentformat' => [
1057  ApiBase::PARAM_TYPE => $this->contentHandlerFactory->getAllContentFormats(),
1058  ],
1059  'contentmodel' => [
1060  ApiBase::PARAM_TYPE => $this->contentHandlerFactory->getContentModels(),
1061  ],
1062  ];
1063  }
1064 
1065  protected function getExamplesMessages() {
1066  return [
1067  'action=parse&page=Project:Sandbox'
1068  => 'apihelp-parse-example-page',
1069  'action=parse&text={{Project:Sandbox}}&contentmodel=wikitext'
1070  => 'apihelp-parse-example-text',
1071  'action=parse&text={{PAGENAME}}&title=Test'
1072  => 'apihelp-parse-example-texttitle',
1073  'action=parse&summary=Some+[[link]]&prop='
1074  => 'apihelp-parse-example-summary',
1075  ];
1076  }
1077 
1078  public function getHelpUrls() {
1079  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Parsing_wikitext#parse';
1080  }
1081 }
ApiBase\checkTitleUserPermissions
checkTitleUserPermissions( $pageIdentity, $actions, array $options=[])
Helper function for permission-denied errors.
Definition: ApiBase.php:1514
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:45
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:49
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:39
LinkCache
Cache for article titles (prefixed DB keys) and ids linked from one source.
Definition: LinkCache.php:40
ApiParse\formatIWLinks
formatIWLinks( $iw)
Definition: ApiParse.php:908
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:35
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:383
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:47
ApiParse\getParsedContent
getParsedContent(WikiPage $page, $popts, $suppressCache, $pageId, $rev, $getContent)
Definition: ApiParse.php:724
MediaWiki\Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:47
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1297
WikiMap\getCurrentWikiDbDomain
static getCurrentWikiDbDomain()
Definition: WikiMap.php:293
IContextSource\getSkin
getSkin()
ApiParse\formatLangLinks
formatLangLinks( $links)
Definition: ApiParse.php:818
WikiPage\getParserOutput
getParserOutput(ParserOptions $parserOptions, $oldid=null, $noCache=false)
Get a ParserOutput for the given ParserOptions and revision ID.
Definition: WikiPage.php:1273
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1379
ApiBase\PARAM_HELP_MSG
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:105
ApiParse\tweakParserOptions
tweakParserOptions(ParserOptions $popts, Title $title, array $params)
Tweaks a ParserOptions object.
Definition: ApiParse.php:698
ApiResult\META_BC_SUBELEMENTS
const META_BC_SUBELEMENTS
Key for the 'BC subelements' metadata item.
Definition: ApiResult.php:143
ApiBase\getTitleOrPageId
getTitleOrPageId( $params, $load=false)
Get a WikiPage object from a title or pageid param, if possible.
Definition: ApiBase.php:976
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:72
ApiParse\formatLinks
formatLinks( $links)
Definition: ApiParse.php:893
ParserOptions\setIsPreview
setIsPreview( $x)
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:646
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:571
ParserOptions\setIsSectionPreview
setIsSectionPreview( $x)
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:663
WikiPage
Class representing a MediaWiki article and history.
Definition: WikiPage.php:60
WikiPage\makeParserOptions
makeParserOptions( $context)
Get parser options suitable for rendering the primary article wikitext.
Definition: WikiPage.php:1996
ParserOptions\setWrapOutputClass
setWrapOutputClass( $className)
CSS class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:851
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1186
ApiBase\getDB
getDB()
Gets a default replica DB connection object.
Definition: ApiBase.php:594
ApiParse\$pstContent
Content null $pstContent
Definition: ApiParse.php:44
PoolCounterWorkViaCallback
Convenience class for dealing with PoolCounters using callbacks.
Definition: PoolCounterWorkViaCallback.php:31
ApiParse\$contentIsDeleted
bool $contentIsDeleted
Definition: ApiParse.php:47
$res
$res
Definition: testCompression.php:57
ContextSource\getUser
getUser()
Definition: ContextSource.php:136
ApiBase\PARAM_DEPRECATED_VALUES
const PARAM_DEPRECATED_VALUES
Definition: ApiBase.php:84
FormatJson\ALL_OK
const ALL_OK
Skip escaping as many characters as reasonably possible.
Definition: FormatJson.php:55
MediaWiki\Revision\RevisionLookup
Service for looking up page revisions.
Definition: RevisionLookup.php:38
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:45
ApiParse\$parser
Parser $parser
Definition: ApiParse.php:68
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:55
MediaWiki\Languages\LanguageNameUtils
A service that provides utilities to do with language names and codes.
Definition: LanguageNameUtils.php:42
ApiParse\getPageParserOutput
getPageParserOutput(WikiPage $page, $revId, ParserOptions $popts, bool $suppressCache)
Definition: ApiParse.php:143
ApiResult\setContentValue
static setContentValue(array &$arr, $name, $value, $flags=0)
Add an output value to the array by name and mark as META_CONTENT.
Definition: ApiResult.php:466
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
Definition: ApiBase.php:77
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:32
ApiParse
Definition: ApiParse.php:35
FormatJson\encode
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:96
ApiResult\setArrayType
static setArrayType(array &$arr, $type, $kvpKeyName=null)
Set the array data type.
Definition: ApiResult.php:715
ApiParse\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiParse.php:1078
Content\getSection
getSection( $sectionId)
Returns the section with the given ID.
ApiResult\addMetadataToResultVars
static addMetadataToResultVars( $vars, $forceHash=true)
Add the correct metadata to an array of vars we want to export through the API.
Definition: ApiResult.php:1139
Skin\normalizeKey
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
Definition: Skin.php:99
ApiParse\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiParse.php:965
PoolCounterWork\execute
execute( $skipcache=false)
Get the result of the work (whatever it is), or the result of the error() function.
Definition: PoolCounterWork.php:127
ApiResult\META_SUBELEMENTS
const META_SUBELEMENTS
Key for the 'subelements' metadata item.
Definition: ApiResult.php:78
ApiParse\formatLimitReportData
formatLimitReportData( $limitReportData)
Definition: ApiParse.php:940
MediaWiki\Cache\LinkBatchFactory
Definition: LinkBatchFactory.php:39
EditPage\getPreviewLimitReport
static getPreviewLimitReport(ParserOutput $output=null)
Get the Limit report for page previews.
Definition: EditPage.php:3813
WikiPage\getTitle
getTitle()
Get the title object of the article.
Definition: WikiPage.php:311
MWContentSerializationException
Exception representing a failure to serialize or unserialize a content object.
Definition: MWContentSerializationException.php:8
ApiParse\$contentHandlerFactory
IContentHandlerFactory $contentHandlerFactory
Definition: ApiParse.php:65
ApiParse\getContentParserOutput
getContentParserOutput(Content $content, Title $title, $revId, ParserOptions $popts)
Definition: ApiParse.php:124
MediaWiki\Content\Transform\ContentTransformer
A service to transform content.
Definition: ContentTransformer.php:15
Page\WikiPageFactory
Definition: WikiPageFactory.php:20
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:707
ParserOptions\newCanonical
static newCanonical( $context, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1134
$title
$title
Definition: testCompression.php:38
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:651
ApiParse\$linkBatchFactory
LinkBatchFactory $linkBatchFactory
Definition: ApiParse.php:59
ApiMessage\create
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
Definition: ApiMessage.php:43
ApiParse\formatSummary
formatSummary( $title, $params)
This mimicks the behavior of EditPage in formatting a summary.
Definition: ApiParse.php:801
OutputPage
This is one of the Core classes and should be read at least once by any new developers.
Definition: OutputPage.php:50
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:146
$wgTitle
$wgTitle
Definition: Setup.php:852
PROTO_CURRENT
const PROTO_CURRENT
Definition: Defines.php:195
ApiParse\formatCategoryLinks
formatCategoryLinks( $links)
Definition: ApiParse.php:844
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:197
WikiPage\getId
getId( $wikiId=self::LOCAL)
Definition: WikiPage.php:584
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:603
ApiParse\$revisionLookup
RevisionLookup $revisionLookup
Definition: ApiParse.php:50
WikiPage\getContent
getContent( $audience=RevisionRecord::FOR_PUBLIC, Authority $performer=null)
Get the content of the current revision.
Definition: WikiPage.php:837
ApiBase\requireMaxOneParameter
requireMaxOneParameter( $params,... $required)
Die if more than one of a certain set of parameters is set and not false.
Definition: ApiBase.php:879
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
SkinFactory
Factory class to create Skin objects.
Definition: SkinFactory.php:31
ApiParse\setIndexedTagNames
setIndexedTagNames(&$array, $mapping)
Definition: ApiParse.php:957
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1459
CONTENT_MODEL_WIKITEXT
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:208
Parser
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition: Parser.php:91
Title\newFromLinkTarget
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition: Title.php:295
Parser\OT_PREPROCESS
const OT_PREPROCESS
Definition: Parser.php:127
Linker\formatComment
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
Definition: Linker.php:1372
Content
Base interface for content objects.
Definition: Content.php:35
ApiParse\$section
string false null $section
Definition: ApiParse.php:38
ParserOptions\enableLimitReport
enableLimitReport( $x=true)
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:521
Title
Represents a title within MediaWiki.
Definition: Title.php:48
ApiParse\__construct
__construct(ApiMain $main, $action, RevisionLookup $revisionLookup, SkinFactory $skinFactory, LanguageNameUtils $languageNameUtils, LinkBatchFactory $linkBatchFactory, LinkCache $linkCache, IContentHandlerFactory $contentHandlerFactory, Parser $parser, WikiPageFactory $wikiPageFactory, ContentTransformer $contentTransformer)
Definition: ApiParse.php:89
ApiParse\$languageNameUtils
LanguageNameUtils $languageNameUtils
Definition: ApiParse.php:56
ApiParse\getPoolKey
getPoolKey()
Definition: ApiParse.php:114
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:70
ApiParse\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiParse.php:1065
ApiBase\dieWithException
dieWithException(Throwable $exception, array $options=[])
Abort execution with an error derived from a throwable.
Definition: ApiBase.php:1392
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:440
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:71
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:78
ApiParse\getSectionContent
getSectionContent(Content $content, $what)
Extract the requested section from the given Content.
Definition: ApiParse.php:781
WikiPage\getLatest
getLatest( $wikiId=self::LOCAL)
Get the page_latest field.
Definition: WikiPage.php:752
ApiParse\$wikiPageFactory
WikiPageFactory $wikiPageFactory
Definition: ApiParse.php:71
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:456
ApiParse\$content
Content null $content
Definition: ApiParse.php:41
Content\getParserOutput
getParserOutput(Title $title, $revId=null, ParserOptions $options=null, $generateHtml=true)
Parse the Content object and generate a ParserOutput from the result.
ApiParse\$linkCache
LinkCache $linkCache
Definition: ApiParse.php:62
ApiParse\formatHeadItems
formatHeadItems( $headItems)
Definition: ApiParse.php:928
RawMessage
Variant of the Message class.
Definition: RawMessage.php:35
ApiResult\setIndexedTagNameRecursive
static setIndexedTagNameRecursive(array &$arr, $tag)
Set indexed tag name on $arr and all subarrays.
Definition: ApiResult.php:628
ApiBase\PARAM_HELP_MSG_PER_VALUE
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition: ApiBase.php:138
ApiBase\getHookRunner
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition: ApiBase.php:653
ApiParse\makeParserOptions
makeParserOptions(WikiPage $pageObj, array $params)
Constructs a ParserOptions object.
Definition: ApiParse.php:684
IContextSource\getOutput
getOutput()
ApiParse\$contentTransformer
ContentTransformer $contentTransformer
Definition: ApiParse.php:74
ApiParse\$skinFactory
SkinFactory $skinFactory
Definition: ApiParse.php:53
MediaWiki\Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40
wfExpandUrl
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
Definition: GlobalFunctions.php:474
ApiParse\$contentIsSuppressed
bool $contentIsSuppressed
Definition: ApiParse.php:47
ApiParse\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiParse.php:162