/**
  * Marshal & execute the RenameUserProcess functions to rename a user
  *
  * @param array $wikiCityIds
  * @param array $params
  *		requestor_id => ID of the user requesting this rename action
  *		requestor_name => Name of the user requesting this rename action
  *		rename_user_id => ID of the user to rename
  *		rename_old_name => Current username of the user to rename
  *		rename_new_name => New username for the user to rename
  *		reason => Reason for requesting username change
  *		rename_fake_user_id => Repeated rename process special case (TODO: Don't know what this is)
  *		phalanx_block_id => Phalanx login block ID
  * @return bool
  */
 public function renameUser(array $wikiCityIds, array $params)
 {
     global $IP;
     $renameIP = !empty($params['rename_ip']);
     $loadBalancerFactory = wfGetLBFactory();
     $process = RenameUserProcess::newFromData($params);
     $process->setLogDestination(\RenameUserProcess::LOG_BATCH_TASK, $this);
     $process->setRequestorUser();
     $noErrors = true;
     // ComSup wants the StaffLogger to keep track of renames...
     $this->staffLog('start', $params, \RenameUserLogFormatter::start($params['requestor_name'], $params['rename_old_name'], $params['rename_new_name'], $params['reason'], [$this->getTaskId()]));
     try {
         foreach ($wikiCityIds as $cityId) {
             /**
              * execute maintenance script
              */
             $cmd = sprintf("SERVER_ID=%s php {$IP}/maintenance/wikia/RenameUser_local.php", $cityId);
             $opts = ['rename-user-id' => $params['rename_user_id'], 'requestor-id' => $params['requestor_id'], 'reason' => $params['reason']];
             if ($renameIP) {
                 $opts['rename-old-name'] = $params['rename_old_name'];
                 $opts['rename-new-name'] = $params['rename_new_name'];
             } else {
                 $opts['rename-old-name-enc'] = rawurlencode($params['rename_old_name']);
                 $opts['rename-new-name-enc'] = rawurlencode($params['rename_new_name']);
                 $opts['rename-fake-user-id'] = $params['rename_fake_user_id'];
                 $opts['phalanx-block-id'] = $params['phalanx_block_id'];
             }
             foreach ($opts as $opt => $val) {
                 $cmd .= sprintf(' --%s %s', $opt, escapeshellarg($val));
             }
             if ($renameIP) {
                 $cmd .= ' --rename-ip-address';
             }
             $exitCode = null;
             $output = wfShellExec($cmd, $exitCode);
             $logMessage = sprintf("Rename user %s to %s on city id %s", $params['rename_old_name'], $params['rename_new_name'], $cityId);
             $logContext = ['command' => $cmd, 'exitStatus' => $exitCode, 'output' => $output];
             if ($exitCode > 0) {
                 $this->error($logMessage, $logContext);
                 $noErrors = false;
             } else {
                 $this->info($logMessage, $logContext);
             }
             $this->staffLog('log', $params, \RenameUserLogFormatter::wiki($params['requestor_name'], $params['rename_old_name'], $params['rename_new_name'], $cityId, $params['reason'], $exitCode > 0));
             $loadBalancerFactory->forEachLBCallMethod('commitMasterChanges');
             $loadBalancerFactory->forEachLBCallMethod('closeAll');
         }
     } catch (Exception $e) {
         $noErrors = false;
         $this->error("error while renaming user", ['message' => $e->getMessage(), 'stack' => $e->getTraceAsString()]);
     }
     // clean up pre-process setup
     $process->cleanup();
     $this->notifyUser(\User::newFromId($params['requestor_id']), $params['rename_old_name'], $params['rename_new_name']);
     if (!$renameIP) {
         //mark user as renamed
         $renamedUser = \User::newFromName($params['rename_new_name']);
         $renamedUser->setGlobalFlag('wasRenamed', true);
         $renamedUser->saveSettings();
         if ($params['notify_renamed']) {
             //send e-mail to the user that rename process has finished
             $this->notifyUser($renamedUser, $params['rename_old_name'], $params['rename_new_name']);
         }
     }
     if ($noErrors) {
         $this->staffLog('finish', $params, \RenameUserLogFormatter::finish($params['requestor_name'], $params['rename_old_name'], $params['rename_new_name'], $params['reason'], [$this->getTaskId()]));
     } else {
         $this->staffLog('fail', $params, \RenameUserLogFormatter::fail($params['requestor_name'], $params['rename_old_name'], $params['rename_new_name'], $params['reason'], [$this->getTaskId()]));
     }
     return $noErrors;
 }
 /**
  * Processes specific local wiki database and makes all needed changes for an IP address
  *
  * Important: should only be run within maintenace script (bound to specified wiki)
  */
 public function updateLocalIP()
 {
     global $wgCityId, $wgUser;
     wfProfileIn(__METHOD__);
     if ($this->mUserId !== 0 || !IP::isIPAddress($this->mOldUsername) || !IP::isIPAddress($this->mNewUsername)) {
         $this->addError(wfMessage('userrenametool-error-invalid-ip')->escaped());
         wfProfileOut(__METHOD__);
         return;
     }
     $wgOldUser = $wgUser;
     $wgUser = User::newFromName('Wikia');
     $cityDb = WikiFactory::IDtoDB($wgCityId);
     $this->addLog("Processing wiki database: {$cityDb}.");
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     $tasks = self::$mLocalIpDefaults;
     $hookName = 'UserRename::LocalIP';
     $this->addLog("Broadcasting hook: {$hookName}");
     wfRunHooks($hookName, [$dbw, $this->mUserId, $this->mOldUsername, $this->mNewUsername, $this, $wgCityId, &$tasks]);
     foreach ($tasks as $task) {
         $this->addLog("Updating wiki \"{$cityDb}\": {$task['table']}:{$task['username_column']}");
         $this->renameInTable($dbw, $task['table'], $this->mUserId, $this->mOldUsername, $this->mNewUsername, $task);
     }
     $hookName = 'UserRename::AfterLocalIP';
     $this->addLog("Broadcasting hook: {$hookName}");
     wfRunHooks($hookName, [$dbw, $this->mUserId, $this->mOldUsername, $this->mNewUsername, $this, $wgCityId, &$tasks]);
     $dbw->commit();
     $this->addLog("Finished updating wiki database: {$cityDb}");
     $this->addMainLog("log", RenameUserLogFormatter::wiki($this->mRequestorName, $this->mOldUsername, $this->mNewUsername, $wgCityId, $this->mReason, !empty($this->warnings) || !empty($this->errors)));
     $wgUser = $wgOldUser;
     wfProfileOut(__METHOD__);
 }
 /**
  * Processes specific local wiki database and makes all needed changes
  *
  * Important: should only be run within maintenace script (bound to specified wiki)
  *
  * @param $cityId int Wiki ID
  */
 public function updateLocal()
 {
     global $wgCityId, $wgUser;
     wfProfileIn(__METHOD__);
     $wgOldUser = $wgUser;
     $wgUser = User::newFromName('Wikia');
     $cityDb = WikiFactory::IDtoDB($wgCityId);
     $this->addLog("Processing wiki database: {$cityDb}.");
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     $tasks = self::$mLocalDefaults;
     $hookName = 'UserRename::Local';
     $this->addLog("Broadcasting hook: {$hookName}");
     wfRunHooks($hookName, array($dbw, $this->mUserId, $this->mOldUsername, $this->mNewUsername, $this, $wgCityId, &$tasks));
     /* Move user pages */
     $this->addLog("Moving user pages.");
     try {
         $oldTitle = Title::makeTitle(NS_USER, $this->mOldUsername);
         $newTitle = Title::makeTitle(NS_USER, $this->mNewUsername);
         // Determine all namespaces which need processing
         $allowedNamespaces = array(NS_USER, NS_USER_TALK);
         // Blogs extension
         if (defined('NS_BLOG_ARTICLE')) {
             $allowedNamespaces = array_merge($allowedNamespaces, array(NS_BLOG_ARTICLE, NS_BLOG_ARTICLE_TALK));
         }
         // NY User profile
         if (defined('NS_USER_WIKI')) {
             $allowedNamespaces = array_merge($allowedNamespaces, array(NS_USER_WIKI, 201, NS_USER_PROFILE));
         }
         if (defined('NS_USER_WALL')) {
             $allowedNamespaces = array_merge($allowedNamespaces, array(NS_USER_WALL, NS_USER_WALL_MESSAGE, NS_USER_WALL_MESSAGE_GREETING));
         }
         $oldKey = $oldTitle->getDBkey();
         $like = $dbw->buildLike(sprintf("%s/", $oldKey), $dbw->anyString());
         $pages = $dbw->select('page', array('page_namespace', 'page_title'), array('page_namespace' => $allowedNamespaces, '(page_title ' . $like . ' OR page_title = ' . $dbw->addQuotes($oldKey) . ')'), __METHOD__);
         $this->addLog("SQL: " . $dbw->lastQuery());
         while ($row = $dbw->fetchObject($pages)) {
             $oldPage = Title::makeTitleSafe($row->page_namespace, $row->page_title);
             $newPage = Title::makeTitleSafe($row->page_namespace, preg_replace('!^[^/]+!', $newTitle->getDBkey(), $row->page_title));
             //Do not autodelete or anything, title must not exist
             //Info: The other case is when renaming is repeated - no action should be taken
             if ($newPage->exists() && !$oldPage->isValidMoveTarget($newPage)) {
                 $this->addLog("Updating wiki \"{$cityDb}\": User page " . $newPage->getText() . " already exists, moving cancelled.");
                 $this->addWarning(wfMsgForContent('userrenametool-page-exists', $newPage->getText()));
             } else {
                 $this->addLog("Moving page " . $oldPage->getText() . " in namespace {$row->page_namespace} to " . $newTitle->getText());
                 $success = $oldPage->moveTo($newPage, false, wfMsgForContent('userrenametool-move-log', $oldTitle->getText(), $newTitle->getText()));
                 if ($success === true) {
                     $this->addLog("Updating wiki \"{$cityDb}\": User page " . $oldPage->getText() . " moved to " . $newPage->getText() . '.');
                 } else {
                     $this->addLog("Updating wiki \"{$cityDb}\": User page " . $oldPage->getText() . " could not be moved to " . $newPage->getText() . '.');
                     $this->addWarning(wfMsgForContent('userrenametool-page-unmoved', array($oldPage->getText(), $newPage->getText())));
                 }
             }
         }
         $dbw->freeResult($pages);
     } catch (Exception $e) {
         $this->addLog("Exception while moving pages: " . $e->getMessage() . ' in ' . $e->getFile() . ' at line ' . $e->getLine());
     }
     /* End of move user pages */
     foreach ($tasks as $task) {
         $this->addLog("Updating wiki \"{$cityDb}\": {$task['table']}:{$task['username_column']}");
         $this->renameInTable($dbw, $task['table'], $this->mUserId, $this->mOldUsername, $this->mNewUsername, $task);
     }
     $hookName = 'UserRename::AfterLocal';
     $this->addLog("Broadcasting hook: {$hookName}");
     wfRunHooks($hookName, array($dbw, $this->mUserId, $this->mOldUsername, $this->mNewUsername, $this, $wgCityId, &$tasks));
     $dbw->commit();
     // Save entry in local Special:Log
     // Important: assuming that run inside the maintenance script
     $this->addLocalLog(wfMsgExt('userrenametool-success', array('content'), $this->mOldUsername, $this->mNewUsername));
     $this->addLog("Finished updating wiki database: {$cityDb}");
     $this->addMainLog("log", RenameUserLogFormatter::wiki($this->mRequestorName, $this->mOldUsername, $this->mNewUsername, $wgCityId, $this->mReason, !empty($this->warnings) || !empty($this->errors)));
     $wgUser = $wgOldUser;
     wfProfileOut(__METHOD__);
 }