Introduce mediawiki.RegExp module
[mediawiki.git] / includes / api / ApiParse.php
blobfa6f30e57b40f4e27124893a797671ecc9582f48
1 <?php
2 /**
3 * Created on Dec 01, 2007
5 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * http://www.gnu.org/copyleft/gpl.html
22 * @file
25 /**
26 * @ingroup API
28 class ApiParse extends ApiBase {
30 /** @var string $section */
31 private $section = null;
33 /** @var Content $content */
34 private $content = null;
36 /** @var Content $pstContent */
37 private $pstContent = null;
39 public function execute() {
40 // The data is hot but user-dependent, like page views, so we set vary cookies
41 $this->getMain()->setCacheMode( 'anon-public-user-private' );
43 // Get parameters
44 $params = $this->extractRequestParams();
45 $text = $params['text'];
46 $title = $params['title'];
47 if ( $title === null ) {
48 $titleProvided = false;
49 // A title is needed for parsing, so arbitrarily choose one
50 $title = 'API';
51 } else {
52 $titleProvided = true;
55 $page = $params['page'];
56 $pageid = $params['pageid'];
57 $oldid = $params['oldid'];
59 $model = $params['contentmodel'];
60 $format = $params['contentformat'];
62 if ( !is_null( $page ) && ( !is_null( $text ) || $titleProvided ) ) {
63 $this->dieUsage(
64 'The page parameter cannot be used together with the text and title parameters',
65 'params'
69 $prop = array_flip( $params['prop'] );
71 if ( isset( $params['section'] ) ) {
72 $this->section = $params['section'];
73 if ( !preg_match( '/^((T-)?\d+|new)$/', $this->section ) ) {
74 $this->dieUsage(
75 "The section parameter must be a valid section id or 'new'", "invalidsection"
78 } else {
79 $this->section = false;
82 // The parser needs $wgTitle to be set, apparently the
83 // $title parameter in Parser::parse isn't enough *sigh*
84 // TODO: Does this still need $wgTitle?
85 global $wgParser, $wgTitle;
87 $redirValues = null;
89 // Return result
90 $result = $this->getResult();
92 if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
93 if ( $this->section === 'new' ) {
94 $this->dieUsage(
95 'section=new cannot be combined with oldid, pageid or page parameters. ' .
96 'Please use text', 'params'
99 if ( !is_null( $oldid ) ) {
100 // Don't use the parser cache
101 $rev = Revision::newFromId( $oldid );
102 if ( !$rev ) {
103 $this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
105 if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
106 $this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
109 $titleObj = $rev->getTitle();
110 $wgTitle = $titleObj;
111 $pageObj = WikiPage::factory( $titleObj );
112 $popts = $this->makeParserOptions( $pageObj, $params );
114 // If for some reason the "oldid" is actually the current revision, it may be cached
115 // Deliberately comparing $pageObj->getLatest() with $rev->getId(), rather than
116 // checking $rev->isCurrent(), because $pageObj is what actually ends up being used,
117 // and if its ->getLatest() is outdated, $rev->isCurrent() won't tell us that.
118 if ( $rev->getId() == $pageObj->getLatest() ) {
119 // May get from/save to parser cache
120 $p_result = $this->getParsedContent( $pageObj, $popts,
121 $pageid, isset( $prop['wikitext'] ) );
122 } else { // This is an old revision, so get the text differently
123 $this->content = $rev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
125 if ( $this->section !== false ) {
126 $this->content = $this->getSectionContent( $this->content, 'r' . $rev->getId() );
129 // Should we save old revision parses to the parser cache?
130 $p_result = $this->content->getParserOutput( $titleObj, $rev->getId(), $popts );
132 } else { // Not $oldid, but $pageid or $page
133 if ( $params['redirects'] ) {
134 $reqParams = array(
135 'redirects' => '',
137 if ( !is_null( $pageid ) ) {
138 $reqParams['pageids'] = $pageid;
139 } else { // $page
140 $reqParams['titles'] = $page;
142 $req = new FauxRequest( $reqParams );
143 $main = new ApiMain( $req );
144 $pageSet = new ApiPageSet( $main );
145 $pageSet->execute();
146 $redirValues = $pageSet->getRedirectTitlesAsResult( $this->getResult() );
148 $to = $page;
149 foreach ( $pageSet->getRedirectTitles() as $title ) {
150 $to = $title->getFullText();
152 $pageParams = array( 'title' => $to );
153 } elseif ( !is_null( $pageid ) ) {
154 $pageParams = array( 'pageid' => $pageid );
155 } else { // $page
156 $pageParams = array( 'title' => $page );
159 $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' );
160 $titleObj = $pageObj->getTitle();
161 if ( !$titleObj || !$titleObj->exists() ) {
162 $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
164 $wgTitle = $titleObj;
166 if ( isset( $prop['revid'] ) ) {
167 $oldid = $pageObj->getLatest();
170 $popts = $this->makeParserOptions( $pageObj, $params );
172 // Potentially cached
173 $p_result = $this->getParsedContent( $pageObj, $popts, $pageid,
174 isset( $prop['wikitext'] ) );
176 } else { // Not $oldid, $pageid, $page. Hence based on $text
177 $titleObj = Title::newFromText( $title );
178 if ( !$titleObj || $titleObj->isExternal() ) {
179 $this->dieUsageMsg( array( 'invalidtitle', $title ) );
181 $wgTitle = $titleObj;
182 if ( $titleObj->canExist() ) {
183 $pageObj = WikiPage::factory( $titleObj );
184 } else {
185 // Do like MediaWiki::initializeArticle()
186 $article = Article::newFromTitle( $titleObj, $this->getContext() );
187 $pageObj = $article->getPage();
190 $popts = $this->makeParserOptions( $pageObj, $params );
191 $textProvided = !is_null( $text );
193 if ( !$textProvided ) {
194 if ( $titleProvided && ( $prop || $params['generatexml'] ) ) {
195 $this->setWarning(
196 "'title' used without 'text', and parsed page properties were requested " .
197 "(did you mean to use 'page' instead of 'title'?)"
200 // Prevent warning from ContentHandler::makeContent()
201 $text = '';
204 // If we are parsing text, do not use the content model of the default
205 // API title, but default to wikitext to keep BC.
206 if ( $textProvided && !$titleProvided && is_null( $model ) ) {
207 $model = CONTENT_MODEL_WIKITEXT;
208 $this->setWarning( "No 'title' or 'contentmodel' was given, assuming $model." );
211 try {
212 $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
213 } catch ( MWContentSerializationException $ex ) {
214 $this->dieUsage( $ex->getMessage(), 'parseerror' );
217 if ( $this->section !== false ) {
218 if ( $this->section === 'new' ) {
219 // Insert the section title above the content.
220 if ( !is_null( $params['sectiontitle'] ) && $params['sectiontitle'] !== '' ) {
221 $this->content = $this->content->addSectionHeader( $params['sectiontitle'] );
223 } else {
224 $this->content = $this->getSectionContent( $this->content, $titleObj->getPrefixedText() );
228 if ( $params['pst'] || $params['onlypst'] ) {
229 $this->pstContent = $this->content->preSaveTransform( $titleObj, $this->getUser(), $popts );
231 if ( $params['onlypst'] ) {
232 // Build a result and bail out
233 $result_array = array();
234 $result_array['text'] = $this->pstContent->serialize( $format );
235 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text';
236 if ( isset( $prop['wikitext'] ) ) {
237 $result_array['wikitext'] = $this->content->serialize( $format );
238 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext';
240 if ( !is_null( $params['summary'] ) ||
241 ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
243 $result_array['parsedsummary'] = $this->formatSummary( $titleObj, $params );
244 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary';
247 $result->addValue( null, $this->getModuleName(), $result_array );
249 return;
252 // Not cached (save or load)
253 if ( $params['pst'] ) {
254 $p_result = $this->pstContent->getParserOutput( $titleObj, null, $popts );
255 } else {
256 $p_result = $this->content->getParserOutput( $titleObj, null, $popts );
260 $result_array = array();
262 $result_array['title'] = $titleObj->getPrefixedText();
264 if ( !is_null( $oldid ) ) {
265 $result_array['revid'] = intval( $oldid );
268 if ( $params['redirects'] && !is_null( $redirValues ) ) {
269 $result_array['redirects'] = $redirValues;
272 if ( $params['disabletoc'] ) {
273 $p_result->setTOCEnabled( false );
276 if ( isset( $prop['text'] ) ) {
277 $result_array['text'] = $p_result->getText();
278 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text';
281 if ( !is_null( $params['summary'] ) ||
282 ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
284 $result_array['parsedsummary'] = $this->formatSummary( $titleObj, $params );
285 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary';
288 if ( isset( $prop['langlinks'] ) ) {
289 $langlinks = $p_result->getLanguageLinks();
291 if ( $params['effectivelanglinks'] ) {
292 // Link flags are ignored for now, but may in the future be
293 // included in the result.
294 $linkFlags = array();
295 Hooks::run( 'LanguageLinks', array( $titleObj, &$langlinks, &$linkFlags ) );
297 } else {
298 $langlinks = false;
301 if ( isset( $prop['langlinks'] ) ) {
302 $result_array['langlinks'] = $this->formatLangLinks( $langlinks );
304 if ( isset( $prop['categories'] ) ) {
305 $result_array['categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
307 if ( isset( $prop['categorieshtml'] ) ) {
308 $result_array['categorieshtml'] = $this->categoriesHtml( $p_result->getCategories() );
309 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'categorieshtml';
311 if ( isset( $prop['links'] ) ) {
312 $result_array['links'] = $this->formatLinks( $p_result->getLinks() );
314 if ( isset( $prop['templates'] ) ) {
315 $result_array['templates'] = $this->formatLinks( $p_result->getTemplates() );
317 if ( isset( $prop['images'] ) ) {
318 $result_array['images'] = array_keys( $p_result->getImages() );
320 if ( isset( $prop['externallinks'] ) ) {
321 $result_array['externallinks'] = array_keys( $p_result->getExternalLinks() );
323 if ( isset( $prop['sections'] ) ) {
324 $result_array['sections'] = $p_result->getSections();
327 if ( isset( $prop['displaytitle'] ) ) {
328 $result_array['displaytitle'] = $p_result->getDisplayTitle() ?
329 $p_result->getDisplayTitle() :
330 $titleObj->getPrefixedText();
333 if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) {
334 $context = $this->getContext();
335 $context->setTitle( $titleObj );
336 $context->getOutput()->addParserOutputMetadata( $p_result );
338 if ( isset( $prop['headitems'] ) ) {
339 $headItems = $this->formatHeadItems( $p_result->getHeadItems() );
341 $css = $this->formatCss( $context->getOutput()->buildCssLinksArray() );
343 $scripts = array( $context->getOutput()->getHeadScripts() );
345 $result_array['headitems'] = array_merge( $headItems, $css, $scripts );
348 if ( isset( $prop['headhtml'] ) ) {
349 $result_array['headhtml'] = $context->getOutput()->headElement( $context->getSkin() );
350 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'headhtml';
354 if ( isset( $prop['modules'] ) ) {
355 $result_array['modules'] = array_values( array_unique( $p_result->getModules() ) );
356 $result_array['modulescripts'] = array_values( array_unique( $p_result->getModuleScripts() ) );
357 $result_array['modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) );
358 // To be removed in 1.27
359 $result_array['modulemessages'] = array();
360 $this->setWarning( 'modulemessages is deprecated since MediaWiki 1.26' );
363 if ( isset( $prop['jsconfigvars'] ) ) {
364 $result_array['jsconfigvars'] =
365 ApiResult::addMetadataToResultVars( $p_result->getJsConfigVars() );
368 if ( isset( $prop['encodedjsconfigvars'] ) ) {
369 $result_array['encodedjsconfigvars'] = FormatJson::encode(
370 $p_result->getJsConfigVars(), false, FormatJson::ALL_OK
372 $result_array[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
375 if ( isset( $prop['modules'] ) &&
376 !isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
377 $this->setWarning( "Property 'modules' was set but not 'jsconfigvars' " .
378 "or 'encodedjsconfigvars'. Configuration variables are necessary " .
379 "for proper module usage." );
382 if ( isset( $prop['indicators'] ) ) {
383 $result_array['indicators'] = (array)$p_result->getIndicators();
384 ApiResult::setArrayType( $result_array['indicators'], 'BCkvp', 'name' );
387 if ( isset( $prop['iwlinks'] ) ) {
388 $result_array['iwlinks'] = $this->formatIWLinks( $p_result->getInterwikiLinks() );
391 if ( isset( $prop['wikitext'] ) ) {
392 $result_array['wikitext'] = $this->content->serialize( $format );
393 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext';
394 if ( !is_null( $this->pstContent ) ) {
395 $result_array['psttext'] = $this->pstContent->serialize( $format );
396 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'psttext';
399 if ( isset( $prop['properties'] ) ) {
400 $result_array['properties'] = (array)$p_result->getProperties();
401 ApiResult::setArrayType( $result_array['properties'], 'BCkvp', 'name' );
404 if ( isset( $prop['limitreportdata'] ) ) {
405 $result_array['limitreportdata'] =
406 $this->formatLimitReportData( $p_result->getLimitReportData() );
408 if ( isset( $prop['limitreporthtml'] ) ) {
409 $result_array['limitreporthtml'] = EditPage::getPreviewLimitReport( $p_result );
410 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'limitreporthtml';
413 if ( $params['generatexml'] ) {
414 if ( $this->content->getModel() != CONTENT_MODEL_WIKITEXT ) {
415 $this->dieUsage( "generatexml is only supported for wikitext content", "notwikitext" );
418 $wgParser->startExternalParse( $titleObj, $popts, Parser::OT_PREPROCESS );
419 $dom = $wgParser->preprocessToDom( $this->content->getNativeData() );
420 if ( is_callable( array( $dom, 'saveXML' ) ) ) {
421 $xml = $dom->saveXML();
422 } else {
423 $xml = $dom->__toString();
425 $result_array['parsetree'] = $xml;
426 $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsetree';
429 $result_mapping = array(
430 'redirects' => 'r',
431 'langlinks' => 'll',
432 'categories' => 'cl',
433 'links' => 'pl',
434 'templates' => 'tl',
435 'images' => 'img',
436 'externallinks' => 'el',
437 'iwlinks' => 'iw',
438 'sections' => 's',
439 'headitems' => 'hi',
440 'modules' => 'm',
441 'indicators' => 'ind',
442 'modulescripts' => 'm',
443 'modulestyles' => 'm',
444 'modulemessages' => 'm',
445 'properties' => 'pp',
446 'limitreportdata' => 'lr',
448 $this->setIndexedTagNames( $result_array, $result_mapping );
449 $result->addValue( null, $this->getModuleName(), $result_array );
453 * Constructs a ParserOptions object
455 * @param WikiPage $pageObj
456 * @param array $params
458 * @return ParserOptions
460 protected function makeParserOptions( WikiPage $pageObj, array $params ) {
462 $popts = $pageObj->makeParserOptions( $this->getContext() );
463 $popts->enableLimitReport( !$params['disablepp'] );
464 $popts->setIsPreview( $params['preview'] || $params['sectionpreview'] );
465 $popts->setIsSectionPreview( $params['sectionpreview'] );
466 $popts->setEditSection( !$params['disableeditsection'] );
468 return $popts;
472 * @param WikiPage $page
473 * @param ParserOptions $popts
474 * @param int $pageId
475 * @param bool $getWikitext
476 * @return ParserOutput
478 private function getParsedContent( WikiPage $page, $popts, $pageId = null, $getWikitext = false ) {
479 $this->content = $page->getContent( Revision::RAW ); //XXX: really raw?
481 if ( $this->section !== false && $this->content !== null ) {
482 $this->content = $this->getSectionContent(
483 $this->content,
484 !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getPrefixedText()
487 // Not cached (save or load)
488 return $this->content->getParserOutput( $page->getTitle(), null, $popts );
491 // Try the parser cache first
492 // getParserOutput will save to Parser cache if able
493 $pout = $page->getParserOutput( $popts );
494 if ( !$pout ) {
495 $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
497 if ( $getWikitext ) {
498 $this->content = $page->getContent( Revision::RAW );
501 return $pout;
505 * @param Content $content
506 * @param string $what Identifies the content in error messages, e.g. page title.
507 * @return Content|bool
509 private function getSectionContent( Content $content, $what ) {
510 // Not cached (save or load)
511 $section = $content->getSection( $this->section );
512 if ( $section === false ) {
513 $this->dieUsage( "There is no section {$this->section} in " . $what, 'nosuchsection' );
515 if ( $section === null ) {
516 $this->dieUsage( "Sections are not supported by " . $what, 'nosuchsection' );
517 $section = false;
520 return $section;
524 * This mimicks the behavior of EditPage in formatting a summary
526 * @param Title $title of the page being parsed
527 * @param Array $params the API parameters of the request
528 * @return Content|bool
530 private function formatSummary( $title, $params ) {
531 global $wgParser;
532 $summary = !is_null( $params['summary'] ) ? $params['summary'] : '';
533 $sectionTitle = !is_null( $params['sectiontitle'] ) ? $params['sectiontitle'] : '';
535 if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
536 if ( $sectionTitle !== '' ) {
537 $summary = $params['sectiontitle'];
539 if ( $summary !== '' ) {
540 $summary = wfMessage( 'newsectionsummary' )
541 ->rawParams( $wgParser->stripSectionName( $summary ) )
542 ->inContentLanguage()->text();
545 return Linker::formatComment( $summary, $title, $this->section === 'new' );
548 private function formatLangLinks( $links ) {
549 $result = array();
550 foreach ( $links as $link ) {
551 $entry = array();
552 $bits = explode( ':', $link, 2 );
553 $title = Title::newFromText( $link );
555 $entry['lang'] = $bits[0];
556 if ( $title ) {
557 $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
558 // localised language name in 'uselang' language
559 $entry['langname'] = Language::fetchLanguageName(
560 $title->getInterwiki(),
561 $this->getLanguage()->getCode()
564 // native language name
565 $entry['autonym'] = Language::fetchLanguageName( $title->getInterwiki() );
567 ApiResult::setContentValue( $entry, 'title', $bits[1] );
568 $result[] = $entry;
571 return $result;
574 private function formatCategoryLinks( $links ) {
575 $result = array();
577 if ( !$links ) {
578 return $result;
581 // Fetch hiddencat property
582 $lb = new LinkBatch;
583 $lb->setArray( array( NS_CATEGORY => $links ) );
584 $db = $this->getDB();
585 $res = $db->select( array( 'page', 'page_props' ),
586 array( 'page_title', 'pp_propname' ),
587 $lb->constructSet( 'page', $db ),
588 __METHOD__,
589 array(),
590 array( 'page_props' => array(
591 'LEFT JOIN', array( 'pp_propname' => 'hiddencat', 'pp_page = page_id' )
594 $hiddencats = array();
595 foreach ( $res as $row ) {
596 $hiddencats[$row->page_title] = isset( $row->pp_propname );
599 foreach ( $links as $link => $sortkey ) {
600 $entry = array();
601 $entry['sortkey'] = $sortkey;
602 ApiResult::setContentValue( $entry, 'category', $link );
603 if ( !isset( $hiddencats[$link] ) ) {
604 $entry['missing'] = true;
605 } elseif ( $hiddencats[$link] ) {
606 $entry['hidden'] = true;
608 $result[] = $entry;
611 return $result;
614 private function categoriesHtml( $categories ) {
615 $context = $this->getContext();
616 $context->getOutput()->addCategoryLinks( $categories );
618 return $context->getSkin()->getCategories();
621 private function formatLinks( $links ) {
622 $result = array();
623 foreach ( $links as $ns => $nslinks ) {
624 foreach ( $nslinks as $title => $id ) {
625 $entry = array();
626 $entry['ns'] = $ns;
627 ApiResult::setContentValue( $entry, 'title', Title::makeTitle( $ns, $title )->getFullText() );
628 $entry['exists'] = $id != 0;
629 $result[] = $entry;
633 return $result;
636 private function formatIWLinks( $iw ) {
637 $result = array();
638 foreach ( $iw as $prefix => $titles ) {
639 foreach ( array_keys( $titles ) as $title ) {
640 $entry = array();
641 $entry['prefix'] = $prefix;
643 $title = Title::newFromText( "{$prefix}:{$title}" );
644 if ( $title ) {
645 $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
648 ApiResult::setContentValue( $entry, 'title', $title->getFullText() );
649 $result[] = $entry;
653 return $result;
656 private function formatHeadItems( $headItems ) {
657 $result = array();
658 foreach ( $headItems as $tag => $content ) {
659 $entry = array();
660 $entry['tag'] = $tag;
661 ApiResult::setContentValue( $entry, 'content', $content );
662 $result[] = $entry;
665 return $result;
668 private function formatCss( $css ) {
669 $result = array();
670 foreach ( $css as $file => $link ) {
671 $entry = array();
672 $entry['file'] = $file;
673 ApiResult::setContentValue( $entry, 'link', $link );
674 $result[] = $entry;
677 return $result;
680 private function formatLimitReportData( $limitReportData ) {
681 $result = array();
682 $apiResult = $this->getResult();
684 foreach ( $limitReportData as $name => $value ) {
685 $entry = array();
686 $entry['name'] = $name;
687 if ( !is_array( $value ) ) {
688 $value = array( $value );
690 ApiResult::setIndexedTagNameRecursive( $value, 'param' );
691 $entry = array_merge( $entry, $value );
692 $result[] = $entry;
695 return $result;
698 private function setIndexedTagNames( &$array, $mapping ) {
699 foreach ( $mapping as $key => $name ) {
700 if ( isset( $array[$key] ) ) {
701 ApiResult::setIndexedTagName( $array[$key], $name );
706 public function getAllowedParams() {
707 return array(
708 'title' => null,
709 'text' => array(
710 ApiBase::PARAM_TYPE => 'text',
712 'summary' => null,
713 'page' => null,
714 'pageid' => array(
715 ApiBase::PARAM_TYPE => 'integer',
717 'redirects' => false,
718 'oldid' => array(
719 ApiBase::PARAM_TYPE => 'integer',
721 'prop' => array(
722 ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|' .
723 'images|externallinks|sections|revid|displaytitle|iwlinks|properties',
724 ApiBase::PARAM_ISMULTI => true,
725 ApiBase::PARAM_TYPE => array(
726 'text',
727 'langlinks',
728 'categories',
729 'categorieshtml',
730 'links',
731 'templates',
732 'images',
733 'externallinks',
734 'sections',
735 'revid',
736 'displaytitle',
737 'headitems',
738 'headhtml',
739 'modules',
740 'jsconfigvars',
741 'encodedjsconfigvars',
742 'indicators',
743 'iwlinks',
744 'wikitext',
745 'properties',
746 'limitreportdata',
747 'limitreporthtml',
749 ApiBase::PARAM_HELP_MSG_PER_VALUE => array(),
751 'pst' => false,
752 'onlypst' => false,
753 'effectivelanglinks' => false,
754 'section' => null,
755 'sectiontitle' => array(
756 ApiBase::PARAM_TYPE => 'string',
758 'disablepp' => false,
759 'disableeditsection' => false,
760 'generatexml' => array(
761 ApiBase::PARAM_DFLT => false,
762 ApiBase::PARAM_HELP_MSG => array(
763 'apihelp-parse-param-generatexml', CONTENT_MODEL_WIKITEXT
766 'preview' => false,
767 'sectionpreview' => false,
768 'disabletoc' => false,
769 'contentformat' => array(
770 ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(),
772 'contentmodel' => array(
773 ApiBase::PARAM_TYPE => ContentHandler::getContentModels(),
778 protected function getExamplesMessages() {
779 return array(
780 'action=parse&page=Project:Sandbox'
781 => 'apihelp-parse-example-page',
782 'action=parse&text={{Project:Sandbox}}&contentmodel=wikitext'
783 => 'apihelp-parse-example-text',
784 'action=parse&text={{PAGENAME}}&title=Test'
785 => 'apihelp-parse-example-texttitle',
786 'action=parse&summary=Some+[[link]]&prop='
787 => 'apihelp-parse-example-summary',
791 public function getHelpUrls() {
792 return 'https://www.mediawiki.org/wiki/API:Parsing_wikitext#parse';