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