MediaWiki  REL1_22
ApiParse.php
Go to the documentation of this file.
00001 <?php
00028 class ApiParse extends ApiBase {
00029 
00031     private $section = null;
00032 
00034     private $content = null;
00035 
00037     private $pstContent = null;
00038 
00039     public function execute() {
00040         // The data is hot but user-dependent, like page views, so we set vary cookies
00041         $this->getMain()->setCacheMode( 'anon-public-user-private' );
00042 
00043         // Get parameters
00044         $params = $this->extractRequestParams();
00045         $text = $params['text'];
00046         $title = $params['title'];
00047         if ( $title === null ) {
00048             $titleProvided = false;
00049             // A title is needed for parsing, so arbitrarily choose one
00050             $title = 'API';
00051         } else {
00052             $titleProvided = true;
00053         }
00054 
00055         $page = $params['page'];
00056         $pageid = $params['pageid'];
00057         $oldid = $params['oldid'];
00058 
00059         $model = $params['contentmodel'];
00060         $format = $params['contentformat'];
00061 
00062         if ( !is_null( $page ) && ( !is_null( $text ) || $titleProvided ) ) {
00063             $this->dieUsage( 'The page parameter cannot be used together with the text and title parameters', 'params' );
00064         }
00065 
00066         $prop = array_flip( $params['prop'] );
00067 
00068         if ( isset( $params['section'] ) ) {
00069             $this->section = $params['section'];
00070         } else {
00071             $this->section = false;
00072         }
00073 
00074         // The parser needs $wgTitle to be set, apparently the
00075         // $title parameter in Parser::parse isn't enough *sigh*
00076         // TODO: Does this still need $wgTitle?
00077         global $wgParser, $wgTitle;
00078 
00079         // Currently unnecessary, code to act as a safeguard against any change in current behavior of uselang
00080         $oldLang = null;
00081         if ( isset( $params['uselang'] ) && $params['uselang'] != $this->getContext()->getLanguage()->getCode() ) {
00082             $oldLang = $this->getContext()->getLanguage(); // Backup language
00083             $this->getContext()->setLanguage( Language::factory( $params['uselang'] ) );
00084         }
00085 
00086         $redirValues = null;
00087 
00088         // Return result
00089         $result = $this->getResult();
00090 
00091         if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
00092             if ( !is_null( $oldid ) ) {
00093                 // Don't use the parser cache
00094                 $rev = Revision::newFromID( $oldid );
00095                 if ( !$rev ) {
00096                     $this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
00097                 }
00098                 if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
00099                     $this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
00100                 }
00101 
00102                 $titleObj = $rev->getTitle();
00103                 $wgTitle = $titleObj;
00104                 $pageObj = WikiPage::factory( $titleObj );
00105                 $popts = $this->makeParserOptions( $pageObj, $params );
00106 
00107                 // If for some reason the "oldid" is actually the current revision, it may be cached
00108                 if ( $rev->isCurrent() ) {
00109                     // May get from/save to parser cache
00110                     $p_result = $this->getParsedContent( $pageObj, $popts,
00111                         $pageid, isset( $prop['wikitext'] ) );
00112                 } else { // This is an old revision, so get the text differently
00113                     $this->content = $rev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
00114 
00115                     if ( $this->section !== false ) {
00116                         $this->content = $this->getSectionContent( $this->content, 'r' . $rev->getId() );
00117                     }
00118 
00119                     // Should we save old revision parses to the parser cache?
00120                     $p_result = $this->content->getParserOutput( $titleObj, $rev->getId(), $popts );
00121                 }
00122             } else { // Not $oldid, but $pageid or $page
00123                 if ( $params['redirects'] ) {
00124                     $reqParams = array(
00125                         'action' => 'query',
00126                         'redirects' => '',
00127                     );
00128                     if ( !is_null ( $pageid ) ) {
00129                         $reqParams['pageids'] = $pageid;
00130                     } else { // $page
00131                         $reqParams['titles'] = $page;
00132                     }
00133                     $req = new FauxRequest( $reqParams );
00134                     $main = new ApiMain( $req );
00135                     $main->execute();
00136                     $data = $main->getResultData();
00137                     $redirValues = isset( $data['query']['redirects'] )
00138                         ? $data['query']['redirects']
00139                         : array();
00140                     $to = $page;
00141                     foreach ( (array)$redirValues as $r ) {
00142                         $to = $r['to'];
00143                     }
00144                     $pageParams = array( 'title' => $to );
00145                 } elseif ( !is_null( $pageid ) ) {
00146                     $pageParams = array( 'pageid' => $pageid );
00147                 } else { // $page
00148                     $pageParams = array( 'title' => $page );
00149                 }
00150 
00151                 $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' );
00152                 $titleObj = $pageObj->getTitle();
00153                 if ( !$titleObj || !$titleObj->exists() ) {
00154                     $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
00155                 }
00156                 $wgTitle = $titleObj;
00157 
00158                 if ( isset( $prop['revid'] ) ) {
00159                     $oldid = $pageObj->getLatest();
00160                 }
00161 
00162                 $popts = $this->makeParserOptions( $pageObj, $params );
00163 
00164                 // Potentially cached
00165                 $p_result = $this->getParsedContent( $pageObj, $popts, $pageid,
00166                     isset( $prop['wikitext'] ) );
00167             }
00168         } else { // Not $oldid, $pageid, $page. Hence based on $text
00169             $titleObj = Title::newFromText( $title );
00170             if ( !$titleObj || $titleObj->isExternal() ) {
00171                 $this->dieUsageMsg( array( 'invalidtitle', $title ) );
00172             }
00173             if ( !$titleObj->canExist() ) {
00174                 $this->dieUsage( "Namespace doesn't allow actual pages", 'pagecannotexist' );
00175             }
00176             $wgTitle = $titleObj;
00177             $pageObj = WikiPage::factory( $titleObj );
00178 
00179             $popts = $this->makeParserOptions( $pageObj, $params );
00180 
00181             if ( is_null( $text ) ) {
00182                 if ( $titleProvided && ( $prop || $params['generatexml'] ) ) {
00183                     $this->setWarning(
00184                         "'title' used without 'text', and parsed page properties were requested " .
00185                         "(did you mean to use 'page' instead of 'title'?)"
00186                     );
00187                 }
00188                 // Prevent warning from ContentHandler::makeContent()
00189                 $text = '';
00190             }
00191 
00192             // If we are parsing text, do not use the content model of the default
00193             // API title, but default to wikitext to keep BC.
00194             if ( !$titleProvided && is_null( $model ) ) {
00195                 $model = CONTENT_MODEL_WIKITEXT;
00196                 $this->setWarning( "No 'title' or 'contentmodel' was given, assuming $model." );
00197             }
00198 
00199             try {
00200                 $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
00201             } catch ( MWContentSerializationException $ex ) {
00202                 $this->dieUsage( $ex->getMessage(), 'parseerror' );
00203             }
00204 
00205             if ( $this->section !== false ) {
00206                 $this->content = $this->getSectionContent( $this->content, $titleObj->getText() );
00207             }
00208 
00209             if ( $params['pst'] || $params['onlypst'] ) {
00210                 $this->pstContent = $this->content->preSaveTransform( $titleObj, $this->getUser(), $popts );
00211             }
00212             if ( $params['onlypst'] ) {
00213                 // Build a result and bail out
00214                 $result_array = array();
00215                 $result_array['text'] = array();
00216                 ApiResult::setContent( $result_array['text'], $this->pstContent->serialize( $format ) );
00217                 if ( isset( $prop['wikitext'] ) ) {
00218                     $result_array['wikitext'] = array();
00219                     ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
00220                 }
00221                 $result->addValue( null, $this->getModuleName(), $result_array );
00222                 return;
00223             }
00224 
00225             // Not cached (save or load)
00226             if ( $params['pst'] ) {
00227                 $p_result = $this->pstContent->getParserOutput( $titleObj, null, $popts );
00228             } else {
00229                 $p_result = $this->content->getParserOutput( $titleObj, null, $popts );
00230             }
00231         }
00232 
00233         $result_array = array();
00234 
00235         $result_array['title'] = $titleObj->getPrefixedText();
00236 
00237         if ( !is_null( $oldid ) ) {
00238             $result_array['revid'] = intval( $oldid );
00239         }
00240 
00241         if ( $params['redirects'] && !is_null( $redirValues ) ) {
00242             $result_array['redirects'] = $redirValues;
00243         }
00244 
00245         if ( isset( $prop['text'] ) ) {
00246             $result_array['text'] = array();
00247             ApiResult::setContent( $result_array['text'], $p_result->getText() );
00248         }
00249 
00250         if ( !is_null( $params['summary'] ) ) {
00251             $result_array['parsedsummary'] = array();
00252             ApiResult::setContent( $result_array['parsedsummary'], Linker::formatComment( $params['summary'], $titleObj ) );
00253         }
00254 
00255         if ( isset( $prop['langlinks'] ) || isset( $prop['languageshtml'] ) ) {
00256             $langlinks = $p_result->getLanguageLinks();
00257 
00258             if ( $params['effectivelanglinks'] ) {
00259                 // Link flags are ignored for now, but may in the future be
00260                 // included in the result.
00261                 $linkFlags = array();
00262                 wfRunHooks( 'LanguageLinks', array( $titleObj, &$langlinks, &$linkFlags ) );
00263             }
00264         } else {
00265             $langlinks = false;
00266         }
00267 
00268         if ( isset( $prop['langlinks'] ) ) {
00269             $result_array['langlinks'] = $this->formatLangLinks( $langlinks );
00270         }
00271         if ( isset( $prop['languageshtml'] ) ) {
00272             $languagesHtml = $this->languagesHtml( $langlinks );
00273 
00274             $result_array['languageshtml'] = array();
00275             ApiResult::setContent( $result_array['languageshtml'], $languagesHtml );
00276         }
00277         if ( isset( $prop['categories'] ) ) {
00278             $result_array['categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
00279         }
00280         if ( isset( $prop['categorieshtml'] ) ) {
00281             $categoriesHtml = $this->categoriesHtml( $p_result->getCategories() );
00282             $result_array['categorieshtml'] = array();
00283             ApiResult::setContent( $result_array['categorieshtml'], $categoriesHtml );
00284         }
00285         if ( isset( $prop['links'] ) ) {
00286             $result_array['links'] = $this->formatLinks( $p_result->getLinks() );
00287         }
00288         if ( isset( $prop['templates'] ) ) {
00289             $result_array['templates'] = $this->formatLinks( $p_result->getTemplates() );
00290         }
00291         if ( isset( $prop['images'] ) ) {
00292             $result_array['images'] = array_keys( $p_result->getImages() );
00293         }
00294         if ( isset( $prop['externallinks'] ) ) {
00295             $result_array['externallinks'] = array_keys( $p_result->getExternalLinks() );
00296         }
00297         if ( isset( $prop['sections'] ) ) {
00298             $result_array['sections'] = $p_result->getSections();
00299         }
00300 
00301         if ( isset( $prop['displaytitle'] ) ) {
00302             $result_array['displaytitle'] = $p_result->getDisplayTitle() ?
00303                             $p_result->getDisplayTitle() :
00304                             $titleObj->getPrefixedText();
00305         }
00306 
00307         if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) {
00308             $context = $this->getContext();
00309             $context->setTitle( $titleObj );
00310             $context->getOutput()->addParserOutputNoText( $p_result );
00311 
00312             if ( isset( $prop['headitems'] ) ) {
00313                 $headItems = $this->formatHeadItems( $p_result->getHeadItems() );
00314 
00315                 $css = $this->formatCss( $context->getOutput()->buildCssLinksArray() );
00316 
00317                 $scripts = array( $context->getOutput()->getHeadScripts() );
00318 
00319                 $result_array['headitems'] = array_merge( $headItems, $css, $scripts );
00320             }
00321 
00322             if ( isset( $prop['headhtml'] ) ) {
00323                 $result_array['headhtml'] = array();
00324                 ApiResult::setContent( $result_array['headhtml'], $context->getOutput()->headElement( $context->getSkin() ) );
00325             }
00326         }
00327 
00328         if ( isset( $prop['iwlinks'] ) ) {
00329             $result_array['iwlinks'] = $this->formatIWLinks( $p_result->getInterwikiLinks() );
00330         }
00331 
00332         if ( isset( $prop['wikitext'] ) ) {
00333             $result_array['wikitext'] = array();
00334             ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
00335             if ( !is_null( $this->pstContent ) ) {
00336                 $result_array['psttext'] = array();
00337                 ApiResult::setContent( $result_array['psttext'], $this->pstContent->serialize( $format ) );
00338             }
00339         }
00340         if ( isset( $prop['properties'] ) ) {
00341             $result_array['properties'] = $this->formatProperties( $p_result->getProperties() );
00342         }
00343 
00344         if ( $params['generatexml'] ) {
00345             if ( $this->content->getModel() != CONTENT_MODEL_WIKITEXT ) {
00346                 $this->dieUsage( "generatexml is only supported for wikitext content", "notwikitext" );
00347             }
00348 
00349             $wgParser->startExternalParse( $titleObj, $popts, OT_PREPROCESS );
00350             $dom = $wgParser->preprocessToDom( $this->content->getNativeData() );
00351             if ( is_callable( array( $dom, 'saveXML' ) ) ) {
00352                 $xml = $dom->saveXML();
00353             } else {
00354                 $xml = $dom->__toString();
00355             }
00356             $result_array['parsetree'] = array();
00357             ApiResult::setContent( $result_array['parsetree'], $xml );
00358         }
00359 
00360         $result_mapping = array(
00361             'redirects' => 'r',
00362             'langlinks' => 'll',
00363             'categories' => 'cl',
00364             'links' => 'pl',
00365             'templates' => 'tl',
00366             'images' => 'img',
00367             'externallinks' => 'el',
00368             'iwlinks' => 'iw',
00369             'sections' => 's',
00370             'headitems' => 'hi',
00371             'properties' => 'pp',
00372         );
00373         $this->setIndexedTagNames( $result_array, $result_mapping );
00374         $result->addValue( null, $this->getModuleName(), $result_array );
00375 
00376         if ( !is_null( $oldLang ) ) {
00377             $this->getContext()->setLanguage( $oldLang ); // Reset language to $oldLang
00378         }
00379     }
00380 
00389     protected function makeParserOptions( WikiPage $pageObj, array $params ) {
00390         wfProfileIn( __METHOD__ );
00391 
00392         $popts = $pageObj->makeParserOptions( $this->getContext() );
00393         $popts->enableLimitReport( !$params['disablepp'] );
00394         $popts->setIsPreview( $params['preview'] || $params['sectionpreview'] );
00395         $popts->setIsSectionPreview( $params['sectionpreview'] );
00396 
00397         wfProfileOut( __METHOD__ );
00398         return $popts;
00399     }
00400 
00408     private function getParsedContent( WikiPage $page, $popts, $pageId = null, $getWikitext = false ) {
00409         $this->content = $page->getContent( Revision::RAW ); //XXX: really raw?
00410 
00411         if ( $this->section !== false && $this->content !== null ) {
00412             $this->content = $this->getSectionContent(
00413                 $this->content,
00414                 !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText() );
00415 
00416             // Not cached (save or load)
00417             return $this->content->getParserOutput( $page->getTitle(), null, $popts );
00418         } else {
00419             // Try the parser cache first
00420             // getParserOutput will save to Parser cache if able
00421             $pout = $page->getParserOutput( $popts );
00422             if ( !$pout ) {
00423                 $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
00424             }
00425             if ( $getWikitext ) {
00426                 $this->content = $page->getContent( Revision::RAW );
00427             }
00428             return $pout;
00429         }
00430     }
00431 
00432     private function getSectionContent( Content $content, $what ) {
00433         // Not cached (save or load)
00434         $section = $content->getSection( $this->section );
00435         if ( $section === false ) {
00436             $this->dieUsage( "There is no section {$this->section} in " . $what, 'nosuchsection' );
00437         }
00438         if ( $section === null ) {
00439             $this->dieUsage( "Sections are not supported by " . $what, 'nosuchsection' );
00440             $section = false;
00441         }
00442         return $section;
00443     }
00444 
00445     private function formatLangLinks( $links ) {
00446         $result = array();
00447         foreach ( $links as $link ) {
00448             $entry = array();
00449             $bits = explode( ':', $link, 2 );
00450             $title = Title::newFromText( $link );
00451 
00452             $entry['lang'] = $bits[0];
00453             if ( $title ) {
00454                 $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
00455             }
00456             ApiResult::setContent( $entry, $bits[1] );
00457             $result[] = $entry;
00458         }
00459         return $result;
00460     }
00461 
00462     private function formatCategoryLinks( $links ) {
00463         $result = array();
00464         foreach ( $links as $link => $sortkey ) {
00465             $entry = array();
00466             $entry['sortkey'] = $sortkey;
00467             ApiResult::setContent( $entry, $link );
00468             $result[] = $entry;
00469         }
00470         return $result;
00471     }
00472 
00473     private function categoriesHtml( $categories ) {
00474         $context = $this->getContext();
00475         $context->getOutput()->addCategoryLinks( $categories );
00476         return $context->getSkin()->getCategories();
00477     }
00478 
00485     private function languagesHtml( $languages ) {
00486         wfDeprecated( __METHOD__, '1.18' );
00487 
00488         global $wgContLang, $wgHideInterlanguageLinks;
00489 
00490         if ( $wgHideInterlanguageLinks || count( $languages ) == 0 ) {
00491             return '';
00492         }
00493 
00494         $s = htmlspecialchars( wfMessage( 'otherlanguages' )->text() . wfMessage( 'colon-separator' )->text() );
00495 
00496         $langs = array();
00497         foreach ( $languages as $l ) {
00498             $nt = Title::newFromText( $l );
00499             $text = Language::fetchLanguageName( $nt->getInterwiki() );
00500 
00501             $langs[] = Html::element( 'a',
00502                 array( 'href' => $nt->getFullURL(), 'title' => $nt->getText(), 'class' => 'external' ),
00503                 $text == '' ? $l : $text );
00504         }
00505 
00506         $s .= implode( wfMessage( 'pipe-separator' )->escaped(), $langs );
00507 
00508         if ( $wgContLang->isRTL() ) {
00509             $s = Html::rawElement( 'span', array( 'dir' => 'LTR' ), $s );
00510         }
00511 
00512         return $s;
00513     }
00514 
00515     private function formatLinks( $links ) {
00516         $result = array();
00517         foreach ( $links as $ns => $nslinks ) {
00518             foreach ( $nslinks as $title => $id ) {
00519                 $entry = array();
00520                 $entry['ns'] = $ns;
00521                 ApiResult::setContent( $entry, Title::makeTitle( $ns, $title )->getFullText() );
00522                 if ( $id != 0 ) {
00523                     $entry['exists'] = '';
00524                 }
00525                 $result[] = $entry;
00526             }
00527         }
00528         return $result;
00529     }
00530 
00531     private function formatIWLinks( $iw ) {
00532         $result = array();
00533         foreach ( $iw as $prefix => $titles ) {
00534             foreach ( array_keys( $titles ) as $title ) {
00535                 $entry = array();
00536                 $entry['prefix'] = $prefix;
00537 
00538                 $title = Title::newFromText( "{$prefix}:{$title}" );
00539                 if ( $title ) {
00540                     $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
00541                 }
00542 
00543                 ApiResult::setContent( $entry, $title->getFullText() );
00544                 $result[] = $entry;
00545             }
00546         }
00547         return $result;
00548     }
00549 
00550     private function formatHeadItems( $headItems ) {
00551         $result = array();
00552         foreach ( $headItems as $tag => $content ) {
00553             $entry = array();
00554             $entry['tag'] = $tag;
00555             ApiResult::setContent( $entry, $content );
00556             $result[] = $entry;
00557         }
00558         return $result;
00559     }
00560 
00561     private function formatProperties( $properties ) {
00562         $result = array();
00563         foreach ( $properties as $name => $value ) {
00564             $entry = array();
00565             $entry['name'] = $name;
00566             ApiResult::setContent( $entry, $value );
00567             $result[] = $entry;
00568         }
00569         return $result;
00570     }
00571 
00572     private function formatCss( $css ) {
00573         $result = array();
00574         foreach ( $css as $file => $link ) {
00575             $entry = array();
00576             $entry['file'] = $file;
00577             ApiResult::setContent( $entry, $link );
00578             $result[] = $entry;
00579         }
00580         return $result;
00581     }
00582 
00583     private function setIndexedTagNames( &$array, $mapping ) {
00584         foreach ( $mapping as $key => $name ) {
00585             if ( isset( $array[$key] ) ) {
00586                 $this->getResult()->setIndexedTagName( $array[$key], $name );
00587             }
00588         }
00589     }
00590 
00591     public function getAllowedParams() {
00592         return array(
00593             'title' => null,
00594             'text' => null,
00595             'summary' => null,
00596             'page' => null,
00597             'pageid' => array(
00598                 ApiBase::PARAM_TYPE => 'integer',
00599             ),
00600             'redirects' => false,
00601             'oldid' => array(
00602                 ApiBase::PARAM_TYPE => 'integer',
00603             ),
00604             'prop' => array(
00605                 ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|images|externallinks|sections|revid|displaytitle|iwlinks|properties',
00606                 ApiBase::PARAM_ISMULTI => true,
00607                 ApiBase::PARAM_TYPE => array(
00608                     'text',
00609                     'langlinks',
00610                     'languageshtml',
00611                     'categories',
00612                     'categorieshtml',
00613                     'links',
00614                     'templates',
00615                     'images',
00616                     'externallinks',
00617                     'sections',
00618                     'revid',
00619                     'displaytitle',
00620                     'headitems',
00621                     'headhtml',
00622                     'iwlinks',
00623                     'wikitext',
00624                     'properties',
00625                 )
00626             ),
00627             'pst' => false,
00628             'onlypst' => false,
00629             'effectivelanglinks' => false,
00630             'uselang' => null,
00631             'section' => null,
00632             'disablepp' => false,
00633             'generatexml' => false,
00634             'preview' => false,
00635             'sectionpreview' => false,
00636             'contentformat' => array(
00637                 ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(),
00638             ),
00639             'contentmodel' => array(
00640                 ApiBase::PARAM_TYPE => ContentHandler::getContentModels(),
00641             )
00642         );
00643     }
00644 
00645     public function getParamDescription() {
00646         $p = $this->getModulePrefix();
00647         $wikitext = CONTENT_MODEL_WIKITEXT;
00648         return array(
00649             'text' => "Text to parse. Use {$p}title or {$p}contentmodel to control the content model",
00650             'summary' => 'Summary to parse',
00651             'redirects' => "If the {$p}page or the {$p}pageid parameter is set to a redirect, resolve it",
00652             'title' => "Title of page the text belongs to. " .
00653                 "If omitted, \"API\" is used as the title with content model $wikitext",
00654             'page' => "Parse the content of this page. Cannot be used together with {$p}text and {$p}title",
00655             'pageid' => "Parse the content of this page. Overrides {$p}page",
00656             'oldid' => "Parse the content of this revision. Overrides {$p}page and {$p}pageid",
00657             'prop' => array(
00658                 'Which pieces of information to get',
00659                 ' text           - Gives the parsed text of the wikitext',
00660                 ' langlinks      - Gives the language links in the parsed wikitext',
00661                 ' categories     - Gives the categories in the parsed wikitext',
00662                 ' categorieshtml - Gives the HTML version of the categories',
00663                 ' languageshtml  - Gives the HTML version of the language links',
00664                 ' links          - Gives the internal links in the parsed wikitext',
00665                 ' templates      - Gives the templates in the parsed wikitext',
00666                 ' images         - Gives the images in the parsed wikitext',
00667                 ' externallinks  - Gives the external links in the parsed wikitext',
00668                 ' sections       - Gives the sections in the parsed wikitext',
00669                 ' revid          - Adds the revision ID of the parsed page',
00670                 ' displaytitle   - Adds the title of the parsed wikitext',
00671                 ' headitems      - Gives items to put in the <head> of the page',
00672                 ' headhtml       - Gives parsed <head> of the page',
00673                 ' iwlinks        - Gives interwiki links in the parsed wikitext',
00674                 ' wikitext       - Gives the original wikitext that was parsed',
00675                 ' properties     - Gives various properties defined in the parsed wikitext',
00676             ),
00677             'effectivelanglinks' => array(
00678                 'Includes language links supplied by extensions',
00679                 '(for use with prop=langlinks|languageshtml)',
00680             ),
00681             'pst' => array(
00682                 'Do a pre-save transform on the input before parsing it',
00683                 "Only valid when used with {$p}text",
00684             ),
00685             'onlypst' => array(
00686                 'Do a pre-save transform (PST) on the input, but don\'t parse it',
00687                 'Returns the same wikitext, after a PST has been applied.',
00688                 "Only valid when used with {$p}text",
00689             ),
00690             'uselang' => 'Which language to parse the request in',
00691             'section' => 'Only retrieve the content of this section number',
00692             'disablepp' => 'Disable the PP Report from the parser output',
00693             'generatexml' => "Generate XML parse tree (requires contentmodel=$wikitext)",
00694             'preview' => 'Parse in preview mode',
00695             'sectionpreview' => 'Parse in section preview mode (enables preview mode too)',
00696             'contentformat' => array(
00697                 'Content serialization format used for the input text',
00698                 "Only valid when used with {$p}text",
00699             ),
00700             'contentmodel' => array(
00701                 "Content model of the input text. Default is the model of the " .
00702                 "specified ${p}title, or $wikitext if ${p}title is not specified",
00703                 "Only valid when used with {$p}text",
00704             ),
00705         );
00706     }
00707 
00708     public function getDescription() {
00709         $p = $this->getModulePrefix();
00710         return array(
00711             'Parses content and returns parser output',
00712             'See the various prop-Modules of action=query to get information from the current version of a page',
00713             'There are several ways to specify the text to parse:',
00714             "1) Specify a page or revision, using {$p}page, {$p}pageid, or {$p}oldid.",
00715             "2) Specify content explicitly, using {$p}text, {$p}title, and {$p}contentmodel.",
00716             "3) Specify only a summary to parse. {$p}prop should be given an empty value.",
00717         );
00718     }
00719 
00720     public function getPossibleErrors() {
00721         return array_merge( parent::getPossibleErrors(), array(
00722             array( 'code' => 'params', 'info' => 'The page parameter cannot be used together with the text and title parameters' ),
00723             array( 'code' => 'missingrev', 'info' => 'There is no revision ID oldid' ),
00724             array( 'code' => 'permissiondenied', 'info' => 'You don\'t have permission to view deleted revisions' ),
00725             array( 'code' => 'missingtitle', 'info' => 'The page you specified doesn\'t exist' ),
00726             array( 'code' => 'nosuchsection', 'info' => 'There is no section sectionnumber in page' ),
00727             array( 'nosuchpageid' ),
00728             array( 'invalidtitle', 'title' ),
00729             array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
00730             array( 'code' => 'notwikitext', 'info' => 'The requested operation is only supported on wikitext content.' ),
00731             array( 'code' => 'pagecannotexist', 'info' => "Namespace doesn't allow actual pages" ),
00732         ) );
00733     }
00734 
00735     public function getExamples() {
00736         return array(
00737             'api.php?action=parse&page=Project:Sandbox' => 'Parse a page',
00738             'api.php?action=parse&text={{Project:Sandbox}}' => 'Parse wikitext',
00739             'api.php?action=parse&text={{PAGENAME}}&title=Test' => 'Parse wikitext, specifying the page title',
00740             'api.php?action=parse&summary=Some+[[link]]&prop=' => 'Parse a summary',
00741         );
00742     }
00743 
00744     public function getHelpUrls() {
00745         return 'https://www.mediawiki.org/wiki/API:Parsing_wikitext#parse';
00746     }
00747 }