/**
  * @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;
 }
 protected function formatRevisionRow($row, $earliestLiveTime, $remaining)
 {
     $rev = Revision::newFromArchiveRow($row, array('title' => $this->mTargetObj));
     $revTextSize = '';
     $ts = wfTimestamp(TS_MW, $row->ar_timestamp);
     // Build checkboxen...
     if ($this->mAllowed) {
         if ($this->mInvert) {
             if (in_array($ts, $this->mTargetTimestamp)) {
                 $checkBox = Xml::check("ts{$ts}");
             } else {
                 $checkBox = Xml::check("ts{$ts}", true);
             }
         } else {
             $checkBox = Xml::check("ts{$ts}");
         }
     } else {
         $checkBox = '';
     }
     // Build page & diff links...
     $user = $this->getUser();
     if ($this->mCanView) {
         $titleObj = $this->getPageTitle();
         # Last link
         if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
             $pageLink = htmlspecialchars($this->getLanguage()->userTimeAndDate($ts, $user));
             $last = $this->msg('diff')->escaped();
         } elseif ($remaining > 0 || $earliestLiveTime && $ts > $earliestLiveTime) {
             $pageLink = $this->getPageLink($rev, $titleObj, $ts);
             $last = Linker::linkKnown($titleObj, $this->msg('diff')->escaped(), array(), array('target' => $this->mTargetObj->getPrefixedText(), 'timestamp' => $ts, 'diff' => 'prev'));
         } else {
             $pageLink = $this->getPageLink($rev, $titleObj, $ts);
             $last = $this->msg('diff')->escaped();
         }
     } else {
         $pageLink = htmlspecialchars($this->getLanguage()->userTimeAndDate($ts, $user));
         $last = $this->msg('diff')->escaped();
     }
     // User links
     $userLink = Linker::revUserTools($rev);
     // Minor edit
     $minor = $rev->isMinor() ? ChangesList::flag('minor') : '';
     // Revision text size
     $size = $row->ar_len;
     if (!is_null($size)) {
         $revTextSize = Linker::formatRevisionSize($size);
     }
     // Edit summary
     $comment = Linker::revComment($rev);
     // Tags
     $attribs = array();
     list($tagSummary, $classes) = ChangeTags::formatSummaryRow($row->ts_tags, 'deletedhistory');
     if ($classes) {
         $attribs['class'] = implode(' ', $classes);
     }
     // Revision delete links
     $revdlink = Linker::getRevDeleteLink($user, $rev, $this->mTargetObj);
     $revisionRow = $this->msg('undelete-revision-row')->rawParams($checkBox, $revdlink, $last, $pageLink, $userLink, $minor, $revTextSize, $comment, $tagSummary)->escaped();
     return Xml::tags('li', $attribs, $revisionRow) . "\n";
 }
 function formatRevisionRow($row)
 {
     $rev = new Revision($row);
     $stxt = '';
     $last = $this->msg('last')->escaped();
     $ts = wfTimestamp(TS_MW, $row->rev_timestamp);
     $checkBox = Xml::radio('mergepoint', $ts, $this->mTimestamp === $ts);
     $user = $this->getUser();
     $pageLink = Linker::linkKnown($rev->getTitle(), htmlspecialchars($this->getLanguage()->userTimeAndDate($ts, $user)), [], ['oldid' => $rev->getId()]);
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
     }
     # Last link
     if (!$rev->userCan(Revision::DELETED_TEXT, $user)) {
         $last = $this->msg('last')->escaped();
     } elseif (isset($this->prevId[$row->rev_id])) {
         $last = Linker::linkKnown($rev->getTitle(), $this->msg('last')->escaped(), [], ['diff' => $row->rev_id, 'oldid' => $this->prevId[$row->rev_id]]);
     }
     $userLink = Linker::revUserTools($rev);
     $size = $row->rev_len;
     if (!is_null($size)) {
         $stxt = Linker::formatRevisionSize($size);
     }
     $comment = Linker::revComment($rev);
     return Html::rawElement('li', [], $this->msg('mergehistory-revisionrow')->rawParams($checkBox, $last, $pageLink, $userLink, $stxt, $comment)->escaped());
 }
 /**
  * Generates each row in the contributions list.
  *
  * Contributions which are marked "top" are currently on top of the history.
  * For these contributions, a [rollback] link is shown for users with roll-
  * back privileges. The rollback link restores the most recent version that
  * was not written by the target user.
  *
  * @todo This would probably look a lot nicer in a table.
  * @param $row
  * @return string
  */
 function formatRow($row)
 {
     wfProfileIn(__METHOD__);
     $ret = '';
     $classes = array();
     /*
      * There may be more than just revision rows. To make sure that we'll only be processing
      * revisions here, let's _try_ to build a revision out of our row (without displaying
      * notices though) and then trying to grab data from the built object. If we succeed,
      * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
      * to extensions to subscribe to the hook to parse the row.
      */
     wfSuppressWarnings();
     $rev = new Revision($row);
     $validRevision = $rev->getParentId() !== null;
     wfRestoreWarnings();
     if ($validRevision) {
         $classes = array();
         $page = Title::newFromRow($row);
         $link = Linker::link($page, htmlspecialchars($page->getPrefixedText()), array('class' => 'mw-contributions-title'), $page->isRedirect() ? array('redirect' => 'no') : array());
         # Mark current revisions
         $topmarktext = '';
         $user = $this->getUser();
         if ($row->rev_id == $row->page_latest) {
             $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>';
             # Add rollback link
             if (!$row->page_is_new && $page->quickUserCan('rollback', $user) && $page->quickUserCan('edit', $user)) {
                 $this->preventClickjacking();
                 $topmarktext .= ' ' . Linker::generateRollback($rev, $this->getContext());
             }
         }
         # Is there a visible previous revision?
         if ($rev->userCan(Revision::DELETED_TEXT, $user) && $rev->getParentId() !== 0) {
             $difftext = Linker::linkKnown($page, $this->messages['diff'], array(), array('diff' => 'prev', 'oldid' => $row->rev_id));
         } else {
             $difftext = $this->messages['diff'];
         }
         $histlink = Linker::linkKnown($page, $this->messages['hist'], array(), array('action' => 'history'));
         if ($row->rev_parent_id === null) {
             // For some reason rev_parent_id isn't populated for this row.
             // Its rumoured this is true on wikipedia for some revisions (bug 34922).
             // Next best thing is to have the total number of bytes.
             $chardiff = ' <span class="mw-changeslist-separator">. .</span> ' . Linker::formatRevisionSize($row->rev_len) . ' <span class="mw-changeslist-separator">. .</span> ';
         } else {
             $parentLen = isset($this->mParentLens[$row->rev_parent_id]) ? $this->mParentLens[$row->rev_parent_id] : 0;
             $chardiff = ' <span class="mw-changeslist-separator">. .</span> ' . ChangesList::showCharacterDifference($parentLen, $row->rev_len, $this->getContext()) . ' <span class="mw-changeslist-separator">. .</span> ';
         }
         $lang = $this->getLanguage();
         $comment = $lang->getDirMark() . Linker::revComment($rev, false, true);
         $date = $lang->userTimeAndDate($row->rev_timestamp, $user);
         if ($rev->userCan(Revision::DELETED_TEXT, $user)) {
             $d = Linker::linkKnown($page, htmlspecialchars($date), array('class' => 'mw-changeslist-date'), array('oldid' => intval($row->rev_id)));
         } else {
             $d = htmlspecialchars($date);
         }
         if ($rev->isDeleted(Revision::DELETED_TEXT)) {
             $d = '<span class="history-deleted">' . $d . '</span>';
         }
         # Show user names for /newbies as there may be different users.
         # Note that we already excluded rows with hidden user names.
         if ($this->contribs == 'newbie') {
             $userlink = ' . . ' . Linker::userLink($rev->getUser(), $rev->getUserText());
             $userlink .= ' ' . $this->msg('parentheses')->rawParams(Linker::userTalkLink($rev->getUser(), $rev->getUserText()))->escaped() . ' ';
         } else {
             $userlink = '';
         }
         if ($rev->getParentId() === 0) {
             $nflag = ChangesList::flag('newpage');
         } else {
             $nflag = '';
         }
         if ($rev->isMinor()) {
             $mflag = ChangesList::flag('minor');
         } else {
             $mflag = '';
         }
         $del = Linker::getRevDeleteLink($user, $rev, $page);
         if ($del !== '') {
             $del .= ' ';
         }
         $diffHistLinks = $this->msg('parentheses')->rawParams($difftext . $this->messages['pipe-separator'] . $histlink)->escaped();
         $ret = "{$del}{$d} {$diffHistLinks}{$chardiff}{$nflag}{$mflag} {$link}{$userlink} {$comment} {$topmarktext}";
         # Denote if username is redacted for this edit
         if ($rev->isDeleted(Revision::DELETED_USER)) {
             $ret .= " <strong>" . $this->msg('rev-deleted-user-contribs')->escaped() . "</strong>";
         }
         # Tags, if any.
         list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow($row->ts_tags, 'contributions');
         $classes = array_merge($classes, $newClasses);
         $ret .= " {$tagSummary}";
     }
     // Let extensions add data
     wfRunHooks('ContributionsLineEnding', array($this, &$ret, $row, &$classes));
     $classes = implode(' ', $classes);
     $ret = "<li class=\"{$classes}\">{$ret}</li>\n";
     wfProfileOut(__METHOD__);
     return $ret;
 }
 /**
  * Returns a row from the history printout.
  *
  * @todo document some more, and maybe clean up the code (some params redundant?)
  *
  * @param stdClass $row The database row corresponding to the previous line.
  * @param mixed $next The database row corresponding to the next line
  *   (chronologically previous)
  * @param bool|string $notificationtimestamp
  * @param bool $latest Whether this row corresponds to the page's latest revision.
  * @param bool $firstInList Whether this row corresponds to the first
  *   displayed on this history page.
  * @return string HTML output for the row
  */
 function historyLine($row, $next, $notificationtimestamp = false, $latest = false, $firstInList = false)
 {
     $rev = new Revision($row);
     $rev->setTitle($this->getTitle());
     if (is_object($next)) {
         $prevRev = new Revision($next);
         $prevRev->setTitle($this->getTitle());
     } else {
         $prevRev = null;
     }
     $curlink = $this->curLink($rev, $latest);
     $lastlink = $this->lastLink($rev, $next);
     $curLastlinks = $curlink . $this->historyPage->message['pipe-separator'] . $lastlink;
     $histLinks = Html::rawElement('span', array('class' => 'mw-history-histlinks'), $this->msg('parentheses')->rawParams($curLastlinks)->escaped());
     $diffButtons = $this->diffButtons($rev, $firstInList);
     $s = $histLinks . $diffButtons;
     $link = $this->revLink($rev);
     $classes = array();
     $del = '';
     $user = $this->getUser();
     // Show checkboxes for each revision
     if ($user->isAllowed('deleterevision')) {
         $this->preventClickjacking();
         // If revision was hidden from sysops, disable the checkbox
         if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
             $del = Xml::check('deleterevisions', false, array('disabled' => 'disabled'));
             // Otherwise, enable the checkbox...
         } else {
             $del = Xml::check('showhiderevisions', false, array('name' => 'ids[' . $rev->getId() . ']'));
         }
         // User can only view deleted revisions...
     } elseif ($rev->getVisibility() && $user->isAllowed('deletedhistory')) {
         // If revision was hidden from sysops, disable the link
         if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
             $del = Linker::revDeleteLinkDisabled(false);
             // Otherwise, show the link...
         } else {
             $query = array('type' => 'revision', 'target' => $this->getTitle()->getPrefixedDBkey(), 'ids' => $rev->getId());
             $del .= Linker::revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), false);
         }
     }
     if ($del) {
         $s .= " {$del} ";
     }
     $lang = $this->getLanguage();
     $dirmark = $lang->getDirMark();
     $s .= " {$link}";
     $s .= $dirmark;
     $s .= " <span class='history-user'>" . Linker::revUserTools($rev, true) . "</span>";
     $s .= $dirmark;
     if ($rev->isMinor()) {
         $s .= ' ' . ChangesList::flag('minor');
     }
     # Sometimes rev_len isn't populated
     if ($rev->getSize() !== null) {
         # Size is always public data
         $prevSize = isset($this->parentLens[$row->rev_parent_id]) ? $this->parentLens[$row->rev_parent_id] : 0;
         $sDiff = ChangesList::showCharacterDifference($prevSize, $rev->getSize());
         $fSize = Linker::formatRevisionSize($rev->getSize());
         $s .= ' <span class="mw-changeslist-separator">. .</span> ' . "{$fSize} {$sDiff}";
     }
     # Text following the character difference is added just before running hooks
     $s2 = Linker::revComment($rev, false, true);
     if ($notificationtimestamp && $row->rev_timestamp >= $notificationtimestamp) {
         $s2 .= ' <span class="updatedmarker">' . $this->msg('updatedmarker')->escaped() . '</span>';
         $classes[] = 'mw-history-line-updated';
     }
     $tools = array();
     # Rollback and undo links
     if ($prevRev && $this->getTitle()->quickUserCan('edit', $user)) {
         if ($latest && $this->getTitle()->quickUserCan('rollback', $user)) {
             // Get a rollback link without the brackets
             $rollbackLink = Linker::generateRollback($rev, $this->getContext(), array('verify', 'noBrackets'));
             if ($rollbackLink) {
                 $this->preventClickjacking();
                 $tools[] = $rollbackLink;
             }
         }
         if (!$rev->isDeleted(Revision::DELETED_TEXT) && !$prevRev->isDeleted(Revision::DELETED_TEXT)) {
             # Create undo tooltip for the first (=latest) line only
             $undoTooltip = $latest ? array('title' => $this->msg('tooltip-undo')->text()) : array();
             $undolink = Linker::linkKnown($this->getTitle(), $this->msg('editundo')->escaped(), $undoTooltip, array('action' => 'edit', 'undoafter' => $prevRev->getId(), 'undo' => $rev->getId()));
             $tools[] = "<span class=\"mw-history-undo\">{$undolink}</span>";
         }
     }
     // Allow extension to add their own links here
     wfRunHooks('HistoryRevisionTools', array($rev, &$tools));
     if ($tools) {
         $s2 .= ' ' . $this->msg('parentheses')->rawParams($lang->pipeList($tools))->escaped();
     }
     # Tags
     list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow($row->ts_tags, 'history');
     $classes = array_merge($classes, $newClasses);
     if ($tagSummary !== '') {
         $s2 .= " {$tagSummary}";
     }
     # Include separator between character difference and following text
     if ($s2 !== '') {
         $s .= ' <span class="mw-changeslist-separator">. .</span> ' . $s2;
     }
     wfRunHooks('PageHistoryLineEnding', array($this, &$row, &$s, &$classes));
     $attribs = array();
     if ($classes) {
         $attribs['class'] = implode(' ', $classes);
     }
     return Xml::tags('li', $attribs, $s) . "\n";
 }
Example #6
0
 public function formatRevisionSize($size)
 {
     return Linker::formatRevisionSize($size);
 }
 /**
  * Callback function to output a restriction
  * @param Title $row Protected title
  * @return string Formatted "<li>" element
  */
 public function formatRow($row)
 {
     wfProfileIn(__METHOD__);
     static $infinity = null;
     if (is_null($infinity)) {
         $infinity = wfGetDB(DB_SLAVE)->getInfinity();
     }
     $title = Title::makeTitleSafe($row->page_namespace, $row->page_title);
     if (!$title) {
         wfProfileOut(__METHOD__);
         return Html::rawElement('li', array(), Html::element('span', array('class' => 'mw-invalidtitle'), Linker::getInvalidTitleDescription($this->getContext(), $row->page_namespace, $row->page_title))) . "\n";
     }
     $link = Linker::link($title);
     $description_items = array();
     $protType = $this->msg('restriction-level-' . $row->pr_level)->escaped();
     $description_items[] = $protType;
     if ($row->pr_cascade) {
         $description_items[] = $this->msg('protect-summary-cascade')->text();
     }
     $stxt = '';
     $lang = $this->getLanguage();
     $expiry = $lang->formatExpiry($row->pr_expiry, TS_MW);
     if ($expiry != $infinity) {
         $user = $this->getUser();
         $description_items[] = $this->msg('protect-expiring-local', $lang->userTimeAndDate($expiry, $user), $lang->userDate($expiry, $user), $lang->userTime($expiry, $user))->escaped();
     }
     if (!is_null($size = $row->page_len)) {
         $stxt = $lang->getDirMark() . ' ' . Linker::formatRevisionSize($size);
     }
     # Show a link to the change protection form for allowed users otherwise
     # a link to the protection log
     if ($this->getUser()->isAllowed('protect')) {
         $changeProtection = Linker::linkKnown($title, $this->msg('protect_change')->escaped(), array(), array('action' => 'unprotect'));
     } else {
         $ltitle = SpecialPage::getTitleFor('Log');
         $changeProtection = Linker::linkKnown($ltitle, $this->msg('protectlogpage')->escaped(), array(), array('type' => 'protect', 'page' => $title->getPrefixedText()));
     }
     $changeProtection = ' ' . $this->msg('parentheses')->rawParams($changeProtection)->escaped();
     wfProfileOut(__METHOD__);
     return Html::rawElement('li', array(), $lang->specialList($link . $stxt, $lang->commaList($description_items), false) . $changeProtection) . "\n";
 }
Example #8
0
 /**
  * Returns a row from the history printout.
  *
  * @todo document some more, and maybe clean up the code (some params redundant?)
  *
  * @param $row Object: the database row corresponding to the previous line.
  * @param $next Mixed: the database row corresponding to the next line. (chronologically previous)
  * @param $notificationtimestamp
  * @param $latest Boolean: whether this row corresponds to the page's latest revision.
  * @param $firstInList Boolean: whether this row corresponds to the first displayed on this history page.
  * @return String: HTML output for the row
  */
 function historyLine($row, $next, $notificationtimestamp = false, $latest = false, $firstInList = false)
 {
     $rev = new Revision($row);
     $rev->setTitle($this->getTitle());
     if (is_object($next)) {
         $prevRev = new Revision($next);
         $prevRev->setTitle($this->getTitle());
     } else {
         $prevRev = null;
     }
     $curlink = $this->curLink($rev, $latest);
     $lastlink = $this->lastLink($rev, $next);
     $diffButtons = $this->diffButtons($rev, $firstInList);
     $histLinks = Html::rawElement('span', array('class' => 'mw-history-histlinks'), '(' . $curlink . $this->historyPage->message['pipe-separator'] . $lastlink . ') ');
     $s = $histLinks . $diffButtons;
     $link = $this->revLink($rev);
     $classes = array();
     $del = '';
     $user = $this->getUser();
     // Show checkboxes for each revision
     if ($user->isAllowed('deleterevision')) {
         $this->preventClickjacking();
         // If revision was hidden from sysops, disable the checkbox
         if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
             $del = Xml::check('deleterevisions', false, array('disabled' => 'disabled'));
             // Otherwise, enable the checkbox...
         } else {
             $del = Xml::check('showhiderevisions', false, array('name' => 'ids[' . $rev->getId() . ']'));
         }
         // User can only view deleted revisions...
     } elseif ($rev->getVisibility() && $user->isAllowed('deletedhistory')) {
         // If revision was hidden from sysops, disable the link
         if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
             $cdel = Linker::revDeleteLinkDisabled(false);
             // Otherwise, show the link...
         } else {
             $query = array('type' => 'revision', 'target' => $this->getTitle()->getPrefixedDbkey(), 'ids' => $rev->getId());
             $del .= Linker::revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), false);
         }
     }
     if ($del) {
         $s .= " {$del} ";
     }
     $lang = $this->getLanguage();
     $dirmark = $lang->getDirMark();
     $s .= " {$link}";
     $s .= $dirmark;
     $s .= " <span class='history-user'>" . Linker::revUserTools($rev, true) . "</span>";
     $s .= $dirmark;
     if ($rev->isMinor()) {
         $s .= ' ' . ChangesList::flag('minor');
     }
     # Size is always public data
     $prevSize = $prevRev ? $prevRev->getSize() : 0;
     $sDiff = ChangesList::showCharacterDifference($prevSize, $rev->getSize());
     $fSize = Linker::formatRevisionSize($rev->getSize());
     $s .= " . . {$fSize} {$sDiff} . . ";
     $s .= Linker::revComment($rev, false, true);
     if ($notificationtimestamp && $row->rev_timestamp >= $notificationtimestamp) {
         $s .= ' <span class="updatedmarker">' . $this->msg('updatedmarker')->escaped() . '</span>';
     }
     $tools = array();
     # Rollback and undo links
     if ($prevRev && !count($this->getTitle()->getUserPermissionsErrors('edit', $this->getUser()))) {
         if ($latest && !count($this->getTitle()->getUserPermissionsErrors('rollback', $this->getUser()))) {
             $this->preventClickjacking();
             $tools[] = '<span class="mw-rollback-link">' . Linker::buildRollbackLink($rev) . '</span>';
         }
         if (!$rev->isDeleted(Revision::DELETED_TEXT) && !$prevRev->isDeleted(Revision::DELETED_TEXT)) {
             # Create undo tooltip for the first (=latest) line only
             $undoTooltip = $latest ? array('title' => $this->msg('tooltip-undo')->text()) : array();
             $undolink = Linker::linkKnown($this->getTitle(), $this->msg('editundo')->escaped(), $undoTooltip, array('action' => 'edit', 'undoafter' => $prevRev->getId(), 'undo' => $rev->getId()));
             $tools[] = "<span class=\"mw-history-undo\">{$undolink}</span>";
         }
     }
     if ($tools) {
         $s .= ' (' . $lang->pipeList($tools) . ')';
     }
     # Tags
     list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow($row->ts_tags, 'history');
     $classes = array_merge($classes, $newClasses);
     $s .= " {$tagSummary}";
     wfRunHooks('PageHistoryLineEnding', array($this, &$row, &$s, &$classes));
     $attribs = array();
     if ($classes) {
         $attribs['class'] = implode(' ', $classes);
     }
     return Xml::tags('li', $attribs, $s) . "\n";
 }
Example #9
0
 /**
  * Generates each row in the contributions list.
  *
  * Contributions which are marked "top" are currently on top of the history.
  * For these contributions, a [rollback] link is shown for users with roll-
  * back privileges. The rollback link restores the most recent version that
  * was not written by the target user.
  *
  * @todo This would probably look a lot nicer in a table.
  * @param object $row
  * @return string
  */
 function formatRow($row)
 {
     $ret = '';
     $classes = [];
     /*
      * There may be more than just revision rows. To make sure that we'll only be processing
      * revisions here, let's _try_ to build a revision out of our row (without displaying
      * notices though) and then trying to grab data from the built object. If we succeed,
      * we're definitely dealing with revision data and we may proceed, if not, we'll leave it
      * to extensions to subscribe to the hook to parse the row.
      */
     MediaWiki\suppressWarnings();
     try {
         $rev = new Revision($row);
         $validRevision = (bool) $rev->getId();
     } catch (Exception $e) {
         $validRevision = false;
     }
     MediaWiki\restoreWarnings();
     if ($validRevision) {
         $classes = [];
         $page = Title::newFromRow($row);
         $link = Linker::link($page, htmlspecialchars($page->getPrefixedText()), ['class' => 'mw-contributions-title'], $page->isRedirect() ? ['redirect' => 'no'] : []);
         # Mark current revisions
         $topmarktext = '';
         $user = $this->getUser();
         if ($row->rev_id === $row->page_latest) {
             $topmarktext .= '<span class="mw-uctop">' . $this->messages['uctop'] . '</span>';
             $classes[] = 'mw-contributions-current';
             # Add rollback link
             if (!$row->page_is_new && $page->quickUserCan('rollback', $user) && $page->quickUserCan('edit', $user)) {
                 $this->preventClickjacking();
                 $topmarktext .= ' ' . Linker::generateRollback($rev, $this->getContext());
             }
         }
         # Is there a visible previous revision?
         if ($rev->userCan(Revision::DELETED_TEXT, $user) && $rev->getParentId() !== 0) {
             $difftext = Linker::linkKnown($page, $this->messages['diff'], [], ['diff' => 'prev', 'oldid' => $row->rev_id]);
         } else {
             $difftext = $this->messages['diff'];
         }
         $histlink = Linker::linkKnown($page, $this->messages['hist'], [], ['action' => 'history']);
         if ($row->rev_parent_id === null) {
             // For some reason rev_parent_id isn't populated for this row.
             // Its rumoured this is true on wikipedia for some revisions (bug 34922).
             // Next best thing is to have the total number of bytes.
             $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
             $chardiff .= Linker::formatRevisionSize($row->rev_len);
             $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
         } else {
             $parentLen = 0;
             if (isset($this->mParentLens[$row->rev_parent_id])) {
                 $parentLen = $this->mParentLens[$row->rev_parent_id];
             }
             $chardiff = ' <span class="mw-changeslist-separator">. .</span> ';
             $chardiff .= ChangesList::showCharacterDifference($parentLen, $row->rev_len, $this->getContext());
             $chardiff .= ' <span class="mw-changeslist-separator">. .</span> ';
         }
         $lang = $this->getLanguage();
         $comment = $lang->getDirMark() . Linker::revComment($rev, false, true);
         $date = $lang->userTimeAndDate($row->rev_timestamp, $user);
         if ($rev->userCan(Revision::DELETED_TEXT, $user)) {
             $d = Linker::linkKnown($page, htmlspecialchars($date), ['class' => 'mw-changeslist-date'], ['oldid' => intval($row->rev_id)]);
         } else {
             $d = htmlspecialchars($date);
         }
         if ($rev->isDeleted(Revision::DELETED_TEXT)) {
             $d = '<span class="history-deleted">' . $d . '</span>';
         }
         # Show user names for /newbies as there may be different users.
         # Note that we already excluded rows with hidden user names.
         if ($this->contribs == 'newbie') {
             $userlink = ' . . ' . $lang->getDirMark() . Linker::userLink($rev->getUser(), $rev->getUserText());
             $userlink .= ' ' . $this->msg('parentheses')->rawParams(Linker::userTalkLink($rev->getUser(), $rev->getUserText()))->escaped() . ' ';
         } else {
             $userlink = '';
         }
         $flags = [];
         if ($rev->getParentId() === 0) {
             $flags[] = ChangesList::flag('newpage');
         }
         if ($rev->isMinor()) {
             $flags[] = ChangesList::flag('minor');
         }
         $del = Linker::getRevDeleteLink($user, $rev, $page);
         if ($del !== '') {
             $del .= ' ';
         }
         $diffHistLinks = $this->msg('parentheses')->rawParams($difftext . $this->messages['pipe-separator'] . $histlink)->escaped();
         # Tags, if any.
         list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow($row->ts_tags, 'contributions', $this->getContext());
         $classes = array_merge($classes, $newClasses);
         Hooks::run('SpecialContributions::formatRow::flags', [$this->getContext(), $row, &$flags]);
         $templateParams = ['del' => $del, 'timestamp' => $d, 'diffHistLinks' => $diffHistLinks, 'charDifference' => $chardiff, 'flags' => $flags, 'articleLink' => $link, 'userlink' => $userlink, 'logText' => $comment, 'topmarktext' => $topmarktext, 'tagSummary' => $tagSummary];
         # Denote if username is redacted for this edit
         if ($rev->isDeleted(Revision::DELETED_USER)) {
             $templateParams['rev-deleted-user-contribs'] = $this->msg('rev-deleted-user-contribs')->escaped();
         }
         $templateParser = new TemplateParser();
         $ret = $templateParser->processTemplate('SpecialContributionsLine', $templateParams);
     }
     // Let extensions add data
     Hooks::run('ContributionsLineEnding', [$this, &$ret, $row, &$classes]);
     // TODO: Handle exceptions in the catch block above.  Do any extensions rely on
     // receiving empty rows?
     if ($classes === [] && $ret === '') {
         wfDebug("Dropping Special:Contribution row that could not be formatted\n");
         return "<!-- Could not format Special:Contribution row. -->\n";
     }
     // FIXME: The signature of the ContributionsLineEnding hook makes it
     // very awkward to move this LI wrapper into the template.
     return Html::rawElement('li', ['class' => $classes], $ret) . "\n";
 }
Example #10
0
 private function formatRevisionRow($row, $earliestLiveTime, $remaining)
 {
     $rev = Revision::newFromArchiveRow($row, array('page' => $this->mTargetObj->getArticleId()));
     $stxt = '';
     $ts = wfTimestamp(TS_MW, $row->ar_timestamp);
     // Build checkboxen...
     if ($this->mAllowed) {
         if ($this->mInvert) {
             if (in_array($ts, $this->mTargetTimestamp)) {
                 $checkBox = Xml::check("ts{$ts}");
             } else {
                 $checkBox = Xml::check("ts{$ts}", true);
             }
         } else {
             $checkBox = Xml::check("ts{$ts}");
         }
     } else {
         $checkBox = '';
     }
     $user = $this->getUser();
     // Build page & diff links...
     if ($this->mCanView) {
         $titleObj = $this->getTitle();
         # Last link
         if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
             $pageLink = htmlspecialchars($this->getLanguage()->userTimeAndDate($ts, $user));
             $last = $this->msg('diff')->escaped();
         } elseif ($remaining > 0 || $earliestLiveTime && $ts > $earliestLiveTime) {
             $pageLink = $this->getPageLink($rev, $titleObj, $ts);
             $last = Linker::linkKnown($titleObj, $this->msg('diff')->escaped(), array(), array('target' => $this->mTargetObj->getPrefixedText(), 'timestamp' => $ts, 'diff' => 'prev'));
         } else {
             $pageLink = $this->getPageLink($rev, $titleObj, $ts);
             $last = $this->msg('diff')->escaped();
         }
     } else {
         $pageLink = htmlspecialchars($this->getLanguage()->userTimeAndDate($ts, $user));
         $last = $this->msg('diff')->escaped();
     }
     // User links
     $userLink = Linker::revUserTools($rev);
     // Revision text size
     $size = $row->ar_len;
     if (!is_null($size)) {
         $stxt = Linker::formatRevisionSize($size);
     }
     // Edit summary
     $comment = Linker::revComment($rev);
     // Revision delete links
     $revdlink = Linker::getRevDeleteLink($user, $rev, $this->mTargetObj);
     return "<li>{$checkBox} {$revdlink} ({$last}) {$pageLink} . . {$userLink} {$stxt} {$comment}</li>";
 }
Example #11
0
 function formatRevisionRow($row)
 {
     $rev = new Revision($row);
     $stxt = '';
     $last = $this->message['last'];
     $ts = wfTimestamp(TS_MW, $row->rev_timestamp);
     $checkBox = Xml::radio('mergepoint', $ts, false);
     $pageLink = Linker::linkKnown($rev->getTitle(), htmlspecialchars($this->getLanguage()->timeanddate($ts)), array(), array('oldid' => $rev->getId()));
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
     }
     # Last link
     if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
         $last = $this->message['last'];
     } elseif (isset($this->prevId[$row->rev_id])) {
         $last = Linker::linkKnown($rev->getTitle(), $this->message['last'], array(), array('diff' => $row->rev_id, 'oldid' => $this->prevId[$row->rev_id]));
     }
     $userLink = Linker::revUserTools($rev);
     $size = $row->rev_len;
     if (!is_null($size)) {
         $stxt = Linker::formatRevisionSize($size);
     }
     $comment = Linker::revComment($rev);
     return "<li>{$checkBox} ({$last}) {$pageLink} . . {$userLink} {$stxt} {$comment}</li>";
 }
 /**
  * Callback function to output a restriction
  * @param $row object Protected title
  * @return string Formatted <li> element
  */
 public function formatRow($row)
 {
     wfProfileIn(__METHOD__);
     static $infinity = null;
     if (is_null($infinity)) {
         $infinity = wfGetDB(DB_SLAVE)->getInfinity();
     }
     $title = Title::makeTitleSafe($row->page_namespace, $row->page_title);
     $link = Linker::link($title);
     $description_items = array();
     $protType = wfMsgHtml('restriction-level-' . $row->pr_level);
     $description_items[] = $protType;
     if ($row->pr_cascade) {
         $description_items[] = wfMsg('protect-summary-cascade');
     }
     $stxt = '';
     $lang = $this->getLanguage();
     $expiry = $lang->formatExpiry($row->pr_expiry, TS_MW);
     if ($expiry != $infinity) {
         $expiry_description = wfMsg('protect-expiring-local', $lang->timeanddate($expiry, true), $lang->date($expiry, true), $lang->time($expiry, true));
         $description_items[] = htmlspecialchars($expiry_description);
     }
     if (!is_null($size = $row->page_len)) {
         $stxt = $lang->getDirMark() . ' ' . Linker::formatRevisionSize($size);
     }
     # Show a link to the change protection form for allowed users otherwise a link to the protection log
     if ($this->getUser()->isAllowed('protect')) {
         $changeProtection = ' (' . Linker::linkKnown($title, wfMsgHtml('protect_change'), array(), array('action' => 'unprotect')) . ')';
     } else {
         $ltitle = SpecialPage::getTitleFor('Log');
         $changeProtection = ' (' . Linker::linkKnown($ltitle, wfMsgHtml('protectlogpage'), array(), array('type' => 'protect', 'page' => $title->getPrefixedText())) . ')';
     }
     wfProfileOut(__METHOD__);
     return Html::rawElement('li', array(), $lang->specialList($link . $stxt, $lang->commaList($description_items), false) . $changeProtection) . "\n";
 }