public function execute() { $params = $this->extractRequestParams(); $rev1 = $this->revisionOrTitleOrId($params['fromrev'], $params['fromtitle'], $params['fromid']); $rev2 = $this->revisionOrTitleOrId($params['torev'], $params['totitle'], $params['toid']); $de = new DifferenceEngine($this->getContext(), $rev1, $rev2, null, true, false); $vals = array(); if (isset($params['fromtitle'])) { $vals['fromtitle'] = $params['fromtitle']; } if (isset($params['fromid'])) { $vals['fromid'] = $params['fromid']; } $vals['fromrevid'] = $rev1; if (isset($params['totitle'])) { $vals['totitle'] = $params['totitle']; } if (isset($params['toid'])) { $vals['toid'] = $params['toid']; } $vals['torevid'] = $rev2; $difftext = $de->getDiffBody(); if ($difftext === false) { $this->dieUsage('The diff cannot be retrieved. ' . 'Maybe one or both revisions do not exist or you do not have permission to view them.', 'baddiff'); } else { ApiResult::setContent($vals, $difftext); } $this->getResult()->addValue(null, $this->getModuleName(), $vals); }
/** * Diff would format against two revisions */ public function formatApi(FormatterRow $newRow, FormatterRow $oldRow, IContextSource $ctx) { $oldRes = $this->revisionViewFormatter->formatApi($oldRow, $ctx); $newRes = $this->revisionViewFormatter->formatApi($newRow, $ctx); $oldContent = $oldRow->revision->getContent('wikitext'); $newContent = $newRow->revision->getContent('wikitext'); $differenceEngine = new \DifferenceEngine(); $differenceEngine->setContent(new \TextContent($oldContent), new \TextContent($newContent)); if ($oldRow->revision->isFirstRevision()) { $prevLink = null; } else { $prevLink = $this->urlGenerator->diffLink($oldRow->revision, $ctx->getTitle(), UUID::create($oldRes['workflowId']))->getLocalURL(); } // this is probably a network request which typically goes in the query // half, but we don't have to worry about batching because we only show // one diff at a time so just do it. $nextRevision = $newRow->revision->getCollection()->getNextRevision($newRow->revision); if ($nextRevision === null) { $nextLink = null; } else { $nextLink = $this->urlGenerator->diffLink($nextRevision, $ctx->getTitle(), UUID::create($newRes['workflowId']))->getLocalURL(); } return array('new' => $newRes, 'old' => $oldRes, 'diff_content' => $differenceEngine->getDiffBody(), 'links' => array('previous' => $prevLink, 'next' => $nextLink)); }
/** * Get collapsible diff-to-stable html to add to the review notice as needed * @param FlaggedRevision $srev, stable version * @param bool $quality, revision is quality * @return string, the html line (either "" or "<diff toggle><diff div>") */ protected function getTopDiffToggle(FlaggedRevision $srev, $quality) { $reqUser = $this->getUser(); $this->load(); if (!$reqUser->getBoolOption('flaggedrevsviewdiffs')) { return false; // nothing to do here } # Diff should only show for the draft $oldid = $this->getOldIDFromRequest(); $latest = $this->article->getLatest(); if ($oldid && $oldid != $latest) { return false; // not viewing the draft } $revsSince = $this->article->getPendingRevCount(); if (!$revsSince) { return false; // no pending changes } $title = $this->article->getTitle(); // convenience # Review status of left diff revision... $leftNote = $quality ? 'revreview-hist-quality' : 'revreview-hist-basic'; $lClass = FlaggedRevsXML::getQualityColor((int) $quality); $leftNote = "<span class='{$lClass}'>[" . wfMsgHtml($leftNote) . "]</span>"; # Review status of right diff revision... $rClass = FlaggedRevsXML::getQualityColor(false); $rightNote = "<span class='{$rClass}'>[" . wfMsgHtml('revreview-hist-pending') . "]</span>"; # Get the actual body of the diff... $diffEngine = new DifferenceEngine($title, $srev->getRevId(), $latest); $diffBody = $diffEngine->getDiffBody(); if (strlen($diffBody) > 0) { $nEdits = $revsSince - 1; // full diff-to-stable, no need for query if ($nEdits) { $limit = 100; $nUsers = $title->countAuthorsBetween($srev->getRevId(), $latest, $limit); $multiNotice = DifferenceEngine::intermediateEditsMsg($nEdits, $nUsers, $limit); } else { $multiNotice = ''; } $diffEngine->showDiffStyle(); // add CSS $this->isDiffFromStable = true; // alter default review form tags return FlaggedRevsXML::diffToggle() . "<div id='mw-fr-stablediff'>\n" . self::getFormattedDiff($diffBody, $multiNotice, $leftNote, $rightNote) . "</div>\n"; } return ''; }
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; }
public static function getNotificationDiffHtml($oldRevId, $revId) { $oldRevisionObj = Revision::newFromId($oldRevId); $newRevisionObj = Revision::newFromId($revId); if ($oldRevisionObj->getTitle() != $newRevisionObj->getTitle()) { return '<span class="error">' . htmlspecialchars(wfMsg('notificator-revs-not-from-same-title')) . '</span>'; } $titleObj = $oldRevisionObj->getTitle(); $differenceEngineObj = new DifferenceEngine($titleObj, $oldRevId, $revId); $notificationDiffHtml = '<style media="screen" type="text/css">' . file_get_contents(dirname(__FILE__) . '/diff-in-mail.css') . '</style><table class="diff"> <col class="diff-marker" /> <col class="diff-content" /> <col class="diff-marker" /> <col class="diff-content" /> ' . $differenceEngineObj->getDiffBody() . ' </table>'; return $notificationDiffHtml; }