2013-07-11 17:09:28 +00:00
|
|
|
<?php
|
|
|
|
/**
|
2015-09-14 16:13:31 +00:00
|
|
|
* Parsoid/RESTBase+MediaWiki API wrapper.
|
2013-07-11 17:09:28 +00:00
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @ingroup Extensions
|
2016-01-03 22:56:59 +00:00
|
|
|
* @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
|
2013-07-11 17:09:28 +00:00
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
use \MediaWiki\Logger\LoggerFactory;
|
|
|
|
|
2013-07-11 17:09:28 +00:00
|
|
|
class ApiVisualEditorEdit extends ApiVisualEditor {
|
|
|
|
|
2014-08-13 08:15:42 +00:00
|
|
|
public function __construct( ApiMain $main, $name, Config $config ) {
|
|
|
|
parent::__construct( $main, $name, $config );
|
|
|
|
}
|
|
|
|
|
2013-07-11 17:09:28 +00:00
|
|
|
protected function saveWikitext( $title, $wikitext, $params ) {
|
2016-02-17 16:18:02 +00:00
|
|
|
$apiParams = [
|
2013-07-11 17:09:28 +00:00
|
|
|
'action' => 'edit',
|
|
|
|
'title' => $title->getPrefixedDBkey(),
|
|
|
|
'text' => $wikitext,
|
|
|
|
'summary' => $params['summary'],
|
|
|
|
'basetimestamp' => $params['basetimestamp'],
|
|
|
|
'starttimestamp' => $params['starttimestamp'],
|
|
|
|
'token' => $params['token'],
|
2016-02-17 16:18:02 +00:00
|
|
|
];
|
2013-07-11 17:09:28 +00:00
|
|
|
|
|
|
|
if ( $params['minor'] ) {
|
|
|
|
$apiParams['minor'] = true;
|
2013-07-24 14:07:05 +00:00
|
|
|
} else {
|
|
|
|
$apiParams['notminor'] = true;
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME add some way that the user's preferences can be respected
|
|
|
|
$apiParams['watchlist'] = $params['watch'] ? 'watch' : 'unwatch';
|
|
|
|
|
|
|
|
if ( $params['captchaid'] ) {
|
|
|
|
$apiParams['captchaid'] = $params['captchaid'];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $params['captchaword'] ) {
|
|
|
|
$apiParams['captchaword'] = $params['captchaword'];
|
|
|
|
}
|
|
|
|
|
|
|
|
$api = new ApiMain(
|
|
|
|
new DerivativeRequest(
|
|
|
|
$this->getRequest(),
|
Render check boxes from EditPage
EditPage has a lovely getCheckboxes() function which includes the
minor and watch checkboxes as rendered by MW core, as well as any
checkboxes extensions like FlaggedRevs might have added. Output
these in the API, render them, and send their values back.
ApiVisualEditor.php:
* Build a fake EditPage, get its checkboxes, and return them
ApiVisualEditorEdit.php:
* Pass through posted request data to ApiEdit, which passes it
through to EditPage thanks to Idab5b524b0e3 in core
ve.init.mw.ViewPageTarget.js:
* Remove minor and watch checkboxes from the save dialog template
and replace them with a generic checkbox container
* Have getSaveOptions() pull the state of all checkboxes in
** Special-case minor and watch, and pass the rest straight through
** Move normalization from true/false to presence/absence here, from
ve.init.mw.Target.prototype.save(), because here we know which ones
are checkboxes and we don't know that in save() without
special-casing
* Remove getSaveDialogHtml(), we don't need to hide checkboxes based on
rights anymore because in that case the API just won't send them to us.
** Moved logic for checking the watch checkbox down to where the same
logic for the minor checkbox already is
* Unwrap getSaveDialogHtml() in setupSaveDialog()
* Access minor and watch by their new IDs throughout
ve.init.mw.Target.js:
* Get and store checkboxes from the API
* Pass all keys straight through to the API
Bug: 49699
Change-Id: I09d02a42b05146bc9b7080ab38338ae869bf15e3
2013-07-24 06:39:03 +00:00
|
|
|
$apiParams + $this->getRequest()->getValues(),
|
2013-07-11 17:09:28 +00:00
|
|
|
true // was posted
|
|
|
|
),
|
|
|
|
true // enable write
|
|
|
|
);
|
|
|
|
|
|
|
|
$api->execute();
|
|
|
|
|
2016-09-20 19:28:15 +00:00
|
|
|
return $api->getResult()->getResultData();
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
2015-04-08 20:22:48 +00:00
|
|
|
protected function parseWikitext( $title, $newRevId ) {
|
2016-02-17 16:18:02 +00:00
|
|
|
$apiParams = [
|
2015-03-13 20:10:49 +00:00
|
|
|
'action' => 'parse',
|
|
|
|
'page' => $title->getPrefixedDBkey(),
|
2015-04-08 20:22:48 +00:00
|
|
|
'oldid' => $newRevId,
|
2015-07-27 19:27:03 +00:00
|
|
|
'prop' => 'text|revid|categorieshtml|displaytitle|modules|jsconfigvars',
|
2016-02-17 16:18:02 +00:00
|
|
|
];
|
2015-03-13 20:10:49 +00:00
|
|
|
$api = new ApiMain(
|
|
|
|
new DerivativeRequest(
|
|
|
|
$this->getRequest(),
|
|
|
|
$apiParams,
|
|
|
|
false // was posted?
|
|
|
|
),
|
|
|
|
true // enable write?
|
|
|
|
);
|
|
|
|
|
|
|
|
$api->execute();
|
2016-09-20 19:28:15 +00:00
|
|
|
$result = $api->getResult()->getResultData( null, [
|
|
|
|
'BC' => [], // Transform content nodes to '*'
|
|
|
|
'Types' => [], // Add back-compat subelements
|
|
|
|
'Strip' => 'all', // Remove any metadata keys from the links array
|
|
|
|
] );
|
2015-03-13 20:10:49 +00:00
|
|
|
$content = isset( $result['parse']['text']['*'] ) ? $result['parse']['text']['*'] : false;
|
|
|
|
$categorieshtml = isset( $result['parse']['categorieshtml']['*'] ) ?
|
|
|
|
$result['parse']['categorieshtml']['*'] : false;
|
2016-02-17 16:18:02 +00:00
|
|
|
$links = isset( $result['parse']['links'] ) ? $result['parse']['links'] : [];
|
2015-03-13 20:10:49 +00:00
|
|
|
$revision = Revision::newFromId( $result['parse']['revid'] );
|
|
|
|
$timestamp = $revision ? $revision->getTimestamp() : wfTimestampNow();
|
|
|
|
$displaytitle = isset( $result['parse']['displaytitle'] ) ?
|
|
|
|
$result['parse']['displaytitle'] : false;
|
2016-02-17 16:18:02 +00:00
|
|
|
$modules = isset( $result['parse']['modules'] ) ? $result['parse']['modules'] : [];
|
2015-07-27 19:27:03 +00:00
|
|
|
$jsconfigvars = isset( $result['parse']['jsconfigvars'] ) ?
|
2016-02-17 16:18:02 +00:00
|
|
|
$result['parse']['jsconfigvars'] : [];
|
2015-03-13 20:10:49 +00:00
|
|
|
|
|
|
|
if ( $content === false || ( strlen( $content ) && $revision === null ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $displaytitle !== false ) {
|
|
|
|
// Escape entities as in OutputPage::setPageTitle()
|
|
|
|
$displaytitle = Sanitizer::normalizeCharReferences(
|
|
|
|
Sanitizer::removeHTMLtags( $displaytitle ) );
|
|
|
|
}
|
|
|
|
|
2016-02-17 16:18:02 +00:00
|
|
|
return [
|
2015-03-13 20:10:49 +00:00
|
|
|
'content' => $content,
|
|
|
|
'categorieshtml' => $categorieshtml,
|
|
|
|
'basetimestamp' => $timestamp,
|
|
|
|
'starttimestamp' => wfTimestampNow(),
|
2015-07-27 19:27:03 +00:00
|
|
|
'displayTitleHtml' => $displaytitle,
|
|
|
|
'modules' => $modules,
|
|
|
|
'jsconfigvars' => $jsconfigvars
|
2016-02-17 16:18:02 +00:00
|
|
|
];
|
2015-03-13 20:10:49 +00:00
|
|
|
}
|
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
protected function tryDeflate( $content ) {
|
|
|
|
if ( substr( $content, 0, 11 ) === 'rawdeflate,' ) {
|
|
|
|
$deflated = base64_decode( substr( $content, 11 ) );
|
|
|
|
wfSuppressWarnings();
|
|
|
|
$inflated = gzinflate( $deflated );
|
|
|
|
wfRestoreWarnings();
|
|
|
|
if ( $deflated === $inflated || $inflated === false ) {
|
|
|
|
$this->dieUsage( "Content provided is not properly deflated", 'invaliddeflate' );
|
|
|
|
}
|
|
|
|
return $inflated;
|
|
|
|
}
|
|
|
|
return $content;
|
|
|
|
}
|
|
|
|
|
2016-10-31 17:45:49 +00:00
|
|
|
protected function getWikitext( $title, $params, $parserParams ) {
|
|
|
|
if ( $params['cachekey'] !== null ) {
|
|
|
|
$wikitext = $this->trySerializationCache( $params['cachekey'] );
|
|
|
|
if ( !is_string( $wikitext ) ) {
|
|
|
|
$this->dieUsage( 'No cached serialization found with that key', 'badcachekey' );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$wikitext = $this->getWikitextNoCache( $title, $params, $parserParams );
|
|
|
|
}
|
|
|
|
return $wikitext;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getWikitextNoCache( $title, $params, $parserParams ) {
|
|
|
|
$this->requireOnlyOneParameter( $params, 'html' );
|
|
|
|
$wikitext = $this->postHTML(
|
|
|
|
$title, $this->tryDeflate( $params['html'] ), $parserParams, $params['etag']
|
|
|
|
);
|
|
|
|
if ( $wikitext === false ) {
|
|
|
|
$this->dieUsage( 'Error contacting the document server', 'docserver' );
|
|
|
|
}
|
|
|
|
return $wikitext;
|
|
|
|
}
|
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
protected function storeInSerializationCache( $title, $wikitext ) {
|
|
|
|
global $wgMemc;
|
|
|
|
|
|
|
|
if ( $wikitext === false ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the corresponding wikitext, referenceable by a new key
|
|
|
|
$hash = md5( $wikitext );
|
|
|
|
$key = wfMemcKey( 'visualeditor', 'serialization', $hash );
|
|
|
|
$wgMemc->set( $key, $wikitext,
|
|
|
|
$this->veConfig->get( 'VisualEditorSerializationCacheTimeout' ) );
|
|
|
|
|
|
|
|
// Also parse and prepare the edit in case it might be saved later
|
|
|
|
$page = WikiPage::factory( $title );
|
|
|
|
$content = ContentHandler::makeContent( $wikitext, $title, CONTENT_MODEL_WIKITEXT );
|
|
|
|
|
|
|
|
$status = ApiStashEdit::parseAndStash( $page, $content, $this->getUser(), '' );
|
|
|
|
if ( $status === ApiStashEdit::ERROR_NONE ) {
|
|
|
|
$logger = LoggerFactory::getInstance( 'StashEdit' );
|
|
|
|
$logger->debug( "Cached parser output for VE content key '$key'." );
|
|
|
|
}
|
|
|
|
$this->getStats()->increment( "editstash.ve_cache_stores.$status" );
|
|
|
|
|
|
|
|
return $hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function trySerializationCache( $hash ) {
|
|
|
|
global $wgMemc;
|
|
|
|
$key = wfMemcKey( 'visualeditor', 'serialization', $hash );
|
|
|
|
return $wgMemc->get( $key );
|
|
|
|
}
|
|
|
|
|
2016-10-31 17:45:49 +00:00
|
|
|
protected function postData( $path, $title, $data, $parserParams, $etag ) {
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( $parserParams['oldid'] === 0 ) {
|
|
|
|
$parserParams['oldid'] = '';
|
|
|
|
}
|
2016-10-31 17:45:49 +00:00
|
|
|
$path .= urlencode( $title->getPrefixedDBkey() );
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( $parserParams['oldid'] ) {
|
|
|
|
$path .= '/' . $parserParams['oldid'];
|
|
|
|
}
|
|
|
|
return $this->requestRestbase(
|
2016-10-31 17:45:49 +00:00
|
|
|
'POST', $path, $data,
|
2016-09-08 04:28:59 +00:00
|
|
|
[ 'If-Match' => $etag ]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-10-31 17:45:49 +00:00
|
|
|
protected function postHTML( $title, $html, $parserParams, $etag ) {
|
|
|
|
return $this->postData(
|
|
|
|
'transform/html/to/wikitext/', $title,
|
|
|
|
[ 'html' => $html, 'scrub_wikitext' => 1 ], $parserParams, $etag
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
protected function diffWikitext( $title, $wikitext, $section = null ) {
|
|
|
|
$apiParams = [
|
|
|
|
'action' => 'query',
|
|
|
|
'prop' => 'revisions',
|
|
|
|
'titles' => $title->getPrefixedDBkey(),
|
|
|
|
'rvdifftotext' => $this->pstWikitext( $title, $wikitext ),
|
|
|
|
'rvsection' => $section
|
|
|
|
];
|
|
|
|
|
|
|
|
$api = new ApiMain(
|
|
|
|
new DerivativeRequest(
|
|
|
|
$this->getRequest(),
|
|
|
|
$apiParams,
|
|
|
|
false // was posted?
|
|
|
|
),
|
|
|
|
false // enable write?
|
|
|
|
);
|
|
|
|
$api->execute();
|
|
|
|
$result = $api->getResult()->getResultData( null, [
|
|
|
|
'BC' => [], // Transform content nodes to '*'
|
|
|
|
'Types' => [], // Add back-compat subelements
|
|
|
|
] );
|
|
|
|
if ( !isset( $result['query']['pages'][$title->getArticleID()]['revisions'][0]['diff']['*'] ) ) {
|
|
|
|
return [ 'result' => 'fail' ];
|
|
|
|
}
|
|
|
|
$diffRows = $result['query']['pages'][$title->getArticleID()]['revisions'][0]['diff']['*'];
|
|
|
|
|
|
|
|
if ( $diffRows !== '' ) {
|
|
|
|
$context = new DerivativeContext( $this->getContext() );
|
|
|
|
$context->setTitle( $title );
|
|
|
|
$engine = new DifferenceEngine( $context );
|
|
|
|
return [
|
|
|
|
'result' => 'success',
|
|
|
|
'diff' => $engine->addHeader(
|
|
|
|
$diffRows,
|
|
|
|
$context->msg( 'currentrev' )->parse(),
|
|
|
|
$context->msg( 'yourtext' )->parse()
|
|
|
|
)
|
|
|
|
];
|
|
|
|
} else {
|
|
|
|
return [ 'result' => 'nochanges' ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-11 17:09:28 +00:00
|
|
|
public function execute() {
|
|
|
|
$user = $this->getUser();
|
|
|
|
$params = $this->extractRequestParams();
|
2016-04-29 16:00:57 +00:00
|
|
|
$title = Title::newFromText( $params['page'] );
|
|
|
|
if ( !$title ) {
|
2013-07-11 17:09:28 +00:00
|
|
|
$this->dieUsageMsg( 'invalidtitle', $params['page'] );
|
|
|
|
}
|
2016-04-29 16:00:57 +00:00
|
|
|
|
2016-02-17 16:18:02 +00:00
|
|
|
$parserParams = [];
|
2013-07-11 17:09:28 +00:00
|
|
|
if ( isset( $params['oldid'] ) ) {
|
|
|
|
$parserParams['oldid'] = $params['oldid'];
|
|
|
|
}
|
|
|
|
|
2016-11-19 14:09:16 +00:00
|
|
|
if ( isset( $params['wikitext'] ) ) {
|
|
|
|
$wikitext = $params['wikitext'];
|
|
|
|
} else {
|
2016-10-31 17:45:49 +00:00
|
|
|
$wikitext = $this->getWikitext( $title, $params, $parserParams );
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( $params['paction'] === 'serialize' ) {
|
|
|
|
$result = [ 'result' => 'success', 'content' => $wikitext ];
|
|
|
|
} elseif ( $params['paction'] === 'serializeforcache' ) {
|
|
|
|
$key = $this->storeInSerializationCache(
|
|
|
|
$title,
|
|
|
|
$wikitext
|
|
|
|
);
|
|
|
|
$result = [ 'result' => 'success', 'cachekey' => $key ];
|
|
|
|
} elseif ( $params['paction'] === 'diff' ) {
|
|
|
|
$section = isset( $params['section'] ) ? $params['section'] : null;
|
|
|
|
$diff = $this->diffWikitext( $title, $wikitext, $section );
|
|
|
|
if ( $diff['result'] === 'fail' ) {
|
|
|
|
$this->dieUsage( 'Diff failed', 'difffailed' );
|
2015-06-30 15:28:35 +00:00
|
|
|
}
|
2016-09-08 04:28:59 +00:00
|
|
|
$result = $diff;
|
|
|
|
} elseif ( $params['paction'] === 'save' ) {
|
|
|
|
$saveresult = $this->saveWikitext( $title, $wikitext, $params );
|
|
|
|
$editStatus = $saveresult['edit']['result'];
|
|
|
|
|
|
|
|
// Error
|
|
|
|
if ( $editStatus !== 'Success' ) {
|
|
|
|
$result = [
|
|
|
|
'result' => 'error',
|
|
|
|
'edit' => $saveresult['edit']
|
|
|
|
];
|
2015-06-30 15:28:35 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( isset( $saveresult['edit']['spamblacklist'] ) ) {
|
|
|
|
$matches = explode( '|', $saveresult['edit']['spamblacklist'] );
|
|
|
|
$matcheslist = $this->getLanguage()->listToText( $matches );
|
|
|
|
$result['edit']['sberrorparsed'] = $this->msg( 'spamprotectiontext' )->parse() . ' ' .
|
|
|
|
$this->msg( 'spamprotectionmatch', $matcheslist )->parse();
|
2015-04-08 20:22:48 +00:00
|
|
|
}
|
2016-09-08 04:28:59 +00:00
|
|
|
|
|
|
|
// Success
|
2015-04-08 20:22:48 +00:00
|
|
|
} else {
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( isset( $saveresult['edit']['newrevid'] ) ) {
|
|
|
|
$newRevId = intval( $saveresult['edit']['newrevid'] );
|
|
|
|
if ( $this->veConfig->get( 'VisualEditorUseChangeTagging' ) ) {
|
|
|
|
// Defer till after the RC row is inserted
|
|
|
|
// @TODO: doEditContent should let callers specify desired tags
|
|
|
|
$tag = $params['wikitext'] ? 'visualeditor-wikitext' : 'visualeditor';
|
|
|
|
DeferredUpdates::addCallableUpdate( function() use ( $tag, $newRevId ) {
|
|
|
|
ChangeTags::addTags( $tag, null, $newRevId, null );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$newRevId = $title->getLatestRevId();
|
|
|
|
}
|
2013-07-11 17:09:28 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
// Return result of parseWikitext instead of saveWikitext so that the
|
|
|
|
// frontend can update the page rendering without a refresh.
|
|
|
|
$result = $this->parseWikitext( $title, $newRevId );
|
|
|
|
if ( $result === false ) {
|
|
|
|
$this->dieUsage( 'Error contacting the Parsoid/RESTBase server', 'docserver' );
|
|
|
|
}
|
2014-11-07 00:31:34 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$result['isRedirect'] = (string) $title->isRedirect();
|
|
|
|
|
|
|
|
if ( class_exists( 'FlaggablePageView' ) ) {
|
|
|
|
$view = FlaggablePageView::singleton();
|
|
|
|
|
|
|
|
$originalRequest = $view->getContext()->getRequest();
|
|
|
|
$originalTitle = RequestContext::getMain()->getTitle();
|
|
|
|
// Defeat !$this->isPageView( $request ) || $request->getVal( 'oldid' ) check in setPageContent
|
|
|
|
$newRequest = new DerivativeRequest(
|
|
|
|
$this->getRequest(),
|
|
|
|
[
|
|
|
|
'diff' => null,
|
|
|
|
'oldid' => '',
|
|
|
|
'title' => $title->getPrefixedText(),
|
|
|
|
'action' => 'view'
|
|
|
|
] + $this->getRequest()->getValues()
|
|
|
|
);
|
|
|
|
$view->getContext()->setRequest( $newRequest );
|
|
|
|
RequestContext::getMain()->setTitle( $title );
|
|
|
|
|
|
|
|
// The two parameters here are references but we don't care
|
|
|
|
// about what FlaggedRevs does with them.
|
|
|
|
$outputDone = null;
|
|
|
|
$useParserCache = null;
|
|
|
|
$view->setPageContent( $outputDone, $useParserCache );
|
|
|
|
$view->displayTag();
|
|
|
|
$view->getContext()->setRequest( $originalRequest );
|
|
|
|
RequestContext::getMain()->setTitle( $originalTitle );
|
|
|
|
}
|
2016-04-04 16:27:46 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$context = new RequestContext;
|
|
|
|
$context->setTitle( $title );
|
|
|
|
$tempOut = new OutputPage( $context );
|
|
|
|
$tempOut->setArticleFlag( true );
|
2016-04-04 16:27:46 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$subpagestr = $this->getSkin()->subPageSubtitle( $tempOut );
|
|
|
|
if ( $subpagestr !== '' ) {
|
|
|
|
$subpagestr = '<span class="subpages">' . $subpagestr . '</span>';
|
|
|
|
}
|
|
|
|
$result['contentSub'] = $subpagestr . $this->getOutput()->getSubtitle();
|
2016-04-04 16:27:46 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$lang = $this->getLanguage();
|
2014-10-31 00:26:32 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( isset( $saveresult['edit']['newtimestamp'] ) ) {
|
|
|
|
$ts = $saveresult['edit']['newtimestamp'];
|
2014-11-17 01:00:06 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$result['lastModified'] = [
|
|
|
|
'date' => $lang->userDate( $ts, $user ),
|
|
|
|
'time' => $lang->userTime( $ts, $user )
|
|
|
|
];
|
|
|
|
}
|
2014-10-31 00:26:32 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
if ( isset( $saveresult['edit']['newrevid'] ) ) {
|
|
|
|
$result['newrevid'] = intval( $saveresult['edit']['newrevid'] );
|
|
|
|
}
|
2013-07-11 17:09:28 +00:00
|
|
|
|
2016-09-08 04:28:59 +00:00
|
|
|
$result['result'] = 'success';
|
|
|
|
}
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$this->getResult()->addValue( null, $this->getModuleName(), $result );
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAllowedParams() {
|
2016-02-17 16:18:02 +00:00
|
|
|
return [
|
2016-09-08 04:28:59 +00:00
|
|
|
'paction' => [
|
|
|
|
ApiBase::PARAM_REQUIRED => true,
|
|
|
|
ApiBase::PARAM_TYPE => [
|
|
|
|
'serialize',
|
|
|
|
'serializeforcache',
|
|
|
|
'diff',
|
|
|
|
'save',
|
|
|
|
],
|
|
|
|
ApiBase::PARAM_DFLT => 'save',
|
|
|
|
],
|
2016-02-17 16:18:02 +00:00
|
|
|
'page' => [
|
2013-07-11 17:09:28 +00:00
|
|
|
ApiBase::PARAM_REQUIRED => true,
|
2016-02-17 16:18:02 +00:00
|
|
|
],
|
|
|
|
'token' => [
|
2013-07-11 17:09:28 +00:00
|
|
|
ApiBase::PARAM_REQUIRED => true,
|
2016-02-17 16:18:02 +00:00
|
|
|
],
|
2013-07-11 17:09:28 +00:00
|
|
|
'wikitext' => null,
|
2016-09-06 19:16:55 +00:00
|
|
|
'section' => null,
|
2013-07-11 17:09:28 +00:00
|
|
|
'basetimestamp' => null,
|
|
|
|
'starttimestamp' => null,
|
|
|
|
'oldid' => null,
|
|
|
|
'minor' => null,
|
|
|
|
'watch' => null,
|
|
|
|
'html' => null,
|
2015-10-08 22:16:56 +00:00
|
|
|
'etag' => null,
|
2013-07-11 17:09:28 +00:00
|
|
|
'summary' => null,
|
|
|
|
'captchaid' => null,
|
|
|
|
'captchaword' => null,
|
2013-11-01 21:30:22 +00:00
|
|
|
'cachekey' => null,
|
2016-02-17 16:18:02 +00:00
|
|
|
];
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function needsToken() {
|
2014-08-09 13:08:14 +00:00
|
|
|
return 'csrf';
|
2013-07-11 17:09:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function mustBePosted() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isWriteMode() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|