return new ApiFormatFeedWrapper($this->getMain());
}
+ /**
+ * Make a nested call to the API to request watchlist items in the last $hours.
+ * Wrap the result as an RSS/Atom feed.
+ */
public function execute() {
global $wgFeedClasses, $wgSitename, $wgContLanguageCode;
'meta' => 'siteinfo',
'siprop' => 'general',
'list' => 'watchlist',
- 'wlprop' => 'user|comment|timestamp',
+ 'wlprop' => 'title|user|comment|timestamp',
'wldir' => 'older', // reverse order - from newest to oldest
'wlend' => $endTime, // stop at this time
'wllimit' => 50
if (++ $count > $limit) {
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
if ($redirect) {
- $ns = $row-> {
- $this->bl_ns };
- $t = $row-> {
- $this->bl_title };
+ $ns = $row-> { $this->bl_ns };
+ $t = $row-> { $this->bl_title };
$continue = $this->getContinueRedirStr(false, 0, $ns, $t, $row->page_id);
} else
$continue = $this->getContinueStr($row->page_id);
return $res;
}
- protected function addRowInfo($prefix, $row) {
-
- $vals = array ();
-
- // ID
- if ( isset( $row-> { $prefix . '_id' } ) )
- $vals[$prefix . 'id'] = intval( $row-> { $prefix . '_id' } );
-
- // Title
- $title = ApiQueryBase :: addRowInfo_title($row, $prefix . '_namespace', $prefix . '_title');
- if ($title)
- ApiQueryBase :: addTitleInfo($vals, $title);
-
- switch ($prefix) {
-
- case 'page' :
- // page_is_redirect
- @ $tmp = $row->page_is_redirect;
- if ($tmp)
- $vals['redirect'] = '';
-
- break;
-
- case 'rc' :
- // PageId
- @ $tmp = $row->rc_cur_id;
- if (!is_null($tmp))
- $vals['pageid'] = intval($tmp);
-
- @ $tmp = $row->rc_this_oldid;
- if (!is_null($tmp))
- $vals['revid'] = intval($tmp);
-
- if ( isset( $row->rc_last_oldid ) )
- $vals['old_revid'] = intval( $row->rc_last_oldid );
-
- $title = ApiQueryBase :: addRowInfo_title($row, 'rc_moved_to_ns', 'rc_moved_to_title');
- if ($title) {
- if (!$title->userCanRead())
- return false;
- ApiQueryBase :: addTitleInfo($vals, $title, 'new_');
- }
-
- if ( isset( $row->rc_patrolled ) )
- $vals['patrolled'] = '';
-
- break;
-
- case 'log' :
- // PageId
- @ $tmp = $row->page_id;
- if (!is_null($tmp))
- $vals['pageid'] = intval($tmp);
-
- if ($row->log_params !== '') {
- $params = explode("\n", $row->log_params);
- if ($row->log_type == 'move' && isset ($params[0])) {
- $newTitle = Title :: newFromText($params[0]);
- if ($newTitle) {
- ApiQueryBase :: addTitleInfo($vals, $newTitle, 'new_');
- $params = null;
- }
- }
-
- if (!empty ($params)) {
- $this->getResult()->setIndexedTagName($params, 'param');
- $vals = array_merge($vals, $params);
- }
- }
-
- break;
-
- case 'rev' :
- // PageID
- @ $tmp = $row->rev_page;
- if (!is_null($tmp))
- $vals['pageid'] = intval($tmp);
+ protected static function addTitleInfo(&$arr, $title, $includeRestricted=false, $prefix='') {
+ if ($includeRestricted || $title->userCanRead()) {
+ $arr[$prefix . 'ns'] = intval($title->getNamespace());
+ $arr[$prefix . 'title'] = $title->getPrefixedText();
}
-
- // Type
- @ $tmp = $row-> { $prefix . '_type' };
- if (!is_null($tmp))
- $vals['type'] = $tmp;
-
- // Action
- @ $tmp = $row-> { $prefix . '_action' };
- if (!is_null($tmp))
- $vals['action'] = $tmp;
-
- // Old ID
- @ $tmp = $row-> { $prefix . '_text_id' };
- if (!is_null($tmp))
- $vals['oldid'] = intval($tmp);
-
- // User Name / Anon IP
- @ $tmp = $row-> { $prefix . '_user_text' };
- if (is_null($tmp))
- @ $tmp = $row->user_name;
- if (!is_null($tmp)) {
- $vals['user'] = $tmp;
- @ $tmp = !$row-> { $prefix . '_user' };
- if (!is_null($tmp) && $tmp)
- $vals['anon'] = '';
- }
-
- // Bot Edit
- @ $tmp = $row-> { $prefix . '_bot' };
- if (!is_null($tmp) && $tmp)
- $vals['bot'] = '';
-
- // New Edit
- @ $tmp = $row-> { $prefix . '_new' };
- if (is_null($tmp))
- @ $tmp = $row-> { $prefix . '_is_new' };
- if (!is_null($tmp) && $tmp)
- $vals['new'] = '';
-
- // Minor Edit
- @ $tmp = $row-> { $prefix . '_minor_edit' };
- if (is_null($tmp))
- @ $tmp = $row-> { $prefix . '_minor' };
- if (!is_null($tmp) && $tmp)
- $vals['minor'] = '';
-
- // Timestamp
- @ $tmp = $row-> { $prefix . '_timestamp' };
- if (!is_null($tmp))
- $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $tmp);
-
- // Comment
- @ $tmp = $row-> { $prefix . '_comment' };
- if (!empty ($tmp)) // optimize bandwidth
- $vals['comment'] = $tmp;
-
- return $vals;
- }
-
- protected static function addTitleInfo(&$arr, $title, $prefix='') {
- $arr[$prefix . 'ns'] = $title->getNamespace();
- $arr[$prefix . 'title'] = $title->getPrefixedText();
if (!$title->userCanRead())
$arr[$prefix . 'inaccessible'] = "";
}
- private static function addRowInfo_title($row, $nsfld, $titlefld) {
- if ( isset( $row-> $nsfld ) ) {
- $ns = $row-> $nsfld;
- @ $title = $row-> $titlefld;
- if (!empty ($title))
- return Title :: makeTitle($ns, $title);
- }
- return false;
- }
-
/**
* Override this method to request extra fields from the pageSet
* using $this->getPageSet()->requestField('fieldName')
// and category is listed there.
$vals = array();
- ApiQueryBase :: addTitleInfo($vals, $title);
+ ApiQueryBase :: addTitleInfo($vals, $title, true);
if ($fld_sortkey)
$vals['sortkey'] = $row->cl_sortkey;
// and images are listed there.
$vals = array();
- ApiQueryBase :: addTitleInfo($vals, $title);
+ ApiQueryBase :: addTitleInfo($vals, $title, true);
$data[] = $vals;
}
$title = Title :: makeTitle($row->pl_namespace, $row->pl_title);
$vals = array();
- ApiQueryBase :: addTitleInfo($vals, $title);
+ ApiQueryBase :: addTitleInfo($vals, $title, true);
$data[] = $vals;
}
if (isset ($params[0])) {
$title = Title :: newFromText($params[0]);
if ($title) {
- ApiQueryBase :: addTitleInfo($vals, $title, "new_");
+ ApiQueryBase :: addTitleInfo($vals, $title, false, "new_");
$params = null;
}
}
parent :: __construct($query, $moduleName, 'rc');
}
+ private $fld_comment = false, $fld_user = false, $fld_flags = false,
+ $fld_timestamp = false, $fld_title = false, $fld_ids = false,
+ $fld_sizes = false;
+
public function execute() {
$limit = $prop = $namespace = $show = $dir = $start = $end = null;
extract($this->extractRequestParams());
'rc_timestamp',
'rc_namespace',
'rc_title',
- 'rc_cur_id',
- 'rc_this_oldid',
- 'rc_last_oldid',
'rc_type',
'rc_moved_to_ns',
'rc_moved_to_title'
if (!is_null($prop)) {
$prop = array_flip($prop);
- $this->addFieldsIf('rc_comment', isset ($prop['comment']));
- if (isset ($prop['user'])) {
- $this->addFields('rc_user');
- $this->addFields('rc_user_text');
- }
- if (isset ($prop['flags'])) {
- $this->addFields('rc_minor');
- $this->addFields('rc_bot');
- $this->addFields('rc_new');
- }
+
+ $this->fld_comment = isset ($prop['comment']);
+ $this->fld_user = isset ($prop['user']);
+ $this->fld_flags = isset ($prop['flags']);
+ $this->fld_timestamp = isset ($prop['timestamp']);
+ $this->fld_title = isset ($prop['title']);
+ $this->fld_ids = isset ($prop['ids']);
+ $this->fld_sizes = isset ($prop['sizes']);
+
+ $this->addFieldsIf('rc_cur_id', $this->fld_ids);
+ $this->addFieldsIf('rc_this_oldid', $this->fld_ids);
+ $this->addFieldsIf('rc_last_oldid', $this->fld_ids);
+ $this->addFieldsIf('rc_comment', $this->fld_comment);
+ $this->addFieldsIf('rc_user', $this->fld_user);
+ $this->addFieldsIf('rc_user_text', $this->fld_user);
+ $this->addFieldsIf('rc_minor', $this->fld_flags);
+ $this->addFieldsIf('rc_bot', $this->fld_flags);
+ $this->addFieldsIf('rc_new', $this->fld_flags);
+ $this->addFieldsIf('rc_old_len', $this->fld_sizes);
+ $this->addFieldsIf('rc_new_len', $this->fld_sizes);
}
$this->addOption('LIMIT', $limit +1);
$count = 0;
$db = $this->getDB();
$res = $this->select(__METHOD__);
+
while ($row = $db->fetchObject($res)) {
if (++ $count > $limit) {
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
break;
}
- $vals = $this->addRowInfo('rc', $row);
- if ($vals)
+ $vals = $this->extractRowInfo($row);
+ if($vals)
$data[] = $vals;
}
$db->freeResult($res);
$result->addValue('query', $this->getModuleName(), $data);
}
+ /**
+ * Security overview: As implemented, any change to a restricted page (userCanRead() == false)
+ * is hidden from the client, except when a page is being moved to a non-restricted name,
+ * or when a non-restricted becomes restricted. When shown, all other fields are shown as well.
+ */
+ private function extractRowInfo($row) {
+ $title = Title :: makeTitle($row->rc_namespace, $row->rc_title);
+ $movedToTitle = false;
+ if (!empty($row->rc_moved_to_title))
+ $movedToTitle = Title :: makeTitle($row->rc_moved_to_ns, $row->rc_moved_to_title);
+
+ // If either this is an edit of a restricted page,
+ // or a move where both to and from names are restricted, skip
+ if (!$title->userCanRead() && (!$movedToTitle ||
+ ($movedToTitle && !$movedToTitle->userCanRead())))
+ return false;
+
+ $vals = array ();
+
+ $vals['type'] = intval($row->rc_type);
+
+ if ($this->fld_title) {
+ ApiQueryBase :: addTitleInfo($vals, $title);
+ if ($movedToTitle)
+ ApiQueryBase :: addTitleInfo($vals, $movedToTitle, false, "new_");
+ }
+
+ if ($this->fld_ids) {
+ $vals['pageid'] = intval($row->rc_cur_id);
+ $vals['revid'] = intval($row->rc_this_oldid);
+ $vals['old_revid'] = intval( $row->rc_last_oldid );
+ }
+
+ if ($this->fld_user) {
+ $vals['user'] = $row->rc_user_text;
+ if(!$row->rc_user)
+ $vals['anon'] = '';
+ }
+
+ if ($this->fld_flags) {
+ if ($row->rc_bot)
+ $vals['bot'] = '';
+ if ($row->rc_new)
+ $vals['new'] = '';
+ if ($row->rc_minor)
+ $vals['minor'] = '';
+ }
+
+ if ($this->fld_sizes) {
+ $vals['oldlen'] = intval($row->rc_old_len);
+ $vals['newlen'] = intval($row->rc_new_len);
+ }
+
+ if ($this->fld_timestamp)
+ $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp);
+
+ if ($this->fld_comment && !empty ($row->rc_comment)) {
+ $vals['comment'] = $row->rc_comment;
+ }
+
+ return $vals;
+ }
+
protected function getAllowedParams() {
return array (
'start' => array (
),
'prop' => array (
ApiBase :: PARAM_ISMULTI => true,
+ ApiBase :: PARAM_DFLT => 'title|timestamp|ids',
ApiBase :: PARAM_TYPE => array (
'user',
'comment',
- 'flags'
+ 'flags',
+ 'timestamp',
+ 'title',
+ 'ids',
+ 'sizes'
)
),
'show' => array (
$vals = array ();
- $vals['revid'] = intval( $row->rev_id );
+ $vals['revid'] = intval($row->rev_id);
$vals['pageid'] = intval($row->rev_page);
$vals['oldid'] = intval($row->rev_text_id);
}
private $params, $userTitle;
- private $fld_title = false, $fld_timestamp = false, $fld_comment = false, $fld_flags = false;
+ private $fld_ids = false, $fld_title = false, $fld_timestamp = false,
+ $fld_comment = false, $fld_flags = false;
public function execute() {
if (!is_null($prop)) {
$prop = array_flip($prop);
+ $this->fld_ids = isset($prop['ids']);
$this->fld_title = isset($prop['title']);
- $this->fld_comment = isset ($prop['comment']);
- $this->fld_flags = isset ($prop['flags']);
- $this->fld_timestamp = isset ($prop['timestamp']);
+ $this->fld_comment = isset($prop['comment']);
+ $this->fld_flags = isset($prop['flags']);
+ $this->fld_timestamp = isset($prop['timestamp']);
}
// TODO: if the query is going only against the revision table, should this be done?
*/
private function prepareQuery() {
- if ($this->fld_title || $this->fld_flags) {
- //We're after the revision table, and the corresponding page row for
- //anything we retrieve.
- list ($tbl_page, $tbl_revision) = $this->getDB()->tableNamesN('page', 'revision');
- $this->addTables("$tbl_revision LEFT OUTER JOIN $tbl_page ON page_id=rev_page");
- } else {
- $this->addTables("revision");
- }
+ //We're after the revision table, and the corresponding page row for
+ //anything we retrieve.
+ list ($tbl_page, $tbl_revision) = $this->getDB()->tableNamesN('page', 'revision');
+ $this->addTables("$tbl_revision LEFT OUTER JOIN $tbl_page ON page_id=rev_page");
// We only want pages by the specified user.
$this->addWhereFld('rev_user_text', $this->userTitle->getText());
$this->addOption('LIMIT', $this->params['limit'] + 1);
- // We want to know the namespace, title, new-ness, and ID of a page,
- // and the id, text-id, timestamp, minor-status, summary and page
- // of a revision.
+ // Mandatory fields: timestamp allows request continuation
+ // ns+title checks if the user has access rights for this page
$this->addFields(array(
- 'rev_page',
- 'rev_id',
- 'rev_timestamp', // Always include timestamp to enable request continuation
- // 'rev_text_id', // Should this field be exposed?
+ 'rev_timestamp',
+ 'page_namespace',
+ 'page_title',
));
+ $this->addFieldsIf('rev_page', $this->fld_ids);
+ $this->addFieldsIf('rev_id', $this->fld_ids);
+ // $this->addFieldsIf('rev_text_id', $this->fld_ids); // Should this field be exposed?
$this->addFieldsIf('rev_comment', $this->fld_comment);
$this->addFieldsIf('rev_minor_edit', $this->fld_flags);
// These fields depend only work if the page table is joined
$this->addFieldsIf('page_is_new', $this->fld_flags);
- $this->addFieldsIf('page_namespace', $this->fld_title);
- $this->addFieldsIf('page_title', $this->fld_title);
}
/**
$vals = array();
- $vals['pageid'] = intval($row->rev_page);
- $vals['revid'] = intval($row->rev_id);
-
+ if ($this->fld_ids) {
+ $vals['pageid'] = intval($row->rev_page);
+ $vals['revid'] = intval($row->rev_id);
+ // $vals['textid'] = intval($row->rev_text_id); // todo: Should this field be exposed?
+ }
+
if ($this->fld_title)
ApiQueryBase :: addTitleInfo($vals, $title);
- // Should this field be exposed?
-// $vals['textid'] = intval($row->rev_text_id);
-
if ($this->fld_timestamp)
$vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rev_timestamp);
),
'prop' => array (
ApiBase :: PARAM_ISMULTI => true,
- ApiBase :: PARAM_DFLT => 'title|timestamp|flags|comment',
+ ApiBase :: PARAM_DFLT => 'ids|title|timestamp|flags|comment',
ApiBase :: PARAM_TYPE => array (
- '',
+ 'ids',
'title',
'timestamp',
'comment',
$this->run($resultPageSet);
}
- private $fld_patrol = false, $fld_flags = false, $fld_timestamp = false, $fld_user = false, $fld_comment = false;
+ private $fld_ids = false, $fld_title = false, $fld_patrol = false, $fld_flags = false, $fld_timestamp = false, $fld_user = false, $fld_comment = false;
private function run($resultPageSet = null) {
global $wgUser;
if (!is_null($prop)) {
if (!is_null($resultPageSet))
- $this->dieUsage('prop parameter may not be used in a generator', 'params');
+ $this->dieUsage($this->encodeParamName('prop') . ' parameter may not be used in a generator', 'params');
$prop = array_flip($prop);
+ $this->fld_ids = isset($prop['ids']);
+ $this->fld_title = isset($prop['title']);
$this->fld_flags = isset($prop['flags']);
$this->fld_user = isset($prop['user']);
$this->fld_comment = isset($prop['comment']);
if (is_null($resultPageSet)) {
$this->addFields(array (
'rc_cur_id',
- // 'rc_this_oldid', // Should this field be exposed?
+ 'rc_this_oldid',
'rc_namespace',
'rc_title',
'rc_timestamp'
$vals = array ();
- $vals['pageid'] = intval($row->rc_cur_id);
- // $vals['textid'] = intval($row->rc_this_oldid); // Should this field be exposed?
-
- ApiQueryBase :: addTitleInfo($vals, $title);
+ if ($this->fld_ids) {
+ $vals['pageid'] = intval($row->rc_cur_id);
+ $vals['revid'] = intval($row->rc_this_oldid);
+ }
+
+ if ($this->fld_title)
+ ApiQueryBase :: addTitleInfo($vals, $title);
if ($this->fld_user) {
$vals['user'] = $row->rc_user_text;
),
'prop' => array (
APIBase :: PARAM_ISMULTI => true,
+ APIBase :: PARAM_DFLT => 'ids|title|flags',
APIBase :: PARAM_TYPE => array (
+ 'ids',
+ 'title',
'flags',
'user',
'comment',
protected function getExamples() {
return array (
- 'api.php?action=query&list=watchlist&wlprop=timestamp|user|comment',
- 'api.php?action=query&list=watchlist&wlallrev&wlprop=timestamp|user|comment',
+ 'api.php?action=query&list=watchlist',
+ 'api.php?action=query&list=watchlist&wlprop=ids|title|timestamp|user|comment',
+ 'api.php?action=query&list=watchlist&wlallrev&wlprop=ids|title|timestamp|user|comment',
'api.php?action=query&generator=watchlist&prop=info',
'api.php?action=query&generator=watchlist&gwlallrev&prop=revisions&rvprop=timestamp|user'
);