From fde54a83958f13a1956c18df0b94c3387035c96f Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Mon, 12 Jan 2009 16:39:04 +0000 Subject: [PATCH] API: (bug 16858) Revamped list=deletedrevs to make listing deleted contributions and all deleted pages possible. This reintroduces drnamespace (removed earlier because of performance concerns, now implemented efficiently) and introduces druser, drexcludeuser, drfrom, drcontinue and drunique --- RELEASE-NOTES | 2 + includes/api/ApiQueryDeletedrevs.php | 123 +++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 15 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index d744a0cd78..c16d887d2e 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -44,6 +44,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * (bug 16798) JSON encoding errors for some characters outside the BMP * (bug 16629) prop=info&inprop=protection lists empty legacy protections incorrectly +* (bug 16858) Revamped list=deletedrevs to make listing deleted contributions + and listing all deleted pages possible === Languages updated in 1.15 === diff --git a/includes/api/ApiQueryDeletedrevs.php b/includes/api/ApiQueryDeletedrevs.php index fcb80d52df..36490eb5bc 100644 --- a/includes/api/ApiQueryDeletedrevs.php +++ b/includes/api/ApiQueryDeletedrevs.php @@ -56,11 +56,24 @@ class ApiQueryDeletedrevs extends ApiQueryBase { $fld_len = isset($prop['len']); $fld_content = isset($prop['content']); $fld_token = isset($prop['token']); - + $result = $this->getResult(); $pageSet = $this->getPageSet(); $titles = $pageSet->getTitles(); $data = array(); + + // This module operates in three modes: + // 'revs': List deleted revs for certain titles + // 'user': List deleted revs by a certain user + // 'all': List all deleted revs + $mode = 'all'; + if(count($titles) > 0) + $mode = 'revs'; + else if(!is_null($params['user'])) + $mode = 'user'; + + if(!is_null($params['user']) && !is_null($params['excludeuser'])) + $this->dieUsage('user and excludeuser cannot be used together', 'badparams'); $this->addTables('archive'); $this->addFields(array('ar_title', 'ar_namespace', 'ar_timestamp')); @@ -102,17 +115,63 @@ class ApiQueryDeletedrevs extends ApiQueryBase { $token = $wgUser->editToken(); // We need a custom WHERE clause that matches all titles. - if(count($titles) > 0) + if($mode == 'revs') { $lb = new LinkBatch($titles); $where = $lb->constructSet('ar', $db); $this->addWhere($where); - } else { - $this->dieUsage('You have to specify a page title or titles'); + } + elseif($mode == 'all') + { + $this->addWhereFld('ar_namespace', $params['namespace']); + if(!is_null($params['from'])) + { + $from = $this->getDB()->strencode($this->titleToKey($params['from'])); + $this->addWhere("ar_title >= '$from'"); + } + } + + if(!is_null($params['user'])) { + $this->addWhereFld('ar_user_text', $params['user']); + } elseif(!is_null($params['excludeuser'])) { + $this->addWhere('ar_user_text != ' . + $this->getDB()->addQuotes($params['excludeuser'])); + } + + if(!is_null($params['continue']) && $mode == 'all') + { + $cont = explode('|', $params['continue']); + if(count($cont) != 2) + $this->dieUsage("Invalid continue param. You should pass the original value returned by the previous query", "badcontinue"); + $title = $this->getDB()->strencode($this->titleToKey($cont[0])); + $ts = $this->getDB()->strencode($cont[1]); + $this->addWhere("ar_title > '$title' OR " . + "(ar_title = '$title' AND " . + "ar_timestamp >= '$ts')"); } $this->addOption('LIMIT', $limit + 1); - $this->addWhereRange('ar_timestamp', $params['dir'], $params['start'], $params['end']); + $this->addOption('USE INDEX', array('archive' => ($mode == 'user' ? 'usertext_timestamp' : 'name_title_timestamp'))); + if($mode == 'all') + { + if($params['unique']) + { + $this->addOption('GROUP BY', 'ar_title'); + $this->addOption('ORDER BY', 'ar_title'); + } + else + $this->addOption('ORDER BY', 'ar_title, ar_timestamp'); + } + else + { + if($mode == 'revs') + { + // Sort by ns and title in the same order as timestamp for efficiency + $this->addWhereRange('ar_namespace', $params['dir'], null, null); + $this->addWhereRange('ar_title', $params['dir'], null, null); + } + $this->addWhereRange('ar_timestamp', $params['dir'], $params['start'], $params['end']); + } $res = $this->select(__METHOD__); $pages = array(); $count = 0; @@ -122,7 +181,11 @@ class ApiQueryDeletedrevs extends ApiQueryBase { if(++$count > $limit) { // We've had enough - $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ar_timestamp)); + if($mode == 'all') + $this->setContinueEnumParameter('continue', $this->keyToTitle($row->ar_title) . '|' . + $row->ar_timestamp); + else + $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->ar_timestamp)); break; } @@ -183,6 +246,19 @@ class ApiQueryDeletedrevs extends ApiQueryBase { ), ApiBase :: PARAM_DFLT => 'older' ), + 'from' => null, + 'continue' => null, + 'unique' => false, + 'user' => array( + ApiBase :: PARAM_TYPE => 'user' + ), + 'excludeuser' => array( + ApiBase :: PARAM_TYPE => 'user' + ), + 'namespace' => array( + ApiBase :: PARAM_TYPE => 'namespace', + ApiBase :: PARAM_DFLT => 0, + ), 'limit' => array( ApiBase :: PARAM_DFLT => 10, ApiBase :: PARAM_TYPE => 'limit', @@ -202,30 +278,47 @@ class ApiQueryDeletedrevs extends ApiQueryBase { 'token' ), ApiBase :: PARAM_ISMULTI => true - ) + ), ); } public function getParamDescription() { return array ( - 'start' => 'The timestamp to start enumerating from', - 'end' => 'The timestamp to stop enumerating at', - 'dir' => 'The direction in which to enumerate', + 'start' => 'The timestamp to start enumerating from. (1,2)', + 'end' => 'The timestamp to stop enumerating at. (1,2)', + 'dir' => 'The direction in which to enumerate. (1,2)', 'limit' => 'The maximum amount of revisions to list', - 'prop' => 'Which properties to get' + 'prop' => 'Which properties to get', + 'namespace' => 'Only list pages in this namespace (3)', + 'user' => 'Only list revisions by this user', + 'excludeuser' => 'Don\'t list revisions by this user', + 'from' => 'Start listing at this title (3)', + 'continue' => 'When more results are available, use this to continue (3)', + 'unique' => 'List only one revision for each page (3)', ); } public function getDescription() { - return 'List deleted revisions.'; + return array( 'List deleted revisions.', + 'This module operates in three modes:', + '1) List deleted revisions for the given title(s), sorted by timestamp', + '2) List deleted contributions for the given user, sorted by timestamp (no titles specified)', + '3) List all deleted revisions in the given namespace, sorted by title and timestamp (no titles specified, druser not set)', + 'Certain parameters only apply to some modes and are ignored in others.', + 'For instance, a parameter marked (1) only applies to mode 1 and is ignored in modes 2 and 3.', + ); } protected function getExamples() { return array ( - 'List the first 50 deleted revisions', + 'List the last deleted revisions of Main Page and Talk:Main Page, with content (mode 1):', + ' api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content', + 'List the last 50 deleted contributions by Bob (mode 2):', + ' api.php?action=query&list=deletedrevs&druser=Bob&drlimit=50', + 'List the first 50 deleted revisions in the main namespace (mode 3):', ' api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50', - 'List the last deleted revisions of Main Page and Talk:Main Page, with content:', - ' api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content' + 'List the first 50 deleted pages in the Talk namespace (mode 3):', + ' api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50&drnamespace=1&drunique', ); } -- 2.20.1