public function doRun()
 {
     if (!class_exists('RenameuserSQL')) {
         throw new Exception('Extension:Renameuser is not installed');
     }
     $from = $this->params['from'];
     $to = $this->params['to'];
     $this->updateStatus('inprogress');
     if (isset($this->params['force']) && $this->params['force']) {
         // If we're dealing with an invalid username, load the data ourselves to avoid
         // any normalization at all done by User or Title.
         $row = wfGetDB(DB_MASTER)->selectRow('user', User::selectFields(), array('user_name' => $from), __METHOD__);
         $oldUser = User::newFromRow($row);
     } else {
         $oldUser = User::newFromName($from);
     }
     $rename = new RenameuserSQL($from, $to, $oldUser->getId(), $this->getRenameUser(), array('checkIfUserExists' => false, 'debugPrefix' => 'GlobalRename', 'reason' => $this->params['reason']));
     if (!$rename->rename()) {
         // This should never happen!
         // If it does happen, the user will be locked out of their account
         // until a sysadmin intervenes...
         throw new Exception('RenameuserSQL::rename returned false.');
     }
     if ($this->params['movepages']) {
         $this->movePages($oldUser);
     }
     if ($this->params['promotetoglobal']) {
         $this->promoteToGlobal();
     }
     $this->done();
 }
Example #2
0
 /** Helpers */
 private function getTestUser()
 {
     $userData = new stdClass();
     $userData->user_id = -1;
     $userData->user_name = 'testUser';
     $userData->user_editcount = 0;
     return User::newFromRow($userData);
 }
 /**
  * @param  $row
  * @return void
  */
 protected function setCurrent($row)
 {
     if ($row === false) {
         $this->current = false;
     } else {
         $this->current = User::newFromRow($row);
     }
 }
 function convertOptionBatch($res, $dbw)
 {
     $id = null;
     foreach ($res as $row) {
         $this->mConversionCount++;
         $u = User::newFromRow($row);
         $u->saveSettings();
         $id = $row->user_id;
     }
     return $id;
 }
 /**
  * @param $res
  * @param $dbw DatabaseBase
  * @return null|int
  */
 function convertOptionBatch($res, $dbw)
 {
     $id = null;
     foreach ($res as $row) {
         $this->mConversionCount++;
         $u = User::newFromRow($row);
         $u->saveSettings();
         // Do this here as saveSettings() doesn't set user_options to '' anymore!
         $dbw->update('user', array('user_options' => ''), array('user_id' => $row->user_id), __METHOD__);
         $id = $row->user_id;
     }
     return $id;
 }
 public function execute()
 {
     global $wgContentNamespaces, $wgFlaggedRevsAutopromote;
     $this->output("Populating and updating flaggedrevs_promote table\n");
     $dbr = wfGetDB(DB_SLAVE);
     $dbw = wfGetDB(DB_MASTER);
     $start = $dbr->selectField('user', 'MIN(user_id)', false, __METHOD__);
     $end = $dbr->selectField('user', 'MAX(user_id)', false, __METHOD__);
     if (is_null($start) || is_null($end)) {
         $this->output("...user table seems to be empty.\n");
         return;
     }
     $count = 0;
     $changed = 0;
     for ($blockStart = $start; $blockStart <= $end; $blockStart += $this->mBatchSize) {
         $blockEnd = min($end, $blockStart + $this->mBatchSize - 1);
         $this->output("...doing user_id from {$blockStart} to {$blockEnd}\n");
         $cond = "user_id BETWEEN {$blockStart} AND {$blockEnd}\n";
         $res = $dbr->select('user', '*', $cond, __METHOD__);
         # Go through and clean up missing items, as well as correct fr_quality...
         foreach ($res as $row) {
             $dbw->begin();
             $user = User::newFromRow($row);
             $p = FRUserCounters::getUserParams($user->getId(), FR_FOR_UPDATE);
             $oldp = $p;
             # Get edit comments used
             $sres = $dbr->select('revision', '1', array('rev_user' => $user->getID(), "rev_comment NOT LIKE '/*%*/'"), __METHOD__, array('LIMIT' => max($wgFlaggedRevsAutopromote['editComments'], 500)));
             $p['editComments'] = $dbr->numRows($sres);
             # Get content page edits
             $sres = $dbr->select(array('revision', 'page'), '1', array('rev_user' => $user->getID(), 'page_id = rev_page', 'page_namespace' => $wgContentNamespaces), __METHOD__, array('LIMIT' => max($wgFlaggedRevsAutopromote['totalContentEdits'], 500)));
             $p['totalContentEdits'] = $dbr->numRows($sres);
             # Get unique content pages edited
             $sres = $dbr->select(array('revision', 'page'), 'DISTINCT(rev_page)', array('rev_user' => $user->getID(), 'page_id = rev_page', 'page_namespace' => $wgContentNamespaces), __METHOD__, array('LIMIT' => max($wgFlaggedRevsAutopromote['uniqueContentPages'], 50)));
             $p['uniqueContentPages'] = array();
             foreach ($sres as $innerRow) {
                 $p['uniqueContentPages'][] = (int) $innerRow->rev_page;
             }
             # Save the new params...
             if ($oldp != $p) {
                 FRUserCounters::saveUserParams($user->getId(), $p);
                 $changed++;
             }
             $count++;
             $dbw->commit();
         }
         wfWaitForSlaves(5);
     }
     $this->output("flaggedrevs_promote table update complete ..." . " {$count} rows [{$changed} changed or added]\n");
 }
 protected function outputRow($fh, $row)
 {
     //if there is an exception when setting this single record
     //record it so it won't stop the outputting of other records
     try {
         $item = MBFeedbackItem::load($row);
         $user = User::newFromRow($row);
         $outData = array();
         foreach ($this->fields as $field) {
             $outData[] = MoodBarFormatter::getInternalRepresentation($item, $field);
         }
     } catch (Exception $e) {
         $outData[] = wfMessage('moodbar-feedback-load-record-error')->escaped();
     }
     fputcsv($fh, $outData);
 }
 /**
  * Initialiser for MBFeedbackItems loaded from the database
  * @param $row A row object from DatabaseBase::fetchObject
  * @see MBFeedbackItem::load
  */
 protected function initialiseFromRow($row)
 {
     static $propMappings = array('id' => 'mbf_id', 'type' => 'mbf_type', 'comment' => 'mbf_comment', 'timestamp' => 'mbf_timestamp', 'anonymize' => 'mbf_anonymous', 'useragent' => 'mbf_user_agent', 'system' => 'mbf_system_type', 'locale' => 'mbf_locale', 'bucket' => 'mbf_bucket', 'editmode' => 'mbf_editing', 'user-editcount' => 'mbf_user_editcount', 'hidden-state' => 'mbf_hidden_state');
     $properties = array();
     foreach ($propMappings as $property => $field) {
         if (isset($row->{$field})) {
             $properties[$property] = $row->{$field};
         }
     }
     if (isset($row->mbf_namespace) && isset($row->mbf_title)) {
         $properties['page'] = Title::makeTitleSafe($row->mbf_namespace, $row->mbf_title);
     }
     if (!empty($row->user_id)) {
         $properties['user'] = User::newFromRow($row);
     } elseif ($row->mbf_user_id > 0) {
         $properties['user'] = User::newFromId($row->mbf_user_id);
     } elseif ($row->mbf_user_ip) {
         $properties['user'] = User::newFromName($row->mbf_user_ip);
     }
     $this->setProperties($properties, true);
 }
Example #9
0
 public function execute()
 {
     $params = $this->extractRequestParams();
     if (!is_null($params['prop'])) {
         $this->prop = array_flip($params['prop']);
     } else {
         $this->prop = array();
     }
     $users = (array) $params['users'];
     $goodNames = $done = array();
     $result = $this->getResult();
     // Canonicalize user names
     foreach ($users as $u) {
         $n = User::getCanonicalName($u);
         if ($n === false || $n === '') {
             $vals = array('name' => $u, 'invalid' => '');
             $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
                 $goodNames = array();
                 break;
             }
             $done[] = $u;
         } else {
             $goodNames[] = $n;
         }
     }
     if (count($goodNames)) {
         $this->addTables('user', 'u1');
         $this->addFields('u1.*');
         $this->addWhereFld('u1.user_name', $goodNames);
         if (isset($this->prop['groups'])) {
             $this->addTables('user_groups');
             $this->addJoinConds(array('user_groups' => array('LEFT JOIN', 'ug_user=u1.user_id')));
             $this->addFields('ug_group');
         }
         $this->showHiddenUsersAddBlockInfo(isset($this->prop['blockinfo']));
         $data = array();
         $res = $this->select(__METHOD__);
         foreach ($res as $row) {
             $user = User::newFromRow($row);
             $name = $user->getName();
             $data[$name]['name'] = $name;
             if (isset($this->prop['editcount'])) {
                 $data[$name]['editcount'] = intval($user->getEditCount());
             }
             if (isset($this->prop['registration'])) {
                 $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration());
             }
             if (isset($this->prop['groups']) && !is_null($row->ug_group)) {
                 // This row contains only one group, others will be added from other rows
                 $data[$name]['groups'][] = $row->ug_group;
             }
             if (isset($this->prop['rights']) && !is_null($row->ug_group)) {
                 if (!isset($data[$name]['rights'])) {
                     $data[$name]['rights'] = User::getGroupPermissions(User::getImplicitGroups());
                 }
                 $data[$name]['rights'] = array_unique(array_merge($data[$name]['rights'], User::getGroupPermissions(array($row->ug_group))));
                 $result->setIndexedTagName($data[$name]['rights'], 'r');
             }
             if ($row->ipb_deleted) {
                 $data[$name]['hidden'] = '';
             }
             if (isset($this->prop['blockinfo']) && !is_null($row->ipb_by_text)) {
                 $data[$name]['blockedby'] = $row->ipb_by_text;
                 $data[$name]['blockreason'] = $row->ipb_reason;
                 $data[$name]['blockexpiry'] = $row->ipb_expiry;
             }
             if (isset($this->prop['emailable']) && $user->canReceiveEmail()) {
                 $data[$name]['emailable'] = '';
             }
             if (isset($this->prop['gender'])) {
                 $gender = $user->getOption('gender');
                 if (strval($gender) === '') {
                     $gender = 'unknown';
                 }
                 $data[$name]['gender'] = $gender;
             }
             if (!is_null($params['token'])) {
                 $tokenFunctions = $this->getTokenFunctions();
                 foreach ($params['token'] as $t) {
                     $val = call_user_func($tokenFunctions[$t], $user);
                     if ($val === false) {
                         $this->setWarning("Action '{$t}' is not allowed for the current user");
                     } else {
                         $data[$name][$t . 'token'] = $val;
                     }
                 }
             }
         }
     }
     // Second pass: add result data to $retval
     foreach ($goodNames as $u) {
         if (!isset($data[$u])) {
             $data[$u] = array('name' => $u);
             $urPage = new UserrightsPage();
             $iwUser = $urPage->fetchUser($u);
             if ($iwUser instanceof UserRightsProxy) {
                 $data[$u]['interwiki'] = '';
                 if (!is_null($params['token'])) {
                     $tokenFunctions = $this->getTokenFunctions();
                     foreach ($params['token'] as $t) {
                         $val = call_user_func($tokenFunctions[$t], $iwUser);
                         if ($val === false) {
                             $this->setWarning("Action '{$t}' is not allowed for the current user");
                         } else {
                             $data[$u][$t . 'token'] = $val;
                         }
                     }
                 }
             } else {
                 $data[$u]['missing'] = '';
             }
         } else {
             if (isset($this->prop['groups']) && isset($data[$u]['groups'])) {
                 $autolist = ApiQueryUsers::getAutoGroups(User::newFromName($u));
                 $data[$u]['groups'] = array_merge($autolist, $data[$u]['groups']);
                 $this->getResult()->setIndexedTagName($data[$u]['groups'], 'g');
             }
         }
         $fit = $result->addValue(array('query', $this->getModuleName()), null, $data[$u]);
         if (!$fit) {
             $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
             break;
         }
         $done[] = $u;
     }
     return $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'user');
 }
Example #10
0
 public function getLocalUser($obj = true)
 {
     wfProfileIn(__METHOD__);
     if (empty($this->mRow)) {
         wfProfileOut(__METHOD__);
         return null;
     }
     if ($obj) {
         $res = User::newFromRow($this->mRow);
     } else {
         $res = $this->mRow;
     }
     wfProfileOut(__METHOD__);
     return $res;
 }
 /**
  * Process the form.  At this point we know that the user passes all the criteria in
  * userCanExecute(), and if the data array contains 'Username', etc, then Username
  * resets are allowed.
  * @param $data array
  * @return Bool|Array
  */
 public function onSubmit(array $data)
 {
     global $wgAuth;
     if (isset($data['Domain'])) {
         if ($wgAuth->validDomain($data['Domain'])) {
             $wgAuth->setDomain($data['Domain']);
         } else {
             $wgAuth->setDomain('invaliddomain');
         }
     }
     if (isset($data['Username']) && $data['Username'] !== '') {
         $method = 'username';
         $users = array(User::newFromName($data['Username']));
     } elseif (isset($data['Email']) && $data['Email'] !== '' && Sanitizer::validateEmail($data['Email'])) {
         $method = 'email';
         $res = wfGetDB(DB_SLAVE)->select('user', '*', array('user_email' => $data['Email']), __METHOD__);
         if ($res) {
             $users = array();
             foreach ($res as $row) {
                 $users[] = User::newFromRow($row);
             }
         } else {
             // Some sort of database error, probably unreachable
             throw new MWException('Unknown database error in ' . __METHOD__);
         }
     } else {
         // The user didn't supply any data
         return false;
     }
     // Check for hooks (captcha etc), and allow them to modify the users list
     $error = array();
     if (!wfRunHooks('SpecialPasswordResetOnSubmit', array(&$users, $data, &$error))) {
         return array($error);
     }
     if (count($users) == 0) {
         if ($method == 'email') {
             // Don't reveal whether or not an email address is in use
             return true;
         } else {
             return array('noname');
         }
     }
     $firstUser = $users[0];
     if (!$firstUser instanceof User || !$firstUser->getID()) {
         return array(array('nosuchuser', $data['Username']));
     }
     // Check against the rate limiter
     if ($this->getUser()->pingLimiter('mailpassword')) {
         throw new ThrottledError();
     }
     // Check against password throttle
     foreach ($users as $user) {
         if ($user->isPasswordReminderThrottled()) {
             global $wgPasswordReminderResendTime;
             # Round the time in hours to 3 d.p., in case someone is specifying
             # minutes or seconds.
             return array(array('throttled-mailpassword', round($wgPasswordReminderResendTime, 3)));
         }
     }
     global $wgNewPasswordExpiry;
     // All the users will have the same email address
     if ($firstUser->getEmail() == '') {
         // This won't be reachable from the email route, so safe to expose the username
         return array(array('noemail', $firstUser->getName()));
     }
     // We need to have a valid IP address for the hook, but per bug 18347, we should
     // send the user's name if they're logged in.
     $ip = wfGetIP();
     if (!$ip) {
         return array('badipaddress');
     }
     $caller = $this->getUser();
     wfRunHooks('User::mailPasswordInternal', array(&$caller, &$ip, &$firstUser));
     $username = $caller->getName();
     $msg = IP::isValid($username) ? 'passwordreset-emailtext-ip' : 'passwordreset-emailtext-user';
     // Send in the user's language; which should hopefully be the same
     $userLanguage = $firstUser->getOption('language');
     $passwords = array();
     foreach ($users as $user) {
         $password = $user->randomPassword();
         $user->setNewpassword($password);
         $user->saveSettings();
         $passwords[] = wfMessage('passwordreset-emailelement', $user->getName(), $password)->inLanguage($userLanguage)->plain();
         // We'll escape the whole thing later
     }
     $passwordBlock = implode("\n\n", $passwords);
     $body = wfMessage($msg)->inLanguage($userLanguage);
     $body->params($username, $passwordBlock, count($passwords), Title::newMainPage()->getCanonicalUrl(), round($wgNewPasswordExpiry / 86400));
     $title = wfMessage('passwordreset-emailtitle');
     $result = $firstUser->sendMail($title->text(), $body->text());
     if ($result->isGood()) {
         return true;
     } else {
         // @todo FIXME: The email didn't send, but we have already set the password throttle
         // timestamp, so they won't be able to try again until it expires...  :(
         return array(array('mailerror', $result->getMessage()));
     }
 }
Example #12
0
 /**
  * @param string $email
  * @return User[]
  * @throws MWException On unexpected database errors
  */
 protected function getUsersByEmail($email)
 {
     $res = wfGetDB(DB_REPLICA)->select('user', User::selectFields(), ['user_email' => $email], __METHOD__);
     if (!$res) {
         // Some sort of database error, probably unreachable
         throw new MWException('Unknown database error in ' . __METHOD__);
     }
     $users = [];
     foreach ($res as $row) {
         $users[] = User::newFromRow($row);
     }
     return $users;
 }
Example #13
0
 public function execute()
 {
     $params = $this->extractRequestParams();
     $result = $this->getResult();
     $r = array();
     if (!is_null($params['prop'])) {
         $this->prop = array_flip($params['prop']);
     } else {
         $this->prop = array();
     }
     $users = (array) $params['users'];
     $goodNames = $done = array();
     $result = $this->getResult();
     // Canonicalize user names
     foreach ($users as $u) {
         $n = User::getCanonicalName($u);
         if ($n === false || $n === '') {
             $vals = array('name' => $u, 'invalid' => '');
             $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
                 $goodNames = array();
                 break;
             }
             $done[] = $u;
         } else {
             $goodNames[] = $n;
         }
     }
     if (count($goodNames)) {
         $db = $this->getDb();
         $this->addTables('user', 'u1');
         $this->addFields('u1.*');
         $this->addWhereFld('u1.user_name', $goodNames);
         if (isset($this->prop['groups'])) {
             $this->addTables('user_groups');
             $this->addJoinConds(array('user_groups' => array('LEFT JOIN', 'ug_user=u1.user_id')));
             $this->addFields('ug_group');
         }
         if (isset($this->prop['blockinfo'])) {
             $this->addTables('ipblocks');
             $this->addTables('user', 'u2');
             $u2 = $this->getAliasedName('user', 'u2');
             $this->addJoinConds(array('ipblocks' => array('LEFT JOIN', 'ipb_user=u1.user_id'), $u2 => array('LEFT JOIN', 'ipb_by=u2.user_id')));
             $this->addFields(array('ipb_reason', 'u2.user_name AS blocker_name'));
         }
         $data = array();
         $res = $this->select(__METHOD__);
         while ($r = $db->fetchObject($res)) {
             $user = User::newFromRow($r);
             $name = $user->getName();
             $data[$name]['name'] = $name;
             if (isset($this->prop['editcount'])) {
                 $data[$name]['editcount'] = intval($user->getEditCount());
             }
             if (isset($this->prop['registration'])) {
                 $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration());
             }
             if (isset($this->prop['groups']) && !is_null($r->ug_group)) {
                 // This row contains only one group, others will be added from other rows
                 $data[$name]['groups'][] = $r->ug_group;
             }
             if (isset($this->prop['blockinfo']) && !is_null($r->blocker_name)) {
                 $data[$name]['blockedby'] = $r->blocker_name;
                 $data[$name]['blockreason'] = $r->ipb_reason;
             }
             if (isset($this->prop['emailable']) && $user->canReceiveEmail()) {
                 $data[$name]['emailable'] = '';
             }
         }
     }
     // Second pass: add result data to $retval
     foreach ($goodNames as $u) {
         if (!isset($data[$u])) {
             $data[$u] = array('name' => $u, 'missing' => '');
         } else {
             if (isset($this->prop['groups']) && isset($data[$u]['groups'])) {
                 $this->getResult()->setIndexedTagName($data[$u]['groups'], 'g');
             }
         }
         $fit = $result->addValue(array('query', $this->getModuleName()), null, $data[$u]);
         if (!$fit) {
             $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
             break;
         }
         $done[] = $u;
     }
     return $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'user');
 }
Example #14
0
 protected function getOtherUsersInfo($users)
 {
     $goodNames = $retval = array();
     // Canonicalize user names
     foreach ($users as $u) {
         $n = User::getCanonicalName($u);
         if ($n === false || $n === '') {
             $retval[] = array('name' => $u, 'invalid' => '');
         } else {
             $goodNames[] = $n;
         }
     }
     if (!count($goodNames)) {
         return $retval;
     }
     $db = $this->getDB();
     $this->addTables('user', 'u1');
     $this->addFields('u1.*');
     $this->addWhereFld('u1.user_name', $goodNames);
     if (isset($this->prop['groups'])) {
         $this->addTables('user_groups');
         $this->addJoinConds(array('user_groups' => array('LEFT JOIN', 'ug_user=u1.user_id')));
         $this->addFields('ug_group');
     }
     if (isset($this->prop['blockinfo'])) {
         $this->addTables('ipblocks');
         $this->addTables('user', 'u2');
         $u2 = $this->getAliasedName('user', 'u2');
         $this->addJoinConds(array('ipblocks' => array('LEFT JOIN', 'ipb_user=u1.user_id'), $u2 => array('LEFT JOIN', 'ipb_by=u2.user_id')));
         $this->addFields(array('ipb_reason', 'u2.user_name blocker_name'));
     }
     $data = array();
     $res = $this->select(__METHOD__);
     while ($r = $db->fetchObject($res)) {
         $user = User::newFromRow($r);
         $name = $user->getName();
         $data[$name]['name'] = $name;
         if (isset($this->prop['editcount'])) {
             // No proper member function in User class for this
             $data[$name]['editcount'] = $r->user_editcount;
         }
         if (isset($this->prop['registration'])) {
             // Nor for this one
             $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $r->user_registration);
         }
         if (isset($this->prop['groups'])) {
             // This row contains only one group, others will be added from other rows
             if (!is_null($r->ug_group)) {
                 $data[$name]['groups'][] = $r->ug_group;
             }
         }
         if (isset($this->prop['blockinfo'])) {
             if (!is_null($r->blocker_name)) {
                 $data[$name]['blockedby'] = $r->blocker_name;
                 $data[$name]['blockreason'] = $r->ipb_reason;
             }
         }
         if (isset($this->prop['emailable']) && $user->canReceiveEmail()) {
             $data[$name]['emailable'] = '';
         }
     }
     // Second pass: add result data to $retval
     foreach ($goodNames as $u) {
         if (!isset($data[$u])) {
             $retval[] = array('name' => $u, 'missing' => '');
         } else {
             if (isset($this->prop['groups']) && isset($data[$u]['groups'])) {
                 $this->getResult()->setIndexedTagName($data[$u]['groups'], 'g');
             }
             $retval[] = $data[$u];
         }
     }
     return $retval;
 }
    protected static function buildResponseElement($feedbackItem, $response)
    {
        global $wgLang, $wgUser;
        $responseElements = '';
        $id = $feedbackItem->getProperty('id');
        $showResponseBox = true;
        //Do not show response box if there is a response already
        if (isset($response[$id])) {
            $response_detail = $response[$id];
            $responder = User::newFromRow($response_detail);
            if ($responder && !$responder->isAnon()) {
                $responsetime = MoodBarUtil::formatTimeSince(wfTimestamp(TS_UNIX, $response_detail->mbfr_timestamp));
                $permalinkTitle = $feedbackItem->getProperty('user')->getTalkPage()->getFullText();
                $individual_response = wfMsgExt('moodbar-feedback-response-summary', array('parse'), $responder->getUserPage()->getFullText(), $responder->getName(), $permalinkTitle . '#feedback-dashboard-response-' . $response_detail->mbfr_id, $responsetime);
                $showResponseBox = false;
                $responseElements = <<<HTML
\t\t\t\t\t\t\t\t<div class="fbd-item-response">
\t\t\t\t\t\t\t\t\t{$individual_response}
\t\t\t\t\t\t\t\t</div>
HTML;
            }
        } elseif ($showResponseBox && $feedbackItem->getProperty('hidden-state') == false && !$wgUser->isAnon()) {
            //$respondToThis = "<span>".wfMessage('moodbar-respond-collapsed')->escaped().'</span> '.wfMessage("moodbar-respond-text")->escaped();
            $respondToThis = '<span class="fbd-item-response-collapsed"></span> ' . wfMessage("moodbar-respond-text")->escaped();
            $responseElements = <<<HTML
\t\t\t\t<div class="fbd-item-response">
\t\t\t\t\t<a class="fbd-respond-link">{$respondToThis}</a>
\t\t\t\t</div>
HTML;
        }
        return $responseElements;
    }
Example #16
0
$wgRequestTime = microtime(true);
/** */
# Abort if called from a web server
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
    print "This script must be run from the command line\n";
    exit;
}
if (version_compare(PHP_VERSION, '5.0.0') < 0) {
    print "Sorry! This version of MediaWiki requires PHP 5; you are running " . PHP_VERSION . ".\n\n" . "If you are sure you already have PHP 5 installed, it may be " . "installed\n" . "in a different path from PHP 4. Check with your system administrator.\n";
    die(-1);
}
// include commandLine script which provides some basic
// methodes for maintenance scripts
$mediaWikiLocation = dirname(__FILE__) . '/../../../..';
require_once "{$mediaWikiLocation}/maintenance/commandLine.inc";
global $smwgNMIP;
require_once $smwgNMIP . '/includes/SMW_NMStorage.php';
$sStore = NMStorage::getDatabase();
$msgs = $sStore->getUnmailedNMMessages();
foreach ($msgs as $msg) {
    // send notifications by mail
    if ($msg['user_id'] == null) {
        continue;
    }
    $user_info = $sStore->getUserInfo($msg['user_id']);
    $user = User::newFromRow($user_info);
    if ($user_info->user_email != '' && $user->getGlobalPreference('enotifyme')) {
        $name = $user_info->user_real_name == '' ? $user_info->user_name : $user_info->user_real_name;
        UserMailer::send(new MailAddress($user_info->user_email, $name), new MailAddress($wgEmergencyContact, 'Admin'), wfMsg('smw_nm_hint_mail_title', $msg['title'], $wgSitename), wfMsg('smw_nm_hint_mail_body_html', $name, $msg['notify']), new MailAddress($wgEmergencyContact, 'Admin'), 'text/html; charset=UTF-8');
    }
}
 /**
  * Handler for EchoGetDefaultNotifiedUsers hook.
  * @param EchoEvent $event EchoEvent to get implicitly subscribed users for
  * @param array &$users Array to append implicitly subscribed users to.
  * @return bool true in all cases
  */
 public static function onEchoGetDefaultNotifiedUsers($event, &$users)
 {
     switch ($event->getType()) {
         case 'bs-shoutbox-mention':
             $extra = $event->getExtra();
             if (!$extra || !isset($extra['mentioned-user-id'])) {
                 break;
             }
             $recipientId = $extra['mentioned-user-id'];
             //really ugly, but newFromId appears to be broken...
             $oDBr = wfGetDB(DB_SLAVE);
             $row = $oDBr->selectRow('user', '*', array('user_id' => (int) $recipientId));
             $recipient = User::newFromRow($row);
             $users[$recipientId] = $recipient;
             //$event->setExtra('username', $recipient->);
             break;
     }
     return true;
 }
 /**
  * Process the form.  At this point we know that the user passes all the criteria in
  * userCanExecute(), and if the data array contains 'Username', etc, then Username
  * resets are allowed.
  * @param array $data
  * @throws MWException
  * @throws ThrottledError|PermissionsError
  * @return bool|array
  */
 public function onSubmit(array $data)
 {
     global $wgAuth;
     if (isset($data['Domain'])) {
         if ($wgAuth->validDomain($data['Domain'])) {
             $wgAuth->setDomain($data['Domain']);
         } else {
             $wgAuth->setDomain('invaliddomain');
         }
     }
     if (isset($data['Capture']) && !$this->getUser()->isAllowed('passwordreset')) {
         // The user knows they don't have the passwordreset permission,
         // but they tried to spoof the form. That's naughty
         throw new PermissionsError('passwordreset');
     }
     /**
      * @var $firstUser User
      * @var $users User[]
      */
     if (isset($data['Username']) && $data['Username'] !== '') {
         $method = 'username';
         $users = array(User::newFromName($data['Username']));
     } elseif (isset($data['Email']) && $data['Email'] !== '' && Sanitizer::validateEmail($data['Email'])) {
         $method = 'email';
         $res = wfGetDB(DB_SLAVE)->select('user', User::selectFields(), array('user_email' => $data['Email']), __METHOD__);
         if ($res) {
             $users = array();
             foreach ($res as $row) {
                 $users[] = User::newFromRow($row);
             }
         } else {
             // Some sort of database error, probably unreachable
             throw new MWException('Unknown database error in ' . __METHOD__);
         }
     } else {
         // The user didn't supply any data
         return false;
     }
     // Check for hooks (captcha etc), and allow them to modify the users list
     $error = array();
     if (!Hooks::run('SpecialPasswordResetOnSubmit', array(&$users, $data, &$error))) {
         return array($error);
     }
     if (count($users) == 0) {
         if ($method == 'email') {
             // Don't reveal whether or not an email address is in use
             return true;
         } else {
             return array('noname');
         }
     }
     $firstUser = $users[0];
     if (!$firstUser instanceof User || !$firstUser->getID()) {
         // Don't parse username as wikitext (bug 65501)
         return array(array('nosuchuser', wfEscapeWikiText($data['Username'])));
     }
     // Check against the rate limiter
     if ($this->getUser()->pingLimiter('mailpassword')) {
         throw new ThrottledError();
     }
     // Check against password throttle
     foreach ($users as $user) {
         if ($user->isPasswordReminderThrottled()) {
             # Round the time in hours to 3 d.p., in case someone is specifying
             # minutes or seconds.
             return array(array('throttled-mailpassword', round($this->getConfig()->get('PasswordReminderResendTime'), 3)));
         }
     }
     // All the users will have the same email address
     if ($firstUser->getEmail() == '') {
         // This won't be reachable from the email route, so safe to expose the username
         return array(array('noemail', wfEscapeWikiText($firstUser->getName())));
     }
     // We need to have a valid IP address for the hook, but per bug 18347, we should
     // send the user's name if they're logged in.
     $ip = $this->getRequest()->getIP();
     if (!$ip) {
         return array('badipaddress');
     }
     $caller = $this->getUser();
     Hooks::run('User::mailPasswordInternal', array(&$caller, &$ip, &$firstUser));
     $username = $caller->getName();
     $msg = IP::isValid($username) ? 'passwordreset-emailtext-ip' : 'passwordreset-emailtext-user';
     // Send in the user's language; which should hopefully be the same
     $userLanguage = $firstUser->getOption('language');
     $passwords = array();
     foreach ($users as $user) {
         $password = $user->randomPassword();
         $user->setNewpassword($password);
         $user->saveSettings();
         $passwords[] = $this->msg('passwordreset-emailelement', $user->getName(), $password)->inLanguage($userLanguage)->text();
         // We'll escape the whole thing later
     }
     $passwordBlock = implode("\n\n", $passwords);
     $this->email = $this->msg($msg)->inLanguage($userLanguage);
     $this->email->params($username, $passwordBlock, count($passwords), '<' . Title::newMainPage()->getCanonicalURL() . '>', round($this->getConfig()->get('NewPasswordExpiry') / 86400));
     $title = $this->msg('passwordreset-emailtitle');
     $this->result = $firstUser->sendMail($title->text(), $this->email->text());
     if (isset($data['Capture']) && $data['Capture']) {
         // Save the user, will be used if an error occurs when sending the email
         $this->firstUser = $firstUser;
     } else {
         // Blank the email if the user is not supposed to see it
         $this->email = null;
     }
     if ($this->result->isGood()) {
         return true;
     } elseif (isset($data['Capture']) && $data['Capture']) {
         // The email didn't send, but maybe they knew that and that's why they captured it
         return true;
     } else {
         // @todo FIXME: The email wasn't sent, but we have already set
         // the password throttle timestamp, so they won't be able to try
         // again until it expires...  :(
         return array(array('mailerror', $this->result->getMessage()));
     }
 }
 public function getPerformer()
 {
     if (!$this->performer) {
         $userId = (int) $this->row->log_user;
         if ($userId !== 0) {
             // logged-in users
             if (isset($this->row->user_name)) {
                 $this->performer = User::newFromRow($this->row);
             } else {
                 $this->performer = User::newFromId($userId);
             }
         } else {
             // IP users
             $userText = $this->row->log_user_text;
             $this->performer = User::newFromName($userText, false);
         }
     }
     return $this->performer;
 }
	public function execute( $par ) {
		global $wgRequest, $wgOut, $wgLang, $wgAutoloadClasses;

		$this->setHeaders();
		$this->outputHeader();

		if ( !class_exists( 'PHPlot' ) && !isset($wgAutoloadClasses['PHPlot'] ) ) {
			$wgOut->addWikiMsg( 'uos-warn' );
			return;
		}

		$par = trim(strtolower($par));

		foreach ( $this->blacklist as $b ) {
			if ( $b === $par ) {
				$par = false;
				break;
			}
		}

		if ( !$par ) {
			$opts = array();
			$hiddenoptions = $this->getHiddenOptions();
			$name = SpecialPage::getTitleFor( 'UserOptionStats' )->getPrefixedText();
			foreach ( $this->getOptions() as $k ) {
				if( in_array( $k, $hiddenoptions ) ) {
					continue; # List hidden options separately (see below)
				}
				$opts[] = "[[$name/$k|$k]]";
			}
			$wgOut->addWikiMsg( 'uos-choose', $wgLang->commaList( $opts ) );
			if ( count( $hiddenoptions ) > 0 ) {
				$hiddenopts = array();
				foreach ( $hiddenoptions as $hk ) {
					$hiddenopts[] = "[[$name/$hk|$hk]]";
				}
				$wgOut->addWikiMsg( 'uos-choose-hidden', $wgLang->commaList( $hiddenopts ) );
			}
			return;
		}

		$dbr = wfGetDB( DB_SLAVE );

		$users = $dbr->select( 'user', '*', '', __METHOD__ );
		$data = array();
		$optionName = $par;
		foreach ( $users as $u ) {
			// New from row doesn't load user_properties, hence this is slow!
			$obj = User::newFromRow( $u );
			$opt = $obj->getOption( $optionName, wfMsg( 'uos-unknown' ) );

			if ( !isset($data[$opt]) ) $data[$opt] = 0;
			$data[$opt]++;
		}

		$realdata = array();
		$labels = array();

		// Most popular first, barring other
		arsort( $data );

		// After more than 7 the default colors start to loop :(
		// So use the last free color for "other" which includes the rest
		$max = 7;
		$rest = array_slice( $data, $max );
		$data = array_slice( $data, 0, $max );
		foreach ( $data as $k => $d ) {
			$labels[] = "$k ($d)";
			$realdata[] = array( $k, $d );
		}
		if ( count($rest) ) {
			$other = 0;
			foreach ( $rest as $v ) $other += $v;
			$labels[] = wfMsg( 'uos-other' ) . " ($other)";
			$realdata[] = array( 'other', $other );
		}

		$title = $wgRequest->getText( 'pietitle', wfMsg( 'uos-title', $optionName ) );
		$width = $wgRequest->getInt( 'width', 700 );
		$height = $wgRequest->getInt( 'height', 500 );
		$width = max( 200, min( 1000, $width ) );
		$height = max( 200, min( 1000, $height ) );
		$shading = $wgRequest->getInt( 'shading', 10 );
		$height = max( 0, min( 1000, $height ) );

		// Define the object
		$plot = new PHPlot( $width, $height );
		$plot->SetDataType('text-data-single');
		$plot->setDataValues( $realdata );
		$plot->SetPlotType('pie');
		$plot->SetLegend($labels);
		$plot->SetShading( $shading );
		$plot->SetLabelScalePosition(0.3);
		$plot->SetTitle( $title );

		// Better fonts
		$realFunction = array( 'FCFontFinder', 'find' );
		if ( is_callable( $realFunction ) ) {
			$font = FCFontFinder::find( $wgLang->getCode() );
			if ( $font ) {
				$plot->SetDefaultTTFont( $font );
			}
		}

		global $wgOut;
		$wgOut->disable();
		$plot->DrawGraph();
	}
	public function notifyUsers() {
		global $wgSitename, $wgSMTP, $wgEmergencyContact, $wgEnotifyMeJob;
		$sStore = NMStorage::getDatabase();

		$nm_send_jobs = array();
		$id = 0;

		if ( count( $this->m_notifyHtmlMsgs ) > 0 ) {
			$notifications = $sStore->getNotifyMe( array_keys( $this->m_notifyHtmlMsgs ) );
		}
		$html_style = '';
		// <style>
		// table.smwtable{background-color: #EEEEFF;}
		// table.smwtable th{background-color: #EEEEFF;text-align: left;}
		// table.smwtable td{background-color: #FFFFFF;padding: 1px;padding-left: 5px;padding-right: 5px;text-align: left;vertical-align: top;}
		// table.smwtable tr.smwfooter td{font-size: 90%;line-height: 1;background-color: #EEEEFF;padding: 0px;padding-left: 5px;padding-right: 5px;text-align: right;vertical-align: top;}
		// </style>';
		$html_showall = array();
		foreach ( $this->m_notifyHtmlMsgs as $notify_id => $msg ) {
			$html_msg = $html_style;
			$showing_all = false;
			if ( isset( $notifications[$notify_id] ) && $notifications[$notify_id]['show_all'] ) {
				SMWQueryProcessor::processFunctionParams( SMWNotifyProcessor::getQueryRawParams( $notifications[$notify_id]['query'] ), $querystring, $params, $printouts );

				$format = 'auto';
				if ( array_key_exists( 'format', $params ) ) {
					$format = strtolower( trim( $params['format'] ) );
					global $smwgResultFormats;
					if ( !array_key_exists( $format, $smwgResultFormats ) ) {
						$format = 'auto';
					}
				}
				$query  = SMWQueryProcessor::createQuery( $querystring, $params, SMWQueryProcessor::INLINE_QUERY, $format, $printouts );
				$res = smwfGetStore()->getQueryResult( $query );
				$printer = SMWQueryProcessor::getResultPrinter( $format, SMWQueryProcessor::INLINE_QUERY, $res );
				$result = $printer->getResult( $res, $params, SMW_OUTPUT_HTML );
				// FIXME: hardcode switch to full url
				global $wgScriptPath, $wgServer;
				$result = str_replace ( $wgScriptPath, $wgServer . $wgScriptPath, $result );
				$html_msg .= $result . '<br/>';
				$html_showall[$notify_id] = array ( 'name' => $notifications[$notify_id]['name'], 'html' => $result );

				$showing_all = true;
				$link = $res->getQueryLink()->getURL();
			}
			global $smwgNMHideDiffWhenShowAll;
			if ( !( $smwgNMHideDiffWhenShowAll && $showing_all ) ) {
				$html_msg .= wfMsg( 'smw_nm_hint_notification_html', $this->m_notifyHtmlMsgs[$notify_id] );
				if ( isset( $this->m_notifyHtmlPropMsgs[$notify_id] ) ) {
					$html_msg .= wfMsg( 'smw_nm_hint_nmtable_html', $this->m_notifyHtmlPropMsgs[$notify_id] );
				}
			}
			if ( $showing_all ) {
				$id = $sStore->addNotifyRSS( 'nid', $notify_id, "All current items, " . date( 'Y-m-d H:i:s', time() ), $this->applyStyle( $html_msg ), $link );
			} else {
				$id = $sStore->addNotifyRSS( 'nid', $notify_id, $this->m_title->getText(), $this->applyStyle( $html_msg ) );
			}
		}
		foreach ( $this->m_userMsgs as $user_id => $msg ) {
			// generate RSS items
			$html_msg = $html_style;
			foreach ( array_unique( $this->m_userNMs[$user_id] ) as $showall_nid ) {
				if ( isset( $html_showall[$showall_nid] ) ) {
					$html_msg .= wfMsg( 'smw_nm_hint_item_html', $html_showall[$showall_nid]['name'], $html_showall[$showall_nid]['html'] );
				}
			}

			$html_msg .= wfMsg( 'smw_nm_hint_notification_html', $this->m_userHtmlNMMsgs[$user_id] );
			if ( isset( $this->m_userHtmlPropMsgs[$user_id] ) ) {
				$html_msg .= wfMsg( 'smw_nm_hint_nmtable_html', $this->m_userHtmlPropMsgs[$user_id] );
			}

			global $wgNMReportModifier, $wgUser;
			if ( $wgNMReportModifier ) {
				$userText = $wgUser->getName();
				if ( $wgUser->getId() == 0 ) {
					$page = SpecialPage::getTitleFor( 'Contributions', $userText );
				} else {
					$page = Title::makeTitle( NS_USER, $userText );
				}
				$l = '<a href="' . $page->getFullUrl() . '">' . htmlspecialchars( $userText ) . '</a>';
				$html_msg .= wfMsg( 'smw_nm_hint_modifier_html', $l );
				$msg .= wfMsg( 'smw_nm_hint_modifier', $wgUser->getName() );
			}

			$id = $sStore->addNotifyRSS( 'uid', $user_id, $this->m_title->getText(), $this->applyStyle( $html_msg ) );

			if ( $wgEnotifyMeJob ) {
				// send notifications by mail
				$user_info = $sStore->getUserInfo( $user_id );
				$user = User::newFromRow( $user_info );
				if ( ( $user_info->user_email != '' ) && $user->getOption( 'enotifyme' ) ) {
					$name = ( ( $user_info->user_real_name == '' ) ? $user_info->user_name:$user_info->user_real_name );

					$params = array( 'to' => new MailAddress( $user_info->user_email, $name ),
						'from' => new MailAddress( $wgEmergencyContact, 'Admin' ),
						'subj' => wfMsg( 'smw_nm_hint_mail_title', $this->m_title->getText(), $wgSitename ),
						'body' => wfMsg( 'smw_nm_hint_mail_body', $name, $msg ),
						'replyto' => new MailAddress( $wgEmergencyContact, 'Admin' ) );

					$nm_send_jobs[] = new SMW_NMSendMailJob( $this->m_title, $params );
				}
			}
		}

		if ( $wgEnotifyMeJob ) {
			if ( count( $nm_send_jobs ) ) {
				Job :: batchInsert( $nm_send_jobs );
			}
		} else {
			global $phpInterpreter;
			if ( !isset( $phpInterpreter ) ) {
				// if $phpInterpreter is not set, assume it is in search path
				// if not, starting of bot will FAIL!
				$phpInterpreter = "php";
			}
			// copy from SMW_GardeningBot.php
			ob_start();
			phpinfo();
			$info = ob_get_contents();
			ob_end_clean();
			// Get Systemstring
			preg_match( '!\nSystem(.*?)\n!is', strip_tags( $info ), $ma );
			// Check if it consists 'windows' as string
			preg_match( '/[Ww]indows/', $ma[1], $os );
			global $smwgNMIP ;
			if ( $os[0] == '' && $os[0] == null ) {

				// FIXME: $runCommand must allow whitespaces in paths too
				$runCommand = "$phpInterpreter -q $smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php";
				// TODO: test async code for linux.
				// low prio
				$nullResult = `$runCommand > /dev/null &`;
			}
			else // windowze
			{
				$runCommand = "\"\"$phpInterpreter\" -q \"$smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php\"\"";
				$wshShell = new COM( "WScript.Shell" );
				$runCommand = "cmd /C " . $runCommand;

				$oExec = $wshShell->Run( $runCommand, 7, false );
			}
		}
	}
 /**
  * Script entry point
  */
 public function execute()
 {
     global $wgUser;
     $wgUser = User::newFromName('WikiaBot');
     $this->output(sprintf("User %s will be used, with the following rights: %s\n", $wgUser->getName(), join(', ', $wgUser->getRights())));
     // do not use ulimit4 when calling wfShellExec()
     global $wgMaxShellTime;
     $wgMaxShellTime = 0;
     // read options
     $this->isDryRun = $this->hasOption('dry-run') || !$this->hasOption('force');
     $this->onlyRenameGlobalUsers = $this->hasOption('only-rename-global-users');
     if ($this->isDryRun) {
         $this->dryRunMode();
     } else {
         // disable read-only mode for this script to work
         // even if disabled via WikiFactory
         global $wgReadOnly, $wgDBReadOnly;
         $wgReadOnly = null;
         $wgDBReadOnly = false;
     }
     // allow cluster to be forced via --cluster option
     if ($forceCluster = $this->getOption('cluster')) {
         global $wgDBcluster;
         $wgDBcluster = $forceCluster;
     }
     // setup the CSV header
     if ($this->hasOption('csv')) {
         $this->csv = fopen($this->getOption('csv'), 'w');
         fputcsv($this->csv, ['User ID', 'User Name', 'New user name', 'Email', 'Valid email', 'Shared email', 'Merge?', 'Uncyclo edits', 'Uncyclo edits after Jan 2014', 'Global edits', 'Action']);
         $this->output(sprintf("Will generate CSV file - <%s>...\n", $this->getOption('csv')));
     }
     global $wgDBname, $wgDBcluster;
     $this->output("Working on {$wgDBname} database (cluster {$wgDBcluster}, master {$this->getUncycloDB(DB_MASTER)->getServer()}, slave {$this->getUncycloDB(DB_SLAVE)->getServer()})\n");
     // get all uncyclopedia accounts
     $conds = [];
     $from_id = intval($this->getOption('from'));
     $to_id = intval($this->getOption('to'));
     if ($from_id) {
         $conds[] = 'user_id >= ' . $from_id;
     }
     if ($to_id) {
         $conds[] = 'user_id <= ' . $to_id;
     }
     $this->output("Preparing the list of accounts to migrate... conds = " . json_encode($conds));
     $res = $this->getUncycloDB()->select(self::USER_TABLE, '*', $conds, __METHOD__);
     $this->output(sprintf("\nMigrating %d accounts...\n", $res->numRows()));
     $this->output("Will start in 5 seconds...\n");
     sleep(5);
     // close the current transaction (if any)
     $dbw = $this->getUncycloDB(DB_MASTER);
     $dbw->commit(__METHOD__);
     $i = 0;
     while ($row = $res->fetchObject()) {
         $i++;
         $user = User::newFromRow((object) $row);
         // block the user for five minutes
         $block = new MemcacheUserBlock($user);
         $block->setBlock('Uncyclopedia account migration', 300);
         try {
             $dbw->begin(__METHOD__);
             $this->migrateUser($user);
             $dbw->commit(__METHOD__);
         } catch (Exception $e) {
             $dbw->rollback(__METHOD__);
             $this->output(sprintf("\n%s: %s\n", get_class($e), $e->getMessage()));
             $this->output($e->getTraceAsString());
             $this->err(__METHOD__, ['exception' => $e, 'user_id' => $user->getId(), 'user_name' => $user->getName()]);
         }
         if (!$this->isDryRun) {
             if ($i % 2 === 0) {
                 $this->info(__METHOD__ . '::lag', ['lag' => $this->getUncycloDB(DB_SLAVE)->getLag(), 'server' => $this->getUncycloDB(DB_SLAVE)->getServer()]);
                 wfWaitForSlaves();
             }
         }
         // we're done migrating the account, remove the block
         $block->removeBlock();
     }
     // print the stats
     $this->output("\n\nDone!\n\n");
     $this->output(sprintf("Accounts processed:            %d\n", $res->numRows()));
     $this->output(sprintf("Created Wikia accounts:        %d\n", $this->createdAccounts));
     $this->output(sprintf("Merged accounts:               %d\n", $this->mergedAccounts));
     $this->output(sprintf("Renamed Uncyclo accounts:      %d\n", $this->renamedUnclycloAccounts));
     $this->output(sprintf("Renamed Wikia accounts:        %d\n", $this->renamedWikiaAccounts));
     $this->output(sprintf("Accounts with no email:        %d\n", $this->accountsWithNoEmail));
     $this->output(sprintf("  (but active after Jan 2014): %d\n", $this->accountsWithNoEmailWithEdits));
     if (is_resource($this->csv)) {
         fclose($this->csv);
     }
 }
Example #23
0
 public function execute()
 {
     $params = $this->extractRequestParams();
     if (!is_null($params['prop'])) {
         $this->prop = array_flip($params['prop']);
     } else {
         $this->prop = [];
     }
     $users = (array) $params['users'];
     $goodNames = $done = [];
     $result = $this->getResult();
     // Canonicalize user names
     foreach ($users as $u) {
         $n = User::getCanonicalName($u);
         if ($n === false || $n === '') {
             $vals = ['name' => $u, 'invalid' => true];
             $fit = $result->addValue(['query', $this->getModuleName()], null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
                 $goodNames = [];
                 break;
             }
             $done[] = $u;
         } else {
             $goodNames[] = $n;
         }
     }
     $result = $this->getResult();
     if (count($goodNames)) {
         $this->addTables('user');
         $this->addFields(User::selectFields());
         $this->addWhereFld('user_name', $goodNames);
         $this->showHiddenUsersAddBlockInfo(isset($this->prop['blockinfo']));
         $data = [];
         $res = $this->select(__METHOD__);
         $this->resetQueryParams();
         // get user groups if needed
         if (isset($this->prop['groups']) || isset($this->prop['rights'])) {
             $userGroups = [];
             $this->addTables('user');
             $this->addWhereFld('user_name', $goodNames);
             $this->addTables('user_groups');
             $this->addJoinConds(['user_groups' => ['INNER JOIN', 'ug_user=user_id']]);
             $this->addFields(['user_name', 'ug_group']);
             $userGroupsRes = $this->select(__METHOD__);
             foreach ($userGroupsRes as $row) {
                 $userGroups[$row->user_name][] = $row->ug_group;
             }
         }
         foreach ($res as $row) {
             // create user object and pass along $userGroups if set
             // that reduces the number of database queries needed in User dramatically
             if (!isset($userGroups)) {
                 $user = User::newFromRow($row);
             } else {
                 if (!isset($userGroups[$row->user_name]) || !is_array($userGroups[$row->user_name])) {
                     $userGroups[$row->user_name] = [];
                 }
                 $user = User::newFromRow($row, ['user_groups' => $userGroups[$row->user_name]]);
             }
             $name = $user->getName();
             $data[$name]['userid'] = $user->getId();
             $data[$name]['name'] = $name;
             if (isset($this->prop['editcount'])) {
                 $data[$name]['editcount'] = $user->getEditCount();
             }
             if (isset($this->prop['registration'])) {
                 $data[$name]['registration'] = wfTimestampOrNull(TS_ISO_8601, $user->getRegistration());
             }
             if (isset($this->prop['groups'])) {
                 $data[$name]['groups'] = $user->getEffectiveGroups();
             }
             if (isset($this->prop['implicitgroups'])) {
                 $data[$name]['implicitgroups'] = $user->getAutomaticGroups();
             }
             if (isset($this->prop['rights'])) {
                 $data[$name]['rights'] = $user->getRights();
             }
             if ($row->ipb_deleted) {
                 $data[$name]['hidden'] = true;
             }
             if (isset($this->prop['blockinfo']) && !is_null($row->ipb_by_text)) {
                 $data[$name]['blockid'] = (int) $row->ipb_id;
                 $data[$name]['blockedby'] = $row->ipb_by_text;
                 $data[$name]['blockedbyid'] = (int) $row->ipb_by;
                 $data[$name]['blockedtimestamp'] = wfTimestamp(TS_ISO_8601, $row->ipb_timestamp);
                 $data[$name]['blockreason'] = $row->ipb_reason;
                 $data[$name]['blockexpiry'] = $row->ipb_expiry;
             }
             if (isset($this->prop['emailable'])) {
                 $data[$name]['emailable'] = $user->canReceiveEmail();
             }
             if (isset($this->prop['gender'])) {
                 $gender = $user->getOption('gender');
                 if (strval($gender) === '') {
                     $gender = 'unknown';
                 }
                 $data[$name]['gender'] = $gender;
             }
             if (isset($this->prop['centralids'])) {
                 $data[$name] += ApiQueryUserInfo::getCentralUserInfo($this->getConfig(), $user, $params['attachedwiki']);
             }
             if (!is_null($params['token'])) {
                 $tokenFunctions = $this->getTokenFunctions();
                 foreach ($params['token'] as $t) {
                     $val = call_user_func($tokenFunctions[$t], $user);
                     if ($val === false) {
                         $this->setWarning("Action '{$t}' is not allowed for the current user");
                     } else {
                         $data[$name][$t . 'token'] = $val;
                     }
                 }
             }
         }
     }
     $context = $this->getContext();
     // Second pass: add result data to $retval
     foreach ($goodNames as $u) {
         if (!isset($data[$u])) {
             $data[$u] = ['name' => $u];
             $urPage = new UserrightsPage();
             $urPage->setContext($context);
             $iwUser = $urPage->fetchUser($u);
             if ($iwUser instanceof UserRightsProxy) {
                 $data[$u]['interwiki'] = true;
                 if (!is_null($params['token'])) {
                     $tokenFunctions = $this->getTokenFunctions();
                     foreach ($params['token'] as $t) {
                         $val = call_user_func($tokenFunctions[$t], $iwUser);
                         if ($val === false) {
                             $this->setWarning("Action '{$t}' is not allowed for the current user");
                         } else {
                             $data[$u][$t . 'token'] = $val;
                         }
                     }
                 }
             } else {
                 $data[$u]['missing'] = true;
                 if (isset($this->prop['cancreate'])) {
                     $status = MediaWiki\Auth\AuthManager::singleton()->canCreateAccount($u);
                     $data[$u]['cancreate'] = $status->isGood();
                     if (!$status->isGood()) {
                         $data[$u]['cancreateerror'] = $this->getErrorFormatter()->arrayFromStatus($status);
                     }
                 }
             }
         } else {
             if (isset($this->prop['groups']) && isset($data[$u]['groups'])) {
                 ApiResult::setArrayType($data[$u]['groups'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['groups'], 'g');
             }
             if (isset($this->prop['implicitgroups']) && isset($data[$u]['implicitgroups'])) {
                 ApiResult::setArrayType($data[$u]['implicitgroups'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['implicitgroups'], 'g');
             }
             if (isset($this->prop['rights']) && isset($data[$u]['rights'])) {
                 ApiResult::setArrayType($data[$u]['rights'], 'array');
                 ApiResult::setIndexedTagName($data[$u]['rights'], 'r');
             }
         }
         $fit = $result->addValue(['query', $this->getModuleName()], null, $data[$u]);
         if (!$fit) {
             $this->setContinueEnumParameter('users', implode('|', array_diff($users, $done)));
             break;
         }
         $done[] = $u;
     }
     $result->addIndexedTagName(['query', $this->getModuleName()], 'user');
 }
 static function notifyUsersByMail($t, $watching_users, $timestamp, $type)
 {
     $messages = array(Threads::CHANGE_REPLY_CREATED => 'lqt-enotif-reply', Threads::CHANGE_NEW_THREAD => 'lqt-enotif-newthread');
     $subjects = array(Threads::CHANGE_REPLY_CREATED => 'lqt-enotif-subject-reply', Threads::CHANGE_NEW_THREAD => 'lqt-enotif-subject-newthread');
     if (!isset($messages[$type]) || !isset($subjects[$type])) {
         wfDebugLog('LiquidThreads', "Email notification failed: type {$type} unrecognised");
         return;
     } else {
         $msgName = $messages[$type];
         $subjectMsg = $subjects[$type];
     }
     // Send email notification, fetching all the data in one go
     $dbr = wfGetDB(DB_SLAVE);
     $tables = array('user', 'tc_prop' => 'user_properties', 'l_prop' => 'user_properties');
     $fields = array($dbr->tableName('user') . '.*', 'tc_prop.up_value AS timecorrection', 'l_prop.up_value as language');
     $join_conds = array('tc_prop' => array('LEFT JOIN', array('tc_prop.up_user=user_id', 'tc_prop.up_property' => 'timecorrection')), 'l_prop' => array('LEFT JOIN', array('l_prop.up_user=user_id', 'l_prop.up_property' => 'language')));
     $res = $dbr->select($tables, $fields, array('user_id' => $watching_users), __METHOD__, array(), $join_conds);
     // Set up one-time data.
     global $wgPasswordSender;
     $link_title = clone $t->getTitle();
     $link_title->setFragment('#' . $t->getAnchorName());
     $permalink = LqtView::linkInContextCanonicalURL($t);
     $talkPage = $t->getTitle()->getPrefixedText();
     $from = new MailAddress($wgPasswordSender, 'WikiAdmin');
     $threadSubject = $t->subject();
     // Parse content and strip HTML of post content
     foreach ($res as $row) {
         $u = User::newFromRow($row);
         if ($row->language) {
             $langCode = $row->language;
         } else {
             global $wgLanguageCode;
             $langCode = $wgLanguageCode;
         }
         $lang = Language::factory($langCode);
         // Adjust with time correction
         $timeCorrection = $row->timecorrection;
         $adjustedTimestamp = $lang->userAdjust($timestamp, $timeCorrection);
         $date = $lang->date($adjustedTimestamp);
         $time = $lang->time($adjustedTimestamp);
         $params = array($u->getName(), $t->subjectWithoutIncrement(), $date, $time, $talkPage, $permalink, $t->root()->getContent(), $t->author()->getName());
         // Get message in user's own language, bug 20645
         $msg = wfMsgReal($msgName, $params, true, $langCode, true);
         $to = new MailAddress($u);
         $subject = wfMsgReal($subjectMsg, array($threadSubject), true, $langCode, true);
         UserMailer::send($to, $from, $subject, $msg);
     }
 }