Page MenuHomePhabricator

13209.patch

Authored By
bzimport
Nov 21 2014, 10:05 PM
Size
11 KB
Referenced Files
None
Subscribers
None

13209.patch

Index: includes/api/ApiBase.php
===================================================================
--- includes/api/ApiBase.php (revision 45687)
+++ includes/api/ApiBase.php (working copy)
@@ -703,6 +703,7 @@
'missingparam' => array('code' => 'no$1', 'info' => "The \$1 parameter must be set"),
'invalidtitle' => array('code' => 'invalidtitle', 'info' => "Bad title ``\$1''"),
'nosuchpageid' => array('code' => 'nosuchpageid', 'info' => "There is no page with ID \$1"),
+ 'nosuchrevid' => array('code' => 'nosuchrevid', 'info' => "There is no revision with ID \$1"),
'invaliduser' => array('code' => 'invaliduser', 'info' => "Invalid username ``\$1''"),
'invalidexpiry' => array('code' => 'invalidexpiry', 'info' => "Invalid expiry time ``\$1''"),
'pastexpiry' => array('code' => 'pastexpiry', 'info' => "Expiry time ``\$1'' is in the past"),
Index: includes/api/ApiQueryRevisions.php
===================================================================
--- includes/api/ApiQueryRevisions.php (revision 45687)
+++ includes/api/ApiQueryRevisions.php (working copy)
@@ -83,7 +83,9 @@
$enumRevMode = (!is_null($params['user']) || !is_null($params['excludeuser']) ||
!is_null($params['limit']) || !is_null($params['startid']) ||
!is_null($params['endid']) || $params['dir'] === 'newer' ||
- !is_null($params['start']) || !is_null($params['end']));
+ !is_null($params['start']) || !is_null($params['end']) ||
+ $params['difftoprev'] || $params['difftotop']);
+ $this->enumRevMode = $enumRevMode;
$pageSet = $this->getPageSet();
@@ -98,11 +100,11 @@
$this->dieUsage('The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).', 'revids');
if ($pageCount > 1 && $enumRevMode)
- $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start and end parameters may only be used on a single page.', 'multpages');
+ $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start, end, difftoprev and difftotop parameters may only be used on a single page.', 'multpages');
$this->addTables('revision');
- $this->addFields( Revision::selectFields() );
- $this->addTables( 'page' );
+ $this->addFields(Revision::selectFields());
+ $this->addTables('page');
$this->addWhere('page_id = rev_page');
$prop = array_flip($params['prop']);
@@ -116,12 +118,37 @@
$this->fld_size = isset ($prop['size']);
$this->fld_user = isset ($prop['user']);
$this->token = $params['token'];
+
+ $this->diffto = $params['diffto'];
+ $this->difftoprev = $params['difftoprev'];
+ $this->difftotop = $params['difftotop'];
+ $this->diffprop = array_flip($params['diffprop']);
+ $this->needDiff = !is_null($this->diffto) || $this->difftoprev || $this->difftotop;
+ if($this->needDiff)
+ $this->formatter = new DiffFormatter;
+ if($this->difftoprev)
+ // Cache revision texts
+ $this->difftoprevCache = array();
+ if($this->difftotop)
+ $this->difftotopCached = null;
+
+ if(!is_null($this->diffto)) {
+ global $wgContLang;
+ $diffToRev = Revision::newFromID($this->diffto);
+ if(!$diffToRev instanceof Revision)
+ $this->dieUsageMsg(array('nosuchrevid', $this->diffto));
+ $this->diffToText = $diffToRev->revText();
+ if($this->diffToText == '' && !$diffToRev->userCan(self::DELETED_TEXT))
+ // Deleted revision; fake non-existence
+ $this->dieUsageMsg(array('nosuchrevid', $this->diffto));
+ $this->diffToText = explode("\n", $wgContLang->segmentForDiff($this->diffToText));
+ }
- if ( !is_null($this->token) || $pageCount > 0) {
+ if (!is_null($this->token) || $pageCount > 0) {
$this->addFields( Revision::selectPageFields() );
}
- if (isset ($prop['content'])) {
+ if (isset ($prop['content']) || $this->needDiff) {
// For each page we will request, the user must have read rights for that page
foreach ($pageSet->getGoodTitles() as $title) {
@@ -136,7 +163,7 @@
$this->addFields('old_id');
$this->addFields( Revision::selectTextFields() );
- $this->fld_content = true;
+ $this->fld_content = isset($prop['content']);
$this->expandTemplates = $params['expandtemplates'];
$this->generateXML = $params['generatexml'];
@@ -146,8 +173,8 @@
$this->section = false;
}
- $userMax = ( $this->fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1 );
- $botMax = ( $this->fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
+ $userMax = ( $this->fld_content || $this->needDiff ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1 );
+ $botMax = ( $this->fld_content || $this->needDiff ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2 );
$limit = $params['limit'];
if( $limit == 'max' ) {
$limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
@@ -233,8 +260,8 @@
$res = $this->select(__METHOD__);
$db = $this->getDB();
+ global $wgContLang;
while ($row = $db->fetchObject($res)) {
-
if (++ $count > $limit) {
// We've reached the one extra which shows that there are additional pages to be had. Stop here...
if (!$enumRevMode)
@@ -242,33 +269,60 @@
$this->setContinueEnumParameter('startid', intval($row->rev_id));
break;
}
+
+ $revision = new Revision( $row );
+ if ($this->difftoprev)
+ // Cache this revision's text
+ $this->difftoprevCache[$revision->getID()] = explode("\n", $wgContLang->segmentForDiff($revision->revText()));
- $revision = new Revision( $row );
$this->getResult()->addValue(
array (
'query',
'pages',
$revision->getPage(),
'revisions'),
- null,
+ $revision->getID(),
$this->extractRowInfo( $revision ));
}
$db->freeResult($res);
-
- // Ensure that all revisions are shown as '<rev>' elements
+
$result = $this->getResult();
- if ($result->getIsRawMode()) {
- $data =& $result->getData();
- foreach ($data['query']['pages'] as & $page) {
- if (is_array($page) && array_key_exists('revisions', $page)) {
- $result->setIndexedTagName($page['revisions'], 'rev');
+ $data =& $result->getData();
+ $diffArr = array();
+ if($this->difftoprev)
+ {
+ ksort($this->difftoprevCache, SORT_NUMERIC);
+ $prevID = null;
+ foreach($this->difftoprevCache as $revid => $newText)
+ {
+ if(is_null($prevID))
+ {
+ // The first one doesn't have a previous
+ // one so it doesn't get a diff
+ $prevID = $revid;
+ continue;
}
+ $diff = new Diff($this->difftoprevCache[$prevID], $this->difftoprevCache[$revid]);
+ $diffArr[$revid] = $this->diffResult($diff, $prevID, $revid);
+ $prevID = $revid;
}
}
+
+ // Ensure that all revisions are shown as '<rev>' elements
+ // and add difftoprevs if needed
+ foreach ($data['query']['pages'] as & $page) {
+ if (is_array($page) && array_key_exists('revisions', $page)) {
+ $result->setIndexedTagName($page['revisions'], 'rev');
+ if($this->difftoprev)
+ foreach($page['revisions'] as $revid => &$rev)
+ if(isset($diffArr[$revid]))
+ $rev['difftoprev'] = $diffArr[$revid];
+ }
+ }
}
private function extractRowInfo( $revision ) {
-
+ global $wgContLang;
$vals = array ();
if ($this->fld_ids) {
@@ -299,7 +353,7 @@
$vals['comment'] = $comment;
}
- if(!is_null($this->token) || ($this->fld_content && $this->expandTemplates))
+ if(!is_null($this->token) || ($this->fld_content && $this->expandTemplates) || $this->needDiff)
$title = $revision->getTitle();
if(!is_null($this->token))
@@ -314,10 +368,43 @@
$vals[$t . 'token'] = $val;
}
}
+
+ if($this->needDiff)
+ $thisText = explode("\n", $wgContLang->segmentForDiff($revision->revText()));
+
+ if(!is_null($this->diffto))
+ {
+ $diff = new Diff($thisText, $this->diffToText);
+ $vals['diffto'] = $this->diffResult($diff, $revision->getID(), $this->diffto);
+ }
+
+ if($this->difftotop)
+ {
+ if(!is_null($this->difftotopCached))
+ {
+ $topText = $this->difftotopCached;
+ $topID = $this->difftotopID;
+ }
+ else
+ {
+ if($revision->getID() == $title->getLatestRevID())
+ // This is the top revision
+ $topRev = $revision;
+ else
+ $topRev = Revision::newFromTitle($title);
+ $topText = explode("\n", $wgContLang->segmentForDiff($topRev->revText()));
+ $topID = $topRev->getID();
+ // Cache the top text and ID for later use
+ $this->difftotopCached = $topText;
+ $this->difftotopID = $topID;
+ }
+ $diff = new Diff($thisText, $topText);
+ $vals['difftotop'] = $this->diffResult($diff, $revision->getID(), $topID);
+ }
if ($this->fld_content) {
global $wgParser;
- $text = $revision->getText();
+ $text = $revision->revText();
# Expand templates after getting section content because
# template-added sections don't count and Parser::preprocess()
# will have less input
@@ -344,6 +431,28 @@
}
return $vals;
}
+
+ private function diffResult($diff, $fromID, $toID)
+ {
+ global $wgContLang;
+ $r = array();
+ if(isset($this->diffprop['revids']))
+ {
+ $r['from'] = $fromID;
+ $r['to'] = $toID;
+ }
+ if(isset($this->diffprop['diff']) ||
+ isset($this->diffprop['size']) ||
+ isset($this->diffprop['lines']))
+ $diff = $wgContLang->unsegmentForDiff($this->formatter->format($diff));
+ if(isset($this->diffprop['diff']))
+ ApiResult::setContent($r, $diff);
+ if(isset($this->diffprop['size']))
+ $r['size'] = strlen($diff);
+ if(isset($this->diffprop['lines']))
+ $r['lines'] = substr_count($diff, "\n");
+ return $r;
+ }
public function getAllowedParams() {
return array (
@@ -398,6 +507,21 @@
ApiBase :: PARAM_TYPE => array_keys($this->getTokenFunctions()),
ApiBase :: PARAM_ISMULTI => true
),
+ 'diffto' => array(
+ ApiBase :: PARAM_TYPE => 'integer',
+ ),
+ 'difftoprev' => false,
+ 'difftotop' => false,
+ 'diffprop' => array(
+ ApiBase :: PARAM_ISMULTI => true,
+ ApiBase :: PARAM_DFLT => 'diff|lines|size|revids',
+ ApiBase :: PARAM_TYPE => array(
+ 'diff',
+ 'lines',
+ 'size',
+ 'revids',
+ )
+ ),
);
}
@@ -416,6 +540,13 @@
'generatexml' => 'generate XML parse tree for revision content',
'section' => 'only retrieve the content of this section',
'token' => 'Which tokens to obtain for each revision',
+ 'diffto' => 'Revision ID to diff each revision to',
+ 'difftoprev' => array(
+ 'Diff each revision to the previous (rvdir=older) or next (rvdir=newer) revision IN THE LIST (enum)',
+ 'NOTE: This is not necessarily the previous/next revision when rvuser/rvexcludeuser is set',
+ ),
+ 'difftotop' => 'Diff each revision to the page\'s current revision (enum)',
+ 'diffprop' => 'Diff properties to return',
);
}
Index: RELEASE-NOTES
===================================================================
--- RELEASE-NOTES (revision 45687)
+++ RELEASE-NOTES (working copy)
@@ -46,6 +46,7 @@
incorrectly
* (bug 16858) Revamped list=deletedrevs to make listing deleted contributions
and listing all deleted pages possible
+* (bug 13209) Added diff functionality to prop=revisions
=== Languages updated in 1.15 ===

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4273
Default Alt Text
13209.patch (11 KB)

Event Timeline