parent::__construct( $query, $moduleName, 'uc' );
}
- private $params, $prefixMode, $userprefix, $multiUserMode, $usernames, $parentLens;
+ private $params, $prefixMode, $userprefix, $multiUserMode, $idMode, $usernames, $userids,
+ $parentLens;
private $fld_ids = false, $fld_title = false, $fld_timestamp = false,
$fld_comment = false, $fld_parsedcomment = false, $fld_flags = false,
$fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
// TODO: if the query is going only against the revision table, should this be done?
$this->selectNamedDB( 'contributions', DB_SLAVE, 'contributions' );
+ $this->idMode = false;
if ( isset( $this->params['userprefix'] ) ) {
$this->prefixMode = true;
$this->multiUserMode = true;
$this->userprefix = $this->params['userprefix'];
} else {
- $this->usernames = array();
+ $anyIPs = false;
+ $this->userids = [];
+ $this->usernames = [];
if ( !is_array( $this->params['user'] ) ) {
- $this->params['user'] = array( $this->params['user'] );
+ $this->params['user'] = [ $this->params['user'] ];
}
if ( !count( $this->params['user'] ) ) {
$this->dieUsage( 'User parameter may not be empty.', 'param_user' );
}
foreach ( $this->params['user'] as $u ) {
- $this->prepareUsername( $u );
+ if ( is_null( $u ) || $u === '' ) {
+ $this->dieUsage( 'User parameter may not be empty', 'param_user' );
+ }
+
+ if ( User::isIP( $u ) ) {
+ $anyIPs = true;
+ $this->usernames[] = $u;
+ } else {
+ $name = User::getCanonicalName( $u, 'valid' );
+ if ( $name === false ) {
+ $this->dieUsage( "User name {$u} is not valid", 'param_user' );
+ }
+ $this->usernames[] = $name;
+ }
}
$this->prefixMode = false;
$this->multiUserMode = ( count( $this->params['user'] ) > 1 );
+
+ if ( !$anyIPs ) {
+ $dbr = $this->getDB();
+ $res = $dbr->select( 'user', 'user_id', [ 'user_name' => $this->usernames ], __METHOD__ );
+ foreach ( $res as $row ) {
+ $this->userids[] = $row->user_id;
+ }
+ $this->idMode = count( $this->userids ) === count( $this->usernames );
+ }
}
$this->prepareQuery();
$res = $this->select( __METHOD__ );
if ( $this->fld_sizediff ) {
- $revIds = array();
+ $revIds = [];
foreach ( $res as $row ) {
if ( $row->rev_parent_id ) {
$revIds[] = $row->rev_parent_id;
}
$vals = $this->extractRowInfo( $row );
- $fit = $this->getResult()->addValue( array( 'query', $this->getModuleName() ), null, $vals );
+ $fit = $this->getResult()->addValue( [ 'query', $this->getModuleName() ], null, $vals );
if ( !$fit ) {
$this->setContinueEnumParameter( 'continue', $this->continueStr( $row ) );
break;
}
$this->getResult()->addIndexedTagName(
- array( 'query', $this->getModuleName() ),
+ [ 'query', $this->getModuleName() ],
'item'
);
}
- /**
- * Validate the 'user' parameter and set the value to compare
- * against `revision`.`rev_user_text`
- *
- * @param string $user
- */
- private function prepareUsername( $user ) {
- if ( !is_null( $user ) && $user !== '' ) {
- $name = User::isIP( $user )
- ? $user
- : User::getCanonicalName( $user, 'valid' );
- if ( $name === false ) {
- $this->dieUsage( "User name {$user} is not valid", 'param_user' );
- } else {
- $this->usernames[] = $name;
- }
- } else {
- $this->dieUsage( 'User parameter may not be empty', 'param_user' );
- }
- }
-
/**
* Prepares the query and returns the limit of rows requested
*/
// row for anything we retrieve. We may also need the
// recentchanges row and/or tag summary row.
$user = $this->getUser();
- $tables = array( 'page', 'revision' ); // Order may change
+ $tables = [ 'page', 'revision' ]; // Order may change
$this->addWhere( 'page_id=rev_page' );
// Handle continue parameter
$continue = explode( '|', $this->params['continue'] );
$db = $this->getDB();
if ( $this->multiUserMode ) {
- $this->dieContinueUsageIf( count( $continue ) != 3 );
+ $this->dieContinueUsageIf( count( $continue ) != 4 );
+ $modeFlag = array_shift( $continue );
+ $this->dieContinueUsageIf( !in_array( $modeFlag, [ 'id', 'name' ] ) );
+ if ( $this->idMode && $modeFlag === 'name' ) {
+ // The users were created since this query started, but we
+ // can't go back and change modes now. So just keep on with
+ // name mode.
+ $this->idMode = false;
+ }
+ $this->dieContinueUsageIf( ( $modeFlag === 'id' ) !== $this->idMode );
+ $userField = $this->idMode ? 'rev_user' : 'rev_user_text';
$encUser = $db->addQuotes( array_shift( $continue ) );
} else {
$this->dieContinueUsageIf( count( $continue ) != 2 );
$op = ( $this->params['dir'] == 'older' ? '<' : '>' );
if ( $this->multiUserMode ) {
$this->addWhere(
- "rev_user_text $op $encUser OR " .
- "(rev_user_text = $encUser AND " .
+ "$userField $op $encUser OR " .
+ "($userField = $encUser AND " .
"(rev_timestamp $op $encTS OR " .
"(rev_timestamp = $encTS AND " .
"rev_id $op= $encId)))"
if ( $this->prefixMode ) {
$this->addWhere( 'rev_user_text' .
$this->getDB()->buildLike( $this->userprefix, $this->getDB()->anyString() ) );
+ } elseif ( $this->idMode ) {
+ $this->addWhereFld( 'rev_user', $this->userids );
} else {
$this->addWhereFld( 'rev_user_text', $this->usernames );
}
// ... and in the specified timeframe.
- // Ensure the same sort order for rev_user_text and rev_timestamp
+ // Ensure the same sort order for rev_user/rev_user_text and rev_timestamp
// so our query is indexed
if ( $this->multiUserMode ) {
- $this->addWhereRange( 'rev_user_text', $this->params['dir'], null, null );
+ $this->addWhereRange( $this->idMode ? 'rev_user' : 'rev_user_text',
+ $this->params['dir'], null, null );
}
$this->addTimestampWhereRange( 'rev_timestamp',
$this->params['dir'], $this->params['start'], $this->params['end'] );
$this->addWhereIf( 'rev_parent_id = 0', isset( $show['new'] ) );
}
$this->addOption( 'LIMIT', $this->params['limit'] + 1 );
- $index = array( 'revision' => 'usertext_timestamp' );
// Mandatory fields: timestamp allows request continuation
// ns+title checks if the user has access rights for this page
// user_text is necessary if multiple users were specified
- $this->addFields( array(
+ $this->addFields( [
'rev_id',
'rev_timestamp',
'page_namespace',
'rev_user',
'rev_user_text',
'rev_deleted'
- ) );
+ ] );
if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ||
$this->fld_patrolled
if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
// Put the tables in the right order for
// STRAIGHT_JOIN
- $tables = array( 'revision', 'recentchanges', 'page' );
+ $tables = [ 'revision', 'recentchanges', 'page' ];
$this->addOption( 'STRAIGHT_JOIN' );
$this->addWhere( 'rc_user_text=rev_user_text' );
$this->addWhere( 'rc_timestamp=rev_timestamp' );
$this->addWhere( 'rc_this_oldid=rev_id' );
} else {
$tables[] = 'recentchanges';
- $this->addJoinConds( array( 'recentchanges' => array(
- 'LEFT JOIN', array(
+ $this->addJoinConds( [ 'recentchanges' => [
+ 'LEFT JOIN', [
'rc_user_text=rev_user_text',
'rc_timestamp=rev_timestamp',
- 'rc_this_oldid=rev_id' ) ) ) );
+ 'rc_this_oldid=rev_id' ] ] ] );
}
}
if ( $this->fld_tags ) {
$this->addTables( 'tag_summary' );
$this->addJoinConds(
- array( 'tag_summary' => array( 'LEFT JOIN', array( 'rev_id=ts_rev_id' ) ) )
+ [ 'tag_summary' => [ 'LEFT JOIN', [ 'rev_id=ts_rev_id' ] ] ]
);
$this->addFields( 'ts_tags' );
}
if ( isset( $this->params['tag'] ) ) {
$this->addTables( 'change_tag' );
$this->addJoinConds(
- array( 'change_tag' => array( 'INNER JOIN', array( 'rev_id=ct_rev_id' ) ) )
+ [ 'change_tag' => [ 'INNER JOIN', [ 'rev_id=ct_rev_id' ] ] ]
);
$this->addWhereFld( 'ct_tag', $this->params['tag'] );
}
- $this->addOption( 'USE INDEX', $index );
+ if ( isset( $index ) ) {
+ $this->addOption( 'USE INDEX', $index );
+ }
}
/**
* @return array
*/
private function extractRowInfo( $row ) {
- $vals = array();
+ $vals = [];
$anyHidden = false;
if ( $row->rev_deleted & Revision::DELETED_TEXT ) {
ApiResult::setIndexedTagName( $tags, 'tag' );
$vals['tags'] = $tags;
} else {
- $vals['tags'] = array();
+ $vals['tags'] = [];
}
}
private function continueStr( $row ) {
if ( $this->multiUserMode ) {
- return "$row->rev_user_text|$row->rev_timestamp|$row->rev_id";
+ if ( $this->idMode ) {
+ return "id|$row->rev_user|$row->rev_timestamp|$row->rev_id";
+ } else {
+ return "name|$row->rev_user_text|$row->rev_timestamp|$row->rev_id";
+ }
} else {
return "$row->rev_timestamp|$row->rev_id";
}
}
public function getAllowedParams() {
- return array(
- 'limit' => array(
+ return [
+ 'limit' => [
ApiBase::PARAM_DFLT => 10,
ApiBase::PARAM_TYPE => 'limit',
ApiBase::PARAM_MIN => 1,
ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
- ),
- 'start' => array(
+ ],
+ 'start' => [
ApiBase::PARAM_TYPE => 'timestamp'
- ),
- 'end' => array(
+ ],
+ 'end' => [
ApiBase::PARAM_TYPE => 'timestamp'
- ),
- 'continue' => array(
+ ],
+ 'continue' => [
ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
- ),
- 'user' => array(
+ ],
+ 'user' => [
+ ApiBase::PARAM_TYPE => 'user',
ApiBase::PARAM_ISMULTI => true
- ),
+ ],
'userprefix' => null,
- 'dir' => array(
+ 'dir' => [
ApiBase::PARAM_DFLT => 'older',
- ApiBase::PARAM_TYPE => array(
+ ApiBase::PARAM_TYPE => [
'newer',
'older'
- ),
+ ],
ApiBase::PARAM_HELP_MSG => 'api-help-param-direction',
- ),
- 'namespace' => array(
+ ],
+ 'namespace' => [
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_TYPE => 'namespace'
- ),
- 'prop' => array(
+ ],
+ 'prop' => [
ApiBase::PARAM_ISMULTI => true,
ApiBase::PARAM_DFLT => 'ids|title|timestamp|comment|size|flags',
- ApiBase::PARAM_TYPE => array(
+ ApiBase::PARAM_TYPE => [
'ids',
'title',
'timestamp',
'flags',
'patrolled',
'tags'
- ),
- ApiBase::PARAM_HELP_MSG_PER_VALUE => array(),
- ),
- 'show' => array(
+ ],
+ ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
+ ],
+ 'show' => [
ApiBase::PARAM_ISMULTI => true,
- ApiBase::PARAM_TYPE => array(
+ ApiBase::PARAM_TYPE => [
'minor',
'!minor',
'patrolled',
'!top',
'new',
'!new',
- ),
- ApiBase::PARAM_HELP_MSG => array(
+ ],
+ ApiBase::PARAM_HELP_MSG => [
'apihelp-query+usercontribs-param-show',
$this->getConfig()->get( 'RCMaxAge' )
- ),
- ),
+ ],
+ ],
'tag' => null,
- 'toponly' => array(
+ 'toponly' => [
ApiBase::PARAM_DFLT => false,
ApiBase::PARAM_DEPRECATED => true,
- ),
- );
+ ],
+ ];
}
protected function getExamplesMessages() {
- return array(
+ return [
'action=query&list=usercontribs&ucuser=Example'
=> 'apihelp-query+usercontribs-example-user',
'action=query&list=usercontribs&ucuserprefix=192.0.2.'
=> 'apihelp-query+usercontribs-example-ipprefix',
- );
+ ];
}
public function getHelpUrls() {