/** * If the revision requested for view is deleted, check permissions. * Send either an error message or a warning header to $wgOut. * * @return boolean true if the view is allowed, false if not. */ public function showDeletedRevisionHeader() { global $wgOut, $wgRequest; if (!$this->mRevision->isDeleted(Revision::DELETED_TEXT)) { // Not deleted return true; } // If the user is not allowed to see it... if (!$this->mRevision->userCan(Revision::DELETED_TEXT)) { $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", 'rev-deleted-text-permission'); return false; // If the user needs to confirm that they want to see it... } elseif ($wgRequest->getInt('unhide') != 1) { # Give explanation and add a link to view the revision... $oldid = intval($this->getOldID()); $link = $this->getTitle()->getFullUrl("oldid={$oldid}&unhide=1"); $msg = $this->mRevision->isDeleted(Revision::DELETED_RESTRICTED) ? 'rev-suppressed-text-unhide' : 'rev-deleted-text-unhide'; $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", array($msg, $link)); return false; // We are allowed to see... } else { $msg = $this->mRevision->isDeleted(Revision::DELETED_RESTRICTED) ? 'rev-suppressed-text-view' : 'rev-deleted-text-view'; $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1\n</div>\n", $msg); return true; } }
/** * 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; }
function formatRevisionRow($row) { global $wgUser, $wgLang; $rev = new Revision($row); $stxt = ''; $last = $this->message['last']; $ts = wfTimestamp(TS_MW, $row->rev_timestamp); $checkBox = Xml::radio("mergepoint", $ts, false); $pageLink = $this->sk->makeKnownLinkObj($rev->getTitle(), htmlspecialchars($wgLang->timeanddate($ts)), 'oldid=' . $rev->getId()); if ($rev->isDeleted(Revision::DELETED_TEXT)) { $pageLink = '<span class="history-deleted">' . $pageLink . '</span>'; } # Last link if (!$rev->userCan(Revision::DELETED_TEXT)) { $last = $this->message['last']; } else { if (isset($this->prevId[$row->rev_id])) { $last = $this->sk->makeKnownLinkObj($rev->getTitle(), $this->message['last'], "diff=" . $row->rev_id . "&oldid=" . $this->prevId[$row->rev_id]); } } $userLink = $this->sk->revUserTools($rev); if (!is_null($size = $row->rev_len)) { $stxt = $this->sk->formatRevisionSize($size); } $comment = $this->sk->revComment($rev); return "<li>{$checkBox} ({$last}) {$pageLink} . . {$userLink} {$stxt} {$comment}</li>"; }
/** * 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); } }
/** * @param Revision $rev * @returns string */ private function historyLine($rev) { global $wgLang, $wgUser; $date = $wgLang->timeanddate($rev->getTimestamp()); $difflink = $del = ''; // Live revisions if ($this->deleteKey == 'oldid') { $tokenParams = '&unhide=1&token=' . urlencode($wgUser->editToken($rev->getId())); $revlink = $this->skin->makeLinkObj($this->page, $date, 'oldid=' . $rev->getId() . $tokenParams); $difflink = '(' . $this->skin->makeKnownLinkObj($this->page, wfMsgHtml('diff'), 'diff=' . $rev->getId() . '&oldid=prev' . $tokenParams) . ')'; // Archived revisions } else { $undelete = SpecialPage::getTitleFor('Undelete'); $target = $this->page->getPrefixedText(); $revlink = $this->skin->makeLinkObj($undelete, $date, "target={$target}×tamp=" . $rev->getTimestamp()); $difflink = '(' . $this->skin->makeKnownLinkObj($undelete, wfMsgHtml('diff'), "target={$target}&diff=prev×tamp=" . $rev->getTimestamp()) . ')'; } // Check permissions; items may be "suppressed" if ($rev->isDeleted(Revision::DELETED_TEXT)) { $revlink = '<span class="history-deleted">' . $revlink . '</span>'; $del = ' <tt>' . wfMsgHtml('deletedrev') . '</tt>'; if (!$rev->userCan(Revision::DELETED_TEXT)) { $revlink = '<span class="history-deleted">' . $date . '</span>'; $difflink = '(' . wfMsgHtml('diff') . ')'; } } $userlink = $this->skin->revUserLink($rev); $comment = $this->skin->revComment($rev); return "<li>{$difflink} {$revlink} {$userlink} {$comment}{$del}</li>"; }
/** * Create a diff-to-current link for this revision for this page * @param Revision $rev * @param Bool $latest, this is the latest revision of the page? * @returns string */ function curLink($rev, $latest) { $cur = $this->message['cur']; if ($latest || $rev->isDeleted(Revision::DELETED_TEXT)) { return $cur; } else { return $this->mSkin->makeKnownLinkObj($this->mTitle, $cur, 'diff=' . $this->mTitle->getLatestRevID() . "&oldid=" . $rev->getId()); } }
/** * Wrap and format the given revision's comment block, if the current * user is allowed to view it. * * @param $rev Revision object * @param $local Boolean: whether section links should refer to local page * @param $isPublic Boolean: show only if all users can see it * @return String: HTML fragment */ static function revComment(Revision $rev, $local = false, $isPublic = false) { if ($rev->getRawComment() == "") { return ""; } if ($rev->isDeleted(Revision::DELETED_COMMENT) && $isPublic) { $block = " <span class=\"comment\">" . wfMsgHtml('rev-deleted-comment') . "</span>"; } elseif ($rev->userCan(Revision::DELETED_COMMENT)) { $block = self::commentBlock($rev->getComment(Revision::FOR_THIS_USER), $rev->getTitle(), $local); } else { $block = " <span class=\"comment\">" . wfMsgHtml('rev-deleted-comment') . "</span>"; } if ($rev->isDeleted(Revision::DELETED_COMMENT)) { return " <span class=\"history-deleted\">{$block}</span>"; } return $block; }
/** * Fetch revision text link if it's available to all users * * @param Revision $rev * @param Title $titleObj * @param string $ts Timestamp * @return string */ function getPageLink($rev, $titleObj, $ts) { $user = $this->getUser(); $time = $this->getLanguage()->userTimeAndDate($ts, $user); if (!$rev->userCan(Revision::DELETED_TEXT, $user)) { return '<span class="history-deleted">' . $time . '</span>'; } $link = Linker::linkKnown($titleObj, htmlspecialchars($time), array(), array('target' => $this->mTargetObj->getPrefixedText(), 'timestamp' => $ts)); if ($rev->isDeleted(Revision::DELETED_TEXT)) { $link = '<span class="history-deleted">' . $link . '</span>'; } return $link; }
/** * 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 Revision $rev * @return string HTML fragment */ function revDeleteLink($rev) { $canHide = $this->getUser()->isAllowed('deleterevision'); if ($canHide || $rev->getVisibility() && $this->getUser()->isAllowed('deletedhistory')) { if (!$rev->userCan(Revision::DELETED_RESTRICTED)) { $revdlink = 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' => $this->mTargetObj->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' => $this->mTargetObj->getPrefixedDBkey(), 'ids' => $rev->getTimestamp()); } return Linker::revDeleteLink($query, $rev->isDeleted(File::DELETED_RESTRICTED), $canHide); } } else { return ''; } }
/** * Wrap and format the given revision's comment block, if the current * user is allowed to view it. * * @param Revision $rev * @param bool $local Whether section links should refer to local page * @return string HTML */ function revComment(Revision $rev, $local = false) { if ($rev->userCan(Revision::DELETED_COMMENT)) { $block = $this->commentBlock($rev->getRawComment(), $rev->getTitle(), $local); } else { $block = " <span class=\"comment\">" . wfMsgHtml('rev-deleted-comment') . "</span>"; } if ($rev->isDeleted(Revision::DELETED_COMMENT)) { return " <span class=\"history-deleted\">{$block}</span>"; } return $block; }
/** * Get a header for a specified revision. * * @param $rev Revision * @param $complete String: 'complete' to get the header wrapped depending * the visibility of the revision and a link to edit the page. * @return String HTML fragment */ private 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(); } $msg = $this->msg($title->userCan('edit', $user) ? 'editold' : 'viewsourceold')->escaped(); /* Wikia Change begin */ $header .= ' <span class="mw-rev-head-action">(' . Linker::linkKnown($title, $msg, array(), $editQuery) . ')</span>'; /* Wikia Change end */ 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; }
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_contentmodel) { $vals['contentmodel'] = $revision->getContentModel(); } 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; } } } $content = null; global $wgParser; if ($this->fld_content || !is_null($this->difftotext)) { $content = $revision->getContent(); // Expand templates after getting section content because // template-added sections don't count and Parser::preprocess() // will have less input if ($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 ($this->fld_content && !$revision->isDeleted(Revision::DELETED_TEXT)) { $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()), OT_PREPROCESS); $dom = $wgParser->preprocessToDom($t); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $vals['parsetree'] = $xml; } else { $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() . ")"); $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(); if (!$content->isSupportedFormat($format)) { $model = $content->getModel(); $name = $title->getPrefixedDBkey(); $this->dieUsage("The requested format {$this->contentFormat} is not supported " . "for content model {$model} used by {$name}", 'badformat'); } $text = $content->serialize($format); $vals['contentformat'] = $format; } if ($text !== false) { 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); $handler = $revision->getContentHandler(); if (!is_null($this->difftotext)) { $model = $title->getContentModel(); if ($this->contentFormat && !ContentHandler::getForModelID($model)->isSupportedFormat($this->contentFormat)) { $name = $title->getPrefixedDBkey(); $this->dieUsage("The requested format {$this->contentFormat} is not supported for " . "content model {$model} used by {$name}", 'badformat'); } $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(); } $difftext = $engine->getDiffBody(); ApiResult::setContent($vals['diff'], $difftext); if (!$engine->wasCacheHit()) { $n++; } } else { $vals['diff']['notcached'] = ''; } } return $vals; }
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>"; }
/** * Get the "are you sure you want to reject these changes?" form * @return array (html string, error string or true) */ public function getHtml() { global $wgLang, $wgContLang; $status = $this->form->checkTarget(); if ($status !== true) { return array('', $status); // not a reviewable existing page } $oldRev = $this->oldRev; // convenience $newRev = $this->newRev; // convenience # Do not mess with archived/deleted revisions if (!$oldRev || $newRev->isDeleted(Revision::DELETED_TEXT)) { return array('', 'review_bad_oldid'); } elseif (!$newRev || $newRev->isDeleted(Revision::DELETED_TEXT)) { return array('', 'review_bad_oldid'); } $form = '<div class="plainlinks">'; $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('revision', Revision::selectFields(), array('rev_page' => $oldRev->getPage(), 'rev_timestamp > ' . $dbr->addQuotes($dbr->timestamp($oldRev->getTimestamp())), 'rev_timestamp <= ' . $dbr->addQuotes($dbr->timestamp($newRev->getTimestamp()))), __METHOD__, array('ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 251)); if (!$dbr->numRows($res)) { return array('', 'review_bad_oldid'); } elseif ($dbr->numRows($res) > 250) { return array('', 'review_reject_excessive'); } $contribs = SpecialPage::getTitleFor('Contributions')->getPrefixedText(); $lastTextId = 0; $rejectIds = $rejectAuthors = array(); foreach ($res as $row) { $rev = new Revision($row); if ($rev->getTextId() != $lastTextId) { // skip null edits $rejectIds[] = $rev->getId(); $rejectAuthors[] = $rev->isDeleted(Revision::DELETED_USER) ? wfMsg('rev-deleted-user') : "[[{$contribs}/{$rev->getUserText()}|{$rev->getUserText()}]]"; } $lastTextId = $rev->getTextId(); } $rejectAuthors = array_values(array_unique($rejectAuthors)); if (!$rejectIds) { // all null edits? (this shouldn't happen) return array('', 'review_reject_nulledits'); } // List of revisions being undone... $form .= wfMsgExt('revreview-reject-text-list', 'parseinline', $wgLang->formatNum(count($rejectIds)), $oldRev->getTitle()->getPrefixedText()); $form .= '<ul>'; $list = new RevisionList(RequestContext::getMain(), $oldRev->getTitle()); $list->filterByIds($rejectIds); for ($list->reset(); $list->current(); $list->next()) { $item = $list->current(); if ($item->canView()) { $form .= $item->getHTML(); } } $form .= '</ul>'; if ($newRev->isCurrent()) { // Revision this will revert to (when reverting the top X revs)... $form .= wfMsgExt('revreview-reject-text-revto', 'parseinline', $oldRev->getTitle()->getPrefixedDBKey(), $oldRev->getId(), $wgLang->timeanddate($oldRev->getTimestamp(), true)); } $comment = $this->form->getComment(); // convenience // Determine the default edit summary... $oldRevAuthor = $oldRev->isDeleted(Revision::DELETED_USER) ? wfMsg('rev-deleted-user') : $oldRev->getUserText(); // NOTE: *-cur msg wording not safe for (unlikely) edit auto-merge $msg = $newRev->isCurrent() ? 'revreview-reject-summary-cur' : 'revreview-reject-summary-old'; $defaultSummary = wfMsgExt($msg, array('parsemag', 'content'), $wgContLang->formatNum(count($rejectIds)), $wgContLang->listToText($rejectAuthors), $oldRev->getId(), $oldRevAuthor); // If the message is too big, then fallback to the shorter one $colonSeparator = wfMsgForContent('colon-separator'); $maxLen = 255 - count($colonSeparator) - count($comment); if (strlen($defaultSummary) > $maxLen) { $msg = $newRev->isCurrent() ? 'revreview-reject-summary-cur-short' : 'revreview-reject-summary-old-short'; $defaultSummary = wfMsgExt($msg, array('parsemag', 'content'), $wgContLang->formatNum(count($rejectIds)), $oldRev->getId(), $oldRevAuthor); } // Append any review comment... if ($comment != '') { if ($defaultSummary != '') { $defaultSummary .= $colonSeparator; } $defaultSummary .= $comment; } $form .= '</div>'; $skin = $this->form->getUser()->getSkin(); $reviewTitle = SpecialPage::getTitleFor('RevisionReview'); $form .= Xml::openElement('form', array('method' => 'POST', 'action' => $reviewTitle->getFullUrl())); $form .= Html::hidden('action', 'reject'); $form .= Html::hidden('wpReject', 1); $form .= Html::hidden('wpRejectConfirm', 1); $form .= Html::hidden('oldid', $this->form->getOldId()); $form .= Html::hidden('refid', $this->form->getRefId()); $form .= Html::hidden('target', $oldRev->getTitle()->getPrefixedDBKey()); $form .= Html::hidden('wpEditToken', $this->form->getUser()->editToken()); $form .= Html::hidden('changetime', $newRev->getTimestamp()); $form .= Xml::inputLabel(wfMsg('revreview-reject-summary'), 'wpReason', 'wpReason', 120, $defaultSummary, array('maxlength' => 200)) . "<br />"; $form .= Html::input('wpSubmit', wfMsg('revreview-reject-confirm'), 'submit'); $form .= ' '; $form .= $skin->link($this->form->getPage(), wfMsg('revreview-reject-cancel'), array('onClick' => 'history.back(); return history.length <= 1;'), array('oldid' => $this->form->getRefId(), 'diff' => $this->form->getOldId())); $form .= Xml::closeElement('form'); return array($form, true); }
/** * @param Revision $rev * @returns string */ private function historyLine($rev) { global $wgLang; $date = $wgLang->timeanddate($rev->getTimestamp()); $difflink = $del = ''; // Live revisions if ($this->deleteKey == 'oldid') { $revlink = $this->skin->makeLinkObj($this->page, $date, 'oldid=' . $rev->getId()); $difflink = '(' . $this->skin->makeKnownLinkObj($this->page, wfMsgHtml('diff'), 'diff=' . $rev->getId() . '&oldid=prev') . ')'; // Archived revisions } else { $undelete = SpecialPage::getTitleFor('Undelete'); $target = $this->page->getPrefixedText(); $revlink = $this->skin->makeLinkObj($undelete, $date, "target={$target}×tamp=" . $rev->getTimestamp()); $difflink = '(' . $this->skin->makeKnownLinkObj($undelete, wfMsgHtml('diff'), "target={$target}&diff=prev×tamp=" . $rev->getTimestamp()) . ')'; } if ($rev->isDeleted(Revision::DELETED_TEXT)) { $revlink = '<span class="history-deleted">' . $revlink . '</span>'; $del = ' <tt>' . wfMsgHtml('deletedrev') . '</tt>'; if (!$rev->userCan(Revision::DELETED_TEXT)) { $revlink = '<span class="history-deleted">' . $date . '</span>'; $difflink = '(' . wfMsgHtml('diff') . ')'; } } return "<li> {$difflink} {$revlink} " . $this->skin->revUserLink($rev) . " " . $this->skin->revComment($rev) . "{$del}</li>"; }
/** * 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; }
public function isDeleted() { return $this->revision->isDeleted(Revision::DELETED_TEXT); }
/** * @brief Adjusting Special:Contributions * * @param ContribsPager $contribsPager * @param String $ret string passed to wgOutput * @param Object $row Std Object with values from database table * * @return true */ public function onContributionsLineEnding(&$contribsPager, &$ret, $row) { wfProfileIn(__METHOD__); $app = F::app(); if (isset($row->page_namespace) && in_array(MWNamespace::getSubject($row->page_namespace), $app->wg->WallNS)) { $topmarktext = ''; $rev = new Revision($row); $page = $rev->getTitle(); $page->resetArticleId($row->rev_page); $skin = $app->wg->User->getSkin(); $wfMsgOptsBase = $this->getMessageOptions(null, $row, true); $isThread = $wfMsgOptsBase['isThread']; $isNew = $wfMsgOptsBase['isNew']; $wfMsgOptsBase['createdAt'] = Xml::element('a', array('href' => $wfMsgOptsBase['articleUrl']), $app->wg->Lang->timeanddate($app->wf->Timestamp(TS_MW, $row->rev_timestamp), true)); if ($isNew) { $wfMsgOptsBase['DiffLink'] = $app->wf->Msg('diff'); } else { $query = array('diff' => 'prev', 'oldid' => $row->rev_id); $wfMsgOptsBase['DiffLink'] = Xml::element('a', array('href' => $rev->getTitle()->getLocalUrl($query)), $app->wf->Msg('diff')); } $wallMessage = F::build('WallMessage', array($page)); $historyLink = $wallMessage->getMessagePageUrl(true) . '?action=history'; $wfMsgOptsBase['historyLink'] = Xml::element('a', array('href' => $historyLink), $app->wf->Msg('hist')); // Don't show useless link to people who cannot hide revisions $canHide = $app->wg->User->isAllowed('deleterevision'); if ($canHide || $rev->getVisibility() && $app->wg->User->isAllowed('deletedhistory')) { if (!$rev->userCan(Revision::DELETED_RESTRICTED)) { $del = $skin->revDeleteLinkDisabled($canHide); // revision was hidden from sysops } else { $query = array('type' => 'revision', 'target' => $page->getPrefixedDbkey(), 'ids' => $rev->getId()); $del = $skin->revDeleteLink($query, $rev->isDeleted(Revision::DELETED_RESTRICTED), $canHide); } $del .= ' '; } else { $del = ''; } $ret = $del; if (wfRunHooks('WallContributionsLine', array(MWNamespace::getSubject($row->page_namespace), $wallMessage, $wfMsgOptsBase, &$ret))) { $wfMsgOpts = array($wfMsgOptsBase['articleUrl'], $wfMsgOptsBase['articleTitleTxt'], $wfMsgOptsBase['wallPageUrl'], $wfMsgOptsBase['wallPageName'], $wfMsgOptsBase['createdAt'], $wfMsgOptsBase['DiffLink'], $wfMsgOptsBase['historyLink']); if ($isThread && $isNew) { $wfMsgOpts[7] = Xml::element('strong', array(), wfMsg('newpageletter') . ' '); } else { $wfMsgOpts[7] = ''; } $ret .= $app->wf->Msg('wall-contributions-wall-line', $wfMsgOpts); } if (!$isNew) { $summary = $rev->getComment(); if (empty($summary)) { $msg = $app->wf->MsgForContent($this->getMessagePrefix($row->page_namespace) . '-edit'); } else { $msg = $app->wf->MsgForContent('wall-recentchanges-summary', $summary); } $ret .= ' ' . Xml::openElement('span', array('class' => 'comment')) . $msg . Xml::closeElement('span'); } } wfProfileOut(__METHOD__); return true; }
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()); }
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; }
/** * 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; }
/** * Create a link to view this revision of the page * @param Revision $rev * @returns string */ function revLink($rev) { global $wgLang; $date = $wgLang->timeanddate(wfTimestamp(TS_MW, $rev->getTimestamp()), true); if ($rev->userCan(Revision::DELETED_TEXT)) { $link = $this->mSkin->makeKnownLinkObj($this->mTitle, $date, "oldid=" . $rev->getId()); } else { $link = $date; } if ($rev->isDeleted(Revision::DELETED_TEXT)) { return '<span class="history-deleted">' . $link . '</span>'; } return $link; }