Index: trunk/phase3/includes/api/ApiQueryRevisions.php |
— | — | @@ -45,14 +45,14 @@ |
46 | 46 | $fld_comment = false, $fld_user = false, $fld_content = false; |
47 | 47 | |
48 | 48 | public function execute() { |
49 | | - $limit = $startid = $endid = $start = $end = $dir = $prop = $user = $excludeuser = null; |
| 49 | + $limit = $startid = $endid = $start = $end = $dir = $prop = $user = $excludeuser = $diffto = $difftoprev = null; |
50 | 50 | extract($this->extractRequestParams()); |
51 | 51 | |
52 | 52 | // If any of those parameters are used, work in 'enumeration' mode. |
53 | 53 | // Enum mode can only be used when exactly one page is provided. |
54 | | - // Enumerating revisions on multiple pages make it extremelly |
55 | | - // difficult to manage continuations and require additional sql indexes |
56 | | - $enumRevMode = (!is_null($user) || !is_null($excludeuser) || !is_null($limit) || !is_null($startid) || !is_null($endid) || $dir === 'newer' || !is_null($start) || !is_null($end)); |
| 54 | + // Enumerating revisions on multiple pages make it extremely |
| 55 | + // difficult to manage continuations and require additional SQL indexes |
| 56 | + $enumRevMode = (!is_null($user) || !is_null($excludeuser) || !is_null($limit) || !is_null($startid) || !is_null($endid) || $dir === 'newer' || !is_null($start) || !is_null($end) | !$difftoprev); |
57 | 57 | |
58 | 58 | |
59 | 59 | $pageSet = $this->getPageSet(); |
— | — | @@ -67,7 +67,7 @@ |
68 | 68 | $this->dieUsage('The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).', 'revids'); |
69 | 69 | |
70 | 70 | if ($pageCount > 1 && $enumRevMode) |
71 | | - $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'); |
| 71 | + $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start, end and difftoprev parameters may only be used on a single page.', 'multpages'); |
72 | 72 | |
73 | 73 | $this->addTables('revision'); |
74 | 74 | $this->addWhere('rev_deleted=0'); |
— | — | @@ -86,12 +86,36 @@ |
87 | 87 | $this->fld_comment = $this->addFieldsIf('rev_comment', isset ($prop['comment'])); |
88 | 88 | $this->fld_size = $this->addFieldsIf('rev_len', isset ($prop['size'])); |
89 | 89 | |
| 90 | + if($diffto || $difftoprev) |
| 91 | + $this->formatter = new DiffFormatter; |
| 92 | + if($diffto) |
| 93 | + { |
| 94 | + global $wgContLang; |
| 95 | + $difftoRev = Revision::newFromID($diffto); |
| 96 | + if(!($difftoRev instanceof Revision)) |
| 97 | + $this->dieUsage("There is no revision with ID $diffto", 'nosuchrev'); |
| 98 | + $this->diffOldText = $difftoRev->revText(); |
| 99 | + if($this->diffOldText == '') // deleted revision |
| 100 | + $this->dieUsage("There is no revision with ID $diffto", 'nosuchrev'); // fake non-existence |
| 101 | + $this->diffOldText = explode("\n", $wgContLang->segmentForDiff($this->diffOldText)); |
| 102 | + $this->diffto = $diffto; |
| 103 | + } |
| 104 | + else |
| 105 | + $this->diffto = false; |
| 106 | + if($difftoprev) |
| 107 | + { |
| 108 | + $this->revCache = array(); |
| 109 | + $this->difftoprev = true; |
| 110 | + } |
| 111 | + else |
| 112 | + $this->difftoprev = false; |
| 113 | + |
90 | 114 | if (isset ($prop['user'])) { |
91 | 115 | $this->addFields('rev_user'); |
92 | 116 | $this->addFields('rev_user_text'); |
93 | 117 | $this->fld_user = true; |
94 | 118 | } |
95 | | - if (isset ($prop['content'])) { |
| 119 | + if (isset ($prop['content']) || !is_null($diffto) || $difftoprev) { |
96 | 120 | |
97 | 121 | // For each page we will request, the user must have read rights for that page |
98 | 122 | foreach ($pageSet->getGoodTitles() as $title) { |
— | — | @@ -107,17 +131,17 @@ |
108 | 132 | $this->addFields('old_text'); |
109 | 133 | $this->addFields('old_flags'); |
110 | 134 | |
111 | | - $this->fld_content = true; |
| 135 | + $this->fld_content = isset($prop['content']); |
112 | 136 | |
113 | 137 | $this->expandTemplates = $expandtemplates; |
114 | 138 | } |
115 | 139 | |
116 | | - $userMax = ($this->fld_content ? 50 : 500); |
117 | | - $botMax = ($this->fld_content ? 200 : 10000); |
| 140 | + $userMax = ($this->fld_content || $diffto || $difftoprev ? 50 : 500); |
| 141 | + $botMax = ($this->fld_content || $diffto || $difftoprev ? 200 : 10000); |
118 | 142 | |
119 | 143 | if ($enumRevMode) { |
120 | 144 | |
121 | | - // This is mostly to prevent parameter errors (and optimize sql?) |
| 145 | + // This is mostly to prevent parameter errors (and optimize SQL?) |
122 | 146 | if (!is_null($startid) && !is_null($start)) |
123 | 147 | $this->dieUsage('start and startid cannot be used together', 'badparams'); |
124 | 148 | |
— | — | @@ -205,7 +229,41 @@ |
206 | 230 | $this->extractRowInfo($row)); |
207 | 231 | } |
208 | 232 | $db->freeResult($res); |
209 | | - |
| 233 | + |
| 234 | + if($this->difftoprev) |
| 235 | + { |
| 236 | + global $wgContLang; |
| 237 | + ksort($this->revCache, SORT_NUMERIC); |
| 238 | + $previousRevID = null; |
| 239 | + $oldText = null; |
| 240 | + $data =& $this->getResult()->getData(); |
| 241 | + $pageID = current(array_keys($pageSet->getGoodTitles())); |
| 242 | + $this->diffArr = array(); |
| 243 | + foreach($this->revCache as $revid => $revtext) |
| 244 | + { |
| 245 | + $r = array(); |
| 246 | + if(is_null($previousRevID)) |
| 247 | + { |
| 248 | + // First run |
| 249 | + $previousRevID = $revid; |
| 250 | + $oldText = explode("\n", $wgContLang->segmentForDiff($revtext)); |
| 251 | + continue; |
| 252 | + } |
| 253 | + $newText = explode("\n", $wgContLang->segmentForDiff($revtext)); |
| 254 | + $diff = new Diff($oldText, $newText); |
| 255 | + $r['from'] = $previousRevID; |
| 256 | + ApiResult::setContent($r, $wgContLang->unsegmentForDiff($this->formatter->format($diff))); |
| 257 | + $diffArr[$revid] = $r; |
| 258 | + |
| 259 | + $previousRevID = $revid; |
| 260 | + $oldText = $newText; |
| 261 | + } |
| 262 | + // Now that $this->diffArr is filled with diffprev elements, add them to the result |
| 263 | + foreach($data['query']['pages'][$pageID]['revisions'] as &$rev) |
| 264 | + if(isset($diffArr[$rev['revid']])) |
| 265 | + $rev['difftoprev'] = $diffArr[$rev['revid']]; |
| 266 | + } |
| 267 | + |
210 | 268 | // Ensure that all revisions are shown as '<rev>' elements |
211 | 269 | $result = $this->getResult(); |
212 | 270 | if ($result->getIsRawMode()) { |
— | — | @@ -248,8 +306,9 @@ |
249 | 307 | $vals['comment'] = $row->rev_comment; |
250 | 308 | } |
251 | 309 | |
| 310 | + if ($this->fld_content || $this->diffto || $this->difftoprev) |
| 311 | + $text = Revision :: getRevisionText($row); |
252 | 312 | if ($this->fld_content) { |
253 | | - $text = Revision :: getRevisionText($row); |
254 | 313 | if ($this->expandTemplates) { |
255 | 314 | global $wgParser; |
256 | 315 | $text = $wgParser->preprocess( $text, Title::newFromID($row->rev_page), new ParserOptions() ); |
— | — | @@ -257,6 +316,18 @@ |
258 | 317 | ApiResult :: setContent($vals, $text); |
259 | 318 | } |
260 | 319 | |
| 320 | + if($this->diffto) |
| 321 | + { |
| 322 | + global $wgContLang; |
| 323 | + $newText = explode("\n", $wgContLang->segmentForDiff($text)); |
| 324 | + $diff = new Diff($this->diffOldText, $newText); |
| 325 | + $vals['diffto']['from'] = $this->diffto; |
| 326 | + ApiResult::setContent($vals['diffto'], $wgContLang->unsegmentForDiff($this->formatter->format($diff))); |
| 327 | + } |
| 328 | + if($this->difftoprev) |
| 329 | + // Cache the revision's content for later use |
| 330 | + $this->revCache[$row->rev_id] = $text; |
| 331 | + |
261 | 332 | return $vals; |
262 | 333 | } |
263 | 334 | |
— | — | @@ -308,6 +379,10 @@ |
309 | 380 | ), |
310 | 381 | |
311 | 382 | 'expandtemplates' => false, |
| 383 | + 'diffto' => array( |
| 384 | + ApiBase :: PARAM_TYPE => 'integer' |
| 385 | + ), |
| 386 | + 'difftoprev' => false, |
312 | 387 | ); |
313 | 388 | } |
314 | 389 | |
— | — | @@ -322,7 +397,9 @@ |
323 | 398 | 'dir' => 'direction of enumeration - towards "newer" or "older" revisions (enum)', |
324 | 399 | 'user' => 'only include revisions made by user', |
325 | 400 | 'excludeuser' => 'exclude revisions made by user', |
326 | | - 'expandtemplates' => 'expand templates in revision content' |
| 401 | + 'expandtemplates' => 'expand templates in revision content', |
| 402 | + 'diffto' => 'Revision number to compare all revisions with', |
| 403 | + 'difftoprev' => 'Diff each revision to the previous one (enum)', |
327 | 404 | ); |
328 | 405 | } |
329 | 406 | |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -297,6 +297,7 @@ |
298 | 298 | * Outputting list of all user preferences rather than having to request them by |
299 | 299 | name |
300 | 300 | * (bug 11206) api.php should honor maxlag |
| 301 | +* Added diff generation to prop=revisions |
301 | 302 | |
302 | 303 | === Languages updated in 1.12 === |
303 | 304 | |