'ApiRsd' => __DIR__ . '/includes/api/ApiRsd.php',
'ApiSerializable' => __DIR__ . '/includes/api/ApiSerializable.php',
'ApiSetNotificationTimestamp' => __DIR__ . '/includes/api/ApiSetNotificationTimestamp.php',
+ 'ApiSetPageLanguage' => __DIR__ . '/includes/api/ApiSetPageLanguage.php',
'ApiStashEdit' => __DIR__ . '/includes/api/ApiStashEdit.php',
'ApiTag' => __DIR__ . '/includes/api/ApiTag.php',
'ApiTokens' => __DIR__ . '/includes/api/ApiTokens.php',
'managetags' => 'ApiManageTags',
'tag' => 'ApiTag',
'mergehistory' => 'ApiMergeHistory',
+ 'setpagelanguage' => 'ApiSetPageLanguage',
];
/**
--- /dev/null
+<?php
+/**
+ *
+ *
+ * Created on January 1, 2017
+ *
+ * Copyright © 2017 Justin Du "<justin.d128@gmail.com>"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * API module that facilitates changing the language of a page.
+ * The API equivalent of SpecialPageLanguage.
+ * Requires API write mode to be enabled.
+ *
+ * @ingroup API
+ */
+class ApiSetPageLanguage extends ApiBase {
+ // Check if change language feature is enabled
+ protected function getDescriptionMessage() {
+ if ( !$this->getConfig()->get( 'PageLanguageUseDB' ) ) {
+ return 'apihelp-setpagelanguage-description-disabled';
+ }
+ return parent::getDescriptionMessage();
+ }
+
+ /**
+ * Extracts the title and language from the request parameters and invokes
+ * the static SpecialPageLanguage::changePageLanguage() function with these as arguments.
+ * If the language change succeeds, the title, old language, and new language
+ * of the article changed, as well as the performer of the language change
+ * are added to the result object.
+ */
+ public function execute() {
+ // Check if change language feature is enabled
+ if ( !$this->getConfig()->get( 'PageLanguageUseDB' ) ) {
+ $this->dieWithError( 'apierror-pagelang-disabled' );
+ }
+
+ // Check if the user has permissions
+ $this->checkUserRightsAny( 'pagelang' );
+
+ $this->useTransactionalTimeLimit();
+
+ $params = $this->extractRequestParams();
+
+ $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
+ if ( !$pageObj->exists() ) {
+ $this->dieWithError( 'apierror-missingtitle' );
+ }
+
+ $titleObj = $pageObj->getTitle();
+ $user = $this->getUser();
+
+ // Check that the user is allowed to edit the page
+ $this->checkTitleUserPermissions( $titleObj, 'edit' );
+
+ // If change tagging was requested, check that the user is allowed to tag,
+ // and the tags are valid
+ if ( count( $params['tags'] ) ) {
+ $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
+ if ( !$tagStatus->isOK() ) {
+ $this->dieStatus( $tagStatus );
+ }
+ }
+
+ $status = SpecialPageLanguage::changePageLanguage(
+ $this,
+ $titleObj,
+ $params['lang'],
+ $params['tags'] ?: []
+ );
+
+ if ( !$status->isOK() ) {
+ $this->dieStatus( $status );
+ }
+
+ $r = [
+ 'title' => $titleObj->getPrefixedText(),
+ 'oldlanguage' => $status->value->oldLanguage,
+ 'newlanguage' => $status->value->newLanguage,
+ 'logid' => $status->value->logId
+ ];
+ $this->getResult()->addValue( null, $this->getModuleName(), $r );
+ }
+
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function isWriteMode() {
+ return true;
+ }
+
+ public function getAllowedParams() {
+ return [
+ 'title' => null,
+ 'pageid' => [
+ ApiBase::PARAM_TYPE => 'integer'
+ ],
+ 'lang' => [
+ ApiBase::PARAM_TYPE => array_merge(
+ [ 'default' ],
+ array_keys( Language::fetchLanguageNames( null, 'mwfile' ) )
+ ),
+ ApiBase::PARAM_REQUIRED => true,
+ ],
+ 'tags' => [
+ ApiBase::PARAM_TYPE => 'tags',
+ ApiBase::PARAM_ISMULTI => true,
+ ],
+ ];
+ }
+
+ public function needsToken() {
+ return 'csrf';
+ }
+
+ protected function getExamplesMessages() {
+ return [
+ 'action=setpagelanguage&title=Main%20Page&lang=eu&token=123ABC'
+ => 'apihelp-setpagelanguage-example-language',
+ 'action=setpagelanguage&pageid=123&lang=default&token=123ABC'
+ => 'apihelp-setpagelanguage-example-default',
+ ];
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/API:SetPageLanguage';
+ }
+}
"apihelp-setnotificationtimestamp-example-pagetimestamp": "Set the notification timestamp for <kbd>Main page</kbd> so all edits since 1 January 2012 are unviewed.",
"apihelp-setnotificationtimestamp-example-allpages": "Reset the notification status for pages in the <kbd>{{ns:user}}</kbd> namespace.",
+ "apihelp-setpagelanguage-description": "Change the language of a page.",
+ "apihelp-setpagelanguage-description-disabled": "Changing the language of a page is not allowed on this wiki.\n\nEnable <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> to use the API.",
+ "apihelp-setpagelanguage-param-title": "Title of the page whose language you wish to change. Cannot be used together with <var>$1pageid</var>.",
+ "apihelp-setpagelanguage-param-pageid": "Page ID of the page whose language you wish to change. Cannot be used together with <var>$1title</var>.",
+ "apihelp-setpagelanguage-param-lang": "Language code of the language to change the page to. Use <kbd>default</kbd> to reset the page to the wiki's default content language.",
+ "apihelp-setpagelanguage-param-tags": "Change tags to apply to the log entry resulting from this action.",
+ "apihelp-setpagelanguage-example-language": "Change the language of <kbd>Main Page</kbd> to Basque.",
+ "apihelp-setpagelanguage-example-default": "Change the language of the page with ID 123 to the wiki's default content language.",
+
"apihelp-stashedit-description": "Prepare an edit in shared cache.\n\nThis is intended to be used via AJAX from the edit form to improve the performance of the page save.",
"apihelp-stashedit-param-title": "Title of the page being edited.",
"apihelp-stashedit-param-section": "Section number. <kbd>0</kbd> for the top section, <kbd>new</kbd> for a new section.",
"apierror-opensearch-json-warnings": "Warnings cannot be represented in OpenSearch JSON format.",
"apierror-pagecannotexist": "Namespace doesn't allow actual pages.",
"apierror-pagedeleted": "The page has been deleted since you fetched its timestamp.",
+ "apierror-pagelang-disabled": "Changing the language of a page is not allowed on this wiki.",
"apierror-paramempty": "The parameter <var>$1</var> may not be empty.",
"apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> is only supported for wikitext content.",
"apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> is only supported for wikitext content. $1 uses content model $2.",
"apihelp-setnotificationtimestamp-example-page": "{{doc-apihelp-example|setnotificationtimestamp}}",
"apihelp-setnotificationtimestamp-example-pagetimestamp": "{{doc-apihelp-example|setnotificationtimestamp}}",
"apihelp-setnotificationtimestamp-example-allpages": "{{doc-apihelp-example|setnotificationtimestamp}}",
+ "apihelp-setpagelanguage-description": "{{doc-apihelp-description|setpagelanguage}}",
+ "apihelp-setpagelanguage-description-disabled": "{{doc-apihelp-description|setpagelanguage|info=This message is used when changing the language of a page is not allowed on the wiki because <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> is not enabled.|seealso={{msg-mw|apihelp-setpagelanguage-description}}}}",
+ "apihelp-setpagelanguage-param-title": "{{doc-apihelp-param|setpagelanguage|title}}",
+ "apihelp-setpagelanguage-param-pageid": "{{doc-apihelp-param|setpagelanguage|pageid}}",
+ "apihelp-setpagelanguage-param-lang": "{{doc-apihelp-param|setpagelanguage|lang}}",
+ "apihelp-setpagelanguage-param-tags": "{{doc-apihelp-param|setpagelanguage|tags}}",
+ "apihelp-setpagelanguage-example-language": "{{doc-apihelp-example|setpagelanguage}}",
+ "apihelp-setpagelanguage-example-default": "{{doc-apihelp-example|setpagelanguage}}",
"apihelp-stashedit-description": "{{doc-apihelp-description|stashedit}}",
"apihelp-stashedit-param-title": "{{doc-apihelp-param|stashedit|title}}",
"apihelp-stashedit-param-section": "{{doc-apihelp-param|stashedit|section}}",
"apierror-opensearch-json-warnings": "{{doc-apierror}}",
"apierror-pagecannotexist": "{{doc-apierror}}",
"apierror-pagedeleted": "{{doc-apierror}}",
+ "apierror-pagelang-disabled": "{{doc-apierror}}",
"apierror-paramempty": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
"apierror-parsetree-notwikitext": "{{doc-apierror}}",
"apierror-parsetree-notwikitext-title": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
/**
*
* @param array $data
- * @return bool
+ * @return Status
*/
public function onSubmit( array $data ) {
- $title = Title::newFromText( $data['pagename'] );
+ $pageName = $data['pagename'];
- // Check if title is valid
- if ( !$title ) {
- return false;
+ // Check if user wants to use default language
+ if ( $data['selectoptions'] == 1 ) {
+ $newLanguage = 'default';
+ } else {
+ $newLanguage = $data['language'];
+ }
+
+ try {
+ $title = Title::newFromTextThrow( $pageName );
+ } catch ( MalformedTitleException $ex ) {
+ return Status::newFatal( $ex->getMessageObject() );
}
+ // Url to redirect to after the operation
+ $this->goToUrl = $title->getFullURL();
+
+ return self::changePageLanguage( $this->getContext(), $title, $newLanguage );
+ }
+
+ /**
+ * @param IContextSource $context
+ * @param Title $title
+ * @param string $newLanguage Language code
+ * @param array $tags Change tags to apply to the log entry
+ * @return Status
+ */
+ public static function changePageLanguage( IContextSource $context, Title $title,
+ $newLanguage, array $tags = [] ) {
// Get the default language for the wiki
- $defLang = $this->getConfig()->get( 'LanguageCode' );
+ $defLang = $context->getConfig()->get( 'LanguageCode' );
$pageId = $title->getArticleID();
// Check if article exists
if ( !$pageId ) {
- return false;
+ return Status::newFatal(
+ 'pagelang-nonexistent-page',
+ wfEscapeWikiText( $title->getPrefixedText() )
+ );
}
// Load the page language from DB
$dbw = wfGetDB( DB_MASTER );
- $langOld = $dbw->selectField(
+ $oldLanguage = $dbw->selectField(
'page',
'page_lang',
[ 'page_id' => $pageId ],
__METHOD__
);
- // Url to redirect to after the operation
- $this->goToUrl = $title->getFullURL();
-
- // Check if user wants to use default language
- if ( $data['selectoptions'] == 1 ) {
- $langNew = null;
- } else {
- $langNew = $data['language'];
+ // Check if user wants to use the default language
+ if ( $newLanguage === 'default' ) {
+ $newLanguage = null;
}
// No change in language
- if ( $langNew === $langOld ) {
- return false;
+ if ( $newLanguage === $oldLanguage ) {
+ // Check if old language does not exist
+ if ( !$oldLanguage ) {
+ return Status::newFatal(
+ 'pagelang-unchanged-language-default',
+ wfEscapeWikiText( $title->getPrefixedText() )
+ );
+ }
+ return Status::newFatal(
+ 'pagelang-unchanged-language',
+ wfEscapeWikiText( $title->getPrefixedText() ),
+ $oldLanguage
+ );
}
// Hardcoded [def] if the language is set to null
- $logOld = $langOld ? $langOld : $defLang . '[def]';
- $logNew = $langNew ? $langNew : $defLang . '[def]';
+ $logOld = $oldLanguage ? $oldLanguage : $defLang . '[def]';
+ $logNew = $newLanguage ? $newLanguage : $defLang . '[def]';
// Writing new page language to database
- $dbw = wfGetDB( DB_MASTER );
$dbw->update(
'page',
- [ 'page_lang' => $langNew ],
+ [ 'page_lang' => $newLanguage ],
[
'page_id' => $pageId,
- 'page_lang' => $langOld
+ 'page_lang' => $oldLanguage
],
__METHOD__
);
if ( !$dbw->affectedRows() ) {
- return false;
+ return Status::newFatal( 'pagelang-db-failed' );
}
// Logging change of language
'5::newlanguage' => $logNew
];
$entry = new ManualLogEntry( 'pagelang', 'pagelang' );
- $entry->setPerformer( $this->getUser() );
+ $entry->setPerformer( $context->getUser() );
$entry->setTarget( $title );
$entry->setParameters( $logParams );
+ $entry->setTags( $tags );
$logid = $entry->insert();
$entry->publish( $logid );
// Force re-render so that language-based content (parser functions etc.) gets updated
$title->invalidateCache();
- return true;
+ return Status::newGood( (object)[
+ 'oldLanguage' => $logOld,
+ 'newLanguage' => $logNew,
+ 'logId' => $logid,
+ ] );
}
public function onSuccess() {
"pagelang-use-default": "Use default language",
"pagelang-select-lang": "Select language",
"pagelang-submit": "Submit",
+ "pagelang-nonexistent-page": "The page $1 does not exist.",
+ "pagelang-unchanged-language": "The page $1 is already set to language $2.",
+ "pagelang-unchanged-language-default": "The page $1 is already set to the wiki's default content language.",
+ "pagelang-db-failed": "The database failed to change the page language.",
"right-pagelang": "Change page language",
"action-pagelang": "change the page language",
"log-name-pagelang": "Language change log",
"pagelang-use-default": "Radio label for selector on Special:PageLanguage for default language",
"pagelang-select-lang": "Radio label for selector on Special:PageLanguage for language selection\n{{Identical|Select language}}",
"pagelang-submit": "Submit button label for Special:PageLanguage form\n{{Identical|Submit}}",
+ "pagelang-nonexistent-page": "Error message shown when the page the user is trying to change the language on does not exist.\n\nParameters:\n* $1 - the title of the nonexistent page",
+ "pagelang-unchanged-language": "Error message shown when the language the user is trying to change the page to and the current language the page is in are the same.\n\nParameters:\n* $1 - the title of the target page\n* $2 - the current language of the page",
+ "pagelang-unchanged-language-default": "Error message shown when the language the user is trying to change the page to is already the wiki's default content language.\n\nParameters:\n* $1 - the title of the target page",
+ "pagelang-db-failed": "Error message shown when the database fails to update the language of the page",
"right-pagelang": "{{Doc-right|pagelang}}\nRight to change page language on Special:PageLanguage",
"action-pagelang": "{{Doc-action|pagelang}}",
"log-name-pagelang": "Display entry for log name for changes in page language in Special:Log.",