mDescription = "Attaches the specified usernames to a global account"; $this->start = microtime( true ); $this->partial = 0; $this->migrated = 0; $this->total = 0; $this->dbBackground = null; $this->batchSize = 1000; $this->addOption( 'userlist', 'List of usernames to migrate', false, true ); } public function execute() { $this->dbBackground = CentralAuthUtils::getCentralSlaveDB(); if ( $this->getOption( 'userlist', false ) === false ) { $this->output( "ERROR - No list of usernames given\n" ); exit( 1 ); } $list = $this->getOption( 'userlist' ); if ( !is_file( $list ) ) { $this->output( "ERROR - File not found: $list" ); exit( 1 ); } $file = fopen( $list, 'r' ); if ( $file === false ) { $this->output( "ERROR - Could not open file: $list" ); exit( 1 ); } while( strlen( $line = trim( fgets( $file ) ) ) ) { $values = explode( "\t", $line ); switch( count( $values ) ){ case 1: $this->migrate( $values[0] ); break; default: $this->output( "ERROR: Invalid account specification: '$line'\n" ); continue; } if ( $this->total % $this->batchSize == 0 ) { $this->output( "Waiting for slaves to catch up ... " ); CentralAuthUtils::waitForSlaves(); $this->output( "done\n" ); } } fclose( $file ); $this->migratePassOneReport(); $this->output( "done.\n" ); } function migrate( $username ) { $this->total++; $this->output( "CentralAuth account attach for: {$username}\n"); $central = new CentralAuthUser( $username, CentralAuthUser::READ_LATEST ); try { $unattached = $central->queryUnattached(); } catch ( Exception $e ) { // This might happen due to localnames inconsistencies (bug 67350) $this->output( "ERROR: Fetching unattached accounts for {$username} failed." ); return; } if ( $central->exists() ) { foreach ( $unattached as $wiki => $local ) { $this->output( "ATTACHING: $username@$wiki\n" ); $central->attach( $wiki, 'login', false ); } } else { $this->output( "ERROR: No CA account found for: $username\n" ); return; } $unattachedAfter = $central->queryUnattached(); if ( count( $unattachedAfter ) == 0 ) { $this->migrated++; return; } elseif ( count( $unattachedAfter ) > 0 && count( $unattachedAfter ) < count( $unattached ) ) { $this->partial++; $this->output( "INFO: Incomplete migration for '$username'\n" ); } } function migratePassOneReport() { $delta = microtime( true ) - $this->start; $this->output( sprintf( "%s processed %d usernames (%.1f/sec), %d (%.1f%%) fully migrated, %d (%.1f%%) partially migrated\n", wfTimestamp( TS_DB ), $this->total, $this->total / $delta, $this->migrated, $this->total > 0 ? ( $this->migrated / $this->total * 100.0 ) : 0, $this->partial, $this->total > 0 ? ( $this->partial / $this->total * 100.0 ) : 0 ) ); } } $maintClass = "AttachAccount"; require_once( RUN_MAINTENANCE_IF_MAIN );