57 'table' =>
'revision_actor_temp',
58 'pk' =>
'revactor_rev',
59 'field' =>
'revactor_actor',
62 'revactor_timestamp' =>
'rev_timestamp',
63 'revactor_page' =>
'rev_page',
103 'ipb_by' => [
'ipb_by_text',
'ipb_by_actor' ],
118 throw new InvalidArgumentException(
'$stage must include a write mode' );
121 throw new InvalidArgumentException(
'$stage must include a read mode' );
124 throw new InvalidArgumentException(
'Cannot read both schemas' );
127 throw new InvalidArgumentException(
'Cannot read the old schema without also writing it' );
130 throw new InvalidArgumentException(
'Cannot read the new schema without also writing it' );
141 return MediaWikiServices::getInstance()->getActorMigration();
149 if ( isset( self::$removed[$key] ) ) {
150 throw new InvalidArgumentException(
151 "Use of " . static::class .
" for '$key' was removed in MediaWiki " . self::$removed[$key]
154 if ( !empty( self::$deprecated[$key] ) ) {
155 wfDeprecated( static::class .
" for '$key'", self::$deprecated[$key],
false, 3 );
183 return self::$specialFields[$key] ?? [ $key .
'_text', substr( $key, 0, -5 ) .
'_actor' ];
199 self::checkDeprecation( $key );
201 if ( !isset( $this->joinCache[$key] ) ) {
206 list( $text, $actor ) = self::getFieldNames( $key );
209 $fields[$key] = $key;
210 $fields[$text] = $text;
211 $fields[$actor] =
'NULL';
213 if ( isset( self::$tempTables[$key] ) ) {
214 $t = self::$tempTables[$key];
215 $alias =
"temp_$key";
216 $tables[$alias] =
$t[
'table'];
217 $joins[$alias] = [
'JOIN',
"{$alias}.{$t['pk']} = {$t['joinPK']}" ];
218 $joinField =
"{$alias}.{$t['field']}";
223 $alias =
"actor_$key";
224 $tables[$alias] =
'actor';
225 $joins[$alias] = [
'JOIN',
"{$alias}.actor_id = {$joinField}" ];
227 $fields[$key] =
"{$alias}.actor_user";
228 $fields[$text] =
"{$alias}.actor_name";
229 $fields[$actor] = $joinField;
232 $this->joinCache[$key] = [
239 return $this->joinCache[$key];
255 [
'actor_name' => $user->
getName() ],
258 if ( $row ===
false ) {
262 return (
int)$row->actor_id;
278 $userNameUtils = MediaWikiServices::getInstance()->getUserNameUtils();
281 'actor_user' => $user->
getId() ?:
null,
282 'actor_name' => (string)$user->
getName(),
284 if ( $q[
'actor_user'] ===
null && $userNameUtils->isUsable( $q[
'actor_name'] ) ) {
286 'Cannot create an actor for a usable name that is not an existing user: ' .
287 "user_id={$user->getId()} user_name=\"{$user->getName()}\""
290 if ( $q[
'actor_name'] ===
'' ) {
292 'Cannot create an actor for a user with no name: ' .
293 "user_id={$user->getId()} user_name=\"{$user->getName()}\""
297 $dbw->
insert(
'actor', $q, __METHOD__, [
'IGNORE' ] );
309 [
'LOCK IN SHARE MODE' ]
313 "Failed to create actor ID for " .
314 "user_id={$user->getId()} user_name=\"{$user->getName()}\""
332 self::checkDeprecation( $key );
334 if ( isset( self::$tempTables[$key] ) ) {
335 throw new InvalidArgumentException(
"Must use getInsertValuesWithTempTable() for $key" );
338 list( $text, $actor ) = self::getFieldNames( $key );
341 $ret[$key] = $user->
getId();
342 $ret[$text] = $user->
getName();
348 if ( $existingActorId !==
false ) {
349 $ret[$actor] = $existingActorId;
370 self::checkDeprecation( $key );
372 if ( isset( self::$formerTempTables[$key] ) ) {
373 wfDeprecated( __METHOD__ .
" for $key", self::$formerTempTables[$key] );
374 } elseif ( !isset( self::$tempTables[$key] ) ) {
375 throw new InvalidArgumentException(
"Must use getInsertValues() for $key" );
378 list( $text, $actor ) = self::getFieldNames( $key );
382 $ret[$key] = $user->
getId();
383 $ret[$text] = $user->
getName();
392 if ( isset( self::$tempTables[$key] ) ) {
394 $callback =
function ( $pk, array $extra ) use ( $dbw, $key, $id, $func ) {
395 $t = self::$tempTables[$key];
396 $set = [
$t[
'field'] => $id ];
397 foreach (
$t[
'extra'] as $to => $from ) {
398 if ( !array_key_exists( $from, $extra ) ) {
399 throw new InvalidArgumentException(
"$func callback: \$extra[$from] is not provided" );
401 $set[$to] = $extra[$from];
405 [
$t[
'pk'] => $pk ] + $set,
413 $callback =
function ( $pk, array $extra ) {
416 } elseif ( isset( self::$tempTables[$key] ) ) {
418 $callback =
function ( $pk, array $extra ) use ( $key, $func ) {
419 $t = self::$tempTables[$key];
420 foreach (
$t[
'extra'] as $to => $from ) {
421 if ( !array_key_exists( $from, $extra ) ) {
422 throw new InvalidArgumentException(
"$func callback: \$extra[$from] is not provided" );
427 $callback =
function ( $pk, array $extra ) {
430 return [ $ret, $callback ];
457 self::checkDeprecation( $key );
465 } elseif ( $users ===
null || $users ===
false ) {
468 } elseif ( !is_array( $users ) ) {
469 $what = is_object( $users ) ? get_class( $users ) : gettype( $users );
470 throw new InvalidArgumentException(
471 __METHOD__ .
": Value for \$users must be a UserIdentity or array, got $what"
479 foreach ( $users as $user ) {
480 if ( $useId && $user->getId() ) {
481 $ids[] = $user->getId();
483 $names[] = $user->getName();
485 $actorId = $user->getActorId();
487 $actors[] = $actorId;
491 list( $text, $actor ) = self::getFieldNames( $key );
496 if ( isset( self::$tempTables[$key] ) ) {
497 $t = self::$tempTables[$key];
498 $alias =
"temp_$key";
499 $tables[$alias] =
$t[
'table'];
500 $joins[$alias] = [
'JOIN',
"{$alias}.{$t['pk']} = {$t['joinPK']}" ];
501 $joinField =
"{$alias}.{$t['field']}";
505 $conds[
'actor'] = $db->
makeList( [ $joinField => $actors ], IDatabase::LIST_AND );
509 $conds[
'userid'] = $db->
makeList( [ $key => $ids ], IDatabase::LIST_AND );
512 $conds[
'username'] = $db->
makeList( [ $text => $names ], IDatabase::LIST_AND );
518 'conds' => $conds ? $db->
makeList( array_values( $conds ), IDatabase::LIST_OR ) :
'1=0',
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
This class handles the logic for the actor table migration and should always be used in lieu of direc...
const MIGRATION_STAGE_SCHEMA_COMPAT
Constant for extensions to feature-test whether $wgActorTableSchemaMigrationStage (in MW <1....
static array $formerTempTables
Fields that formerly used $tempTables Key is '$key', value is the MediaWiki version in which it was r...
isAnon( $field)
Return an SQL condition to test if a user field is anonymous.
getInsertValues(IDatabase $dbw, $key, UserIdentity $user)
Get UPDATE fields for the actor.
static array $tempTables
Define fields that use temporary tables for transitional purposes Keys are '$key',...
static array $specialFields
Define fields that use non-standard mapping Keys are the user id column name, values are arrays with ...
array $joinCache
Cache for self::getJoin()
static newMigration()
Static constructor.
static checkDeprecation( $key)
Issue deprecation warning/error as appropriate.
getInsertValuesWithTempTable(IDatabase $dbw, $key, UserIdentity $user)
Get UPDATE fields for the actor.
getNewActorId(IDatabase $dbw, UserIdentity $user)
Attempt to assign an actor ID to the given user.
int $stage
Combination of SCHEMA_COMPAT_* constants.
isNotAnon( $field)
Return an SQL condition to test if a user field is non-anonymous.
getExistingActorId(IDatabase $db, UserIdentity $user)
Get actor ID from UserIdentity, if it exists.
static string[] $removed
Define fields that are removed for use with this class.
getWhere(IDatabase $db, $key, $users, $useId=true)
Get WHERE condition for the actor.
static string null[] $deprecated
Define fields that are deprecated for use with this class.
getJoin( $key)
Get SELECT fields and joins for the actor key.
static getFieldNames( $key)
Exception thrown when an actor can't be created.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
static newFromAnyId( $userId, $userName, $actorId, $dbDomain=false)
Static factory method for creation from an ID, name, and/or actor ID.
const SCHEMA_COMPAT_WRITE_BOTH
const SCHEMA_COMPAT_READ_NEW
const SCHEMA_COMPAT_READ_BOTH
const SCHEMA_COMPAT_WRITE_OLD
const SCHEMA_COMPAT_READ_OLD
const SCHEMA_COMPAT_WRITE_NEW