Mainframe98 has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/341133 )
Change subject: add an API module for Nuke
......................................................................
add an API module for Nuke
This patch introduces an API module.
The pattern field is untested as it currently does not work on
the special page. See T154276. This should function after the
aforementioned bug is fixed, as it just passes the parameter
content to the function in the special page.
Also: please note that this patch is developed against 1.29, and
utilizes API methods provided since said version.
Bug: T35470
Change-Id: I1100fc6254fc353c95a51b0cc7af282dc75005e6
---
A Nuke.api.php
M Nuke_body.php
M extension.json
M i18n/en.json
M i18n/qqq.json
5 files changed, 235 insertions(+), 7 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Nuke
refs/changes/33/341133/1
diff --git a/Nuke.api.php b/Nuke.api.php
new file mode 100644
index 0000000..ec6b923
--- /dev/null
+++ b/Nuke.api.php
@@ -0,0 +1,201 @@
+<?php
+
+class NukeApi extends ApiBase {
+
+ public function execute() {
+ $apiResult = $this->getResult();
+ $params = $this->extractRequestParams();
+
+ // Check the user rights. You need both to use this module.
+ // nuke to restrict usage to privileged users, delete to do the
actual deleting
+ $this->checkUserRightsAny( 'nuke' );
+ $this->checkUserRightsAny( 'delete' );
+
+ $this->requireMaxOneParameter( $params, 'username', 'userid' );
+
+ $pages = $this->getPages( $params );
+
+ $reason = $params['reason'];
+
+ if ( $reason === null ) {
+ if ( $params['username'] === null ) {
+ $reason = wfMessage( 'nuke-multiplepeople'
)->inContentLanguage()->text();
+ } else {
+ $reason = wfMessage( 'nuke-defaultreason',
$params['username'] )
+
->inContentLanguage()->text();
+ }
+ }
+
+ $excludedTitles = [];
+
+ if ( $params['exclude'] !== null ) {
+ foreach ( $params['exclude'] as $page ) {
+ $title = Title::newFromText( $page );
+ if ( $title !== null ) {
+ $excludedTitles[] = $title;
+ }
+ }
+ }
+
+ $result = $this->doDelete( $pages, $excludedTitles, $reason );
+
+ if ( $params['username'] !== '' ) {
+ $apiResult->addValue( $this->getModuleName(), 'user',
$params['username'] );
+ }
+
+ $apiResult->addValue( $this->getModuleName(), 'reason', $reason
);
+ $apiResult->addValue( $this->getModuleName(), 'pages', $result
);
+ $apiResult->addValue( $this->getModuleName(), 'excluded',
$excludedTitles );
+
+ }
+
+ /**
+ * Gets the set of pages to nuke.
+ *
+ * @param array $params parameters passed to this module
+ * @return array
+ */
+ private function getPages( array $params ) {
+
+ if ( $params['userid'] !== null ) {
+ $username = User::whoIs( $params['userid'] );
+ if ( $username === false ) {
+ $this->dieWithError( [ 'apierror-nosuchuserid',
$params['userid'] ], 'nosuchuserid' );
+ } else {
+ $params['username'] = $username;
+ }
+ } elseif ( $params['username'] !== null ) {
+ $target = User::newFromName( $params['username'] );
+
+ // Bug 38633 - if the target is a user (not an IP
address), but it
+ // doesn't exist or is unusable, error.
+ if ( $target instanceof User &&
+ ( $target->isAnon() /* doesn't exist */ ||
!User::isUsableName( $target->getName() ) )
+ ) {
+ $this->dieWithError( [ 'nosuchusershort',
$params['username'] ], 'nosuchuser' );
+ }
+ } else {
+ $params['username'] = '';
+ }
+
+ $pages = SpecialNuke::getNewPages( $params['username'],
$params['limit'], $params['pattern'],
+ $params['namespace'] );
+
+ return $pages;
+ }
+
+ /**
+ * Does the actual deletion of the pages.
+ * Because the one in Nuke_body.php has integrated UI elements
+ * and there's no way to specify pages skipped (due the way Special:Nuke
+ * works), the api needs its own.
+ *
+ * @param array $pages The pages to delete
+ * @param array $excludeTitles The pages to exclude from deletion
+ * @param string $reason
+ * @return array
+ */
+ private function doDelete( array $pages, array $excludeTitles, $reason
) {
+
+ $results = [];
+
+ foreach ( $pages as list( $page ) ) {
+ $isMatch = false;
+
+ foreach ( $excludeTitles as $index => $title ) {
+ $isMatch = $title->getText() == $page->getText()
+ &&
$title->getNamespace() == $page->getNamespace();
+ if ( $isMatch ) {
+ unset( $excludeTitles[$index] );
+ break;
+ }
+ }
+
+ // Skip the page if it was in the list of excludedTitles
+ if ( $isMatch ) {
+ continue;
+ }
+
+ $result = [];
+
+ ApiQueryBase::addTitleInfo( $result, $page );
+
+ $deletionResult = false;
+ if ( !Hooks::run( 'NukeDeletePage', [ $page, $reason,
&$deletionResult ] ) ) {
+ $result['missing'] = $deletionResult;
+ continue;
+ }
+
+ $file = $page->getNamespace() === NS_FILE ?
wfLocalFile( $page ) : false;
+
+ if ( $file ) {
+ $oldimage = null; // Must be passed by reference
+ $result['missing'] = FileDeleteForm::doDelete(
$page, $file, $oldimage, $reason, false )->isOK();
+ } else {
+ $article = new Article( $page, 0 );
+ $result['missing'] = $article->doDeleteArticle(
$reason );
+ }
+
+ $results[] = $result;
+ }
+
+ return $results;
+ }
+
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function needsToken() {
+ return 'csrf';
+ }
+
+ public function isWriteMode() {
+ return true;
+ }
+
+ public function getAllowedParams() {
+ return array_merge( parent::getAllowedParams(), [
+ 'username' => [
+ ApiBase::PARAM_TYPE => 'user'
+ ],
+ 'userid' => [
+ ApiBase::PARAM_TYPE => 'integer',
+ ],
+ 'pattern' => [
+ ApiBase::PARAM_TYPE => 'string'
+ ],
+ 'namespace' => [
+ ApiBase::PARAM_TYPE => 'namespace'
+ ],
+ 'limit' => [
+ ApiBase::PARAM_DFLT => 500,
+ ApiBase::PARAM_TYPE => 'limit',
+ ApiBase::PARAM_MIN => 1,
+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+ ],
+ 'exclude' => [
+ ApiBase::PARAM_ISMULTI => true,
+ ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+ ],
+ 'reason' => [
+ ApiBase::PARAM_TYPE => 'string'
+ ]
+ ] );
+ }
+
+ public function getExamplesMessages() {
+ return [
+ 'action=nuke&user=Bob&token=123ABC+\\' =>
'apihelp-nuke-example-user',
+
'action=nuke&user=Bob&exclude=User%3ABob|User%20talk%3ABob&token=123ABC+\\' =>
'apihelp-nuke-example-exclude-pages',
+ 'action=nuke&namespace=1&limit=25&token=123ABC+\\' =>
'apihelp-nuke-example-nouser',
+ ];
+ }
+
+ public function getHelpUrls() {
+ return 'https://www.mediawiki.org/wiki/Extension:Nuke/API';
+ }
+}
diff --git a/Nuke_body.php b/Nuke_body.php
index 1887be9..656fb40 100644
--- a/Nuke_body.php
+++ b/Nuke_body.php
@@ -133,7 +133,8 @@
protected function listForm( $username, $reason, $limit, $namespace =
null ) {
$out = $this->getOutput();
- $pages = $this->getNewPages( $username, $limit, $namespace );
+ $pattern = $this->getRequest()->getText( 'pattern' );
+ $pages = SpecialNuke::getNewPages( $username, $limit, $pattern,
$namespace );
if ( count( $pages ) === 0 ) {
if ( $username === '' ) {
@@ -246,11 +247,12 @@
*
* @param string $username
* @param integer $limit
+ * @param string $pattern
* @param integer|null $namespace
*
* @return array
*/
- protected function getNewPages( $username, $limit, $namespace = null ) {
+ public static function getNewPages( $username, $limit, $pattern,
$namespace = null ) {
$dbr = wfGetDB( DB_SLAVE );
$what = [
@@ -271,7 +273,6 @@
$where['rc_namespace'] = $namespace;
}
- $pattern = $this->getRequest()->getText( 'pattern' );
if ( !is_null( $pattern ) && trim( $pattern ) !== '' ) {
$where[] = 'rc_title ' . $dbr->buildLike( $pattern );
}
diff --git a/extension.json b/extension.json
index 329d7df..610b143 100644
--- a/extension.json
+++ b/extension.json
@@ -1,6 +1,6 @@
{
"name": "Nuke",
- "version": "1.3.0",
+ "version": "1.4.0",
"author": [
"Brion Vibber",
"Jeroen De Dauw"
@@ -47,9 +47,13 @@
"SpecialPages": {
"Nuke": "SpecialNuke"
},
+ "APIModules": {
+ "nuke": "NukeApi"
+ },
"AutoloadClasses": {
"SpecialNuke": "Nuke_body.php",
- "NukeHooks": "Nuke.hooks.php"
+ "NukeHooks": "Nuke.hooks.php",
+ "NukeApi": "Nuke.api.php"
},
"manifest_version": 1
}
diff --git a/i18n/en.json b/i18n/en.json
index d8f29a2..f3d9500 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -30,5 +30,16 @@
"nuke-viewchanges": "view changes",
"nuke-namespace": "Limit to namespace:",
"nuke-linkoncontribs": "mass delete",
- "nuke-linkoncontribs-text": "Mass delete pages where this user is the
only author"
+ "nuke-linkoncontribs-text": "Mass delete pages where this user is the
only author",
+ "apihelp-nuke-description": "Mass delete pages through the API",
+ "apihelp-nuke-param-username": "Username of the user or IP address to
nuke. Cannot be used together with <var>$1userid</var>",
+ "apihelp-nuke-param-userid": "User ID. Cannot be used together with
<var>$1username</var>.",
+ "apihelp-nuke-param-pattern": "Pattern for the page name.",
+ "apihelp-nuke-param-namespace": "Namespace to limit.",
+ "apihelp-nuke-param-limit": "Maximum number of pages to nuke.",
+ "apihelp-nuke-param-exclude": "Pages to exclude from deletion.",
+ "apihelp-nuke-param-reason": "Reason for the deletion. If not set, an
automatically generated reason will be used.",
+ "apihelp-nuke-example-user": "Delete pages created by <kbd>Bob</kbd>,
with the default summary.",
+ "apihelp-nuke-example-exclude-pages": "Delete pages created by
<kbd>Bob<kbd>, with the default summary, but exclude his user and talk page.",
+ "apihelp-nuke-example-nouser": "Delete the newest 25 pages in the
article talk namespace."
}
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 93c0ca0..5c5836b 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -41,5 +41,16 @@
"nuke-viewchanges": "Used as link text.\n\nThe link points to History
page of the page.\n\nThis message follows:\n* {{msg-mw|nuke-editby}} and
{{msg-mw|comma-separator}}\n* or empty string (if username is
empty).\n{{Identical|View changes}}",
"nuke-namespace": "Label shown on [[Special:Nuke]] in front of the
namespace input that allows choosing a namespace to filter the search by",
"nuke-linkoncontribs": "Used as link text which is used on
[[Special:Contributions]] and [[Special:DeletedContributions]].\n\nOnly added
if a user has rights to nuke pages.\n\nThe link has the tooltip
{{msg-mw|Nuke-linkoncontribs-text}}.\n{{Identical|Mass delete}}",
- "nuke-linkoncontribs-text": "Tooltip for the link which is labeled
{{msg-mw|Nuke-linkoncontribs}}."
+ "nuke-linkoncontribs-text": "Tooltip for the link which is labeled
{{msg-mw|Nuke-linkoncontribs}}.",
+ "apihelp-nuke-description": "{{doc-apihelp-description|nuke}}",
+ "apihelp-nuke-param-username": "{{doc-apihelp-param|nuke|username}}",
+ "apihelp-nuke-param-userid": "{{doc-apihelp-param|nuke|userid}}",
+ "apihelp-nuke-param-pattern": "{{doc-apihelp-param|nuke|pattern}}",
+ "apihelp-nuke-param-namespace": "{{doc-apihelp-param|nuke|namespace}}",
+ "apihelp-nuke-param-limit": "{{doc-apihelp-param|nuke|limit}}",
+ "apihelp-nuke-param-exclude": "{{doc-apihelp-param|nuke|exclude}}",
+ "apihelp-nuke-param-reason": "{{doc-apihelp-param|nuke|reason}}",
+ "apihelp-nuke-example-user": "{{doc-apihelp-example|nuke}}",
+ "apihelp-nuke-example-exclude-pages": "{{doc-apihelp-example|nuke}}",
+ "apihelp-nuke-example-nouser": "{{doc-apihelp-example|nuke}}"
}
--
To view, visit https://gerrit.wikimedia.org/r/341133
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1100fc6254fc353c95a51b0cc7af282dc75005e6
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Nuke
Gerrit-Branch: master
Gerrit-Owner: Mainframe98 <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits