MediaWiki  1.23.13
ApiEditPage.php
Go to the documentation of this file.
1 <?php
34 class ApiEditPage extends ApiBase {
35  public function execute() {
36  $user = $this->getUser();
37  $params = $this->extractRequestParams();
38 
39  if ( is_null( $params['text'] ) && is_null( $params['appendtext'] ) &&
40  is_null( $params['prependtext'] ) &&
41  $params['undo'] == 0
42  ) {
43  $this->dieUsageMsg( 'missingtext' );
44  }
45 
46  $pageObj = $this->getTitleOrPageId( $params );
47  $titleObj = $pageObj->getTitle();
48  $apiResult = $this->getResult();
49 
50  if ( $params['redirect'] ) {
51  if ( $titleObj->isRedirect() ) {
52  $oldTitle = $titleObj;
53 
55  ->getContent( Revision::FOR_THIS_USER, $user )
56  ->getRedirectChain();
57  // array_shift( $titles );
58 
59  $redirValues = array();
60 
62  foreach ( $titles as $id => $newTitle ) {
63 
64  if ( !isset( $titles[$id - 1] ) ) {
65  $titles[$id - 1] = $oldTitle;
66  }
67 
68  $redirValues[] = array(
69  'from' => $titles[$id - 1]->getPrefixedText(),
70  'to' => $newTitle->getPrefixedText()
71  );
72 
73  $titleObj = $newTitle;
74  }
75 
76  $apiResult->setIndexedTagName( $redirValues, 'r' );
77  $apiResult->addValue( null, 'redirects', $redirValues );
78 
79  // Since the page changed, update $pageObj
80  $pageObj = WikiPage::factory( $titleObj );
81  }
82  }
83 
84  if ( !isset( $params['contentmodel'] ) || $params['contentmodel'] == '' ) {
85  $contentHandler = $pageObj->getContentHandler();
86  } else {
87  $contentHandler = ContentHandler::getForModelID( $params['contentmodel'] );
88  }
89 
90  // @todo Ask handler whether direct editing is supported at all! make
91  // allowFlatEdit() method or some such
92 
93  if ( !isset( $params['contentformat'] ) || $params['contentformat'] == '' ) {
94  $params['contentformat'] = $contentHandler->getDefaultFormat();
95  }
96 
97  $contentFormat = $params['contentformat'];
98 
99  if ( !$contentHandler->isSupportedFormat( $contentFormat ) ) {
100  $name = $titleObj->getPrefixedDBkey();
101  $model = $contentHandler->getModelID();
102 
103  $this->dieUsage( "The requested format $contentFormat is not supported for content model " .
104  " $model used by $name", 'badformat' );
105  }
106 
107  if ( $params['createonly'] && $titleObj->exists() ) {
108  $this->dieUsageMsg( 'createonly-exists' );
109  }
110  if ( $params['nocreate'] && !$titleObj->exists() ) {
111  $this->dieUsageMsg( 'nocreate-missing' );
112  }
113 
114  // Now let's check whether we're even allowed to do this
115  $errors = $titleObj->getUserPermissionsErrors( 'edit', $user );
116  if ( !$titleObj->exists() ) {
117  $errors = array_merge( $errors, $titleObj->getUserPermissionsErrors( 'create', $user ) );
118  }
119  if ( count( $errors ) ) {
120  $this->dieUsageMsg( $errors[0] );
121  }
122 
123  $toMD5 = $params['text'];
124  if ( !is_null( $params['appendtext'] ) || !is_null( $params['prependtext'] ) ) {
125  $content = $pageObj->getContent();
126 
127  if ( !$content ) {
128  if ( $titleObj->getNamespace() == NS_MEDIAWIKI ) {
129  # If this is a MediaWiki:x message, then load the messages
130  # and return the message value for x.
131  $text = $titleObj->getDefaultMessageText();
132  if ( $text === false ) {
133  $text = '';
134  }
135 
136  try {
137  $content = ContentHandler::makeContent( $text, $this->getTitle() );
138  } catch ( MWContentSerializationException $ex ) {
139  $this->dieUsage( $ex->getMessage(), 'parseerror' );
140 
141  return;
142  }
143  } else {
144  # Otherwise, make a new empty content.
145  $content = $contentHandler->makeEmptyContent();
146  }
147  }
148 
149  // @todo Add support for appending/prepending to the Content interface
150 
151  if ( !( $content instanceof TextContent ) ) {
152  $mode = $contentHandler->getModelID();
153  $this->dieUsage( "Can't append to pages using content model $mode", 'appendnotsupported' );
154  }
155 
156  if ( !is_null( $params['section'] ) ) {
157  if ( !$contentHandler->supportsSections() ) {
158  $modelName = $contentHandler->getModelID();
159  $this->dieUsage(
160  "Sections are not supported for this content model: $modelName.",
161  'sectionsnotsupported'
162  );
163  }
164 
165  if ( $params['section'] == 'new' ) {
166  // DWIM if they're trying to prepend/append to a new section.
167  $content = null;
168  } else {
169  // Process the content for section edits
170  $section = intval( $params['section'] );
171  $content = $content->getSection( $section );
172 
173  if ( !$content ) {
174  $this->dieUsage( "There is no section {$section}.", 'nosuchsection' );
175  }
176  }
177  }
178 
179  if ( !$content ) {
180  $text = '';
181  } else {
182  $text = $content->serialize( $contentFormat );
183  }
184 
185  $params['text'] = $params['prependtext'] . $text . $params['appendtext'];
186  $toMD5 = $params['prependtext'] . $params['appendtext'];
187  }
188 
189  if ( $params['undo'] > 0 ) {
190  if ( $params['undoafter'] > 0 ) {
191  if ( $params['undo'] < $params['undoafter'] ) {
192  list( $params['undo'], $params['undoafter'] ) =
193  array( $params['undoafter'], $params['undo'] );
194  }
195  $undoafterRev = Revision::newFromID( $params['undoafter'] );
196  }
197  $undoRev = Revision::newFromID( $params['undo'] );
198  if ( is_null( $undoRev ) || $undoRev->isDeleted( Revision::DELETED_TEXT ) ) {
199  $this->dieUsageMsg( array( 'nosuchrevid', $params['undo'] ) );
200  }
201 
202  if ( $params['undoafter'] == 0 ) {
203  $undoafterRev = $undoRev->getPrevious();
204  }
205  if ( is_null( $undoafterRev ) || $undoafterRev->isDeleted( Revision::DELETED_TEXT ) ) {
206  $this->dieUsageMsg( array( 'nosuchrevid', $params['undoafter'] ) );
207  }
208 
209  if ( $undoRev->getPage() != $pageObj->getID() ) {
210  $this->dieUsageMsg( array( 'revwrongpage', $undoRev->getID(),
211  $titleObj->getPrefixedText() ) );
212  }
213  if ( $undoafterRev->getPage() != $pageObj->getID() ) {
214  $this->dieUsageMsg( array( 'revwrongpage', $undoafterRev->getID(),
215  $titleObj->getPrefixedText() ) );
216  }
217 
218  $newContent = $contentHandler->getUndoContent(
219  $pageObj->getRevision(),
220  $undoRev,
221  $undoafterRev
222  );
223 
224  if ( !$newContent ) {
225  $this->dieUsageMsg( 'undo-failure' );
226  }
227 
228  $params['text'] = $newContent->serialize( $params['contentformat'] );
229 
230  // If no summary was given and we only undid one rev,
231  // use an autosummary
232  if ( is_null( $params['summary'] ) &&
233  $titleObj->getNextRevisionID( $undoafterRev->getID() ) == $params['undo']
234  ) {
235  $params['summary'] = wfMessage( 'undo-summary' )
236  ->params ( $params['undo'], $undoRev->getUserText() )->inContentLanguage()->text();
237  }
238  }
239 
240  // See if the MD5 hash checks out
241  if ( !is_null( $params['md5'] ) && md5( $toMD5 ) !== $params['md5'] ) {
242  $this->dieUsageMsg( 'hashcheckfailed' );
243  }
244 
245  // EditPage wants to parse its stuff from a WebRequest
246  // That interface kind of sucks, but it's workable
247  $requestArray = array(
248  'wpTextbox1' => $params['text'],
249  'format' => $contentFormat,
250  'model' => $contentHandler->getModelID(),
251  'wpEditToken' => $params['token'],
252  'wpIgnoreBlankSummary' => ''
253  );
254 
255  if ( !is_null( $params['summary'] ) ) {
256  $requestArray['wpSummary'] = $params['summary'];
257  }
258 
259  if ( !is_null( $params['sectiontitle'] ) ) {
260  $requestArray['wpSectionTitle'] = $params['sectiontitle'];
261  }
262 
263  // TODO: Pass along information from 'undoafter' as well
264  if ( $params['undo'] > 0 ) {
265  $requestArray['wpUndidRevision'] = $params['undo'];
266  }
267 
268  // Watch out for basetimestamp == ''
269  // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
270  if ( !is_null( $params['basetimestamp'] ) && $params['basetimestamp'] != '' ) {
271  $requestArray['wpEdittime'] = wfTimestamp( TS_MW, $params['basetimestamp'] );
272  } else {
273  $requestArray['wpEdittime'] = $pageObj->getTimestamp();
274  }
275 
276  if ( !is_null( $params['starttimestamp'] ) && $params['starttimestamp'] != '' ) {
277  $requestArray['wpStarttime'] = wfTimestamp( TS_MW, $params['starttimestamp'] );
278  } else {
279  $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
280  }
281 
282  if ( $params['minor'] || ( !$params['notminor'] && $user->getOption( 'minordefault' ) ) ) {
283  $requestArray['wpMinoredit'] = '';
284  }
285 
286  if ( $params['recreate'] ) {
287  $requestArray['wpRecreate'] = '';
288  }
289 
290  if ( !is_null( $params['section'] ) ) {
291  $section = intval( $params['section'] );
292  if ( $section == 0 && $params['section'] != '0' && $params['section'] != 'new' ) {
293  $this->dieUsage( "The section parameter must be set to an integer or 'new'", "invalidsection" );
294  }
295  $content = $pageObj->getContent();
296  if ( $section !== 0 && ( !$content || !$content->getSection( $section ) ) ) {
297  $this->dieUsage( "There is no section {$section}.", 'nosuchsection' );
298  }
299  $requestArray['wpSection'] = $params['section'];
300  } else {
301  $requestArray['wpSection'] = '';
302  }
303 
304  $watch = $this->getWatchlistValue( $params['watchlist'], $titleObj );
305 
306  // Deprecated parameters
307  if ( $params['watch'] ) {
308  $watch = true;
309  } elseif ( $params['unwatch'] ) {
310  $watch = false;
311  }
312 
313  if ( $watch ) {
314  $requestArray['wpWatchthis'] = '';
315  }
316 
317  // Pass through anything else we might have been given, to support extensions
318  // This is kind of a hack but it's the best we can do to make extensions work
319  $requestArray += $this->getRequest()->getValues();
320 
321  global $wgTitle, $wgRequest;
322 
323  $req = new DerivativeRequest( $this->getRequest(), $requestArray, true );
324 
325  // Some functions depend on $wgTitle == $ep->mTitle
326  // TODO: Make them not or check if they still do
327  $wgTitle = $titleObj;
328 
329  $articleContext = new RequestContext;
330  $articleContext->setRequest( $req );
331  $articleContext->setWikiPage( $pageObj );
332  $articleContext->setUser( $this->getUser() );
333 
335  $articleObject = Article::newFromWikiPage( $pageObj, $articleContext );
336 
337  $ep = new EditPage( $articleObject );
338 
339  // allow editing of non-textual content.
340  $ep->allowNonTextContent = true;
341 
342  $ep->setContextTitle( $titleObj );
343  $ep->importFormData( $req );
344  $content = $ep->textbox1;
345 
346  // The following is needed to give the hook the full content of the
347  // new revision rather than just the current section. (Bug 52077)
348  if ( !is_null( $params['section'] ) &&
349  $contentHandler->supportsSections() && $titleObj->exists()
350  ) {
351  // If sectiontitle is set, use it, otherwise use the summary as the section title (for
352  // backwards compatibility with old forms/bots).
353  if ( $ep->sectiontitle !== '' ) {
354  $sectionTitle = $ep->sectiontitle;
355  } else {
356  $sectionTitle = $ep->summary;
357  }
358 
359  $contentObj = $contentHandler->unserializeContent( $content, $contentFormat );
360 
361  $fullContentObj = $articleObject->replaceSectionContent(
362  $params['section'],
363  $contentObj,
364  $sectionTitle
365  );
366  if ( $fullContentObj ) {
367  $content = $fullContentObj->serialize( $contentFormat );
368  } else {
369  // This most likely means we have an edit conflict which means that the edit
370  // wont succeed anyway.
371  $this->dieUsageMsg( 'editconflict' );
372  }
373  }
374 
375  // Run hooks
376  // Handle APIEditBeforeSave parameters
377  $r = array();
378  if ( !wfRunHooks( 'APIEditBeforeSave', array( $ep, $content, &$r ) ) ) {
379  if ( count( $r ) ) {
380  $r['result'] = 'Failure';
381  $apiResult->addValue( null, $this->getModuleName(), $r );
382 
383  return;
384  }
385 
386  $this->dieUsageMsg( 'hookaborted' );
387  }
388 
389  // Do the actual save
390  $oldRevId = $articleObject->getRevIdFetched();
391  $result = null;
392  // Fake $wgRequest for some hooks inside EditPage
393  // @todo FIXME: This interface SUCKS
394  $oldRequest = $wgRequest;
395  $wgRequest = $req;
396 
397  $status = $ep->internalAttemptSave( $result, $user->isAllowed( 'bot' ) && $params['bot'] );
398  $wgRequest = $oldRequest;
399  global $wgMaxArticleSize;
400 
401  switch ( $status->value ) {
402  case EditPage::AS_HOOK_ERROR:
403  case EditPage::AS_HOOK_ERROR_EXPECTED:
404  $this->dieUsageMsg( 'hookaborted' );
405 
406  case EditPage::AS_PARSE_ERROR:
407  $this->dieUsage( $status->getMessage(), 'parseerror' );
408 
409  case EditPage::AS_IMAGE_REDIRECT_ANON:
410  $this->dieUsageMsg( 'noimageredirect-anon' );
411 
412  case EditPage::AS_IMAGE_REDIRECT_LOGGED:
413  $this->dieUsageMsg( 'noimageredirect-logged' );
414 
415  case EditPage::AS_SPAM_ERROR:
416  $this->dieUsageMsg( array( 'spamdetected', $result['spam'] ) );
417 
418  case EditPage::AS_BLOCKED_PAGE_FOR_USER:
419  $this->dieUsageMsg( 'blockedtext' );
420 
421  case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
422  case EditPage::AS_CONTENT_TOO_BIG:
423  $this->dieUsageMsg( array( 'contenttoobig', $wgMaxArticleSize ) );
424 
425  case EditPage::AS_READ_ONLY_PAGE_ANON:
426  $this->dieUsageMsg( 'noedit-anon' );
427 
428  case EditPage::AS_READ_ONLY_PAGE_LOGGED:
429  $this->dieUsageMsg( 'noedit' );
430 
431  case EditPage::AS_READ_ONLY_PAGE:
432  $this->dieReadOnly();
433 
434  case EditPage::AS_RATE_LIMITED:
435  $this->dieUsageMsg( 'actionthrottledtext' );
436 
437  case EditPage::AS_ARTICLE_WAS_DELETED:
438  $this->dieUsageMsg( 'wasdeleted' );
439 
440  case EditPage::AS_NO_CREATE_PERMISSION:
441  $this->dieUsageMsg( 'nocreate-loggedin' );
442 
443  case EditPage::AS_NO_CHANGE_CONTENT_MODEL:
444  $this->dieUsageMsg( 'cantchangecontentmodel' );
445 
446  case EditPage::AS_BLANK_ARTICLE:
447  $this->dieUsageMsg( 'blankpage' );
448 
449  case EditPage::AS_CONFLICT_DETECTED:
450  $this->dieUsageMsg( 'editconflict' );
451 
452  // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
453  case EditPage::AS_TEXTBOX_EMPTY:
454  $this->dieUsageMsg( 'emptynewsection' );
455 
456  case EditPage::AS_SUCCESS_NEW_ARTICLE:
457  $r['new'] = '';
458  // fall-through
459 
460  case EditPage::AS_SUCCESS_UPDATE:
461  $r['result'] = 'Success';
462  $r['pageid'] = intval( $titleObj->getArticleID() );
463  $r['title'] = $titleObj->getPrefixedText();
464  $r['contentmodel'] = $titleObj->getContentModel();
465  $newRevId = $articleObject->getLatest();
466  if ( $newRevId == $oldRevId ) {
467  $r['nochange'] = '';
468  } else {
469  $r['oldrevid'] = intval( $oldRevId );
470  $r['newrevid'] = intval( $newRevId );
471  $r['newtimestamp'] = wfTimestamp( TS_ISO_8601,
472  $pageObj->getTimestamp() );
473  }
474  break;
475 
476  case EditPage::AS_SUMMARY_NEEDED:
477  $this->dieUsageMsg( 'summaryrequired' );
478 
479  case EditPage::AS_END:
480  default:
481  // $status came from WikiPage::doEdit()
482  $errors = $status->getErrorsArray();
483  $this->dieUsageMsg( $errors[0] ); // TODO: Add new errors to message map
484  break;
485  }
486  $apiResult->addValue( null, $this->getModuleName(), $r );
487  }
488 
489  public function mustBePosted() {
490  return true;
491  }
492 
493  public function isWriteMode() {
494  return true;
495  }
496 
497  public function getDescription() {
498  return 'Create and edit pages.';
499  }
500 
501  public function getPossibleErrors() {
502  global $wgMaxArticleSize;
503 
504  return array_merge( parent::getPossibleErrors(),
506  array(
507  array( 'missingtext' ),
508  array( 'createonly-exists' ),
509  array( 'nocreate-missing' ),
510  array( 'nosuchrevid', 'undo' ),
511  array( 'nosuchrevid', 'undoafter' ),
512  array( 'revwrongpage', 'id', 'text' ),
513  array( 'undo-failure' ),
514  array( 'hashcheckfailed' ),
515  array( 'hookaborted' ),
516  array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
517  array( 'noimageredirect-anon' ),
518  array( 'noimageredirect-logged' ),
519  array( 'spamdetected', 'spam' ),
520  array( 'summaryrequired' ),
521  array( 'blockedtext' ),
522  array( 'contenttoobig', $wgMaxArticleSize ),
523  array( 'noedit-anon' ),
524  array( 'noedit' ),
525  array( 'actionthrottledtext' ),
526  array( 'wasdeleted' ),
527  array( 'nocreate-loggedin' ),
528  array( 'blankpage' ),
529  array( 'editconflict' ),
530  array( 'emptynewsection' ),
531  array( 'unknownerror', 'retval' ),
532  array( 'code' => 'nosuchsection', 'info' => 'There is no section section.' ),
533  array(
534  'code' => 'invalidsection',
535  'info' => 'The section parameter must be set to an integer or \'new\''
536  ),
537  array(
538  'code' => 'sectionsnotsupported',
539  'info' => 'Sections are not supported for this type of page.'
540  ),
541  array(
542  'code' => 'editnotsupported',
543  'info' => 'Editing of this type of page is not supported using the text based edit API.'
544  ),
545  array(
546  'code' => 'appendnotsupported',
547  'info' => 'This type of page can not be edited by appending or prepending text.' ),
548  array(
549  'code' => 'badformat',
550  'info' => 'The requested serialization format can not be applied to the page\'s content model'
551  ),
552  array( 'customcssprotected' ),
553  array( 'customjsprotected' ),
554  )
555  );
556  }
557 
558  public function getAllowedParams() {
559  return array(
560  'title' => array(
561  ApiBase::PARAM_TYPE => 'string',
562  ),
563  'pageid' => array(
564  ApiBase::PARAM_TYPE => 'integer',
565  ),
566  'section' => null,
567  'sectiontitle' => array(
568  ApiBase::PARAM_TYPE => 'string',
569  ),
570  'text' => null,
571  'token' => array(
572  ApiBase::PARAM_TYPE => 'string',
574  ),
575  'summary' => null,
576  'minor' => false,
577  'notminor' => false,
578  'bot' => false,
579  'basetimestamp' => null,
580  'starttimestamp' => null,
581  'recreate' => false,
582  'createonly' => false,
583  'nocreate' => false,
584  'watch' => array(
585  ApiBase::PARAM_DFLT => false,
587  ),
588  'unwatch' => array(
589  ApiBase::PARAM_DFLT => false,
591  ),
592  'watchlist' => array(
593  ApiBase::PARAM_DFLT => 'preferences',
595  'watch',
596  'unwatch',
597  'preferences',
598  'nochange'
599  ),
600  ),
601  'md5' => null,
602  'prependtext' => null,
603  'appendtext' => null,
604  'undo' => array(
605  ApiBase::PARAM_TYPE => 'integer'
606  ),
607  'undoafter' => array(
608  ApiBase::PARAM_TYPE => 'integer'
609  ),
610  'redirect' => array(
611  ApiBase::PARAM_TYPE => 'boolean',
612  ApiBase::PARAM_DFLT => false,
613  ),
614  'contentformat' => array(
616  ),
617  'contentmodel' => array(
619  )
620  );
621  }
622 
623  public function getParamDescription() {
624  $p = $this->getModulePrefix();
625 
626  return array(
627  'title' => "Title of the page you want to edit. Cannot be used together with {$p}pageid",
628  'pageid' => "Page ID of the page you want to edit. Cannot be used together with {$p}title",
629  'section' => 'Section number. 0 for the top section, \'new\' for a new section',
630  'sectiontitle' => 'The title for a new section',
631  'text' => 'Page content',
632  'token' => array(
633  'Edit token. You can get one of these through prop=info.',
634  "The token should always be sent as the last parameter, or at " .
635  "least, after the {$p}text parameter"
636  ),
637  'summary'
638  => "Edit summary. Also section title when {$p}section=new and {$p}sectiontitle is not set",
639  'minor' => 'Minor edit',
640  'notminor' => 'Non-minor edit',
641  'bot' => 'Mark this edit as bot',
642  'basetimestamp' => array(
643  'Timestamp of the base revision (obtained through prop=revisions&rvprop=timestamp).',
644  'Used to detect edit conflicts; leave unset to ignore conflicts'
645  ),
646  'starttimestamp' => array(
647  'Timestamp when you obtained the edit token.',
648  'Used to detect edit conflicts; leave unset to ignore conflicts'
649  ),
650  'recreate' => 'Override any errors about the article having been deleted in the meantime',
651  'createonly' => 'Don\'t edit the page if it exists already',
652  'nocreate' => 'Throw an error if the page doesn\'t exist',
653  'watch' => 'Add the page to your watchlist',
654  'unwatch' => 'Remove the page from your watchlist',
655  'watchlist' => 'Unconditionally add or remove the page from your ' .
656  'watchlist, use preferences or do not change watch',
657  'md5' => array(
658  "The MD5 hash of the {$p}text parameter, or the {$p}prependtext " .
659  "and {$p}appendtext parameters concatenated.",
660  'If set, the edit won\'t be done unless the hash is correct'
661  ),
662  'prependtext' => "Add this text to the beginning of the page. Overrides {$p}text",
663  'appendtext' => array( "Add this text to the end of the page. Overrides {$p}text.",
664  "Use {$p}section=new to append a new section" ),
665  'undo' => "Undo this revision. Overrides {$p}text, {$p}prependtext and {$p}appendtext",
666  'undoafter' => 'Undo all revisions from undo to this one. If not set, just undo one revision',
667  'redirect' => 'Automatically resolve redirects',
668  'contentformat' => 'Content serialization format used for the input text',
669  'contentmodel' => 'Content model of the new content',
670  );
671  }
672 
673  public function getResultProperties() {
674  return array(
675  '' => array(
676  'new' => 'boolean',
677  'result' => array(
679  'Success',
680  'Failure'
681  ),
682  ),
683  'pageid' => array(
684  ApiBase::PROP_TYPE => 'integer',
685  ApiBase::PROP_NULLABLE => true
686  ),
687  'title' => array(
688  ApiBase::PROP_TYPE => 'string',
689  ApiBase::PROP_NULLABLE => true
690  ),
691  'nochange' => 'boolean',
692  'oldrevid' => array(
693  ApiBase::PROP_TYPE => 'integer',
694  ApiBase::PROP_NULLABLE => true
695  ),
696  'newrevid' => array(
697  ApiBase::PROP_TYPE => 'integer',
698  ApiBase::PROP_NULLABLE => true
699  ),
700  'newtimestamp' => array(
701  ApiBase::PROP_TYPE => 'string',
702  ApiBase::PROP_NULLABLE => true
703  )
704  )
705  );
706  }
707 
708  public function needsToken() {
709  return true;
710  }
711 
712  public function getTokenSalt() {
713  return '';
714  }
715 
716  public function getExamples() {
717  return array(
718  'api.php?action=edit&title=Test&summary=test%20summary&' .
719  'text=article%20content&basetimestamp=20070824123454&token=%2B\\'
720  => 'Edit a page (anonymous user)',
721  'api.php?action=edit&title=Test&summary=NOTOC&minor=&' .
722  'prependtext=__NOTOC__%0A&basetimestamp=20070824123454&token=%2B\\'
723  => 'Prepend __NOTOC__ to a page (anonymous user)',
724  'api.php?action=edit&title=Test&undo=13585&undoafter=13579&' .
725  'basetimestamp=20070824123454&token=%2B\\'
726  => 'Undo r13579 through r13585 with autosummary (anonymous user)',
727  );
728  }
729 
730  public function getHelpUrls() {
731  return 'https://www.mediawiki.org/wiki/API:Edit';
732  }
733 }
ApiEditPage
A module that allows for editing and creating pages.
Definition: ApiEditPage.php:34
ApiEditPage\getParamDescription
getParamDescription()
Returns an array of parameter descriptions.
Definition: ApiEditPage.php:623
DerivativeRequest
Similar to FauxRequest, but only fakes URL parameters and method (POST or GET) and use the base reque...
Definition: WebRequest.php:1463
ContentHandler\getForModelID
static getForModelID( $modelId)
Returns the ContentHandler singleton for the given model ID.
Definition: ContentHandler.php:311
ApiEditPage\getTokenSalt
getTokenSalt()
Returns the token salt if there is one, '' if the module doesn't require a salt, else false if the mo...
Definition: ApiEditPage.php:712
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. $reader:XMLReader object $logInfo:Array of information Return false to stop further processing of the tag 'ImportHandlePageXMLTag':When parsing a XML tag in a page. $reader:XMLReader object $pageInfo:Array of information Return false to stop further processing of the tag 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information Return false to stop further processing of the tag 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. $reader:XMLReader object Return false to stop further processing of the tag 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. $reader:XMLReader object $revisionInfo:Array of information Return false to stop further processing of the tag 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. $title:Title object for the current page $request:WebRequest $ignoreRedirect:boolean to skip redirect check $target:Title/string of redirect target $article:Article object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) $article:article(object) being checked 'IsTrustedProxy':Override the result of wfIsTrustedProxy() $ip:IP being check $result:Change this value to override the result of wfIsTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of User::isValidEmailAddr(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetMagic':DEPRECATED, use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetSpecialPageAliases':DEPRECATED, use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1528
ContentHandler\getAllContentFormats
static getAllContentFormats()
Definition: ContentHandler.php:376
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
ApiBase\PARAM_REQUIRED
const PARAM_REQUIRED
Definition: ApiBase.php:62
ApiEditPage\getHelpUrls
getHelpUrls()
Definition: ApiEditPage.php:730
ApiBase\dieUsageMsg
dieUsageMsg( $error)
Output the error message related to a certain array.
Definition: ApiBase.php:1933
ApiEditPage\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiEditPage.php:558
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:2530
ApiBase\getTitleOrPageId
getTitleOrPageId( $params, $load=false)
Definition: ApiBase.php:853
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:50
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:205
$params
$params
Definition: styleTest.css.php:40
ContextSource\getRequest
getRequest()
Get the WebRequest object.
Definition: ContextSource.php:77
ApiEditPage\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiEditPage.php:489
IDBAccessObject\READ_LATEST
const READ_LATEST
Definition: IDBAccessObject.php:49
ContextSource\getUser
getUser()
Get the User object.
Definition: ContextSource.php:132
ContextSource\getTitle
getTitle()
Get the Title object.
Definition: ContextSource.php:87
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:42
Revision\FOR_THIS_USER
const FOR_THIS_USER
Definition: Revision.php:73
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
Definition: ApiBase.php:60
Article\newFromWikiPage
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:174
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:103
$titles
linkcache txt The LinkCache class maintains a list of article titles and the information about whether or not the article exists in the database This is used to mark up links when displaying a page If the same link appears more than once on any page then it only has to be looked up once In most cases link lookups are done in batches with the LinkBatch class or the equivalent in so the link cache is mostly useful for short snippets of parsed and for links in the navigation areas of the skin The link cache was formerly used to track links used in a document for the purposes of updating the link tables This application is now deprecated To create a you can use the following $titles
Definition: linkcache.txt:17
ContentHandler\getContentModels
static getContentModels()
Definition: ContentHandler.php:370
ApiEditPage\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiEditPage.php:35
TS_ISO_8601
const TS_ISO_8601
ISO 8601 format with no timezone: 1986-02-09T20:00:00Z.
Definition: GlobalFunctions.php:2495
MWContentSerializationException
Exception representing a failure to serialize or unserialize a content object.
Definition: ContentHandler.php:33
wfMessage
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing after in associative array form externallinks including delete and has completed for all link tables default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt
$oldTitle
versus $oldTitle
Definition: globals.txt:16
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4058
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:2561
RequestContext
Group all the pieces relevant to the context of a request into one instance.
Definition: RequestContext.php:30
ApiEditPage\getExamples
getExamples()
Returns usage examples for this module.
Definition: ApiEditPage.php:716
ApiBase\PROP_TYPE
const PROP_TYPE
Definition: ApiBase.php:74
list
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
ApiBase\getWatchlistValue
getWatchlistValue( $watchlist, $titleObj, $userOption=null)
Return true if we're to watch the page, false if not, null if no change.
Definition: ApiBase.php:913
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:144
ApiBase\getModulePrefix
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition: ApiBase.php:165
ApiEditPage\getResultProperties
getResultProperties()
Returns possible properties in the result, grouped by the value of the prop parameter that shows them...
Definition: ApiEditPage.php:673
$section
$section
Definition: Utf8Test.php:88
TS_MW
const TS_MW
MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
Definition: GlobalFunctions.php:2478
Revision\newFromTitle
static newFromTitle( $title, $id=0, $flags=0)
Load either the current, or a specified, revision that's attached to a given title.
Definition: Revision.php:106
ApiBase\extractRequestParams
extractRequestParams( $parseLimit=true)
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:687
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:336
ApiBase\dieUsage
dieUsage( $description, $errorCode, $httpRespCode=0, $extradata=null)
Throw a UsageException, which will (if uncaught) call the main module's error handler and die with an...
Definition: ApiBase.php:1363
ApiBase\dieReadOnly
dieReadOnly()
Helper function for readonly errors.
Definition: ApiBase.php:1923
ApiBase\PROP_NULLABLE
const PROP_NULLABLE
Definition: ApiBase.php:76
ApiEditPage\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiEditPage.php:493
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:237
TextContent
Content object implementation for representing flat text.
Definition: TextContent.php:35
ApiEditPage\getPossibleErrors
getPossibleErrors()
Returns a list of all possible errors returned by the module.
Definition: ApiEditPage.php:501
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:46
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:148
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:87
ApiEditPage\needsToken
needsToken()
Returns whether this module requires a token to execute It is used to show possible errors in action=...
Definition: ApiEditPage.php:708
ApiEditPage\getDescription
getDescription()
Returns the description string for this module.
Definition: ApiEditPage.php:497
Revision\DELETED_TEXT
const DELETED_TEXT
Definition: Revision.php:65
$wgTitle
if(! $wgRequest->checkUrlExtension()) if(! $wgEnableAPI) $wgTitle
Definition: api.php:63
RequestContext\setRequest
setRequest(WebRequest $r)
Set the WebRequest object.
Definition: RequestContext.php:92
ApiBase\getTitleOrPageIdErrorMessage
getTitleOrPageIdErrorMessage()
Definition: ApiBase.php:885