25use InvalidArgumentException;
40 private $joinCache = [];
49 private $actorStoreFactory;
55 private $allowUnknown;
106 $this->fieldInfos = $fieldInfos;
107 $this->allowUnknown = $options[
'allowUnknown'] ??
true;
111 if ( $writeStage === 0 ) {
112 throw new InvalidArgumentException(
'$stage must include a write mode' );
114 if ( $readStage === 0 ) {
115 throw new InvalidArgumentException(
'$stage must include a read mode' );
120 throw new InvalidArgumentException(
'Cannot read multiple schemas' );
123 throw new InvalidArgumentException(
'Cannot read the old schema without also writing it' );
126 throw new InvalidArgumentException(
'Cannot read the temp schema without also writing it' );
129 throw new InvalidArgumentException(
'Cannot read the new schema without also writing it' );
131 $this->readStage = $readStage;
132 $this->writeStage = $writeStage;
134 $this->actorStoreFactory = $actorStoreFactory;
146 if ( isset( $this->fieldInfos[$key] ) ) {
147 return $this->fieldInfos[$key];
148 } elseif ( $this->allowUnknown ) {
151 throw new InvalidArgumentException( $this->
getInstanceName() .
": unknown key $key" );
164 if ( (
new ReflectionClass( $this ) )->isAnonymous() ) {
168 return static::class;
181 if ( isset( $fieldInfo[
'removedVersion'] ) ) {
182 $removedVersion = $fieldInfo[
'removedVersion'];
183 $component = $fieldInfo[
'component'] ??
'MediaWiki';
184 throw new InvalidArgumentException(
185 "Use of {$this->getInstanceName()} for '$key' was removed in $component $removedVersion"
188 if ( isset( $fieldInfo[
'deprecatedVersion'] ) ) {
189 $deprecatedVersion = $fieldInfo[
'deprecatedVersion'];
190 $component = $fieldInfo[
'component'] ??
'MediaWiki';
191 wfDeprecated(
"{$this->getInstanceName()} for '$key'", $deprecatedVersion, $component, 3 );
218 private function getFieldNames( $key ) {
220 $textField = $fieldInfo[
'textField'] ?? $key .
'_text';
221 $actorField = $fieldInfo[
'actorField'] ?? substr( $key, 0, -5 ) .
'_actor';
222 return [ $textField, $actorField ];
231 private function getTempTableInfo( $key ) {
233 return $fieldInfo[
'tempTable'] ??
null;
251 if ( !isset( $this->joinCache[$key] ) ) {
256 [ $text, $actor ] = $this->getFieldNames( $key );
259 $fields[$key] = $key;
260 $fields[$text] = $text;
261 $fields[$actor] =
'NULL';
263 $tempTableInfo = $this->getTempTableInfo( $key );
264 if ( $tempTableInfo ) {
265 $alias =
"temp_$key";
266 $tables[$alias] = $tempTableInfo[
'table'];
269 "{$alias}.{$tempTableInfo['pk']} = {$tempTableInfo['joinPK']}",
271 $joinField =
"{$alias}.{$tempTableInfo['field']}";
276 $alias =
"actor_$key";
277 $tables[$alias] =
'actor';
278 $joins[$alias] = [
'JOIN',
"{$alias}.actor_id = {$joinField}" ];
280 $fields[$key] =
"{$alias}.actor_user";
281 $fields[$text] =
"{$alias}.actor_name";
282 $fields[$actor] = $joinField;
284 $alias =
"actor_$key";
285 $tables[$alias] =
'actor';
286 $joins[$alias] = [
'JOIN',
"{$alias}.actor_id = {$actor}" ];
288 $fields[$key] =
"{$alias}.actor_user";
289 $fields[$text] =
"{$alias}.actor_name";
290 $fields[$actor] = $actor;
293 $this->joinCache[$key] = [
300 return $this->joinCache[$key];
315 if ( $this->getTempTableInfo( $key ) ) {
316 throw new InvalidArgumentException(
"Must use getInsertValuesWithTempTable() for $key" );
319 [ $text, $actor ] = $this->getFieldNames( $key );
322 $ret[$key] = $user->
getId();
323 $ret[$text] = $user->
getName();
327 $this->actorStoreFactory->getActorNormalization( $dbw->
getDomainID() )->acquireActorId( $user, $dbw );
348 $tempTableInfo = $fieldInfo[
'tempTable'] ??
null;
349 if ( isset( $fieldInfo[
'formerTempTableVersion'] ) ) {
351 __METHOD__ .
" for $key",
352 $fieldInfo[
'formerTempTableVersion'],
353 $fieldInfo[
'component'] ??
'MediaWiki'
355 } elseif ( !$tempTableInfo ) {
356 throw new InvalidArgumentException(
"Must use getInsertValues() for $key" );
359 [ $text, $actor ] = $this->getFieldNames( $key );
364 $ret[$key] = $user->
getId();
365 $ret[$text] = $user->
getName();
368 $id = $this->actorStoreFactory
370 ->acquireActorId( $user, $dbw );
372 if ( $tempTableInfo ) {
375 $callback =
static function ( $pk, array $extra ) use ( $tempTableInfo, $dbw, $id, $func ) {
376 $set = [ $tempTableInfo[
'field'] => $id ];
377 foreach ( $tempTableInfo[
'extra'] as $to => $from ) {
378 if ( !array_key_exists( $from, $extra ) ) {
379 throw new InvalidArgumentException(
"$func callback: \$extra[$from] is not provided" );
381 $set[$to] = $extra[$from];
384 $tempTableInfo[
'table'],
385 [ $tempTableInfo[
'pk'] => $pk ] + $set,
386 [ [ $tempTableInfo[
'pk'] ] ],
400 if ( $callback ===
null ) {
402 if ( $tempTableInfo ) {
404 $callback =
static function ( $pk, array $extra ) use ( $tempTableInfo, $func ) {
405 foreach ( $tempTableInfo[
'extra'] as $from ) {
406 if ( !array_key_exists( $from, $extra ) ) {
407 throw new InvalidArgumentException(
"$func callback: \$extra[$from] is not provided" );
412 $callback =
static function ( $pk, array $extra ) {
416 return [ $ret, $callback ];
452 } elseif ( $users ===
null || $users ===
false ) {
455 } elseif ( !is_array( $users ) ) {
456 $what = is_object( $users ) ? get_class( $users ) : gettype( $users );
457 throw new InvalidArgumentException(
458 __METHOD__ .
": Value for \$users must be a UserIdentity or array, got $what"
466 foreach ( $users as $user ) {
467 if ( $useId && $user->isRegistered() ) {
468 $ids[] = $user->getId();
471 $names[] = IPUtils::sanitizeIP( $user->getName() );
473 $actorId = $this->actorStoreFactory
475 ->findActorId( $user, $db );
478 $actors[] = $actorId;
482 [ $text, $actor ] = $this->getFieldNames( $key );
487 $conds[
'newactor'] = $db->
makeList( [ $actor => $actors ], IDatabase::LIST_AND );
491 $tempTableInfo = $this->getTempTableInfo( $key );
492 if ( $tempTableInfo ) {
493 $alias =
"temp_$key";
494 $tables[$alias] = $tempTableInfo[
'table'];
497 "{$alias}.{$tempTableInfo['pk']} = {$tempTableInfo['joinPK']}",
499 $joinField =
"{$alias}.{$tempTableInfo['field']}";
503 $conds[
'actor'] = $db->
makeList( [ $joinField => $actors ], IDatabase::LIST_AND );
507 $conds[
'userid'] = $db->
makeList( [ $key => $ids ], IDatabase::LIST_AND );
510 $conds[
'username'] = $db->
makeList( [ $text => $names ], IDatabase::LIST_AND );
516 'conds' => $conds ? $db->
makeList( array_values( $conds ), IDatabase::LIST_OR ) :
'1=0',
523class_alias( ActorMigrationBase::class,
'ActorMigrationBase' );
const SCHEMA_COMPAT_WRITE_TEMP
const SCHEMA_COMPAT_READ_NEW
const SCHEMA_COMPAT_WRITE_OLD
const SCHEMA_COMPAT_READ_TEMP
const SCHEMA_COMPAT_READ_OLD
const SCHEMA_COMPAT_WRITE_NEW
const SCHEMA_COMPAT_WRITE_MASK
const SCHEMA_COMPAT_READ_MASK
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.