/** * Function generates Contribution Scores tables in HTML format (not wikiText) * * @param $days int Days in the past to run report for * @param $limit int Maximum number of users to return (default 50) * @param $title Title (default null) * @param $options array of options (default none; nosort/notools) * @return Html Table representing the requested Contribution Scores. */ function genContributionScoreTable($days, $limit, $title = null, $options = 'none') { global $wgContribScoreIgnoreBots, $wgContribScoreIgnoreBlockedUsers, $wgContribScoresUseRealName; $opts = explode(',', strtolower($options)); $dbr = wfGetDB(DB_SLAVE); $userTable = $dbr->tableName('user'); $userGroupTable = $dbr->tableName('user_groups'); $revTable = $dbr->tableName('revision'); $ipBlocksTable = $dbr->tableName('ipblocks'); $sqlWhere = ""; $nextPrefix = "WHERE"; if ($days > 0) { $date = time() - 60 * 60 * 24 * $days; $dateString = $dbr->timestamp($date); $sqlWhere .= " {$nextPrefix} rev_timestamp > '{$dateString}'"; $nextPrefix = "AND"; } if ($wgContribScoreIgnoreBlockedUsers) { $sqlWhere .= " {$nextPrefix} rev_user NOT IN (SELECT ipb_user FROM {$ipBlocksTable} WHERE ipb_user <> 0)"; $nextPrefix = "AND"; } if ($wgContribScoreIgnoreBots) { $sqlWhere .= " {$nextPrefix} rev_user NOT IN (SELECT ug_user FROM {$userGroupTable} WHERE ug_group='bot')"; } $sqlMostPages = "SELECT rev_user,\n\t\t\t\t\t\t COUNT(DISTINCT rev_page) AS page_count,\n\t\t\t\t\t\t COUNT(rev_id) AS rev_count\n\t\t\t\t\t\t FROM {$revTable}\n\t\t\t\t\t\t {$sqlWhere}\n\t\t\t\t\t\t GROUP BY rev_user\n\t\t\t\t\t\t ORDER BY page_count DESC\n\t\t\t\t\t\t LIMIT {$limit}"; $sqlMostRevs = "SELECT rev_user,\n\t\t\t\t\t\t COUNT(DISTINCT rev_page) AS page_count,\n\t\t\t\t\t\t COUNT(rev_id) AS rev_count\n\t\t\t\t\t\t FROM {$revTable}\n\t\t\t\t\t\t {$sqlWhere}\n\t\t\t\t\t\t GROUP BY rev_user\n\t\t\t\t\t\t ORDER BY rev_count DESC\n\t\t\t\t\t\t LIMIT {$limit}"; $sql = "SELECT user_id, " . "user_name, " . "user_real_name, " . "page_count, " . "rev_count, " . "page_count+SQRT(rev_count-page_count)*2 AS wiki_rank " . "FROM {$userTable} u JOIN (({$sqlMostPages}) UNION ({$sqlMostRevs})) s ON (user_id=rev_user) " . "ORDER BY wiki_rank DESC " . "LIMIT {$limit}"; $res = $dbr->query($sql); $sortable = in_array('nosort', $opts) ? '' : ' sortable'; $output = "<table class=\"wikitable contributionscores plainlinks{$sortable}\" >\n" . "<tr class='header'>\n" . Html::element('th', array(), $this->msg('contributionscores-score')->text()) . Html::element('th', array(), $this->msg('contributionscores-pages')->text()) . Html::element('th', array(), $this->msg('contributionscores-changes')->text()) . Html::element('th', array(), $this->msg('contributionscores-username')->text()); $altrow = ''; $lang = $this->getLanguage(); foreach ($res as $row) { // Use real name if option used and real name present. if ($wgContribScoresUseRealName && $row->user_real_name !== '') { $userLink = Linker::userLink($row->user_id, $row->user_name, $row->user_real_name); } else { $userLink = Linker::userLink($row->user_id, $row->user_name); } $output .= Html::closeElement('tr'); $output .= "<tr class='{$altrow}'>\n<td class='content'>" . $lang->formatNum(round($row->wiki_rank, 0)) . "\n</td><td class='content'>" . $lang->formatNum($row->page_count) . "\n</td><td class='content'>" . $lang->formatNum($row->rev_count) . "\n</td><td class='content'>" . $userLink; # Option to not display user tools if (!in_array('notools', $opts)) { $output .= Linker::userToolLinks($row->user_id, $row->user_name); } $output .= Html::closeElement('td') . "\n"; if ($altrow == '' && empty($sortable)) { $altrow = 'odd '; } else { $altrow = ''; } } $output .= Html::closeElement('tr'); $output .= Html::closeElement('table'); $dbr->freeResult($res); if (!empty($title)) { $output = Html::rawElement('table', array('style' => 'border-spacing: 0; padding: 0', 'class' => 'contributionscores-wrapper', 'lang' => htmlspecialchars($lang->getCode()), 'dir' => $lang->getDir()), "\n" . "<tr>\n" . "<td style='padding: 0px;'>{$title}</td>\n" . "</tr>\n" . "<tr>\n" . "<td style='padding: 0px;'>{$output}</td>\n" . "</tr>\n"); } return $output; }
/** * (non-PHPdoc) * @see EPPager::getFormattedValue() */ protected function getFormattedValue($name, $value) { switch ($name) { case 'id': $value = Linker::linkKnown(SpecialPage::getTitleFor('Student', $value), htmlspecialchars($this->getLanguage()->formatNum($value, true))); break; case 'user_id': $user = User::newFromId($value); $name = $user->getRealName() === '' ? $user->getName() : $user->getRealName(); $value = Linker::userLink($value, $name) . Linker::userToolLinks($value, $name); break; case 'first_enroll': case 'last_active': $value = htmlspecialchars($this->getLanguage()->date($value)); break; case 'active_enroll': $value = wfMsgHtml($value === '1' ? 'epstudentpager-yes' : 'epstudentpager-no'); break; case '_courses_current': $value = $this->getLanguage()->pipeList(array_map(function (EPCourse $course) { return $course->getLink(); }, $this->currentObject->getCoursesWithState('current', 'name'))); break; } return $value; }
function formatResult($skin, $result) { global $wgLang, $wgContLang; $user = User::newFromID($result->rev_user); $ulinks = Linker::userLink($result->rev_user, $user->getName()); $ulinks .= Linker::userToolLinks($result->rev_user, $user->getName()); $date = date('h:i, d F Y', wfTimestamp(TS_UNIX, $result->rev_timestamp)); return $ulinks . " " . $result->numedits . " edits | {$date}"; }
function formatRow($row) { $comment = Linker::commentBlock($row->cw_comment); $user = Linker::userLink($row->cw_user, $row->user_name) . Linker::userToolLinks($row->cw_user, $row->user_name); $sitename = $row->cw_sitename; $status = $row->cw_status; $idlink = Linker::link(Title::newFromText('Special:RequestWikiQueue/' . $row->cw_id), "#{$row->cw_id}"); return '<li>' . $this->getLanguage()->timeanddate(wfTimestamp(TS_MW, $row->cw_timestamp), true) . ' ' . $this->msg('requestwikiqueue-logpagerentry', $user, htmlspecialchars($sitename), $idlink, $this->msg('requestwikiqueue-pager-status-' . $status))->text() . $comment . '</li>'; }
public function onView() { $details = null; $request = $this->getRequest(); $result = $this->page->doRollback($request->getVal('from'), $request->getText('summary'), $request->getVal('token'), $request->getBool('bot'), $details, $this->getUser()); if (in_array(array('actionthrottledtext'), $result)) { throw new ThrottledError(); } if (isset($result[0][0]) && ($result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback')) { $this->getOutput()->setPageTitle($this->msg('rollbackfailed')); $errArray = $result[0]; $errMsg = array_shift($errArray); $this->getOutput()->addWikiMsgArray($errMsg, $errArray); if (isset($details['current'])) { $current = $details['current']; if ($current->getComment() != '') { $this->getOutput()->addHTML($this->msg('editcomment')->rawParams(Linker::formatComment($current->getComment()))->parse()); } } return; } # Display permissions errors before read-only message -- there's no # point in misleading the user into thinking the inability to rollback # is only temporary. if (!empty($result) && $result !== array(array('readonlytext'))) { # array_diff is completely broken for arrays of arrays, sigh. # Remove any 'readonlytext' error manually. $out = array(); foreach ($result as $error) { if ($error != array('readonlytext')) { $out[] = $error; } } throw new PermissionsError('rollback', $out); } if ($result == array(array('readonlytext'))) { throw new ReadOnlyError(); } $current = $details['current']; $target = $details['target']; $newId = $details['newid']; $this->getOutput()->setPageTitle($this->msg('actioncomplete')); $this->getOutput()->setRobotPolicy('noindex,nofollow'); if ($current->getUserText() === '') { $old = $this->msg('rev-deleted-user')->escaped(); } else { $old = Linker::userLink($current->getUser(), $current->getUserText()) . Linker::userToolLinks($current->getUser(), $current->getUserText()); } $new = Linker::userLink($target->getUser(), $target->getUserText()) . Linker::userToolLinks($target->getUser(), $target->getUserText()); $this->getOutput()->addHTML($this->msg('rollback-success')->rawParams($old, $new)->parseAsBlock()); $this->getOutput()->returnToMain(false, $this->getTitle()); if (!$request->getBool('hidediff', false) && !$this->getUser()->getBoolOption('norollbackdiff', false)) { $de = new DifferenceEngine($this->getContext(), $current->getId(), $newId, false, true); $de->showDiff('', ''); } }
function getUserToolLinks($u) { global $wgUser; if (!$u) { return ""; } $ret = Linker::userToolLinks($u->getID(), $u->getName()); $ret = str_replace('href="/', 'href="http://www.wikihow.com/', $ret); return $ret; }
/** * Gets the summary data. * * @since 0.1 * * @param EPStudent $student * * @return array */ protected function getSummaryData(EPDBObject $student) { $stats = array(); $id = $student->getUser()->getId(); $stats['user'] = Linker::userLink($id, $student->getName()) . Linker::userToolLinks($id, $student->getName()); $stats['first-enroll'] = htmlspecialchars($this->getLanguage()->timeanddate($student->getField('first_enroll'), true)); $stats['last-active'] = htmlspecialchars($this->getLanguage()->timeanddate($student->getField('last_active'), true)); $stats['active-enroll'] = wfMsgHtml($student->getField('active_enroll') ? 'ep-student-actively-enrolled' : 'ep-student-no-active-enroll'); return $stats; }
/** * (non-PHPdoc) * @see EPPager::getFormattedValue() */ protected function getFormattedValue($name, $value) { switch ($name) { case 'user_id': $user = User::newFromId($value); $name = $user->getRealName() === '' ? $user->getName() : $user->getRealName(); $value = Linker::userLink($value, $name) . Linker::userToolLinks($value, $name); break; } return $value; }
public function formatRow($row) { $rdatim = $this->getLang()->timeanddate(wfTimestamp(TS_MW, $row->rev_timestamp), true); $fdatim = $this->getLang()->timeanddate(wfTimestamp(TS_MW, $row->fr_timestamp), true); $fdate = $this->getLang()->date(wfTimestamp(TS_MW, $row->fr_timestamp), true); $ftime = $this->getLang()->time(wfTimestamp(TS_MW, $row->fr_timestamp), true); $review = wfMsgExt('reviewedversions-review', array('parseinline', 'replaceafter'), $fdatim, Linker::userLink($row->fr_user, $row->user_name) . ' ' . Linker::userToolLinks($row->fr_user, $row->user_name), $fdate, $ftime, $row->user_name); $lev = $row->fr_quality >= 1 ? wfMsgHtml('revreview-hist-quality') : wfMsgHtml('revreview-hist-basic'); $link = Linker::makeKnownLinkObj($this->page, $rdatim, 'stableid=' . $row->fr_rev_id); return '<li>' . $link . ' (' . $review . ') <strong>[' . $lev . ']</strong></li>'; }
public function formatRow($row) { $rdatim = $this->getLanguage()->timeanddate(wfTimestamp(TS_MW, $row->rev_timestamp), true); $fdatim = $this->getLanguage()->timeanddate(wfTimestamp(TS_MW, $row->fr_timestamp), true); $fdate = $this->getLanguage()->date(wfTimestamp(TS_MW, $row->fr_timestamp), true); $ftime = $this->getLanguage()->time(wfTimestamp(TS_MW, $row->fr_timestamp), true); $review = $this->msg('reviewedversions-review')->rawParams($fdatim, Linker::userLink($row->fr_user, $row->user_name) . ' ' . Linker::userToolLinks($row->fr_user, $row->user_name), $fdate, $ftime, $row->user_name)->text(); $lev = $row->fr_quality >= 1 ? $this->msg('revreview-hist-quality')->escaped() : $this->msg('revreview-hist-basic')->escaped(); $link = Linker::link($this->page, $rdatim, array(), array('stableid' => $row->fr_rev_id)); return '<li>' . $link . ' (' . $review . ') <strong>[' . $lev . ']</strong></li>'; }
/** * Display a revision notice as subtitle. * * @since 0.1 * * @param EPRevision $rev */ protected function displayRevisionNotice(EPRevision $rev) { $lang = $this->getLanguage(); $current = false; // TODO $td = $lang->timeanddate($rev->getField('time'), true); $tddate = $lang->date($rev->getField('time'), true); $tdtime = $lang->time($rev->getField('time'), true); $userToolLinks = Linker::userLink($rev->getUser()->getId(), $rev->getUser()->getName()) . Linker::userToolLinks($rev->getUser()->getId(), $rev->getUser()->getName()); $infomsg = $current && !wfMessage('revision-info-current')->isDisabled() ? 'revision-info-current' : 'revision-info'; $this->getOutput()->setSubtitle("<div id=\"mw-{$infomsg}\">" . wfMessage($infomsg, $td)->rawParams($userToolLinks)->params($rev->getId(), $tddate, $tdtime, $rev->getUser())->parse() . "</div>"); }
function formatRow($row) { if ($row->cul_reason === '') { $comment = ''; } else { $comment = Linker::commentBlock($row->cul_reason); } $user = Linker::userLink($row->cul_user, $row->user_name); if ($row->cul_type == 'userips' || $row->cul_type == 'useredits') { $target = Linker::userLink($row->cul_target_id, $row->cul_target_text) . Linker::userToolLinks($row->cul_target_id, $row->cul_target_text); } else { $target = $row->cul_target_text; } // Give grep a chance to find the usages: // checkuser-log-userips, checkuser-log-ipedits, checkuser-log-ipusers, // checkuser-log-ipedits-xff, checkuser-log-ipusers-xff, checkuser-log-useredits return '<li>' . $this->getLanguage()->timeanddate(wfTimestamp(TS_MW, $row->cul_timestamp), true) . $this->msg('comma-separator')->text() . $this->msg('checkuser-log-' . $row->cul_type, $user, $target)->text() . $comment . '</li>'; }
function formatValue($name, $value) { global $wgLang, $wgTitle; $row = $this->mCurrentRow; switch ($name) { case 'th_timestamp': $formatted = $wgLang->timeanddate($value, true); return Linker::link($wgTitle, $formatted, array(), array('lqt_oldid' => $row->th_id)); case 'th_user_text': return Linker::userLink($row->th_user, $row->th_user_text) . ' ' . Linker::userToolLinks($row->th_user, $row->th_user_text); case 'th_change_type': return $this->getActionDescription($value); case 'th_change_comment': return Linker::commentBlock($value); default: return "Unable to format {$name}"; break; } }
/** * (non-PHPdoc) * @see EPPager::getFormattedValue() */ protected function getFormattedValue($name, $value) { switch ($name) { case 'photo': $title = Title::newFromText($value, NS_FILE); $value = ''; if (is_object($title)) { $api = new ApiMain(new FauxRequest(array('action' => 'query', 'format' => 'json', 'prop' => 'imageinfo', 'iiprop' => 'url', 'titles' => $title->getFullText(), 'iiurlwidth' => 200), true), true); $api->execute(); $result = $api->getResultData(); if (array_key_exists('query', $result) && array_key_exists('pages', $result['query'])) { foreach ($result['query']['pages'] as $page) { foreach ($page['imageinfo'] as $imageInfo) { $value = Html::element('img', array('src' => $imageInfo['thumburl'], 'width' => '200px')); break; } } } } break; case 'user_id': $oa = $this->currentObject; $value = Linker::userLink($value, $oa->getName()) . Linker::userToolLinks($value, $oa->getName()); break; case 'bio': $value = $this->getOutput()->parseInline($value); break; case '_courses': $oa = $this->currentObject; $value = $this->getLanguage()->listToText(array_map(function (EPCourse $course) { return $course->getLink(); }, $oa->getCoursesWithState('current', 'name'))); break; } return $value; }
/** * @param RecentChange $baseRC * @param bool $watched * * @return RCCacheEntry */ public function newFromRecentChange(RecentChange $baseRC, $watched) { $user = $this->context->getUser(); $counter = $baseRC->counter; $cacheEntry = RCCacheEntry::newFromParent($baseRC); // Should patrol-related stuff be shown? $cacheEntry->unpatrolled = ChangesList::isUnpatrolled($baseRC, $user); $cacheEntry->watched = $cacheEntry->mAttribs['rc_type'] == RC_LOG ? false : $watched; $cacheEntry->numberofWatchingusers = $baseRC->numberofWatchingusers; $cacheEntry->link = $this->buildCLink($cacheEntry); $cacheEntry->timestamp = $this->buildTimestamp($cacheEntry); // Make "cur" and "diff" links. Do not use link(), it is too slow if // called too many times (50% of CPU time on RecentChanges!). $showDiffLinks = $this->showDiffLinks($cacheEntry, $user); $cacheEntry->difflink = $this->buildDiffLink($cacheEntry, $showDiffLinks, $counter); $cacheEntry->curlink = $this->buildCurLink($cacheEntry, $showDiffLinks, $counter); $cacheEntry->lastlink = $this->buildLastLink($cacheEntry, $showDiffLinks); // Make user links $cacheEntry->userlink = $this->getUserLink($cacheEntry); if (!ChangesList::isDeleted($cacheEntry, Revision::DELETED_USER)) { $cacheEntry->usertalklink = Linker::userToolLinks($cacheEntry->mAttribs['rc_user'], $cacheEntry->mAttribs['rc_user_text']); } return $cacheEntry; }
/** * @param $iscur * @param $file File * @return string */ public function imageHistoryLine($iscur, $file) { global $wgContLang; $user = $this->getUser(); $lang = $this->getLanguage(); $timestamp = wfTimestamp(TS_MW, $file->getTimestamp()); $img = $iscur ? $file->getName() : $file->getArchiveName(); $userId = $file->getUser('id'); $userText = $file->getUser('text'); $description = $file->getDescription(File::FOR_THIS_USER, $user); $local = $this->current->isLocal(); $row = $selected = ''; // Deletion link if ($local && $user->isAllowedAny('delete', 'deletedhistory')) { $row .= '<td>'; # Link to remove from history if ($user->isAllowed('delete')) { $q = array('action' => 'delete'); if (!$iscur) { $q['oldimage'] = $img; } $row .= Linker::linkKnown($this->title, $this->msg($iscur ? 'filehist-deleteall' : 'filehist-deleteone')->escaped(), array(), $q); } # Link to hide content. Don't show useless link to people who cannot hide revisions. $canHide = $user->isAllowed('deleterevision'); if ($canHide || $user->isAllowed('deletedhistory') && $file->getVisibility()) { if ($user->isAllowed('delete')) { $row .= '<br />'; } // If file is top revision or locked from this user, don't link if ($iscur || !$file->userCan(File::DELETED_RESTRICTED, $user)) { $del = Linker::revDeleteLinkDisabled($canHide); } else { list($ts, ) = explode('!', $img, 2); $query = array('type' => 'oldimage', 'target' => $this->title->getPrefixedText(), 'ids' => $ts); $del = Linker::revDeleteLink($query, $file->isDeleted(File::DELETED_RESTRICTED), $canHide); } $row .= $del; } $row .= '</td>'; } // Reversion link/current indicator $row .= '<td>'; if ($iscur) { $row .= $this->msg('filehist-current')->escaped(); } elseif ($local && $this->title->quickUserCan('edit', $user) && $this->title->quickUserCan('upload', $user)) { if ($file->isDeleted(File::DELETED_FILE)) { $row .= $this->msg('filehist-revert')->escaped(); } else { $row .= Linker::linkKnown($this->title, $this->msg('filehist-revert')->escaped(), array(), array('action' => 'revert', 'oldimage' => $img, 'wpEditToken' => $user->getEditToken($img))); } } $row .= '</td>'; // Date/time and image link if ($file->getTimestamp() === $this->img->getTimestamp()) { $selected = "class='filehistory-selected'"; } $row .= "<td {$selected} style='white-space: nowrap;'>"; if (!$file->userCan(File::DELETED_FILE, $user)) { # Don't link to unviewable files $row .= '<span class="history-deleted">' . $lang->userTimeAndDate($timestamp, $user) . '</span>'; } elseif ($file->isDeleted(File::DELETED_FILE)) { if ($local) { $this->preventClickjacking(); $revdel = SpecialPage::getTitleFor('Revisiondelete'); # Make a link to review the image $url = Linker::linkKnown($revdel, $lang->userTimeAndDate($timestamp, $user), array(), array('target' => $this->title->getPrefixedText(), 'file' => $img, 'token' => $user->getEditToken($img))); } else { $url = $lang->userTimeAndDate($timestamp, $user); } $row .= '<span class="history-deleted">' . $url . '</span>'; } else { $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl($img); $row .= Xml::element('a', array('href' => $url), $lang->userTimeAndDate($timestamp, $user)); } $row .= "</td>"; // Thumbnail if ($this->showThumb) { $row .= '<td>' . $this->getThumbForLine($file) . '</td>'; } // Image dimensions + size $row .= '<td>'; $row .= htmlspecialchars($file->getDimensionsString()); $row .= $this->msg('word-separator')->plain(); $row .= '<span style="white-space: nowrap;">'; $row .= $this->msg('parentheses')->rawParams(Linker::formatSize($file->getSize()))->plain(); $row .= '</span>'; $row .= '</td>'; // Uploading user $row .= '<td>'; // Hide deleted usernames if ($file->isDeleted(File::DELETED_USER)) { $row .= '<span class="history-deleted">' . $this->msg('rev-deleted-user')->escaped() . '</span>'; } else { if ($local) { $row .= Linker::userLink($userId, $userText); $row .= $this->msg('word-separator')->plain(); $row .= '<span style="white-space: nowrap;">'; $row .= Linker::userToolLinks($userId, $userText); $row .= '</span>'; } else { $row .= htmlspecialchars($userText); } } $row .= '</td>'; // Don't show deleted descriptions if ($file->isDeleted(File::DELETED_COMMENT)) { $row .= '<td><span class="history-deleted">' . $this->msg('rev-deleted-comment')->escaped() . '</span></td>'; } else { $row .= '<td dir="' . $wgContLang->getDir() . '">' . Linker::formatComment($description, $this->title) . '</td>'; } $rowClass = null; wfRunHooks('ImagePageFileHistoryLine', array($this, $file, &$row, &$rowClass)); $classAttr = $rowClass ? " class='{$rowClass}'" : ''; return "<tr{$classAttr}>{$row}</tr>\n"; }
/** * Generate a user tool link cluster if the current user is allowed to view it * @return string HTML */ protected function getUserTools() { if ($this->file->userCan(Revision::DELETED_USER, $this->list->getUser())) { $link = Linker::userLink($this->file->user, $this->file->user_text) . Linker::userToolLinks($this->file->user, $this->file->user_text); } else { $link = $this->list->msg('rev-deleted-user')->escaped(); } if ($this->file->isDeleted(Revision::DELETED_USER)) { return '<span class="history-deleted">' . $link . '</span>'; } return $link; }
/** * Fetch file's user id if it's available to this user * * @param File|ArchivedFile $file * @return string HTML fragment */ function getFileUser($file) { if (!$file->userCan(File::DELETED_USER, $this->getUser())) { return '<span class="history-deleted">' . $this->msg('rev-deleted-user')->escaped() . '</span>'; } $link = Linker::userLink($file->getRawUser(), $file->getRawUserText()) . Linker::userToolLinks($file->getRawUser(), $file->getRawUserText()); if ($file->isDeleted(File::DELETED_USER)) { $link = '<span class="history-deleted">' . $link . '</span>'; } return $link; }
/** * TODO document * @param $type String * @param $lang Language or null * @param $title Title * @param $params Array * @return String */ protected static function getTitleLink($type, $lang, $title, &$params) { global $wgContLang, $wgUserrightsInterwikiDelimiter; if (!$lang) { return $title->getPrefixedText(); } switch ($type) { case 'move': $titleLink = Linker::link($title, htmlspecialchars($title->getPrefixedText()), array(), array('redirect' => 'no')); $targetTitle = Title::newFromText($params[0]); if (!$targetTitle) { # Workaround for broken database $params[0] = htmlspecialchars($params[0]); } else { $params[0] = Linker::link($targetTitle, htmlspecialchars($params[0])); } break; case 'block': if (substr($title->getText(), 0, 1) == '#') { $titleLink = $title->getText(); } else { // TODO: Store the user identifier in the parameters // to make this faster for future log entries $id = User::idFromName($title->getText()); $titleLink = Linker::userLink($id, $title->getText()) . Linker::userToolLinks($id, $title->getText(), false, Linker::TOOL_LINKS_NOBLOCK); } break; case 'rights': $text = $wgContLang->ucfirst($title->getText()); $parts = explode($wgUserrightsInterwikiDelimiter, $text, 2); if (count($parts) == 2) { $titleLink = WikiMap::foreignUserLink($parts[1], $parts[0], htmlspecialchars($title->getPrefixedText())); if ($titleLink !== false) { break; } } $titleLink = Linker::link(Title::makeTitle(NS_USER, $text)); break; case 'merge': $titleLink = Linker::link($title, $title->getPrefixedText(), array(), array('redirect' => 'no')); $params[0] = Linker::link(Title::newFromText($params[0]), htmlspecialchars($params[0])); $params[1] = $lang->timeanddate($params[1]); break; default: if ($title->getNamespace() == NS_SPECIAL) { list($name, $par) = SpecialPageFactory::resolveAlias($title->getDBkey()); # Use the language name for log titles, rather than Log/X if ($name == 'Log') { $titleLink = '(' . Linker::link($title, LogPage::logName($par)) . ')'; } else { $titleLink = Linker::link($title); } } else { $titleLink = Linker::link($title); } } return $titleLink; }
function formatRow($row) { $userName = $row->user_name; $ulinks = Linker::userLink($row->user_id, $userName); $ulinks .= Linker::userToolLinks($row->user_id, $userName); $lang = $this->getLanguage(); $list = array(); $user = User::newFromId($row->user_id); // User right filter foreach ($this->hideRights as $right) { // Calling User::getRights() within the loop so that // if the hideRights() filter is empty, we don't have to // trigger the lazy-init of the big userrights array in the // User object if (in_array($right, $user->getRights())) { return ''; } } // User group filter // Note: This is a different loop than for user rights, // because we're reusing it to build the group links // at the same time foreach ($user->getGroups() as $group) { if (in_array($group, $this->hideGroups)) { return ''; } $list[] = self::buildGroupLink($group, $userName); } $groups = $lang->commaList($list); $item = $lang->specialList($ulinks, $groups); if ($row->ipb_deleted) { $item = "<span class=\"deleted\">{$item}</span>"; } $count = $this->msg('activeusers-count')->numParams($row->recentedits)->params($userName)->numParams($this->RCMaxAge)->escaped(); $blocked = !is_null($row->ipb_deleted) ? ' ' . $this->msg('listusers-blocked', $userName)->escaped() : ''; return Html::rawElement('li', array(), "{$item} [{$count}]{$blocked}"); }
/** * * @param Skin $skin * @param File $result * @return string HTML */ function formatResult($skin, $result) { global $wgContLang; $nt = $result->getTitle(); $text = $wgContLang->convert($nt->getText()); $plink = Linker::link($nt, htmlspecialchars($text)); $userText = $result->getUser('text'); if ($result->isLocal()) { $userId = $result->getUser('id'); $user = Linker::userLink($userId, $userText); $user .= '<span style="white-space: nowrap;">'; $user .= Linker::userToolLinks($userId, $userText); $user .= '</span>'; } else { $user = htmlspecialchars($userText); } $time = htmlspecialchars($this->getLanguage()->userTimeAndDate($result->getTimestamp(), $this->getUser())); return "{$plink} . . {$user} . . {$time}"; }
public function userToolLinks($userId, $userText, $redContribsWhenNoEdits = false, $flags = 0, $edits = null) { return Linker::userToolLinks($userId, $userText, $redContribsWhenNoEdits, $flags, $edits); }
function formatValue($name, $value) { static $msg = null; if ($msg === null) { $keys = ['anononlyblock', 'createaccountblock', 'noautoblockblock', 'emailblock', 'blocklist-nousertalk', 'unblocklink', 'change-blocklink']; foreach ($keys as $key) { $msg[$key] = $this->msg($key)->escaped(); } } /** @var $row object */ $row = $this->mCurrentRow; $language = $this->getLanguage(); $formatted = ''; switch ($name) { case 'ipb_timestamp': $formatted = htmlspecialchars($language->userTimeAndDate($value, $this->getUser())); break; case 'ipb_target': if ($row->ipb_auto) { $formatted = $this->msg('autoblockid', $row->ipb_id)->parse(); } else { list($target, $type) = Block::parseTarget($row->ipb_address); switch ($type) { case Block::TYPE_USER: case Block::TYPE_IP: $formatted = Linker::userLink($target->getId(), $target); $formatted .= Linker::userToolLinks($target->getId(), $target, false, Linker::TOOL_LINKS_NOBLOCK); break; case Block::TYPE_RANGE: $formatted = htmlspecialchars($target); } } break; case 'ipb_expiry': $formatted = htmlspecialchars($language->formatExpiry($value, true)); if ($this->getUser()->isAllowed('block')) { if ($row->ipb_auto) { $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock'), $msg['unblocklink'], [], ['wpTarget' => "#{$row->ipb_id}"]); } else { $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock', $row->ipb_address), $msg['unblocklink']); $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Block', $row->ipb_address), $msg['change-blocklink']); } $formatted .= ' ' . Html::rawElement('span', ['class' => 'mw-blocklist-actions'], $this->msg('parentheses')->rawParams($language->pipeList($links))->escaped()); } if ($value !== 'infinity') { $timestamp = new MWTimestamp($value); $formatted .= '<br />' . $this->msg('ipb-blocklist-duration-left', $language->formatDuration($timestamp->getTimestamp() - time(), ['minutes', 'hours', 'days', 'years']))->escaped(); } break; case 'ipb_by': if (isset($row->by_user_name)) { $formatted = Linker::userLink($value, $row->by_user_name); $formatted .= Linker::userToolLinks($value, $row->by_user_name); } else { $formatted = htmlspecialchars($row->ipb_by_text); // foreign user? } break; case 'ipb_reason': $formatted = Linker::formatComment($value); break; case 'ipb_params': $properties = []; if ($row->ipb_anon_only) { $properties[] = $msg['anononlyblock']; } if ($row->ipb_create_account) { $properties[] = $msg['createaccountblock']; } if ($row->ipb_user && !$row->ipb_enable_autoblock) { $properties[] = $msg['noautoblockblock']; } if ($row->ipb_block_email) { $properties[] = $msg['emailblock']; } if (!$row->ipb_allow_usertalk) { $properties[] = $msg['blocklist-nousertalk']; } $formatted = $language->commaList($properties); break; default: $formatted = "Unable to format {$name}"; break; } return $formatted; }
/** * Format a line for enhanced recentchange (aka with javascript and block of lines). * * @param $baseRC RecentChange * @param $watched bool * * @return string */ public function recentChangesLine(&$baseRC, $watched = false) { wfProfileIn(__METHOD__); # Create a specialised object $rc = RCCacheEntry::newFromParent($baseRC); $curIdEq = array('curid' => $rc->mAttribs['rc_cur_id']); # If it's a new day, add the headline and flush the cache $date = $this->getLanguage()->date($rc->mAttribs['rc_timestamp'], true); $ret = ''; if ($date != $this->lastdate) { # Process current cache $ret = $this->recentChangesBlock(); $this->rc_cache = array(); $ret .= Xml::element('h4', null, $date) . "\n"; $this->lastdate = $date; } # Should patrol-related stuff be shown? $rc->unpatrolled = $this->showAsUnpatrolled($rc); $showdifflinks = true; # Make article link $type = $rc->mAttribs['rc_type']; $logType = $rc->mAttribs['rc_log_type']; // Page moves, very old style, not supported anymore if ($type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT) { // New unpatrolled pages } elseif ($rc->unpatrolled && $type == RC_NEW) { $clink = Linker::linkKnown($rc->getTitle(), null, array(), array('rcid' => $rc->mAttribs['rc_id'])); // Log entries } elseif ($type == RC_LOG) { if ($logType) { $logtitle = SpecialPage::getTitleFor('Log', $logType); $logpage = new LogPage($logType); $logname = $logpage->getName()->escaped(); $clink = '(' . Linker::linkKnown($logtitle, $logname) . ')'; } else { $clink = Linker::link($rc->getTitle()); } $watched = false; // Log entries (old format) and special pages } elseif ($rc->mAttribs['rc_namespace'] == NS_SPECIAL) { wfDebug("Unexpected special page in recentchanges\n"); $clink = ''; // Edits } else { $clink = Linker::linkKnown($rc->getTitle()); } # Don't show unusable diff links if (!ChangesList::userCan($rc, Revision::DELETED_TEXT, $this->getUser())) { $showdifflinks = false; } $time = $this->getLanguage()->time($rc->mAttribs['rc_timestamp'], true, true); $rc->watched = $watched; $rc->link = $clink; $rc->timestamp = $time; $rc->numberofWatchingusers = $baseRC->numberofWatchingusers; # Make "cur" and "diff" links. Do not use link(), it is too slow if # called too many times (50% of CPU time on RecentChanges!). $thisOldid = $rc->mAttribs['rc_this_oldid']; $lastOldid = $rc->mAttribs['rc_last_oldid']; if ($rc->unpatrolled) { $rcIdQuery = array('rcid' => $rc->mAttribs['rc_id']); } else { $rcIdQuery = array(); } $querycur = $curIdEq + array('diff' => '0', 'oldid' => $thisOldid); $querydiff = $curIdEq + array('diff' => $thisOldid, 'oldid' => $lastOldid) + $rcIdQuery; if (!$showdifflinks) { $curLink = $this->message['cur']; $diffLink = $this->message['diff']; } elseif (in_array($type, array(RC_NEW, RC_LOG, RC_MOVE, RC_MOVE_OVER_REDIRECT))) { if ($type != RC_NEW) { $curLink = $this->message['cur']; } else { $curUrl = htmlspecialchars($rc->getTitle()->getLinkURL($querycur)); $curLink = "<a href=\"{$curUrl}\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>"; } $diffLink = $this->message['diff']; } else { $diffUrl = htmlspecialchars($rc->getTitle()->getLinkURL($querydiff)); $curUrl = htmlspecialchars($rc->getTitle()->getLinkURL($querycur)); $diffLink = "<a href=\"{$diffUrl}\" tabindex=\"{$baseRC->counter}\">{$this->message['diff']}</a>"; $curLink = "<a href=\"{$curUrl}\" tabindex=\"{$baseRC->counter}\">{$this->message['cur']}</a>"; } # Make "last" link if (!$showdifflinks || !$lastOldid) { $lastLink = $this->message['last']; } elseif (in_array($type, array(RC_LOG, RC_MOVE, RC_MOVE_OVER_REDIRECT))) { $lastLink = $this->message['last']; } else { $lastLink = Linker::linkKnown($rc->getTitle(), $this->message['last'], array(), $curIdEq + array('diff' => $thisOldid, 'oldid' => $lastOldid) + $rcIdQuery); } # Make user links if ($this->isDeleted($rc, Revision::DELETED_USER)) { $rc->userlink = ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-user') . '</span>'; } else { $rc->userlink = Linker::userLink($rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text']); $rc->usertalklink = Linker::userToolLinks($rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text']); } $rc->lastlink = $lastLink; $rc->curlink = $curLink; $rc->difflink = $diffLink; # Put accumulated information into the cache, for later display # Page moves go on their own line $title = $rc->getTitle(); $secureName = $title->getPrefixedDBkey(); if ($type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT) { # Use an @ character to prevent collision with page names $this->rc_cache['@@' . $this->rcMoveIndex++] = array($rc); } else { # Logs are grouped by type if ($type == RC_LOG) { $secureName = SpecialPage::getTitleFor('Log', $logType)->getPrefixedDBkey(); } if (!isset($this->rc_cache[$secureName])) { $this->rc_cache[$secureName] = array(); } array_push($this->rc_cache[$secureName], $rc); } wfProfileOut(__METHOD__); return $ret; }
protected function makeUserLink(User $user, $toolFlags = 0) { if ($this->plaintext) { $element = $user->getName(); } else { $element = Linker::userLink($user->getId(), $user->getName()); if ($this->linkFlood) { $element .= Linker::userToolLinks($user->getId(), $user->getName(), true, $toolFlags, $user->getEditCount()); } } return $element; }
function formatValue($name, $value) { $lang = $this->getLanguage(); $row = $this->mCurrentRow; switch ($name) { case 'afh_filter': $formatted = $lang->formatNum($row->afh_filter); break; case 'afh_timestamp': $title = SpecialPage::getTitleFor('AbuseFilter', 'history/' . $row->afh_filter . '/item/' . $row->afh_id); $formatted = Linker::link($title, $lang->timeanddate($row->afh_timestamp, true)); break; case 'afh_user_text': $formatted = Linker::userLink($row->afh_user, $row->afh_user_text) . ' ' . Linker::userToolLinks($row->afh_user, $row->afh_user_text); break; case 'afh_public_comments': $formatted = htmlspecialchars($value, ENT_QUOTES, 'UTF-8', false); break; case 'afh_flags': $formatted = AbuseFilter::formatFlags($value); break; case 'afh_actions': $actions = unserialize($value); $display_actions = ''; foreach ($actions as $action => $parameters) { $displayAction = AbuseFilter::formatAction($action, $parameters); $display_actions .= Xml::tags('li', null, $displayAction); } $display_actions = Xml::tags('ul', null, $display_actions); $formatted = $display_actions; break; case 'afh_id': $formatted = ''; if (AbuseFilter::getFirstFilterChange($row->afh_filter) != $value) { // Set a link to a diff with the previous version if this isn't the first edit to the filter $title = $this->mPage->getTitle('history/' . $row->afh_filter . "/diff/prev/{$value}"); $formatted = Linker::link($title, $this->msg('abusefilter-history-diff')->parse()); } break; default: $formatted = "Unable to format {$name}"; break; } $mappings = array_flip(AbuseFilter::$history_mappings) + array('afh_actions' => 'actions', 'afh_id' => 'id'); $changed = explode(',', $row->afh_changed_fields); $fieldChanged = false; if ($name == 'afh_flags') { // This is a bit freaky, but it works. // Basically, returns true if any of those filters are in the $changed array. $filters = array('af_enabled', 'af_hidden', 'af_deleted', 'af_global'); if (count(array_diff($filters, $changed)) < count($filters)) { $fieldChanged = true; } } elseif (in_array($mappings[$name], $changed)) { $fieldChanged = true; } if ($fieldChanged) { $formatted = Xml::tags('div', array('class' => 'mw-abusefilter-history-changed'), $formatted); } return $formatted; }
/** * Display a moved thread * * @param $thread Thread * @throws Exception */ function showMovedThread($thread) { global $wgLang; // Grab target thread if (!$thread->title()) { return; // Odd case: moved thread with no title? } $article = new Article($thread->title(), 0); $target = Title::newFromRedirect($article->getContent()); if (!$target) { throw new Exception("Thread " . $thread->id() . ' purports to be moved, ' . 'but no redirect found in text (' . $article->getContent() . ') of ' . $thread->root()->getTitle()->getPrefixedText() . '. Dying.'); } $t_thread = Threads::withRoot(new Article($target, 0)); // Grab data about the new post. $author = $thread->author(); $sig = Linker::userLink($author->getID(), $author->getName()) . Linker::userToolLinks($author->getID(), $author->getName()); $newTalkpage = is_object($t_thread) ? $t_thread->getTitle() : ''; $html = wfMessage('lqt_move_placeholder')->rawParams(Linker::link($target), $sig)->params($wgLang->date($thread->modified()), $wgLang->time($thread->modified()))->rawParams(Linker::link($newTalkpage))->parse(); $this->output->addHTML($html); }
/** * Insert links to user page, user talk page and eventually a blocking link * * @param string &$s HTML to update * @param RecentChange &$rc */ public function insertUserRelatedLinks(&$s, &$rc) { if ($this->isDeleted($rc, Revision::DELETED_USER)) { $s .= ' <span class="history-deleted">' . $this->msg('rev-deleted-user')->escaped() . '</span>'; } else { $s .= $this->getLanguage()->getDirMark() . Linker::userLink($rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text']); $s .= Linker::userToolLinks($rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text']); } }
/** * @param string $field * @param string $value * @return string HTML * @throws MWException */ function formatValue($field, $value) { /** @var $row object */ $row = $this->mCurrentRow; $formatted = ''; switch ($field) { case 'log_timestamp': // when timestamp is null, this is a old protection row if ($value === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-timestamp')->escaped()); } else { $formatted = htmlspecialchars($this->getLanguage()->userTimeAndDate($value, $this->getUser())); } break; case 'pr_page': $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if (!$title) { $formatted = Html::element('span', array('class' => 'mw-invalidtitle'), Linker::getInvalidTitleDescription($this->getContext(), $row->page_namespace, $row->page_title)); } else { $formatted = Linker::link($title); } if (!is_null($row->page_len)) { $formatted .= $this->getLanguage()->getDirMark() . ' ' . Html::rawElement('span', array('class' => 'mw-protectedpages-length'), Linker::formatRevisionSize($row->page_len)); } break; case 'pr_expiry': $formatted = htmlspecialchars($this->getLanguage()->formatExpiry($value, true)); $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if ($this->getUser()->isAllowed('protect') && $title) { $changeProtection = Linker::linkKnown($title, $this->msg('protect_change')->escaped(), array(), array('action' => 'unprotect')); $formatted .= ' ' . Html::rawElement('span', array('class' => 'mw-protectedpages-actions'), $this->msg('parentheses')->rawParams($changeProtection)->escaped()); } break; case 'log_user': // when timestamp is null, this is a old protection row if ($row->log_timestamp === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-performer')->escaped()); } else { $username = UserCache::singleton()->getProp($value, 'name'); if (LogEventsList::userCanBitfield($row->log_deleted, LogPage::DELETED_USER, $this->getUser())) { if ($username === false) { $formatted = htmlspecialchars($value); } else { $formatted = Linker::userLink($value, $username) . Linker::userToolLinks($value, $username); } } else { $formatted = $this->msg('rev-deleted-user')->escaped(); } if (LogEventsList::isDeleted($row, LogPage::DELETED_USER)) { $formatted = '<span class="history-deleted">' . $formatted . '</span>'; } } break; case 'pr_params': $params = array(); // Messages: restriction-level-sysop, restriction-level-autoconfirmed $params[] = $this->msg('restriction-level-' . $row->pr_level)->escaped(); if ($row->pr_cascade) { $params[] = $this->msg('protect-summary-cascade')->escaped(); } $formatted = $this->getLanguage()->commaList($params); break; case 'log_comment': // when timestamp is null, this is an old protection row if ($row->log_timestamp === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-reason')->escaped()); } else { if (LogEventsList::userCanBitfield($row->log_deleted, LogPage::DELETED_COMMENT, $this->getUser())) { $formatted = Linker::formatComment($value !== null ? $value : ''); } else { $formatted = $this->msg('rev-deleted-comment')->escaped(); } if (LogEventsList::isDeleted($row, LogPage::DELETED_COMMENT)) { $formatted = '<span class="history-deleted">' . $formatted . '</span>'; } } break; default: throw new MWException("Unknown field '{$field}'"); } return $formatted; }
/** * @TODO: split up! * * @param $row * @param Title $title * @param Array $paramArray * @param $comment * @return String */ private function logActionLinks($row, $title, $paramArray, &$comment) { global $wgUser; if ($this->flags & self::NO_ACTION_LINK || self::isDeleted($row, LogPage::DELETED_ACTION)) { return ''; } $revert = ''; if (self::typeAction($row, 'move', 'move', 'move') && !empty($paramArray[0])) { $destTitle = Title::newFromText($paramArray[0]); if ($destTitle) { $revert = '(' . Linker::link(SpecialPage::getTitleFor('Movepage'), $this->message['revertmove'], array(), array('wpOldTitle' => $destTitle->getPrefixedDBkey(), 'wpNewTitle' => $title->getPrefixedDBkey(), 'wpReason' => wfMsgForContent('revertmove'), 'wpMovetalk' => 0), array('known', 'noclasses')) . ')'; } // Show undelete link } elseif (self::typeAction($row, array('delete', 'suppress'), 'delete', 'deletedhistory')) { if (!$wgUser->isAllowed('undelete')) { $viewdeleted = $this->message['undeleteviewlink']; } else { $viewdeleted = $this->message['undeletelink']; } $revert = '(' . Linker::link(SpecialPage::getTitleFor('Undelete'), $viewdeleted, array(), array('target' => $title->getPrefixedDBkey()), array('known', 'noclasses')) . ')'; // Show unblock/change block link } elseif (self::typeAction($row, array('block', 'suppress'), array('block', 'reblock'), 'block')) { $revert = '(' . Linker::link(SpecialPage::getTitleFor('Unblock', $row->log_title), $this->message['unblocklink'], array(), array(), 'known') . $this->message['pipe-separator'] . Linker::link(SpecialPage::getTitleFor('Block', $row->log_title), $this->message['change-blocklink'], array(), array(), 'known') . ')'; // Show change protection link } elseif (self::typeAction($row, 'protect', array('modify', 'protect', 'unprotect'))) { $revert .= ' (' . Linker::link($title, $this->message['hist'], array(), array('action' => 'history', 'offset' => $row->log_timestamp)); if ($wgUser->isAllowed('protect')) { $revert .= $this->message['pipe-separator'] . Linker::link($title, $this->message['protect_change'], array(), array('action' => 'protect'), 'known'); } $revert .= ')'; // Show unmerge link } elseif (self::typeAction($row, 'merge', 'merge', 'mergehistory')) { $revert = '(' . Linker::link(SpecialPage::getTitleFor('MergeHistory'), $this->message['revertmerge'], array(), array('target' => $paramArray[0], 'dest' => $title->getPrefixedDBkey(), 'mergepoint' => $paramArray[1]), array('known', 'noclasses')) . ')'; // If an edit was hidden from a page give a review link to the history } elseif (self::typeAction($row, array('delete', 'suppress'), 'revision', 'deletedhistory')) { $revert = RevisionDeleter::getLogLinks($title, $paramArray, $this->skin, $this->message); // Hidden log items, give review link } elseif (self::typeAction($row, array('delete', 'suppress'), 'event', 'deletedhistory')) { if (count($paramArray) >= 1) { $revdel = SpecialPage::getTitleFor('Revisiondelete'); // $paramArray[1] is a CSV of the IDs $query = $paramArray[0]; // Link to each hidden object ID, $paramArray[1] is the url param $revert = '(' . Linker::link($revdel, $this->message['revdel-restore'], array(), array('target' => $title->getPrefixedText(), 'type' => 'logging', 'ids' => $query), array('known', 'noclasses')) . ')'; } // Self-created users } elseif (self::typeAction($row, 'newusers', 'create2')) { if (isset($paramArray[0])) { $revert = Linker::userToolLinks($paramArray[0], $title->getDBkey(), true); } else { # Fall back to a blue contributions link $revert = Linker::userToolLinks(1, $title->getDBkey()); } if (wfTimestamp(TS_MW, $row->log_timestamp) < '20080129000000') { # Suppress $comment from old entries (before 2008-01-29), # not needed and can contain incorrect links $comment = ''; } // Do nothing. The implementation is handled by the hook modifiying the passed-by-ref parameters. } else { wfRunHooks('LogLine', array($row->log_type, $row->log_action, $title, $paramArray, &$comment, &$revert, $row->log_timestamp)); } if ($revert != '') { $revert = '<span class="mw-logevent-actionlink">' . $revert . '</span>'; } return $revert; }