ApiQueryWatchlist.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. /*
  3. * Created on Sep 25, 2006
  4. *
  5. * API for MediaWiki 1.8+
  6. *
  7. * Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. * http://www.gnu.org/copyleft/gpl.html
  23. */
  24. if (!defined('MEDIAWIKI')) {
  25. // Eclipse helper - will be ignored in production
  26. require_once ('ApiQueryBase.php');
  27. }
  28. /**
  29. * This query action allows clients to retrieve a list of recently modified pages
  30. * that are part of the logged-in user's watchlist.
  31. *
  32. * @ingroup API
  33. */
  34. class ApiQueryWatchlist extends ApiQueryGeneratorBase {
  35. public function __construct($query, $moduleName) {
  36. parent :: __construct($query, $moduleName, 'wl');
  37. }
  38. public function execute() {
  39. $this->run();
  40. }
  41. public function executeGenerator($resultPageSet) {
  42. $this->run($resultPageSet);
  43. }
  44. private $fld_ids = false, $fld_title = false, $fld_patrol = false, $fld_flags = false,
  45. $fld_timestamp = false, $fld_user = false, $fld_comment = false, $fld_sizes = false;
  46. private function run($resultPageSet = null) {
  47. global $wgUser, $wgDBtype;
  48. $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist');
  49. if (!$wgUser->isLoggedIn())
  50. $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin');
  51. $params = $this->extractRequestParams();
  52. if (!is_null($params['prop']) && is_null($resultPageSet)) {
  53. $prop = array_flip($params['prop']);
  54. $this->fld_ids = isset($prop['ids']);
  55. $this->fld_title = isset($prop['title']);
  56. $this->fld_flags = isset($prop['flags']);
  57. $this->fld_user = isset($prop['user']);
  58. $this->fld_comment = isset($prop['comment']);
  59. $this->fld_timestamp = isset($prop['timestamp']);
  60. $this->fld_sizes = isset($prop['sizes']);
  61. $this->fld_patrol = isset($prop['patrol']);
  62. if ($this->fld_patrol) {
  63. global $wgUser;
  64. if (!$wgUser->useRCPatrol() && !$wgUser->useNPPatrol())
  65. $this->dieUsage('patrol property is not available', 'patrol');
  66. }
  67. }
  68. if (is_null($resultPageSet)) {
  69. $this->addFields(array (
  70. 'rc_cur_id',
  71. 'rc_this_oldid',
  72. 'rc_namespace',
  73. 'rc_title',
  74. 'rc_timestamp'
  75. ));
  76. $this->addFieldsIf('rc_new', $this->fld_flags);
  77. $this->addFieldsIf('rc_minor', $this->fld_flags);
  78. $this->addFieldsIf('rc_bot', $this->fld_flags);
  79. $this->addFieldsIf('rc_user', $this->fld_user);
  80. $this->addFieldsIf('rc_user_text', $this->fld_user);
  81. $this->addFieldsIf('rc_comment', $this->fld_comment);
  82. $this->addFieldsIf('rc_patrolled', $this->fld_patrol);
  83. $this->addFieldsIf('rc_old_len', $this->fld_sizes);
  84. $this->addFieldsIf('rc_new_len', $this->fld_sizes);
  85. }
  86. elseif ($params['allrev']) {
  87. $this->addFields(array (
  88. 'rc_this_oldid',
  89. 'rc_namespace',
  90. 'rc_title',
  91. 'rc_timestamp'
  92. ));
  93. } else {
  94. $this->addFields(array (
  95. 'rc_cur_id',
  96. 'rc_namespace',
  97. 'rc_title',
  98. 'rc_timestamp'
  99. ));
  100. }
  101. $this->addTables(array (
  102. 'watchlist',
  103. 'page',
  104. 'recentchanges'
  105. ));
  106. $userId = $wgUser->getId();
  107. $this->addWhere(array (
  108. 'wl_namespace = rc_namespace',
  109. 'wl_title = rc_title',
  110. 'rc_cur_id = page_id',
  111. 'wl_user' => $userId,
  112. 'rc_deleted' => 0,
  113. ));
  114. $this->addWhereRange('rc_timestamp', $params['dir'], $params['start'], $params['end']);
  115. $this->addWhereFld('wl_namespace', $params['namespace']);
  116. $this->addWhereIf('rc_this_oldid=page_latest', !$params['allrev']);
  117. if (!is_null($params['show'])) {
  118. $show = array_flip($params['show']);
  119. /* Check for conflicting parameters. */
  120. if ((isset ($show['minor']) && isset ($show['!minor']))
  121. || (isset ($show['bot']) && isset ($show['!bot']))
  122. || (isset ($show['anon']) && isset ($show['!anon']))
  123. || (isset ($show['patrolled']) && isset ($show['!patrolled']))) {
  124. $this->dieUsage("Incorrect parameter - mutually exclusive values may not be supplied", 'show');
  125. }
  126. // Check permissions
  127. global $wgUser;
  128. if((isset($show['patrolled']) || isset($show['!patrolled'])) && !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol())
  129. $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied');
  130. /* Add additional conditions to query depending upon parameters. */
  131. $this->addWhereIf('rc_minor = 0', isset ($show['!minor']));
  132. $this->addWhereIf('rc_minor != 0', isset ($show['minor']));
  133. $this->addWhereIf('rc_bot = 0', isset ($show['!bot']));
  134. $this->addWhereIf('rc_bot != 0', isset ($show['bot']));
  135. $this->addWhereIf('rc_user = 0', isset ($show['anon']));
  136. $this->addWhereIf('rc_user != 0', isset ($show['!anon']));
  137. $this->addWhereIf('rc_patrolled = 0', isset($show['!patrolled']));
  138. $this->addWhereIf('rc_patrolled != 0', isset($show['patrolled']));
  139. }
  140. # This is an index optimization for mysql, as done in the Special:Watchlist page
  141. $this->addWhereIf("rc_timestamp > ''", !isset ($params['start']) && !isset ($params['end']) && $wgDBtype == 'mysql');
  142. $this->addOption('LIMIT', $params['limit'] +1);
  143. $ids = array ();
  144. $count = 0;
  145. $res = $this->select(__METHOD__);
  146. $db = $this->getDB();
  147. while ($row = $db->fetchObject($res)) {
  148. if (++ $count > $params['limit']) {
  149. // We've reached the one extra which shows that there are additional pages to be had. Stop here...
  150. $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->rc_timestamp));
  151. break;
  152. }
  153. if (is_null($resultPageSet)) {
  154. $vals = $this->extractRowInfo($row);
  155. $fit = $this->getResult()->addValue(array('query', $this->getModuleName()), null, $vals);
  156. if(!$fit)
  157. {
  158. $this->setContinueEnumParameter('start',
  159. wfTimestamp(TS_ISO_8601, $row->rc_timestamp));
  160. break;
  161. }
  162. } else {
  163. if ($params['allrev']) {
  164. $ids[] = intval($row->rc_this_oldid);
  165. } else {
  166. $ids[] = intval($row->rc_cur_id);
  167. }
  168. }
  169. }
  170. $db->freeResult($res);
  171. if (is_null($resultPageSet)) {
  172. $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'item');
  173. }
  174. elseif ($params['allrev']) {
  175. $resultPageSet->populateFromRevisionIDs($ids);
  176. } else {
  177. $resultPageSet->populateFromPageIDs($ids);
  178. }
  179. }
  180. private function extractRowInfo($row) {
  181. $vals = array ();
  182. if ($this->fld_ids) {
  183. $vals['pageid'] = intval($row->rc_cur_id);
  184. $vals['revid'] = intval($row->rc_this_oldid);
  185. }
  186. if ($this->fld_title)
  187. ApiQueryBase :: addTitleInfo($vals, Title :: makeTitle($row->rc_namespace, $row->rc_title));
  188. if ($this->fld_user) {
  189. $vals['user'] = $row->rc_user_text;
  190. if (!$row->rc_user)
  191. $vals['anon'] = '';
  192. }
  193. if ($this->fld_flags) {
  194. if ($row->rc_new)
  195. $vals['new'] = '';
  196. if ($row->rc_minor)
  197. $vals['minor'] = '';
  198. if ($row->rc_bot)
  199. $vals['bot'] = '';
  200. }
  201. if ($this->fld_patrol && isset($row->rc_patrolled))
  202. $vals['patrolled'] = '';
  203. if ($this->fld_timestamp)
  204. $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp);
  205. if ($this->fld_sizes) {
  206. $vals['oldlen'] = intval($row->rc_old_len);
  207. $vals['newlen'] = intval($row->rc_new_len);
  208. }
  209. if ($this->fld_comment && isset( $row->rc_comment ))
  210. $vals['comment'] = $row->rc_comment;
  211. return $vals;
  212. }
  213. public function getAllowedParams() {
  214. return array (
  215. 'allrev' => false,
  216. 'start' => array (
  217. ApiBase :: PARAM_TYPE => 'timestamp'
  218. ),
  219. 'end' => array (
  220. ApiBase :: PARAM_TYPE => 'timestamp'
  221. ),
  222. 'namespace' => array (
  223. ApiBase :: PARAM_ISMULTI => true,
  224. ApiBase :: PARAM_TYPE => 'namespace'
  225. ),
  226. 'dir' => array (
  227. ApiBase :: PARAM_DFLT => 'older',
  228. ApiBase :: PARAM_TYPE => array (
  229. 'newer',
  230. 'older'
  231. )
  232. ),
  233. 'limit' => array (
  234. ApiBase :: PARAM_DFLT => 10,
  235. ApiBase :: PARAM_TYPE => 'limit',
  236. ApiBase :: PARAM_MIN => 1,
  237. ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
  238. ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
  239. ),
  240. 'prop' => array (
  241. APIBase :: PARAM_ISMULTI => true,
  242. APIBase :: PARAM_DFLT => 'ids|title|flags',
  243. APIBase :: PARAM_TYPE => array (
  244. 'ids',
  245. 'title',
  246. 'flags',
  247. 'user',
  248. 'comment',
  249. 'timestamp',
  250. 'patrol',
  251. 'sizes',
  252. )
  253. ),
  254. 'show' => array (
  255. ApiBase :: PARAM_ISMULTI => true,
  256. ApiBase :: PARAM_TYPE => array (
  257. 'minor',
  258. '!minor',
  259. 'bot',
  260. '!bot',
  261. 'anon',
  262. '!anon',
  263. 'patrolled',
  264. '!patrolled',
  265. )
  266. )
  267. );
  268. }
  269. public function getParamDescription() {
  270. return array (
  271. 'allrev' => 'Include multiple revisions of the same page within given timeframe.',
  272. 'start' => 'The timestamp to start enumerating from.',
  273. 'end' => 'The timestamp to end enumerating.',
  274. 'namespace' => 'Filter changes to only the given namespace(s).',
  275. 'dir' => 'In which direction to enumerate pages.',
  276. 'limit' => 'How many total results to return per request.',
  277. 'prop' => 'Which additional items to get (non-generator mode only).',
  278. 'show' => array (
  279. 'Show only items that meet this criteria.',
  280. 'For example, to see only minor edits done by logged-in users, set show=minor|!anon'
  281. )
  282. );
  283. }
  284. public function getDescription() {
  285. return "Get all recent changes to pages in the logged in user's watchlist";
  286. }
  287. protected function getExamples() {
  288. return array (
  289. 'api.php?action=query&list=watchlist',
  290. 'api.php?action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment',
  291. 'api.php?action=query&list=watchlist&wlallrev&wlprop=ids|title|timestamp|user|comment',
  292. 'api.php?action=query&generator=watchlist&prop=info',
  293. 'api.php?action=query&generator=watchlist&gwlallrev&prop=revisions&rvprop=timestamp|user'
  294. );
  295. }
  296. public function getVersion() {
  297. return __CLASS__ . ': $Id: ApiQueryWatchlist.php 47865 2009-02-27 16:03:01Z catrope $';
  298. }
  299. }