Merge "PLURAL support for list lengths in default-skin-not-found"
[lhc/web/wiklou.git] / includes / api / ApiParse.php
1 <?php
2 /**
3 * Created on Dec 01, 2007
4 *
5 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
6 *
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.
11 *
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.
16 *
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
21 *
22 * @file
23 */
24
25 /**
26 * @ingroup API
27 */
28 class ApiParse extends ApiBase {
29
30 /** @var string $section */
31 private $section = null;
32
33 /** @var Content $content */
34 private $content = null;
35
36 /** @var Content $pstContent */
37 private $pstContent = null;
38
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' );
42
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;
53 }
54
55 $page = $params['page'];
56 $pageid = $params['pageid'];
57 $oldid = $params['oldid'];
58
59 $model = $params['contentmodel'];
60 $format = $params['contentformat'];
61
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'
66 );
67 }
68
69 $prop = array_flip( $params['prop'] );
70
71 if ( isset( $params['section'] ) ) {
72 $this->section = $params['section'];
73 if ( !preg_match( '/^((T-)?\d+|new)$/', $this->section ) ) {
74 $this->dieUsage( "The section parameter must be a valid section id or 'new'", "invalidsection" );
75 }
76 } else {
77 $this->section = false;
78 }
79
80 // The parser needs $wgTitle to be set, apparently the
81 // $title parameter in Parser::parse isn't enough *sigh*
82 // TODO: Does this still need $wgTitle?
83 global $wgParser, $wgTitle;
84
85 $redirValues = null;
86
87 // Return result
88 $result = $this->getResult();
89
90 if ( !is_null( $oldid ) || !is_null( $pageid ) || !is_null( $page ) ) {
91 if ( $this->section === 'new' ) {
92 $this->dieUsage( 'section=new cannot be combined with oldid, pageid or page parameters. Please use text', 'params' );
93 }
94 if ( !is_null( $oldid ) ) {
95 // Don't use the parser cache
96 $rev = Revision::newFromId( $oldid );
97 if ( !$rev ) {
98 $this->dieUsage( "There is no revision ID $oldid", 'missingrev' );
99 }
100 if ( !$rev->userCan( Revision::DELETED_TEXT, $this->getUser() ) ) {
101 $this->dieUsage( "You don't have permission to view deleted revisions", 'permissiondenied' );
102 }
103
104 $titleObj = $rev->getTitle();
105 $wgTitle = $titleObj;
106 $pageObj = WikiPage::factory( $titleObj );
107 $popts = $this->makeParserOptions( $pageObj, $params );
108
109 // If for some reason the "oldid" is actually the current revision, it may be cached
110 // Deliberately comparing $pageObj->getLatest() with $rev->getId(), rather than
111 // checking $rev->isCurrent(), because $pageObj is what actually ends up being used,
112 // and if its ->getLatest() is outdated, $rev->isCurrent() won't tell us that.
113 if ( $rev->getId() == $pageObj->getLatest() ) {
114 // May get from/save to parser cache
115 $p_result = $this->getParsedContent( $pageObj, $popts,
116 $pageid, isset( $prop['wikitext'] ) );
117 } else { // This is an old revision, so get the text differently
118 $this->content = $rev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
119
120 if ( $this->section !== false ) {
121 $this->content = $this->getSectionContent( $this->content, 'r' . $rev->getId() );
122 }
123
124 // Should we save old revision parses to the parser cache?
125 $p_result = $this->content->getParserOutput( $titleObj, $rev->getId(), $popts );
126 }
127 } else { // Not $oldid, but $pageid or $page
128 if ( $params['redirects'] ) {
129 $reqParams = array(
130 'action' => 'query',
131 'redirects' => '',
132 );
133 if ( !is_null( $pageid ) ) {
134 $reqParams['pageids'] = $pageid;
135 } else { // $page
136 $reqParams['titles'] = $page;
137 }
138 $req = new FauxRequest( $reqParams );
139 $main = new ApiMain( $req );
140 $main->execute();
141 $data = $main->getResultData();
142 $redirValues = isset( $data['query']['redirects'] )
143 ? $data['query']['redirects']
144 : array();
145 $to = $page;
146 foreach ( (array)$redirValues as $r ) {
147 $to = $r['to'];
148 }
149 $pageParams = array( 'title' => $to );
150 } elseif ( !is_null( $pageid ) ) {
151 $pageParams = array( 'pageid' => $pageid );
152 } else { // $page
153 $pageParams = array( 'title' => $page );
154 }
155
156 $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' );
157 $titleObj = $pageObj->getTitle();
158 if ( !$titleObj || !$titleObj->exists() ) {
159 $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' );
160 }
161 $wgTitle = $titleObj;
162
163 if ( isset( $prop['revid'] ) ) {
164 $oldid = $pageObj->getLatest();
165 }
166
167 $popts = $this->makeParserOptions( $pageObj, $params );
168
169 // Potentially cached
170 $p_result = $this->getParsedContent( $pageObj, $popts, $pageid,
171 isset( $prop['wikitext'] ) );
172 }
173 } else { // Not $oldid, $pageid, $page. Hence based on $text
174 $titleObj = Title::newFromText( $title );
175 if ( !$titleObj || $titleObj->isExternal() ) {
176 $this->dieUsageMsg( array( 'invalidtitle', $title ) );
177 }
178 $wgTitle = $titleObj;
179 if ( $titleObj->canExist() ) {
180 $pageObj = WikiPage::factory( $titleObj );
181 } else {
182 // Do like MediaWiki::initializeArticle()
183 $article = Article::newFromTitle( $titleObj, $this->getContext() );
184 $pageObj = $article->getPage();
185 }
186
187 $popts = $this->makeParserOptions( $pageObj, $params );
188 $textProvided = !is_null( $text );
189
190 if ( !$textProvided ) {
191 if ( $titleProvided && ( $prop || $params['generatexml'] ) ) {
192 $this->setWarning(
193 "'title' used without 'text', and parsed page properties were requested " .
194 "(did you mean to use 'page' instead of 'title'?)"
195 );
196 }
197 // Prevent warning from ContentHandler::makeContent()
198 $text = '';
199 }
200
201 // If we are parsing text, do not use the content model of the default
202 // API title, but default to wikitext to keep BC.
203 if ( $textProvided && !$titleProvided && is_null( $model ) ) {
204 $model = CONTENT_MODEL_WIKITEXT;
205 $this->setWarning( "No 'title' or 'contentmodel' was given, assuming $model." );
206 }
207
208 try {
209 $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
210 } catch ( MWContentSerializationException $ex ) {
211 $this->dieUsage( $ex->getMessage(), 'parseerror' );
212 }
213
214 if ( $this->section !== false ) {
215 if ( $this->section === 'new' ) {
216 // Insert the section title above the content.
217 if ( !is_null( $params['sectiontitle'] ) && $params['sectiontitle'] !== '' ) {
218 $this->content = $this->content->addSectionHeader( $params['sectiontitle'] );
219 }
220 } else {
221 $this->content = $this->getSectionContent( $this->content, $titleObj->getPrefixedText() );
222 }
223 }
224
225 if ( $params['pst'] || $params['onlypst'] ) {
226 $this->pstContent = $this->content->preSaveTransform( $titleObj, $this->getUser(), $popts );
227 }
228 if ( $params['onlypst'] ) {
229 // Build a result and bail out
230 $result_array = array();
231 $result_array['text'] = array();
232 ApiResult::setContent( $result_array['text'], $this->pstContent->serialize( $format ) );
233 if ( isset( $prop['wikitext'] ) ) {
234 $result_array['wikitext'] = array();
235 ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
236 }
237 if ( !is_null( $params['summary'] ) ||
238 ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
239 ) {
240 $result_array['parsedsummary'] = array();
241 ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
242 }
243
244 $result->addValue( null, $this->getModuleName(), $result_array );
245
246 return;
247 }
248
249 // Not cached (save or load)
250 if ( $params['pst'] ) {
251 $p_result = $this->pstContent->getParserOutput( $titleObj, null, $popts );
252 } else {
253 $p_result = $this->content->getParserOutput( $titleObj, null, $popts );
254 }
255 }
256
257 $result_array = array();
258
259 $result_array['title'] = $titleObj->getPrefixedText();
260
261 if ( !is_null( $oldid ) ) {
262 $result_array['revid'] = intval( $oldid );
263 }
264
265 if ( $params['redirects'] && !is_null( $redirValues ) ) {
266 $result_array['redirects'] = $redirValues;
267 }
268
269 if ( $params['disabletoc'] ) {
270 $p_result->setTOCEnabled( false );
271 }
272
273 if ( isset( $prop['text'] ) ) {
274 $result_array['text'] = array();
275 ApiResult::setContent( $result_array['text'], $p_result->getText() );
276 }
277
278 if ( !is_null( $params['summary'] ) ||
279 ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
280 ) {
281 $result_array['parsedsummary'] = array();
282 ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
283 }
284
285 if ( isset( $prop['langlinks'] ) ) {
286 $langlinks = $p_result->getLanguageLinks();
287
288 if ( $params['effectivelanglinks'] ) {
289 // Link flags are ignored for now, but may in the future be
290 // included in the result.
291 $linkFlags = array();
292 Hooks::run( 'LanguageLinks', array( $titleObj, &$langlinks, &$linkFlags ) );
293 }
294 } else {
295 $langlinks = false;
296 }
297
298 if ( isset( $prop['langlinks'] ) ) {
299 $result_array['langlinks'] = $this->formatLangLinks( $langlinks );
300 }
301 if ( isset( $prop['categories'] ) ) {
302 $result_array['categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
303 }
304 if ( isset( $prop['categorieshtml'] ) ) {
305 $categoriesHtml = $this->categoriesHtml( $p_result->getCategories() );
306 $result_array['categorieshtml'] = array();
307 ApiResult::setContent( $result_array['categorieshtml'], $categoriesHtml );
308 }
309 if ( isset( $prop['links'] ) ) {
310 $result_array['links'] = $this->formatLinks( $p_result->getLinks() );
311 }
312 if ( isset( $prop['templates'] ) ) {
313 $result_array['templates'] = $this->formatLinks( $p_result->getTemplates() );
314 }
315 if ( isset( $prop['images'] ) ) {
316 $result_array['images'] = array_keys( $p_result->getImages() );
317 }
318 if ( isset( $prop['externallinks'] ) ) {
319 $result_array['externallinks'] = array_keys( $p_result->getExternalLinks() );
320 }
321 if ( isset( $prop['sections'] ) ) {
322 $result_array['sections'] = $p_result->getSections();
323 }
324
325 if ( isset( $prop['displaytitle'] ) ) {
326 $result_array['displaytitle'] = $p_result->getDisplayTitle() ?
327 $p_result->getDisplayTitle() :
328 $titleObj->getPrefixedText();
329 }
330
331 if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) {
332 $context = $this->getContext();
333 $context->setTitle( $titleObj );
334 $context->getOutput()->addParserOutputMetadata( $p_result );
335
336 if ( isset( $prop['headitems'] ) ) {
337 $headItems = $this->formatHeadItems( $p_result->getHeadItems() );
338
339 $css = $this->formatCss( $context->getOutput()->buildCssLinksArray() );
340
341 $scripts = array( $context->getOutput()->getHeadScripts() );
342
343 $result_array['headitems'] = array_merge( $headItems, $css, $scripts );
344 }
345
346 if ( isset( $prop['headhtml'] ) ) {
347 $result_array['headhtml'] = array();
348 ApiResult::setContent(
349 $result_array['headhtml'],
350 $context->getOutput()->headElement( $context->getSkin() )
351 );
352 }
353 }
354
355 if ( isset( $prop['modules'] ) ) {
356 $result_array['modules'] = array_values( array_unique( $p_result->getModules() ) );
357 $result_array['modulescripts'] = array_values( array_unique( $p_result->getModuleScripts() ) );
358 $result_array['modulestyles'] = array_values( array_unique( $p_result->getModuleStyles() ) );
359 $result_array['modulemessages'] = array_values( array_unique( $p_result->getModuleMessages() ) );
360 }
361
362 if ( isset( $prop['indicators'] ) ) {
363 foreach ( $p_result->getIndicators() as $name => $content ) {
364 $indicator = array( 'name' => $name );
365 ApiResult::setContent( $indicator, $content );
366 $result_array['indicators'][] = $indicator;
367 }
368 }
369
370 if ( isset( $prop['iwlinks'] ) ) {
371 $result_array['iwlinks'] = $this->formatIWLinks( $p_result->getInterwikiLinks() );
372 }
373
374 if ( isset( $prop['wikitext'] ) ) {
375 $result_array['wikitext'] = array();
376 ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
377 if ( !is_null( $this->pstContent ) ) {
378 $result_array['psttext'] = array();
379 ApiResult::setContent( $result_array['psttext'], $this->pstContent->serialize( $format ) );
380 }
381 }
382 if ( isset( $prop['properties'] ) ) {
383 $result_array['properties'] = $this->formatProperties( $p_result->getProperties() );
384 }
385
386 if ( isset( $prop['limitreportdata'] ) ) {
387 $result_array['limitreportdata'] =
388 $this->formatLimitReportData( $p_result->getLimitReportData() );
389 }
390 if ( isset( $prop['limitreporthtml'] ) ) {
391 $limitreportHtml = EditPage::getPreviewLimitReport( $p_result );
392 $result_array['limitreporthtml'] = array();
393 ApiResult::setContent( $result_array['limitreporthtml'], $limitreportHtml );
394 }
395
396 if ( $params['generatexml'] ) {
397 if ( $this->content->getModel() != CONTENT_MODEL_WIKITEXT ) {
398 $this->dieUsage( "generatexml is only supported for wikitext content", "notwikitext" );
399 }
400
401 $wgParser->startExternalParse( $titleObj, $popts, Parser::OT_PREPROCESS );
402 $dom = $wgParser->preprocessToDom( $this->content->getNativeData() );
403 if ( is_callable( array( $dom, 'saveXML' ) ) ) {
404 $xml = $dom->saveXML();
405 } else {
406 $xml = $dom->__toString();
407 }
408 $result_array['parsetree'] = array();
409 ApiResult::setContent( $result_array['parsetree'], $xml );
410 }
411
412 $result_mapping = array(
413 'redirects' => 'r',
414 'langlinks' => 'll',
415 'categories' => 'cl',
416 'links' => 'pl',
417 'templates' => 'tl',
418 'images' => 'img',
419 'externallinks' => 'el',
420 'iwlinks' => 'iw',
421 'sections' => 's',
422 'headitems' => 'hi',
423 'modules' => 'm',
424 'indicators' => 'ind',
425 'modulescripts' => 'm',
426 'modulestyles' => 'm',
427 'modulemessages' => 'm',
428 'properties' => 'pp',
429 'limitreportdata' => 'lr',
430 );
431 $this->setIndexedTagNames( $result_array, $result_mapping );
432 $result->addValue( null, $this->getModuleName(), $result_array );
433 }
434
435 /**
436 * Constructs a ParserOptions object
437 *
438 * @param WikiPage $pageObj
439 * @param array $params
440 *
441 * @return ParserOptions
442 */
443 protected function makeParserOptions( WikiPage $pageObj, array $params ) {
444
445 $popts = $pageObj->makeParserOptions( $this->getContext() );
446 $popts->enableLimitReport( !$params['disablepp'] );
447 $popts->setIsPreview( $params['preview'] || $params['sectionpreview'] );
448 $popts->setIsSectionPreview( $params['sectionpreview'] );
449 $popts->setEditSection( !$params['disableeditsection'] );
450
451 return $popts;
452 }
453
454 /**
455 * @param WikiPage $page
456 * @param ParserOptions $popts
457 * @param int $pageId
458 * @param bool $getWikitext
459 * @return ParserOutput
460 */
461 private function getParsedContent( WikiPage $page, $popts, $pageId = null, $getWikitext = false ) {
462 $this->content = $page->getContent( Revision::RAW ); //XXX: really raw?
463
464 if ( $this->section !== false && $this->content !== null ) {
465 $this->content = $this->getSectionContent(
466 $this->content,
467 !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getPrefixedText()
468 );
469
470 // Not cached (save or load)
471 return $this->content->getParserOutput( $page->getTitle(), null, $popts );
472 }
473
474 // Try the parser cache first
475 // getParserOutput will save to Parser cache if able
476 $pout = $page->getParserOutput( $popts );
477 if ( !$pout ) {
478 $this->dieUsage( "There is no revision ID {$page->getLatest()}", 'missingrev' );
479 }
480 if ( $getWikitext ) {
481 $this->content = $page->getContent( Revision::RAW );
482 }
483
484 return $pout;
485 }
486
487 /**
488 * @param Content $content
489 * @param string $what Identifies the content in error messages, e.g. page title.
490 * @return Content|bool
491 */
492 private function getSectionContent( Content $content, $what ) {
493 // Not cached (save or load)
494 $section = $content->getSection( $this->section );
495 if ( $section === false ) {
496 $this->dieUsage( "There is no section {$this->section} in " . $what, 'nosuchsection' );
497 }
498 if ( $section === null ) {
499 $this->dieUsage( "Sections are not supported by " . $what, 'nosuchsection' );
500 $section = false;
501 }
502
503 return $section;
504 }
505
506 /**
507 * This mimicks the behavior of EditPage in formatting a summary
508 *
509 * @param Title $title of the page being parsed
510 * @param Array $params the API parameters of the request
511 * @return Content|bool
512 */
513 private function formatSummary( $title, $params ) {
514 global $wgParser;
515 $summary = !is_null( $params['summary'] ) ? $params['summary'] : '';
516 $sectionTitle = !is_null( $params['sectiontitle'] ) ? $params['sectiontitle'] : '';
517
518 if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
519 if( $sectionTitle !== '' ) {
520 $summary = $params['sectiontitle'];
521 }
522 if ( $summary !== '' ) {
523 $summary = wfMessage( 'newsectionsummary' )->rawParams( $wgParser->stripSectionName( $summary ) )
524 ->inContentLanguage()->text();
525 }
526 }
527 return Linker::formatComment( $summary, $title, $this->section === 'new' );
528 }
529
530 private function formatLangLinks( $links ) {
531 $result = array();
532 foreach ( $links as $link ) {
533 $entry = array();
534 $bits = explode( ':', $link, 2 );
535 $title = Title::newFromText( $link );
536
537 $entry['lang'] = $bits[0];
538 if ( $title ) {
539 $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
540 // localised language name in 'uselang' language
541 $entry['langname'] = Language::fetchLanguageName(
542 $title->getInterwiki(),
543 $this->getLanguage()->getCode()
544 );
545
546 // native language name
547 $entry['autonym'] = Language::fetchLanguageName( $title->getInterwiki() );
548 }
549 ApiResult::setContent( $entry, $bits[1] );
550 $result[] = $entry;
551 }
552
553 return $result;
554 }
555
556 private function formatCategoryLinks( $links ) {
557 $result = array();
558
559 if ( !$links ) {
560 return $result;
561 }
562
563 // Fetch hiddencat property
564 $lb = new LinkBatch;
565 $lb->setArray( array( NS_CATEGORY => $links ) );
566 $db = $this->getDB();
567 $res = $db->select( array( 'page', 'page_props' ),
568 array( 'page_title', 'pp_propname' ),
569 $lb->constructSet( 'page', $db ),
570 __METHOD__,
571 array(),
572 array( 'page_props' => array(
573 'LEFT JOIN', array( 'pp_propname' => 'hiddencat', 'pp_page = page_id' )
574 ) )
575 );
576 $hiddencats = array();
577 foreach ( $res as $row ) {
578 $hiddencats[$row->page_title] = isset( $row->pp_propname );
579 }
580
581 foreach ( $links as $link => $sortkey ) {
582 $entry = array();
583 $entry['sortkey'] = $sortkey;
584 ApiResult::setContent( $entry, $link );
585 if ( !isset( $hiddencats[$link] ) ) {
586 $entry['missing'] = '';
587 } elseif ( $hiddencats[$link] ) {
588 $entry['hidden'] = '';
589 }
590 $result[] = $entry;
591 }
592
593 return $result;
594 }
595
596 private function categoriesHtml( $categories ) {
597 $context = $this->getContext();
598 $context->getOutput()->addCategoryLinks( $categories );
599
600 return $context->getSkin()->getCategories();
601 }
602
603 private function formatLinks( $links ) {
604 $result = array();
605 foreach ( $links as $ns => $nslinks ) {
606 foreach ( $nslinks as $title => $id ) {
607 $entry = array();
608 $entry['ns'] = $ns;
609 ApiResult::setContent( $entry, Title::makeTitle( $ns, $title )->getFullText() );
610 if ( $id != 0 ) {
611 $entry['exists'] = '';
612 }
613 $result[] = $entry;
614 }
615 }
616
617 return $result;
618 }
619
620 private function formatIWLinks( $iw ) {
621 $result = array();
622 foreach ( $iw as $prefix => $titles ) {
623 foreach ( array_keys( $titles ) as $title ) {
624 $entry = array();
625 $entry['prefix'] = $prefix;
626
627 $title = Title::newFromText( "{$prefix}:{$title}" );
628 if ( $title ) {
629 $entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
630 }
631
632 ApiResult::setContent( $entry, $title->getFullText() );
633 $result[] = $entry;
634 }
635 }
636
637 return $result;
638 }
639
640 private function formatHeadItems( $headItems ) {
641 $result = array();
642 foreach ( $headItems as $tag => $content ) {
643 $entry = array();
644 $entry['tag'] = $tag;
645 ApiResult::setContent( $entry, $content );
646 $result[] = $entry;
647 }
648
649 return $result;
650 }
651
652 private function formatProperties( $properties ) {
653 $result = array();
654 foreach ( $properties as $name => $value ) {
655 $entry = array();
656 $entry['name'] = $name;
657 ApiResult::setContent( $entry, $value );
658 $result[] = $entry;
659 }
660
661 return $result;
662 }
663
664 private function formatCss( $css ) {
665 $result = array();
666 foreach ( $css as $file => $link ) {
667 $entry = array();
668 $entry['file'] = $file;
669 ApiResult::setContent( $entry, $link );
670 $result[] = $entry;
671 }
672
673 return $result;
674 }
675
676 private function formatLimitReportData( $limitReportData ) {
677 $result = array();
678 $apiResult = $this->getResult();
679
680 foreach ( $limitReportData as $name => $value ) {
681 $entry = array();
682 $entry['name'] = $name;
683 if ( !is_array( $value ) ) {
684 $value = array( $value );
685 }
686 $apiResult->setIndexedTagName( $value, 'param' );
687 $apiResult->setIndexedTagName_recursive( $value, 'param' );
688 $entry = array_merge( $entry, $value );
689 $result[] = $entry;
690 }
691
692 return $result;
693 }
694
695 private function setIndexedTagNames( &$array, $mapping ) {
696 foreach ( $mapping as $key => $name ) {
697 if ( isset( $array[$key] ) ) {
698 $this->getResult()->setIndexedTagName( $array[$key], $name );
699 }
700 }
701 }
702
703 public function getAllowedParams() {
704 return array(
705 'title' => null,
706 'text' => null,
707 'summary' => null,
708 'page' => null,
709 'pageid' => array(
710 ApiBase::PARAM_TYPE => 'integer',
711 ),
712 'redirects' => false,
713 'oldid' => array(
714 ApiBase::PARAM_TYPE => 'integer',
715 ),
716 'prop' => array(
717 ApiBase::PARAM_DFLT => 'text|langlinks|categories|links|templates|' .
718 'images|externallinks|sections|revid|displaytitle|iwlinks|properties',
719 ApiBase::PARAM_ISMULTI => true,
720 ApiBase::PARAM_TYPE => array(
721 'text',
722 'langlinks',
723 'categories',
724 'categorieshtml',
725 'links',
726 'templates',
727 'images',
728 'externallinks',
729 'sections',
730 'revid',
731 'displaytitle',
732 'headitems',
733 'headhtml',
734 'modules',
735 'indicators',
736 'iwlinks',
737 'wikitext',
738 'properties',
739 'limitreportdata',
740 'limitreporthtml',
741 )
742 ),
743 'pst' => false,
744 'onlypst' => false,
745 'effectivelanglinks' => false,
746 'section' => null,
747 'sectiontitle' => array(
748 ApiBase::PARAM_TYPE => 'string',
749 ),
750 'disablepp' => false,
751 'disableeditsection' => false,
752 'generatexml' => array(
753 ApiBase::PARAM_DFLT => false,
754 ApiBase::PARAM_HELP_MSG => array(
755 'apihelp-parse-param-generatexml', CONTENT_MODEL_WIKITEXT
756 ),
757 ),
758 'preview' => false,
759 'sectionpreview' => false,
760 'disabletoc' => false,
761 'contentformat' => array(
762 ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(),
763 ),
764 'contentmodel' => array(
765 ApiBase::PARAM_TYPE => ContentHandler::getContentModels(),
766 )
767 );
768 }
769
770 protected function getExamplesMessages() {
771 return array(
772 'action=parse&page=Project:Sandbox'
773 => 'apihelp-parse-example-page',
774 'action=parse&text={{Project:Sandbox}}&contentmodel=wikitext'
775 => 'apihelp-parse-example-text',
776 'action=parse&text={{PAGENAME}}&title=Test'
777 => 'apihelp-parse-example-texttitle',
778 'action=parse&summary=Some+[[link]]&prop='
779 => 'apihelp-parse-example-summary',
780 );
781 }
782
783 public function getHelpUrls() {
784 return 'https://www.mediawiki.org/wiki/API:Parsing_wikitext#parse';
785 }
786 }