/**
  * Render the header of a diff page including:
  * Name with url to page
  * Bytes added/removed
  * Day and time of edit
  * Edit Comment
  */
 function showHeader()
 {
     $title = $this->targetTitle;
     if ($this->prevRev) {
         $bytesChanged = $this->rev->getSize() - $this->prevRev->getSize();
     } else {
         $bytesChanged = $this->rev->getSize();
     }
     if ($bytesChanged > 0) {
         $changeMsg = 'mobile-frontend-diffview-bytesadded';
         $sizeClass = MobileUI::iconClass('bytesadded', 'before', 'icon-12px meta mw-mf-bytesadded');
     } elseif ($bytesChanged === 0) {
         $changeMsg = 'mobile-frontend-diffview-bytesnochange';
         $sizeClass = MobileUI::iconClass('bytesneutral', 'before', 'icon-12px meta mw-mf-bytesneutral');
     } else {
         $changeMsg = 'mobile-frontend-diffview-bytesremoved';
         $sizeClass = MobileUI::iconClass('bytesremoved', 'before', 'icon-12px meta mw-mf-bytesremoved');
         $bytesChanged = abs($bytesChanged);
     }
     if ($this->rev->isMinor()) {
         $minor = ChangesList::flag('minor');
     } else {
         $minor = '';
     }
     if ($this->rev->getComment() !== '') {
         $comment = Linker::formatComment($this->rev->getComment(), $title);
     } else {
         $comment = $this->msg('mobile-frontend-changeslist-nocomment')->escaped();
     }
     $ts = new MWTimestamp($this->rev->getTimestamp());
     $this->getOutput()->addHtml(Html::openElement('div', array('id' => 'mw-mf-diff-info', 'class' => 'page-summary')) . Html::openElement('h2', array()) . Html::element('a', array('href' => $title->getLocalURL()), $title->getPrefixedText()) . Html::closeElement('h2') . $this->msg('mobile-frontend-diffview-comma')->rawParams(Html::element('span', array('class' => $sizeClass), $this->msg($changeMsg)->numParams($bytesChanged)->text()), Html::element('span', array('class' => 'mw-mf-diff-date meta'), $ts->getHumanTimestamp()))->text() . Html::closeElement('div') . $minor . Html::rawElement('div', array('id' => 'mw-mf-diff-comment'), $comment));
 }
 /**
  * Get the HTML link to the revision text.
  * Overridden by RevDelArchiveItem.
  * @return string
  */
 protected function getRevisionLink()
 {
     $date = htmlspecialchars($this->list->getLanguage()->userTimeAndDate($this->revision->getTimestamp(), $this->list->getUser()));
     if ($this->isDeleted() && !$this->canViewContent()) {
         return $date;
     }
     return Linker::linkKnown($this->list->title, $date, array(), array('oldid' => $this->revision->getId(), 'unhide' => 1));
 }
 protected function assertRevEquals(Revision $orig, Revision $rev = null)
 {
     $this->assertNotNull($rev, 'missing revision');
     $this->assertEquals($orig->getId(), $rev->getId());
     $this->assertEquals($orig->getPage(), $rev->getPage());
     $this->assertEquals($orig->getTimestamp(), $rev->getTimestamp());
     $this->assertEquals($orig->getUser(), $rev->getUser());
     $this->assertEquals($orig->getSha1(), $rev->getSha1());
 }
Esempio n. 4
0
 /**
  * @return String: timestamp
  */
 function getTimestamp()
 {
     if ($this->mRevision) {
         return $this->mRevision->getTimestamp();
     } elseif ($this->mImage) {
         return $this->mImage->getTimestamp();
     }
     return '';
 }
 /**
  * @param Title $pageTitle Title instance of the categorized page
  * @param Revision $revision Latest Revision instance of the categorized page
  *
  * @throws MWException
  */
 public function __construct(Title $pageTitle, Revision $revision = null)
 {
     $this->pageTitle = $pageTitle;
     if ($revision === null) {
         $this->timestamp = wfTimestampNow();
     } else {
         $this->timestamp = $revision->getTimestamp();
     }
     $this->revision = $revision;
     $this->newForCategorizationCallback = ['RecentChange', 'newForCategorization'];
 }
Esempio n. 6
0
 /**
  * Update the revision's recentchanges record if fields have been hidden
  * @param Revision $rev
  * @param int $bitfield new rev_deleted bitfield value
  */
 function updateRecentChangesEdits($rev, $bitfield)
 {
     $this->dbw->update('recentchanges', array('rc_deleted' => $bitfield, 'rc_patrolled' => 1), array('rc_this_oldid' => $rev->getId(), 'rc_timestamp' => $this->dbw->timestamp($rev->getTimestamp())), __METHOD__);
 }
Esempio n. 7
0
 private function extractRowInfo($row)
 {
     $revision = new Revision($row);
     $title = $revision->getTitle();
     $vals = array();
     if ($this->fld_ids) {
         $vals['revid'] = intval($revision->getId());
         // $vals['oldid'] = intval( $row->rev_text_id ); // todo: should this be exposed?
         if (!is_null($revision->getParentId())) {
             $vals['parentid'] = intval($revision->getParentId());
         }
     }
     if ($this->fld_flags && $revision->isMinor()) {
         $vals['minor'] = '';
     }
     if ($this->fld_user || $this->fld_userid) {
         if ($revision->isDeleted(Revision::DELETED_USER)) {
             $vals['userhidden'] = '';
         } else {
             if ($this->fld_user) {
                 $vals['user'] = $revision->getUserText();
             }
             $userid = $revision->getUser();
             if (!$userid) {
                 $vals['anon'] = '';
             }
             if ($this->fld_userid) {
                 $vals['userid'] = $userid;
             }
         }
     }
     if ($this->fld_timestamp) {
         $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $revision->getTimestamp());
     }
     if ($this->fld_size) {
         if (!is_null($revision->getSize())) {
             $vals['size'] = intval($revision->getSize());
         } else {
             $vals['size'] = 0;
         }
     }
     if ($this->fld_sha1) {
         if ($revision->getSha1() != '') {
             $vals['sha1'] = wfBaseConvert($revision->getSha1(), 36, 16, 40);
         } else {
             $vals['sha1'] = '';
         }
     }
     if ($this->fld_comment || $this->fld_parsedcomment) {
         if ($revision->isDeleted(Revision::DELETED_COMMENT)) {
             $vals['commenthidden'] = '';
         } else {
             $comment = $revision->getComment();
             if ($this->fld_comment) {
                 $vals['comment'] = $comment;
             }
             if ($this->fld_parsedcomment) {
                 $vals['parsedcomment'] = Linker::formatComment($comment, $title);
             }
         }
     }
     if ($this->fld_tags) {
         if ($row->ts_tags) {
             $tags = explode(',', $row->ts_tags);
             $this->getResult()->setIndexedTagName($tags, 'tag');
             $vals['tags'] = $tags;
         } else {
             $vals['tags'] = array();
         }
     }
     if (!is_null($this->token)) {
         $tokenFunctions = $this->getTokenFunctions();
         foreach ($this->token as $t) {
             $val = call_user_func($tokenFunctions[$t], $title->getArticleID(), $title, $revision);
             if ($val === false) {
                 $this->setWarning("Action '{$t}' is not allowed for the current user");
             } else {
                 $vals[$t . 'token'] = $val;
             }
         }
     }
     $text = null;
     global $wgParser;
     if ($this->fld_content || !is_null($this->difftotext)) {
         $text = $revision->getText();
         // Expand templates after getting section content because
         // template-added sections don't count and Parser::preprocess()
         // will have less input
         if ($this->section !== false) {
             $text = $wgParser->getSection($text, $this->section, false);
             if ($text === false) {
                 $this->dieUsage("There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection');
             }
         }
     }
     if ($this->fld_content && !$revision->isDeleted(Revision::DELETED_TEXT)) {
         if ($this->generateXML) {
             $wgParser->startExternalParse($title, ParserOptions::newFromContext($this->getContext()), OT_PREPROCESS);
             $dom = $wgParser->preprocessToDom($text);
             if (is_callable(array($dom, 'saveXML'))) {
                 $xml = $dom->saveXML();
             } else {
                 $xml = $dom->__toString();
             }
             $vals['parsetree'] = $xml;
         }
         if ($this->expandTemplates && !$this->parseContent) {
             $text = $wgParser->preprocess($text, $title, ParserOptions::newFromContext($this->getContext()));
         }
         if ($this->parseContent) {
             $text = $wgParser->parse($text, $title, ParserOptions::newFromContext($this->getContext()))->getText();
         }
         ApiResult::setContent($vals, $text);
     } elseif ($this->fld_content) {
         $vals['texthidden'] = '';
     }
     if (!is_null($this->diffto) || !is_null($this->difftotext)) {
         global $wgAPIMaxUncachedDiffs;
         static $n = 0;
         // Number of uncached diffs we've had
         if ($n < $wgAPIMaxUncachedDiffs) {
             $vals['diff'] = array();
             $context = new DerivativeContext($this->getContext());
             $context->setTitle($title);
             if (!is_null($this->difftotext)) {
                 $engine = new DifferenceEngine($context);
                 $engine->setText($text, $this->difftotext);
             } else {
                 $engine = new DifferenceEngine($context, $revision->getID(), $this->diffto);
                 $vals['diff']['from'] = $engine->getOldid();
                 $vals['diff']['to'] = $engine->getNewid();
             }
             $difftext = $engine->getDiffBody();
             ApiResult::setContent($vals['diff'], $difftext);
             if (!$engine->wasCacheHit()) {
                 $n++;
             }
         } else {
             $vals['diff']['notcached'] = '';
         }
     }
     return $vals;
 }
 private function getExplicitCategoriesChanges(Title $title, Revision $newRev, Revision $oldRev = null)
 {
     // Inject the same timestamp for both revision parses to avoid seeing category changes
     // due to time-based parser functions. Inject the same page title for the parses too.
     // Note that REPEATABLE-READ makes template/file pages appear unchanged between parses.
     $parseTimestamp = $newRev->getTimestamp();
     // Parse the old rev and get the categories. Do not use link tables as that
     // assumes these updates are perfectly FIFO and that link tables are always
     // up to date, neither of which are true.
     $oldCategories = $oldRev ? $this->getCategoriesAtRev($title, $oldRev, $parseTimestamp) : [];
     // Parse the new revision and get the categories
     $newCategories = $this->getCategoriesAtRev($title, $newRev, $parseTimestamp);
     $categoryInserts = array_values(array_diff($newCategories, $oldCategories));
     $categoryDeletes = array_values(array_diff($oldCategories, $newCategories));
     return [$categoryInserts, $categoryDeletes];
 }
Esempio n. 9
0
/**
 * Hook for deletion archive revision view, giving us a chance to
 * insert a removal tab for a deleted revision.
 *
 * @param $title
 * @param Revision $rev
 */
function hrUndeleteShowRevisionHook($title, $rev)
{
    hrInstallArchiveTab($title, $rev->getTimestamp());
    return true;
}
Esempio n. 10
0
 /**
  * If the given revision is newer than the currently set page_latest,
  * update the page record. Otherwise, do nothing.
  *
  * @param Database $dbw
  * @param Revision $revision
  */
 function updateIfNewerOn(&$dbw, $revision)
 {
     $fname = 'Article::updateIfNewerOn';
     wfProfileIn($fname);
     $row = $dbw->selectRow(array('revision', 'page'), array('rev_id', 'rev_timestamp'), array('page_id' => $this->getId(), 'page_latest=rev_id'), $fname);
     if ($row) {
         if ($row->rev_timestamp >= $revision->getTimestamp()) {
             wfProfileOut($fname);
             return false;
         }
         $prev = $row->rev_id;
     } else {
         # No or missing previous revision; mark the page as new
         $prev = 0;
     }
     $ret = $this->updateRevisionOn($dbw, $revision, $prev);
     wfProfileOut($fname);
     return $ret;
 }
Esempio n. 11
0
 /**
  * Get a header for a specified revision.
  *
  * @param Revision $rev
  * @param string $complete 'complete' to get the header wrapped depending
  *        the visibility of the revision and a link to edit the page.
  *
  * @return string HTML fragment
  */
 protected function getRevisionHeader(Revision $rev, $complete = '')
 {
     $lang = $this->getLanguage();
     $user = $this->getUser();
     $revtimestamp = $rev->getTimestamp();
     $timestamp = $lang->userTimeAndDate($revtimestamp, $user);
     $dateofrev = $lang->userDate($revtimestamp, $user);
     $timeofrev = $lang->userTime($revtimestamp, $user);
     $header = $this->msg($rev->isCurrent() ? 'currentrev-asof' : 'revisionasof', $timestamp, $dateofrev, $timeofrev)->escaped();
     if ($complete !== 'complete') {
         return $header;
     }
     $title = $rev->getTitle();
     $header = Linker::linkKnown($title, $header, array(), array('oldid' => $rev->getID()));
     if ($rev->userCan(Revision::DELETED_TEXT, $user)) {
         $editQuery = array('action' => 'edit');
         if (!$rev->isCurrent()) {
             $editQuery['oldid'] = $rev->getID();
         }
         $key = $title->quickUserCan('edit', $user) ? 'editold' : 'viewsourceold';
         $msg = $this->msg($key)->escaped();
         $editLink = $this->msg('parentheses')->rawParams(Linker::linkKnown($title, $msg, array(), $editQuery))->escaped();
         $header .= ' ' . Html::rawElement('span', array('class' => 'mw-diff-edit'), $editLink);
         if ($rev->isDeleted(Revision::DELETED_TEXT)) {
             $header = Html::rawElement('span', array('class' => 'history-deleted'), $header);
         }
     } else {
         $header = Html::rawElement('span', array('class' => 'history-deleted'), $header);
     }
     return $header;
 }
Esempio n. 12
0
 /**
  * If patrol is possible, output a patrol UI box. This is called from the
  * footer section of ordinary page views. If patrol is not possible or not
  * desired, does nothing.
  * Side effect: When the patrol link is build, this method will call
  * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
  *
  * @return bool
  */
 public function showPatrolFooter()
 {
     global $wgUseNPPatrol, $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $outputPage = $this->getContext()->getOutput();
     $user = $this->getContext()->getUser();
     $cache = wfGetMainCache();
     $rc = false;
     if (!$this->getTitle()->quickUserCan('patrol', $user) || !($wgUseRCPatrol || $wgUseNPPatrol)) {
         // Patrolling is disabled or the user isn't allowed to
         return false;
     }
     wfProfileIn(__METHOD__);
     // New page patrol: Get the timestamp of the oldest revison which
     // the revision table holds for the given page. Then we look
     // whether it's within the RC lifespan and if it is, we try
     // to get the recentchanges row belonging to that entry
     // (with rc_new = 1).
     // Check for cached results
     if ($cache->get(wfMemcKey('NotPatrollablePage', $this->getTitle()->getArticleID()))) {
         wfProfileOut(__METHOD__);
         return false;
     }
     if ($this->mRevision && !RecentChange::isInRCLifespan($this->mRevision->getTimestamp(), 21600)) {
         // The current revision is already older than what could be in the RC table
         // 6h tolerance because the RC might not be cleaned out regularly
         wfProfileOut(__METHOD__);
         return false;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $oldestRevisionTimestamp = $dbr->selectField('revision', 'MIN( rev_timestamp )', array('rev_page' => $this->getTitle()->getArticleID()), __METHOD__);
     if ($oldestRevisionTimestamp && RecentChange::isInRCLifespan($oldestRevisionTimestamp, 21600)) {
         // 6h tolerance because the RC might not be cleaned out regularly
         $rc = RecentChange::newFromConds(array('rc_new' => 1, 'rc_timestamp' => $oldestRevisionTimestamp, 'rc_namespace' => $this->getTitle()->getNamespace(), 'rc_cur_id' => $this->getTitle()->getArticleID(), 'rc_patrolled' => 0), __METHOD__, array('USE INDEX' => 'new_name_timestamp'));
     }
     if (!$rc) {
         // No RC entry around
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set(wfMemcKey('NotPatrollablePage', $this->getTitle()->getArticleID()), '1');
         wfProfileOut(__METHOD__);
         return false;
     }
     if ($rc->getPerformer()->getName() == $user->getName()) {
         // Don't show a patrol link for own creations. If the user could
         // patrol them, they already would be patrolled
         wfProfileOut(__METHOD__);
         return false;
     }
     $rcid = $rc->getAttribute('rc_id');
     $token = $user->getEditToken($rcid);
     $outputPage->preventClickjacking();
     if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
         $outputPage->addModules('mediawiki.page.patrol.ajax');
     }
     $link = Linker::linkKnown($this->getTitle(), wfMessage('markaspatrolledtext')->escaped(), array('class' => 'mw-patrollink'), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token));
     $outputPage->addHTML("<div class='patrollink'>" . wfMessage('markaspatrolledlink')->rawParams($link)->escaped() . '</div>');
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Create a link to view this revision of the page
  *
  * @param Revision $rev
  * @return string
  */
 function revLink($rev)
 {
     $date = $this->getLanguage()->userTimeAndDate($rev->getTimestamp(), $this->getUser());
     $date = htmlspecialchars($date);
     if ($rev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
         $link = Linker::linkKnown($this->getTitle(), $date, array('class' => 'mw-changeslist-date'), array('oldid' => $rev->getId()));
     } else {
         $link = $date;
     }
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $link = "<span class=\"history-deleted\">{$link}</span>";
     }
     return $link;
 }
 protected static function getDiffRevMsgAndClass(Revision $rev, FlaggedRevision $srev = null)
 {
     $tier = FlaggedRevision::getRevQuality($rev->getId());
     if ($tier !== false) {
         $msg = $tier ? 'revreview-hist-quality' : 'revreview-hist-basic';
     } else {
         $msg = $srev && $rev->getTimestamp() > $srev->getRevTimestamp() ? 'revreview-hist-pending' : 'revreview-hist-draft';
     }
     $css = FlaggedRevsXML::getQualityColor($tier);
     return array($msg, $css);
 }
 /**
  * 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 sysop
  * 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.
  */
 function formatRow($row)
 {
     global $wgUser, $wgLang;
     wfProfileIn(__METHOD__);
     $sk = $this->getSkin();
     $rev = new Revision(array('id' => $row->ar_rev_id, 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'deleted' => $row->ar_deleted));
     $page = Title::makeTitle($row->ar_namespace, $row->ar_title);
     $undelete = SpecialPage::getTitleFor('Undelete');
     $logs = SpecialPage::getTitleFor('Log');
     $dellog = $sk->linkKnown($logs, $this->messages['deletionlog'], array(), array('type' => 'delete', 'page' => $page->getPrefixedText()));
     $reviewlink = $sk->linkKnown(SpecialPage::getTitleFor('Undelete', $page->getPrefixedDBkey()), $this->messages['undeleteviewlink']);
     if ($wgUser->isAllowed('deletedtext')) {
         $last = $sk->linkKnown($undelete, $this->messages['diff'], array(), array('target' => $page->getPrefixedText(), 'timestamp' => $rev->getTimestamp(), 'diff' => 'prev'));
     } else {
         $last = $this->messages['diff'];
     }
     $comment = $sk->revComment($rev);
     $date = htmlspecialchars($wgLang->timeanddate($rev->getTimestamp(), true));
     if (!$wgUser->isAllowed('undelete') || !$rev->userCan(Revision::DELETED_TEXT)) {
         $link = $date;
         // unusable link
     } else {
         $link = $sk->linkKnown($undelete, $date, array(), array('target' => $page->getPrefixedText(), 'timestamp' => $rev->getTimestamp()));
     }
     // Style deleted items
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $link = '<span class="history-deleted">' . $link . '</span>';
     }
     $pagelink = $sk->link($page);
     if ($rev->isMinor()) {
         $mflag = ChangesList::flag('minor');
     } else {
         $mflag = '';
     }
     // Revision delete link
     $canHide = $wgUser->isAllowed('deleterevision');
     if ($canHide || $rev->getVisibility() && $wgUser->isAllowed('deletedhistory')) {
         if (!$rev->userCan(Revision::DELETED_RESTRICTED)) {
             $del = $this->mSkin->revDeleteLinkDisabled($canHide);
             // revision was hidden from sysops
         } else {
             $query = array('type' => 'archive', 'target' => $page->getPrefixedDbkey(), 'ids' => $rev->getTimestamp());
             $del = $this->mSkin->revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), $canHide) . ' ';
         }
     } else {
         $del = '';
     }
     $tools = Html::rawElement('span', array('class' => 'mw-deletedcontribs-tools'), wfMsg('parentheses', $wgLang->pipeList(array($last, $dellog, $reviewlink))));
     $ret = "{$del}{$link} {$tools} . . {$mflag} {$pagelink} {$comment}";
     # Denote if username is redacted for this edit
     if ($rev->isDeleted(Revision::DELETED_USER)) {
         $ret .= " <strong>" . wfMsgHtml('rev-deleted-user-contribs') . "</strong>";
     }
     $ret = Html::rawElement('li', array(), $ret) . "\n";
     wfProfileOut(__METHOD__);
     return $ret;
 }
 /**
  * @param Revision $rev
  * @returns string
  */
 function historyLine($rev)
 {
     global $wgContLang;
     $date = $wgContLang->timeanddate($rev->getTimestamp());
     return "<li>" . $this->skin->makeLinkObj($this->page, $date, 'oldid=' . $rev->getId()) . " " . $this->skin->revUserLink($rev) . " " . $this->skin->revComment($rev) . "</li>";
 }
 /**
  * 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 sysop
  * 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.
  */
 function formatRow($row)
 {
     wfProfileIn(__METHOD__);
     global $wgLang, $wgUser;
     $sk = $this->getSkin();
     $rev = new Revision(array('id' => $row->ar_rev_id, 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'rev_deleted' => $row->ar_deleted));
     $page = Title::makeTitle($row->ar_namespace, $row->ar_title);
     $undelete = SpecialPage::getTitleFor('Undelete');
     $logs = SpecialPage::getTitleFor('Log');
     $dellog = $sk->makeKnownLinkObj($logs, $this->messages['deletionlog'], 'type=delete&page=' . $page->getPrefixedUrl());
     $reviewlink = $sk->makeKnownLinkObj(SpecialPage::getTitleFor('Undelete', $page->getPrefixedDBkey()), $this->messages['undeletebtn']);
     $link = $sk->makeKnownLinkObj($undelete, htmlspecialchars($page->getPrefixedText()), 'target=' . $page->getPrefixedUrl() . '&timestamp=' . $rev->getTimestamp());
     $last = $sk->makeKnownLinkObj($undelete, $this->messages['diff'], "target=" . $page->getPrefixedUrl() . "&timestamp=" . $rev->getTimestamp() . "&diff=prev");
     $comment = $sk->revComment($rev);
     $d = $wgLang->timeanddate($rev->getTimestamp(), true);
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $d = '<span class="history-deleted">' . $d . '</span>';
     } else {
         $link = $sk->makeKnownLinkObj($undelete, $d, 'target=' . $page->getPrefixedUrl() . '&timestamp=' . $rev->getTimestamp());
     }
     $pagelink = $sk->makeLinkObj($page);
     if ($rev->isMinor()) {
         $mflag = '<span class="minor">' . $this->messages['minoreditletter'] . '</span> ';
     } else {
         $mflag = '';
     }
     $ret = "{$link} ({$last}) ({$dellog}) ({$reviewlink}) . . {$mflag} {$pagelink} {$comment}";
     if ($rev->isDeleted(Revision::DELETED_TEXT)) {
         $ret .= ' ' . wfMsgHtml('deletedrev');
     }
     $ret = "<li>{$ret}</li>\n";
     wfProfileOut(__METHOD__);
     return $ret;
 }
Esempio n. 18
0
 /**
  * @param Revision $rev
  * @param string $prefix
  * @return string
  */
 private function diffHeader($rev, $prefix)
 {
     $isDeleted = !($rev->getId() && $rev->getTitle());
     if ($isDeleted) {
         /// @todo FIXME: $rev->getTitle() is null for deleted revs...?
         $targetPage = $this->getTitle();
         $targetQuery = array('target' => $this->mTargetObj->getPrefixedText(), 'timestamp' => wfTimestamp(TS_MW, $rev->getTimestamp()));
     } else {
         /// @todo FIXME: getId() may return non-zero for deleted revs...
         $targetPage = $rev->getTitle();
         $targetQuery = array('oldid' => $rev->getId());
     }
     // Add show/hide deletion links if available
     $user = $this->getUser();
     $lang = $this->getLanguage();
     $rdel = Linker::getRevDeleteLink($user, $rev, $this->mTargetObj);
     if ($rdel) {
         $rdel = " {$rdel}";
     }
     return '<div id="mw-diff-' . $prefix . 'title1"><strong>' . Linker::link($targetPage, $this->msg('revisionasof', $lang->userTimeAndDate($rev->getTimestamp(), $user), $lang->userDate($rev->getTimestamp(), $user), $lang->userTime($rev->getTimestamp(), $user))->escaped(), array(), $targetQuery) . '</strong></div>' . '<div id="mw-diff-' . $prefix . 'title2">' . Linker::revUserTools($rev) . '<br />' . '</div>' . '<div id="mw-diff-' . $prefix . 'title3">' . Linker::revComment($rev) . $rdel . '<br />' . '</div>';
 }
Esempio n. 19
0
 /**
  * Get a revision-deletion link, or disabled link, or nothing, depending
  * on user permissions & the settings on the revision.
  *
  * Will use forward-compatible revision ID in the Special:RevDelete link
  * if possible, otherwise the timestamp-based ID which may break after
  * undeletion.
  *
  * @param User $user
  * @param Revision $rev
  * @param Revision $title
  * @return string HTML fragment
  */
 public static function getRevDeleteLink(User $user, Revision $rev, Title $title)
 {
     $canHide = $user->isAllowed('deleterevision');
     if (!$canHide && !($rev->getVisibility() && $user->isAllowed('deletedhistory'))) {
         return '';
     }
     if (!$rev->userCan(Revision::DELETED_RESTRICTED, $user)) {
         return Linker::revDeleteLinkDisabled($canHide);
         // revision was hidden from sysops
     } else {
         if ($rev->getId()) {
             // RevDelete links using revision ID are stable across
             // page deletion and undeletion; use when possible.
             $query = array('type' => 'revision', 'target' => $title->getPrefixedDBkey(), 'ids' => $rev->getId());
         } else {
             // Older deleted entries didn't save a revision ID.
             // We have to refer to these by timestamp, ick!
             $query = array('type' => 'archive', 'target' => $title->getPrefixedDBkey(), 'ids' => $rev->getTimestamp());
         }
         return Linker::revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), $canHide);
     }
 }
Esempio n. 20
0
 /**
  * @param Revision $rev
  * @param string $prefix
  * @return string
  */
 private function diffHeader($rev, $prefix)
 {
     $isDeleted = !($rev->getId() && $rev->getTitle());
     if ($isDeleted) {
         /// @todo FIXME: $rev->getTitle() is null for deleted revs...?
         $targetPage = $this->getPageTitle();
         $targetQuery = array('target' => $this->mTargetObj->getPrefixedText(), 'timestamp' => wfTimestamp(TS_MW, $rev->getTimestamp()));
     } else {
         /// @todo FIXME: getId() may return non-zero for deleted revs...
         $targetPage = $rev->getTitle();
         $targetQuery = array('oldid' => $rev->getId());
     }
     // Add show/hide deletion links if available
     $user = $this->getUser();
     $lang = $this->getLanguage();
     $rdel = Linker::getRevDeleteLink($user, $rev, $this->mTargetObj);
     if ($rdel) {
         $rdel = " {$rdel}";
     }
     $minor = $rev->isMinor() ? ChangesList::flag('minor') : '';
     $tags = wfGetDB(DB_SLAVE)->selectField('tag_summary', 'ts_tags', array('ts_rev_id' => $rev->getId()), __METHOD__);
     $tagSummary = ChangeTags::formatSummaryRow($tags, 'deleteddiff');
     // FIXME This is reimplementing DifferenceEngine#getRevisionHeader
     // and partially #showDiffPage, but worse
     return '<div id="mw-diff-' . $prefix . 'title1"><strong>' . Linker::link($targetPage, $this->msg('revisionasof', $lang->userTimeAndDate($rev->getTimestamp(), $user), $lang->userDate($rev->getTimestamp(), $user), $lang->userTime($rev->getTimestamp(), $user))->escaped(), array(), $targetQuery) . '</strong></div>' . '<div id="mw-diff-' . $prefix . 'title2">' . Linker::revUserTools($rev) . '<br />' . '</div>' . '<div id="mw-diff-' . $prefix . 'title3">' . $minor . Linker::revComment($rev) . $rdel . '<br />' . '</div>' . '<div id="mw-diff-' . $prefix . 'title5">' . $tagSummary[0] . '<br />' . '</div>';
 }
 /**
  * Extract information from the Revision
  *
  * @param Revision $revision
  * @param object $row Should have a field 'ts_tags' if $this->fld_tags is set
  * @return array
  */
 protected function extractRevisionInfo(Revision $revision, $row)
 {
     $title = $revision->getTitle();
     $user = $this->getUser();
     $vals = array();
     $anyHidden = false;
     if ($this->fld_ids) {
         $vals['revid'] = intval($revision->getId());
         if (!is_null($revision->getParentId())) {
             $vals['parentid'] = intval($revision->getParentId());
         }
     }
     if ($this->fld_flags) {
         $vals['minor'] = $revision->isMinor();
     }
     if ($this->fld_user || $this->fld_userid) {
         if ($revision->isDeleted(Revision::DELETED_USER)) {
             $vals['userhidden'] = true;
             $anyHidden = true;
         }
         if ($revision->userCan(Revision::DELETED_USER, $user)) {
             if ($this->fld_user) {
                 $vals['user'] = $revision->getUserText(Revision::RAW);
             }
             $userid = $revision->getUser(Revision::RAW);
             if (!$userid) {
                 $vals['anon'] = true;
             }
             if ($this->fld_userid) {
                 $vals['userid'] = $userid;
             }
         }
     }
     if ($this->fld_timestamp) {
         $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $revision->getTimestamp());
     }
     if ($this->fld_size) {
         if (!is_null($revision->getSize())) {
             $vals['size'] = intval($revision->getSize());
         } else {
             $vals['size'] = 0;
         }
     }
     if ($this->fld_sha1) {
         if ($revision->isDeleted(Revision::DELETED_TEXT)) {
             $vals['sha1hidden'] = true;
             $anyHidden = true;
         }
         if ($revision->userCan(Revision::DELETED_TEXT, $user)) {
             if ($revision->getSha1() != '') {
                 $vals['sha1'] = wfBaseConvert($revision->getSha1(), 36, 16, 40);
             } else {
                 $vals['sha1'] = '';
             }
         }
     }
     if ($this->fld_contentmodel) {
         $vals['contentmodel'] = $revision->getContentModel();
     }
     if ($this->fld_comment || $this->fld_parsedcomment) {
         if ($revision->isDeleted(Revision::DELETED_COMMENT)) {
             $vals['commenthidden'] = true;
             $anyHidden = true;
         }
         if ($revision->userCan(Revision::DELETED_COMMENT, $user)) {
             $comment = $revision->getComment(Revision::RAW);
             if ($this->fld_comment) {
                 $vals['comment'] = $comment;
             }
             if ($this->fld_parsedcomment) {
                 $vals['parsedcomment'] = Linker::formatComment($comment, $title);
             }
         }
     }
     if ($this->fld_tags) {
         if ($row->ts_tags) {
             $tags = explode(',', $row->ts_tags);
             ApiResult::setIndexedTagName($tags, 'tag');
             $vals['tags'] = $tags;
         } else {
             $vals['tags'] = array();
         }
     }
     $content = null;
     global $wgParser;
     if ($this->fetchContent) {
         $content = $revision->getContent(Revision::FOR_THIS_USER, $this->getUser());
         // Expand templates after getting section content because
         // template-added sections don't count and Parser::preprocess()
         // will have less input
         if ($content && $this->section !== false) {
             $content = $content->getSection($this->section, false);
             if (!$content) {
                 $this->dieUsage("There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection');
             }
         }
         if ($revision->isDeleted(Revision::DELETED_TEXT)) {
             $vals['texthidden'] = true;
             $anyHidden = true;
         } elseif (!$content) {
             $vals['textmissing'] = true;
         }
     }
     if ($this->fld_content && $content) {
         $text = null;
         if ($this->generateXML) {
             if ($content->getModel() === CONTENT_MODEL_WIKITEXT) {
                 $t = $content->getNativeData();
                 # note: don't set $text
                 $wgParser->startExternalParse($title, ParserOptions::newFromContext($this->getContext()), Parser::OT_PREPROCESS);
                 $dom = $wgParser->preprocessToDom($t);
                 if (is_callable(array($dom, 'saveXML'))) {
                     $xml = $dom->saveXML();
                 } else {
                     $xml = $dom->__toString();
                 }
                 $vals['parsetree'] = $xml;
             } else {
                 $vals['badcontentformatforparsetree'] = true;
                 $this->setWarning("Conversion to XML is supported for wikitext only, " . $title->getPrefixedDBkey() . " uses content model " . $content->getModel());
             }
         }
         if ($this->expandTemplates && !$this->parseContent) {
             #XXX: implement template expansion for all content types in ContentHandler?
             if ($content->getModel() === CONTENT_MODEL_WIKITEXT) {
                 $text = $content->getNativeData();
                 $text = $wgParser->preprocess($text, $title, ParserOptions::newFromContext($this->getContext()));
             } else {
                 $this->setWarning("Template expansion is supported for wikitext only, " . $title->getPrefixedDBkey() . " uses content model " . $content->getModel());
                 $vals['badcontentformat'] = true;
                 $text = false;
             }
         }
         if ($this->parseContent) {
             $po = $content->getParserOutput($title, $revision->getId(), ParserOptions::newFromContext($this->getContext()));
             $text = $po->getText();
         }
         if ($text === null) {
             $format = $this->contentFormat ? $this->contentFormat : $content->getDefaultFormat();
             $model = $content->getModel();
             if (!$content->isSupportedFormat($format)) {
                 $name = $title->getPrefixedDBkey();
                 $this->setWarning("The requested format {$this->contentFormat} is not " . "supported for content model {$model} used by {$name}");
                 $vals['badcontentformat'] = true;
                 $text = false;
             } else {
                 $text = $content->serialize($format);
                 // always include format and model.
                 // Format is needed to deserialize, model is needed to interpret.
                 $vals['contentformat'] = $format;
                 $vals['contentmodel'] = $model;
             }
         }
         if ($text !== false) {
             ApiResult::setContentValue($vals, 'content', $text);
         }
     }
     if ($content && (!is_null($this->diffto) || !is_null($this->difftotext))) {
         static $n = 0;
         // Number of uncached diffs we've had
         if ($n < $this->getConfig()->get('APIMaxUncachedDiffs')) {
             $vals['diff'] = array();
             $context = new DerivativeContext($this->getContext());
             $context->setTitle($title);
             $handler = $revision->getContentHandler();
             if (!is_null($this->difftotext)) {
                 $model = $title->getContentModel();
                 if ($this->contentFormat && !ContentHandler::getForModelID($model)->isSupportedFormat($this->contentFormat)) {
                     $name = $title->getPrefixedDBkey();
                     $this->setWarning("The requested format {$this->contentFormat} is not " . "supported for content model {$model} used by {$name}");
                     $vals['diff']['badcontentformat'] = true;
                     $engine = null;
                 } else {
                     $difftocontent = ContentHandler::makeContent($this->difftotext, $title, $model, $this->contentFormat);
                     $engine = $handler->createDifferenceEngine($context);
                     $engine->setContent($content, $difftocontent);
                 }
             } else {
                 $engine = $handler->createDifferenceEngine($context, $revision->getID(), $this->diffto);
                 $vals['diff']['from'] = $engine->getOldid();
                 $vals['diff']['to'] = $engine->getNewid();
             }
             if ($engine) {
                 $difftext = $engine->getDiffBody();
                 ApiResult::setContentValue($vals['diff'], 'body', $difftext);
                 if (!$engine->wasCacheHit()) {
                     $n++;
                 }
             }
         } else {
             $vals['diff']['notcached'] = true;
         }
     }
     if ($anyHidden && $revision->isDeleted(Revision::DELETED_RESTRICTED)) {
         $vals['suppressed'] = true;
     }
     return $vals;
 }
 /**
  * Automatically review an revision and add a log entry in the review log.
  *
  * This is called during edit operations after the new revision is added
  * and the page tables updated, but before LinksUpdate is called.
  *
  * $auto is here for revisions checked off to be reviewed. Auto-review
  * triggers on edit, but we don't want those to count as just automatic.
  * This also makes it so the user's name shows up in the page history.
  *
  * If $flags is given, then they will be the review tags. If not, the one
  * from the stable version will be used or minimal tags if that's not possible.
  * If no appropriate tags can be found, then the review will abort.
  */
 public static function autoReviewEdit(WikiPage $article, $user, Revision $rev, array $flags = null, $auto = true)
 {
     wfProfileIn(__METHOD__);
     $title = $article->getTitle();
     // convenience
     # Get current stable version ID (for logging)
     $oldSv = FlaggedRevision::newFromStable($title, FR_MASTER);
     $oldSvId = $oldSv ? $oldSv->getRevId() : 0;
     # Set the auto-review tags from the prior stable version.
     # Normally, this should already be done and given here...
     if (!is_array($flags)) {
         if ($oldSv) {
             # Use the last stable version if $flags not given
             if ($user->isAllowed('bot')) {
                 $flags = $oldSv->getTags();
                 // no change for bot edits
             } else {
                 # Account for perms/tags...
                 $flags = self::getAutoReviewTags($user, $oldSv->getTags());
             }
         } else {
             // new page?
             $flags = self::quickTags(FR_CHECKED);
             // use minimal level
         }
         if (!is_array($flags)) {
             wfProfileOut(__METHOD__);
             return false;
             // can't auto-review this revision
         }
     }
     # Get review property flags
     $propFlags = $auto ? array('auto') : array();
     # Note: this needs to match the prepareContentForEdit() call WikiPage::doEditContent.
     # This is for consistency and also to avoid triggering a second parse otherwise.
     $editInfo = $article->prepareContentForEdit($rev->getContent(), null, $user, $rev->getContentFormat());
     $poutput = $editInfo->output;
     // revision HTML output
     # Get the "review time" versions of templates and files.
     # This tries to make sure each template/file version either came from the stable
     # version of that template/file or was a "review time" version used in the stable
     # version of this page. If a pending version of a template/file is currently vandalism,
     # we try to avoid storing its ID as the "review time" version so it won't show up when
     # someone views the page. If not possible, this stores the current template/file.
     if (FlaggedRevs::inclusionSetting() === FR_INCLUDES_CURRENT) {
         $tVersions = $poutput->getTemplateIds();
         $fVersions = $poutput->getFileSearchOptions();
     } else {
         $tVersions = $oldSv ? $oldSv->getTemplateVersions() : array();
         $fVersions = $oldSv ? $oldSv->getFileVersions() : array();
         foreach ($poutput->getTemplateIds() as $ns => $pages) {
             foreach ($pages as $dbKey => $revId) {
                 if (!isset($tVersions[$ns][$dbKey])) {
                     $srev = FlaggedRevision::newFromStable(Title::makeTitle($ns, $dbKey));
                     if ($srev) {
                         // use stable
                         $tVersions[$ns][$dbKey] = $srev->getRevId();
                     } else {
                         // use current
                         $tVersions[$ns][$dbKey] = $revId;
                     }
                 }
             }
         }
         foreach ($poutput->getFileSearchOptions() as $dbKey => $info) {
             if (!isset($fVersions[$dbKey])) {
                 $srev = FlaggedRevision::newFromStable(Title::makeTitle(NS_FILE, $dbKey));
                 if ($srev && $srev->getFileTimestamp()) {
                     // use stable
                     $fVersions[$dbKey]['time'] = $srev->getFileTimestamp();
                     $fVersions[$dbKey]['sha1'] = $srev->getFileSha1();
                 } else {
                     // use current
                     $fVersions[$dbKey]['time'] = $info['time'];
                     $fVersions[$dbKey]['sha1'] = $info['sha1'];
                 }
             }
         }
     }
     # If this is an image page, get the corresponding file version info...
     $fileData = array('name' => null, 'timestamp' => null, 'sha1' => null);
     if ($title->getNamespace() == NS_FILE) {
         # We must use WikiFilePage process cache on upload or get bitten by slave lag
         $file = $article instanceof WikiFilePage || $article instanceof ImagePage ? $article->getFile() : wfFindFile($title, array('bypassCache' => true));
         // skip cache; bug 31056
         if (is_object($file) && $file->exists()) {
             $fileData['name'] = $title->getDBkey();
             $fileData['timestamp'] = $file->getTimestamp();
             $fileData['sha1'] = $file->getSha1();
         }
     }
     # Our review entry
     $flaggedRevision = new FlaggedRevision(array('rev' => $rev, 'user_id' => $user->getId(), 'timestamp' => $rev->getTimestamp(), 'quality' => FlaggedRevs::getQualityTier($flags, 0), 'tags' => FlaggedRevision::flattenRevisionTags($flags), 'img_name' => $fileData['name'], 'img_timestamp' => $fileData['timestamp'], 'img_sha1' => $fileData['sha1'], 'templateVersions' => $tVersions, 'fileVersions' => $fVersions, 'flags' => implode(',', $propFlags)));
     $flaggedRevision->insert();
     # Update the article review log
     FlaggedRevsLog::updateReviewLog($title, $flags, array(), '', $rev->getId(), $oldSvId, true, $auto);
     # Update page and tracking tables and clear cache
     FlaggedRevs::stableVersionUpdates($article);
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Show a row in history, including:
  * time of edit
  * changed bytes
  * name of editor
  * comment of edit
  * @param Revision $rev Revision id of the row wants to show
  * @param Revision|null $prev Revision id of previous Revision to display the difference
  */
 protected function showRow(Revision $rev, $prev)
 {
     $user = $this->getUser();
     $userId = $rev->getUser(Revision::FOR_THIS_USER, $user);
     if ($userId === 0) {
         $username = IP::prettifyIP($rev->getUserText(Revision::RAW));
         $isAnon = true;
     } else {
         $username = $rev->getUserText(Revision::FOR_THIS_USER, $user);
         $isAnon = false;
     }
     // FIXME: Style differently user comment when this is the case
     if ($rev->userCan(Revision::DELETED_COMMENT, $user)) {
         $comment = $rev->getComment(Revision::FOR_THIS_USER, $user);
         $comment = $this->formatComment($comment, $this->title);
     } else {
         $comment = $this->msg('rev-deleted-comment')->plain();
     }
     $ts = $rev->getTimestamp();
     $this->renderListHeaderWhereNeeded($this->getLanguage()->userDate($ts, $this->getUser()));
     $ts = new MWTimestamp($ts);
     $canSeeText = $rev->userCan(Revision::DELETED_TEXT, $user);
     if ($canSeeText && $prev && $prev->userCan(Revision::DELETED_TEXT, $user)) {
         $diffLink = SpecialPage::getTitleFor('MobileDiff', $rev->getId())->getLocalUrl();
     } elseif ($canSeeText && $rev->getTitle() !== null) {
         $diffLink = $rev->getTitle()->getLocalUrl(array('oldid' => $rev->getId()));
     } else {
         $diffLink = false;
     }
     // FIXME: Style differently user comment when this is the case
     if (!$rev->userCan(Revision::DELETED_USER, $user)) {
         $username = $this->msg('rev-deleted-user')->plain();
     }
     // When the page is named there is no need to print it in output
     if ($this->title) {
         $title = null;
     } else {
         $title = $rev->getTitle();
     }
     $bytes = $rev->getSize();
     if ($prev) {
         $bytes -= $prev->getSize();
     }
     $isMinor = $rev->isMinor();
     $this->renderFeedItemHtml($ts, $diffLink, $username, $comment, $title, $isAnon, $bytes, $isMinor);
 }
Esempio n. 24
0
 /**
  * If the given revision is newer than the currently set page_latest,
  * update the page record. Otherwise, do nothing.
  *
  * @param Database $dbw
  * @param Revision $revision
  */
 function updateIfNewerOn(&$dbw, $revision)
 {
     wfProfileIn(__METHOD__);
     $row = $dbw->selectRow(array('revision', 'page'), array('rev_id', 'rev_timestamp', 'page_is_redirect'), array('page_id' => $this->getId(), 'page_latest=rev_id'), __METHOD__);
     if ($row) {
         if (wfTimestamp(TS_MW, $row->rev_timestamp) >= $revision->getTimestamp()) {
             wfProfileOut(__METHOD__);
             return false;
         }
         $prev = $row->rev_id;
         $lastRevIsRedirect = (bool) $row->page_is_redirect;
     } else {
         # No or missing previous revision; mark the page as new
         $prev = 0;
         $lastRevIsRedirect = null;
     }
     $ret = $this->updateRevisionOn($dbw, $revision, $prev, $lastRevIsRedirect);
     wfProfileOut(__METHOD__);
     return $ret;
 }
Esempio n. 25
0
 /**
  * If the given revision is newer than the currently set page_latest,
  * update the page record. Otherwise, do nothing.
  *
  * @deprecated since 1.24, use updateRevisionOn instead
  *
  * @param IDatabase $dbw
  * @param Revision $revision
  * @return bool
  */
 public function updateIfNewerOn($dbw, $revision)
 {
     $row = $dbw->selectRow(['revision', 'page'], ['rev_id', 'rev_timestamp', 'page_is_redirect'], ['page_id' => $this->getId(), 'page_latest=rev_id'], __METHOD__);
     if ($row) {
         if (wfTimestamp(TS_MW, $row->rev_timestamp) >= $revision->getTimestamp()) {
             return false;
         }
         $prev = $row->rev_id;
         $lastRevIsRedirect = (bool) $row->page_is_redirect;
     } else {
         // No or missing previous revision; mark the page as new
         $prev = 0;
         $lastRevIsRedirect = null;
     }
     $ret = $this->updateRevisionOn($dbw, $revision, $prev, $lastRevIsRedirect);
     return $ret;
 }
Esempio n. 26
0
 /**
  * Generate a FeedItem object from a given revision table row
  * Borrows Recent Changes' feed generation functions for formatting;
  * includes a diff to the previous revision (if any).
  *
  * @param $row Object: database row
  * @return FeedItem
  */
 function feedItem($row)
 {
     $rev = new Revision($row);
     $rev->setTitle($this->getTitle());
     $text = FeedUtils::formatDiffRow($this->getTitle(), $this->getTitle()->getPreviousRevisionID($rev->getId()), $rev->getId(), $rev->getTimestamp(), $rev->getComment());
     if ($rev->getComment() == '') {
         global $wgContLang;
         $title = $this->msg('history-feed-item-nocomment', $rev->getUserText(), $wgContLang->timeanddate($rev->getTimestamp()), $wgContLang->date($rev->getTimestamp()), $wgContLang->time($rev->getTimestamp()))->inContentLanguage()->text();
     } else {
         $title = $rev->getUserText() . $this->msg('colon-separator')->inContentLanguage()->text() . FeedItem::stripComment($rev->getComment());
     }
     return new FeedItem($title, $text, $this->getTitle()->getFullUrl('diff=' . $rev->getId() . '&oldid=prev'), $rev->getTimestamp(), $rev->getUserText(), $this->getTitle()->getTalkPage()->getFullUrl());
 }
 /**
  * Render the contribution of the pagerevision (time, bytes added/deleted, pagename comment)
  * @param Revision $rev
  */
 protected function showContributionsRow(Revision $rev)
 {
     $user = $this->getUser();
     $userId = $rev->getUser(Revision::FOR_THIS_USER, $user);
     if ($userId === 0) {
         $username = IP::prettifyIP($rev->getUserText(Revision::RAW));
         $isAnon = true;
     } else {
         $username = $rev->getUserText(Revision::FOR_THIS_USER, $user);
         $isAnon = false;
     }
     // FIXME: Style differently user comment when this is the case
     if ($rev->userCan(Revision::DELETED_COMMENT, $user)) {
         $comment = $rev->getComment(Revision::FOR_THIS_USER, $user);
         $comment = $this->formatComment($comment, $this->title);
     } else {
         $comment = $this->msg('rev-deleted-comment')->plain();
     }
     $ts = $rev->getTimestamp();
     $this->renderListHeaderWhereNeeded($this->getLanguage()->userDate($ts, $this->getUser()));
     $ts = new MWTimestamp($ts);
     if ($rev->userCan(Revision::DELETED_TEXT, $user)) {
         $diffLink = SpecialPage::getTitleFor('MobileDiff', $rev->getId())->getLocalUrl();
     } else {
         $diffLink = false;
     }
     // FIXME: Style differently user comment when this is the case
     if (!$rev->userCan(Revision::DELETED_USER, $user)) {
         $username = $this->msg('rev-deleted-user')->plain();
     }
     $bytes = null;
     if (isset($this->prevLengths[$rev->getParentId()])) {
         $bytes = $rev->getSize() - $this->prevLengths[$rev->getParentId()];
     }
     $isMinor = $rev->isMinor();
     $this->renderFeedItemHtml($ts, $diffLink, $username, $comment, $rev->getTitle(), $isAnon, $bytes, $isMinor);
 }
	/**
	 * 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 sysop
	 * 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__ );

		$page = Title::makeTitle( $row->ar_namespace, $row->ar_title );

		$rev = new Revision( array(
			'title' => $page,
			'id' => $row->ar_rev_id,
			'comment' => $row->ar_comment,
			'user' => $row->ar_user,
			'user_text' => $row->ar_user_text,
			'timestamp' => $row->ar_timestamp,
			'minor_edit' => $row->ar_minor_edit,
			'deleted' => $row->ar_deleted,
		) );

		$undelete = SpecialPage::getTitleFor( 'Undelete' );

		$logs = SpecialPage::getTitleFor( 'Log' );
		$dellog = Linker::linkKnown(
			$logs,
			$this->messages['deletionlog'],
			array(),
			array(
				'type' => 'delete',
				'page' => $page->getPrefixedText()
			)
		);

		$reviewlink = Linker::linkKnown(
			SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ),
			$this->messages['undeleteviewlink']
		);

		$user = $this->getUser();

		if ( $user->isAllowed( 'deletedtext' ) ) {
			$last = Linker::linkKnown(
				$undelete,
				$this->messages['diff'],
				array(),
				array(
					'target' => $page->getPrefixedText(),
					'timestamp' => $rev->getTimestamp(),
					'diff' => 'prev'
				)
			);
		} else {
			$last = $this->messages['diff'];
		}

		$comment = Linker::revComment( $rev );
		$date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user );
		$date = htmlspecialchars( $date );

		if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) {
			$link = $date; // unusable link
		} else {
			$link = Linker::linkKnown(
				$undelete,
				$date,
				array( 'class' => 'mw-changeslist-date' ),
				array(
					'target' => $page->getPrefixedText(),
					'timestamp' => $rev->getTimestamp()
				)
			);
		}
		// Style deleted items
		if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
			$link = '<span class="history-deleted">' . $link . '</span>';
		}

		$pagelink = Linker::link(
			$page,
			null,
			array( 'class' => 'mw-changeslist-title' )
		);

		if ( $rev->isMinor() ) {
			$mflag = ChangesList::flag( 'minor' );
		} else {
			$mflag = '';
		}

		// Revision delete link
		$del = Linker::getRevDeleteLink( $user, $rev, $page );
		if ( $del ) {
			$del .= ' ';
		}

		$tools = Html::rawElement(
			'span',
			array( 'class' => 'mw-deletedcontribs-tools' ),
			$this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList(
				array( $last, $dellog, $reviewlink ) ) )->escaped()
		);

		$separator = '<span class="mw-changeslist-separator">. .</span>';
		$ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}";

		# Denote if username is redacted for this edit
		if ( $rev->isDeleted( Revision::DELETED_USER ) ) {
			$ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>";
		}

		$ret = Html::rawElement( 'li', array(), $ret ) . "\n";

		wfProfileOut( __METHOD__ );

		return $ret;
	}
Esempio n. 29
0
	/**
	 * Set the latest revision
	 */
	protected function setLastEdit( Revision $revision ) {
		$this->mLastRevision = $revision;
		$this->mTimestamp = $revision->getTimestamp();
	}
Esempio n. 30
0
 /**
  * Generate a FeedItem object from a given revision table row
  * Borrows Recent Changes' feed generation functions for formatting;
  * includes a diff to the previous revision (if any).
  *
  * @param $row
  * @return FeedItem
  */
 function feedItem($row)
 {
     $rev = new Revision($row);
     $rev->setTitle($this->mTitle);
     $text = rcFormatDiffRow($this->mTitle, $this->mTitle->getPreviousRevisionID($rev->getId()), $rev->getId(), $rev->getTimestamp(), $rev->getComment());
     if ($rev->getComment() == '') {
         global $wgContLang;
         $title = wfMsgForContent('history-feed-item-nocomment', $rev->getUserText(), $wgContLang->timeanddate($rev->getTimestamp()));
     } else {
         $title = $rev->getUserText() . ": " . $this->stripComment($rev->getComment());
     }
     return new FeedItem($title, $text, $this->mTitle->getFullUrl('diff=' . $rev->getId() . '&oldid=prev'), $rev->getTimestamp(), $rev->getUserText(), $this->mTitle->getTalkPage()->getFullUrl());
 }