Index: trunk/extensions/FlaggedRevs/FlaggedRevsPage.body.php |
— | — | @@ -1,813 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -#(c) Joerg Baach, Aaron Schulz, 2007 GPL |
5 | | - |
6 | | -global $IP; |
7 | | -require_once( "$IP/includes/LogPage.php" ); |
8 | | -require_once( "$IP/includes/SpecialLog.php" ); |
9 | | - |
10 | | -class Revisionreview extends SpecialPage |
11 | | -{ |
12 | | - |
13 | | - function Revisionreview() { |
14 | | - SpecialPage::SpecialPage('Revisionreview', 'review'); |
15 | | - } |
16 | | - |
17 | | - function execute( $par ) { |
18 | | - global $wgRequest, $wgUser, $wgOut, $wgFlaggedRevComments, $wgFlaggedRevTags; |
19 | | - |
20 | | - $confirm = $wgRequest->wasPosted() && |
21 | | - $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ); |
22 | | - |
23 | | - if( $wgUser->isAllowed( 'review' ) ) { |
24 | | - if( $wgUser->isBlocked( !$confirm ) ) { |
25 | | - $wgOut->blockedPage(); |
26 | | - return; |
27 | | - } |
28 | | - } else { |
29 | | - $wgOut->permissionRequired( 'review' ); |
30 | | - return; |
31 | | - } |
32 | | - |
33 | | - $this->setHeaders(); |
34 | | - // Our target page |
35 | | - $this->target = $wgRequest->getText( 'target' ); |
36 | | - // Revision ID |
37 | | - $this->oldid = $wgRequest->getIntOrNull( 'oldid' ); |
38 | | - // Must be a valid content page |
39 | | - $this->page = Title::newFromUrl( $this->target ); |
40 | | - if ( !$this->target || !$this->oldid || !$this->page->isContentPage() ) { |
41 | | - $wgOut->addHTML( wfMsgExt('revreview-main',array('parse')) ); |
42 | | - return; |
43 | | - } |
44 | | - if( is_null($this->page) || is_null($this->oldid) ) { |
45 | | - $wgOut->showErrorPage('notargettitle', 'notargettext' ); |
46 | | - return; |
47 | | - } |
48 | | - // Check if page is protected |
49 | | - if( !$this->page->quickUserCan( 'edit' ) ) { |
50 | | - $wgOut->permissionRequired( 'badaccess-group0' ); |
51 | | - return; |
52 | | - } |
53 | | - // Special parameter mapping |
54 | | - $this->templateParams = $wgRequest->getVal( 'templateParams' ); |
55 | | - $this->imageParams = $wgRequest->getVal( 'imageParams' ); |
56 | | - // Log comment |
57 | | - $this->comment = $wgRequest->getText( 'wpReason' ); |
58 | | - // Additional notes |
59 | | - $this->notes = ($wgFlaggedRevComments) ? $wgRequest->getText('wpNotes') : ''; |
60 | | - // Get the revision's current flags, if any |
61 | | - $this->oflags = FlaggedRevs::getFlagsForPageRev( $this->oldid ); |
62 | | - // Get our accuracy/quality dimensions |
63 | | - $this->dims = array(); |
64 | | - $this->upprovedTags = 0; |
65 | | - foreach ( array_keys($wgFlaggedRevTags) as $tag ) { |
66 | | - $this->dims[$tag] = $wgRequest->getIntOrNull( "wp$tag" ); |
67 | | - // Must be greater than zero |
68 | | - if ( $this->dims[$tag] < 0 ) { |
69 | | - $wgOut->showErrorPage('notargettitle', 'notargettext' ); |
70 | | - return; |
71 | | - } |
72 | | - if ( $this->dims[$tag]==0 ) |
73 | | - $this->upprovedTags++; |
74 | | - // Check permissions |
75 | | - if( !$this->userCan( $tag, $this->oflags[$tag] ) ) { |
76 | | - # Users can't take away a status they can't set |
77 | | - $wgOut->permissionRequired( 'badaccess-group0' ); |
78 | | - return; |
79 | | - } else if( !$this->userCan( $tag, $this->dims[$tag] ) ) { |
80 | | - // Users cannot review to beyond their rights level |
81 | | - $wgOut->permissionRequired( 'badaccess-group0' ); |
82 | | - return; |
83 | | - } |
84 | | - } |
85 | | - // We must at least rate each category as 1, the minimum |
86 | | - // Exception: we can rate ALL as unapproved to depreciate a revision |
87 | | - $this->isValid = true; |
88 | | - if ( $this->upprovedTags && ($this->upprovedTags < count($wgFlaggedRevTags) || !$this->oflags) ) |
89 | | - $this->isValid = false; |
90 | | - |
91 | | - if( $this->isValid && $wgRequest->wasPosted() ) { |
92 | | - $this->submit( $wgRequest ); |
93 | | - } else { |
94 | | - $this->showRevision( $wgRequest ); |
95 | | - } |
96 | | - } |
97 | | - |
98 | | - /** |
99 | | - * @param string $tag |
100 | | - * @param int $val |
101 | | - * Returns true if a user can do something |
102 | | - */ |
103 | | - public static function userCan( $tag, $value ) { |
104 | | - global $wgFlagRestrictions, $wgUser; |
105 | | - |
106 | | - if ( !isset($wgFlagRestrictions[$tag]) ) |
107 | | - return true; |
108 | | - // Validators always have full access |
109 | | - if ( $wgUser->isAllowed('validate') ) |
110 | | - return true; |
111 | | - // Check if this user has any right that lets him/her set |
112 | | - // up to this particular value |
113 | | - foreach ( $wgFlagRestrictions[$tag] as $right => $level ) { |
114 | | - if ( $value <= $level && $wgUser->isAllowed($right) ) { |
115 | | - return true; |
116 | | - } |
117 | | - } |
118 | | - return false; |
119 | | - } |
120 | | - |
121 | | - /** |
122 | | - * @param webrequest $request |
123 | | - */ |
124 | | - function showRevision( $request ) { |
125 | | - global $wgOut, $wgUser, $wgTitle, $wgFlaggedRevComments, $wgFlaggedRevsOverride, |
126 | | - $wgFlaggedRevTags, $wgFlaggedRevValues; |
127 | | - |
128 | | - if ( !$this->isValid ) |
129 | | - $wgOut->addWikiText( '<strong>' . wfMsg( 'revreview-toolow' ) . '</strong>' ); |
130 | | - |
131 | | - $wgOut->addWikiText( wfMsg( 'revreview-selected', $this->page->getPrefixedText() ) ); |
132 | | - |
133 | | - $this->skin = $wgUser->getSkin(); |
134 | | - $rev = Revision::newFromTitle( $this->page, $this->oldid ); |
135 | | - // Check if rev exists |
136 | | - // Do not mess with deleted revisions |
137 | | - if( !isset( $rev ) || $rev->mDeleted ) { |
138 | | - $wgOut->showErrorPage( 'internalerror', 'notargettitle', 'notargettext' ); |
139 | | - return; |
140 | | - } |
141 | | - |
142 | | - $wgOut->addHtml( "<ul>" ); |
143 | | - $wgOut->addHtml( $this->historyLine( $rev ) ); |
144 | | - $wgOut->addHtml( "</ul>" ); |
145 | | - |
146 | | - if( $wgFlaggedRevsOverride ) |
147 | | - $wgOut->addWikiText( wfMsg('revreview-text') ); |
148 | | - |
149 | | - $formradios = array(); |
150 | | - // Dynamically contruct our radio options |
151 | | - foreach ( array_keys($wgFlaggedRevTags) as $tag ) { |
152 | | - $formradios[$tag] = array(); |
153 | | - for ($i=0; $i <= $wgFlaggedRevValues; $i++) { |
154 | | - $formradios[$tag][] = array( "revreview-$tag-$i", "wp$tag", $i ); |
155 | | - } |
156 | | - } |
157 | | - $items = array( |
158 | | - wfInputLabel( wfMsgHtml( 'revreview-log' ), 'wpReason', 'wpReason', 60 ), |
159 | | - wfSubmitButton( wfMsgHtml( 'revreview-submit' ) ) ); |
160 | | - $hidden = array( |
161 | | - wfHidden( 'wpEditToken', $wgUser->editToken() ), |
162 | | - wfHidden( 'target', $this->page->getPrefixedText() ), |
163 | | - wfHidden( 'oldid', $this->oldid ) ); |
164 | | - |
165 | | - $action = $wgTitle->escapeLocalUrl( 'action=submit' ); |
166 | | - $form = "<form name='revisionreview' action='$action' method='post'>"; |
167 | | - $form .= '<fieldset><legend>' . wfMsgHtml( 'revreview-legend' ) . '</legend><table><tr>'; |
168 | | - // Dynamically contruct our review types |
169 | | - foreach ( array_keys($wgFlaggedRevTags) as $tag ) { |
170 | | - $form .= '<td><strong>' . wfMsgHtml( "revreview-$tag" ) . '</strong></td><td width=\'20\'></td>'; |
171 | | - } |
172 | | - $form .= '</tr><tr>'; |
173 | | - foreach ( $formradios as $set => $ratioset ) { |
174 | | - $form .= '<td>'; |
175 | | - foreach( $ratioset as $item ) { |
176 | | - list( $message, $name, $field ) = $item; |
177 | | - // Don't give options the user can't set unless its the status quo |
178 | | - $attribs = array('id' => $name.$field); |
179 | | - if( !$this->userCan($set,$field) ) |
180 | | - $attribs['disabled'] = 'true'; |
181 | | - $form .= "<div>"; |
182 | | - $form .= Xml::radio( $name, $field, ($field==$this->dims[$set]), $attribs ); |
183 | | - $form .= Xml::label( wfMsg($message), $name.$field ); |
184 | | - $form .= "</div>\n"; |
185 | | - } |
186 | | - $form .= '</td><td width=\'20\'></td>'; |
187 | | - } |
188 | | - $form .= '</tr></table></fieldset>'; |
189 | | - // Add box to add live notes to a flagged revision |
190 | | - if ( $wgFlaggedRevComments ) { |
191 | | - $form .= "<fieldset><legend>" . wfMsgHtml( 'revreview-notes' ) . "</legend>" . |
192 | | - "<textarea tabindex='1' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%'>$this->notes</textarea>" . |
193 | | - "</fieldset>"; |
194 | | - } |
195 | | - |
196 | | - foreach( $items as $item ) { |
197 | | - $form .= '<p>' . $item . '</p>'; |
198 | | - } |
199 | | - foreach( $hidden as $item ) { |
200 | | - $form .= $item; |
201 | | - } |
202 | | - // XXX: hack, versioning params |
203 | | - $form .= Xml::hidden( 'templateParams', $this->templateParams ); |
204 | | - $form .= Xml::hidden( 'imageParams', $this->imageParams ); |
205 | | - |
206 | | - $form .= '</form>'; |
207 | | - $wgOut->addHtml( $form ); |
208 | | - } |
209 | | - |
210 | | - /** |
211 | | - * @param Revision $rev |
212 | | - * @returns string |
213 | | - */ |
214 | | - function historyLine( $rev ) { |
215 | | - global $wgContLang; |
216 | | - $date = $wgContLang->timeanddate( $rev->getTimestamp() ); |
217 | | - |
218 | | - $difflink = '(' . $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml('diff'), |
219 | | - '&diff=' . $rev->getId() . '&oldid=prev' ) . ')'; |
220 | | - |
221 | | - $revlink = $this->skin->makeLinkObj( $this->page, $date, 'oldid=' . $rev->getId() ); |
222 | | - |
223 | | - return |
224 | | - "<li> $difflink $revlink " . $this->skin->revUserLink( $rev ) . " " . $this->skin->revComment( $rev ) . "</li>"; |
225 | | - } |
226 | | - |
227 | | - function submit( $request ) { |
228 | | - global $wgOut, $wgUser; |
229 | | - |
230 | | - $approved = false; |
231 | | - # If all values are set to zero, this has been unapproved |
232 | | - foreach( $this->dims as $quality => $value ) { |
233 | | - if( $value ) { |
234 | | - $approved = true; |
235 | | - break; |
236 | | - } |
237 | | - } |
238 | | - // We can only approve actual revisions... |
239 | | - if ( $approved ) { |
240 | | - $rev = Revision::newFromTitle( $this->page, $this->oldid ); |
241 | | - // Do not mess with archived/deleted revisions |
242 | | - if ( is_null($rev) || $rev->mDeleted ) { |
243 | | - $wgOut->showErrorPage( 'internalerror', 'revnotfoundtext' ); |
244 | | - return; |
245 | | - } |
246 | | - } else { |
247 | | - $frev = FlaggedRevs::getFlaggedRev( $this->oldid ); |
248 | | - // If we can't find this flagged rev, return to page??? |
249 | | - if ( is_null($frev) ) { |
250 | | - $wgOut->redirect( $this->page->escapeLocalUrl() ); |
251 | | - return; |
252 | | - } |
253 | | - } |
254 | | - |
255 | | - $success = $approved ? $this->approveRevision( $rev, $this->notes ) : $this->unapproveRevision( $frev ); |
256 | | - |
257 | | - // Return to our page |
258 | | - if ( $success ) { |
259 | | - if( $request->getCheck( 'wpWatchthis' ) ) { |
260 | | - $wgUser->addWatch( $this->page ); |
261 | | - } else { |
262 | | - $wgUser->removeWatch( $this->page ); |
263 | | - } |
264 | | - $wgOut->redirect( $this->page->escapeLocalUrl() ); |
265 | | - } else { |
266 | | - $wgOut->showErrorPage( 'internalerror', 'revreview-changed' ); |
267 | | - } |
268 | | - } |
269 | | - |
270 | | - /** |
271 | | - * @param Revision $rev |
272 | | - * Adds or updates the flagged revision table for this page/id set |
273 | | - */ |
274 | | - function approveRevision( $rev=NULL, $notes='' ) { |
275 | | - global $wgUser, $wgFlaggedRevsWatch, $wgParser; |
276 | | - |
277 | | - if( is_null($rev) ) |
278 | | - return false; |
279 | | - // Get the page this corresponds to |
280 | | - $title = $rev->getTitle(); |
281 | | - |
282 | | - $quality = 0; |
283 | | - if ( FlaggedRevs::isQuality($this->dims) ) { |
284 | | - $quality = FlaggedRevs::getLCQuality($this->dims); |
285 | | - $quality = ($quality > 1) ? $quality : 1; |
286 | | - } |
287 | | - // Our flags |
288 | | - $flagset = array(); |
289 | | - foreach( $this->dims as $tag => $value ) { |
290 | | - $flagset[] = array( |
291 | | - 'frt_rev_id' => $rev->getId(), |
292 | | - 'frt_dimension' => $tag, |
293 | | - 'frt_value' => $value |
294 | | - ); |
295 | | - } |
296 | | - |
297 | | - // XXX: hack, our template version pointers |
298 | | - $tmpset = $templates = array(); |
299 | | - $templateMap = explode('#',trim($this->templateParams) ); |
300 | | - foreach( $templateMap as $template ) { |
301 | | - if( !$template ) continue; |
302 | | - |
303 | | - $m = explode('|',$template,2); |
304 | | - if( !isset($m[0]) || !isset($m[1]) || !$m[0] ) continue; |
305 | | - |
306 | | - list($prefixed_text,$rev_id) = $m; |
307 | | - |
308 | | - if( in_array($prefixed_text,$templates) ) continue; // No dups! |
309 | | - $templates[] = $prefixed_text; |
310 | | - |
311 | | - $tmp_title = Title::newFromText( $prefixed_text ); // Normalize this to be sure... |
312 | | - if( is_null($title) ) continue; // Page must exist! |
313 | | - |
314 | | - $tmpset[] = array( |
315 | | - 'ft_rev_id' => $rev->getId(), |
316 | | - 'ft_namespace' => $tmp_title->getNamespace(), |
317 | | - 'ft_title' => $tmp_title->getDBKey(), |
318 | | - 'ft_tmp_rev_id' => $rev_id |
319 | | - ); |
320 | | - } |
321 | | - // XXX: hack, our image version pointers |
322 | | - $imgset = $images = array(); |
323 | | - $imageMap = explode('#',trim($this->imageParams) ); |
324 | | - foreach( $imageMap as $image ) { |
325 | | - if( !$image ) continue; |
326 | | - $m = explode('|',$image,2); |
327 | | - |
328 | | - if( !isset($m[0]) || !isset($m[1]) || !$m[0] ) continue; |
329 | | - |
330 | | - list($dbkey,$timestamp) = $m; |
331 | | - |
332 | | - if( in_array($dbkey,$images) ) continue; // No dups! |
333 | | - $images[] = $dbkey; |
334 | | - |
335 | | - $img_title = Title::makeTitle( NS_IMAGE, $dbkey ); // Normalize this to be sure... |
336 | | - if( is_null($img_title) ) continue; // Page must exist! |
337 | | - |
338 | | - $imgset[] = array( |
339 | | - 'fi_rev_id' => $rev->getId(), |
340 | | - 'fi_name' => $img_title->getDBKey(), |
341 | | - 'fi_img_timestamp' => $timestamp |
342 | | - ); |
343 | | - } |
344 | | - |
345 | | - $dbw = wfGetDB( DB_MASTER ); |
346 | | - $dbw->begin(); |
347 | | - // Update our versioning pointers |
348 | | - if( !empty( $tmpset ) ) { |
349 | | - $dbw->replace( 'flaggedtemplates', array( array('ft_rev_id','ft_namespace','ft_title') ), $tmpset, |
350 | | - __METHOD__ ); |
351 | | - } |
352 | | - if( !empty( $imgset ) ) { |
353 | | - $dbw->replace( 'flaggedimages', array( array('fi_rev_id','fi_name') ), $imgset, |
354 | | - __METHOD__ ); |
355 | | - } |
356 | | - // Get the page text and resolve all templates |
357 | | - list($fulltext,$complete) = FlaggedRevs::expandText( $rev->getText(), $rev->getTitle(), $rev->getId() ); |
358 | | - if( !$complete ) { |
359 | | - $dbw->rollback(); // All versions must be specified, 0 for none |
360 | | - return false; |
361 | | - } |
362 | | - // Our review entry |
363 | | - $revset = array( |
364 | | - 'fr_rev_id' => $rev->getId(), |
365 | | - 'fr_namespace' => $title->getNamespace(), |
366 | | - 'fr_title' => $title->getDBkey(), |
367 | | - 'fr_user' => $wgUser->getId(), |
368 | | - 'fr_timestamp' => wfTimestampNow(), |
369 | | - 'fr_comment' => $notes, |
370 | | - 'fr_text' => $fulltext, // Store expanded text for speed |
371 | | - 'fr_quality' => $quality |
372 | | - ); |
373 | | - // Update flagged revisions table |
374 | | - $dbw->replace( 'flaggedrevs', array( array('fr_rev_id','fr_namespace','fr_title') ), $revset, __METHOD__ ); |
375 | | - // Set all of our flags |
376 | | - $dbw->replace( 'flaggedrevtags', array( array('frt_rev_id','frt_dimension') ), $flagset, __METHOD__ ); |
377 | | - // Mark as patrolled |
378 | | - $dbw->update( 'recentchanges', |
379 | | - array( 'rc_patrolled' => 1 ), |
380 | | - array( 'rc_this_oldid' => $rev->getId() ), |
381 | | - __METHOD__ |
382 | | - ); |
383 | | - $dbw->commit(); |
384 | | - |
385 | | - // Update the article review log |
386 | | - $this->updateLog( $this->page, $this->dims, $this->comment, $this->oldid, true ); |
387 | | - |
388 | | - $article = new Article( $this->page ); |
389 | | - // Update the links tables as the stable version may now be the default page... |
390 | | - $parserCache =& ParserCache::singleton(); |
391 | | - $poutput = $parserCache->get( $article, $wgUser ); |
392 | | - if( $poutput==false ) { |
393 | | - $text = $article->getContent(); |
394 | | - $poutput = $wgParser->parse($text, $article->mTitle, ParserOptions::newFromUser($wgUser)); |
395 | | - } |
396 | | - $u = new LinksUpdate( $this->page, $poutput ); |
397 | | - $u->doUpdate(); // Will trigger our hook to add stable links too... |
398 | | - |
399 | | - # Clear the cache... |
400 | | - $this->page->invalidateCache(); |
401 | | - # Might as well save the cache |
402 | | - $parserCache->save( $poutput, $article, $wgUser ); |
403 | | - # Purge squid for this page only |
404 | | - $this->page->purgeSquid(); |
405 | | - |
406 | | - return true; |
407 | | - } |
408 | | - |
409 | | - /** |
410 | | - * @param Revision $rev |
411 | | - * Removes flagged revision data for this page/id set |
412 | | - */ |
413 | | - function unapproveRevision( $row=NULL ) { |
414 | | - global $wgUser, $wgFlaggedRevsWatch; |
415 | | - |
416 | | - if( is_null($row) ) return false; |
417 | | - |
418 | | - $user = $wgUser->getId(); |
419 | | - |
420 | | - wfProfileIn( __METHOD__ ); |
421 | | - $dbw = wfGetDB( DB_MASTER ); |
422 | | - // Delete from table |
423 | | - $dbw->delete( 'flaggedrevs', array( 'fr_rev_id' => $row->fr_rev_id ) ); |
424 | | - // Wipe versioning pointers |
425 | | - $dbw->delete( 'flaggedtemplates', array( 'ft_rev_id' => $row->fr_rev_id ) ); |
426 | | - $dbw->delete( 'flaggedimages', array( 'fi_rev_id' => $row->fr_rev_id ) ); |
427 | | - // And the flags... |
428 | | - $dbw->delete( 'flaggedrevtags', array( 'frt_rev_id' => $row->fr_rev_id ) ); |
429 | | - |
430 | | - // Update the article review log |
431 | | - $this->updateLog( $this->page, $this->dims, $this->comment, $this->oldid, false ); |
432 | | - |
433 | | - $article = new Article( $this->page ); |
434 | | - // Update the links tables as a new stable version |
435 | | - // may now be the default page. |
436 | | - $parserCache =& ParserCache::singleton(); |
437 | | - $poutput = $parserCache->get( $article, $wgUser ); |
438 | | - if ( $poutput==false ) { |
439 | | - $text = $article->getContent(); |
440 | | - $poutput = $wgParser->parse($text, $article->mTitle, ParserOptions::newFromUser($wgUser)); |
441 | | - } |
442 | | - $u = new LinksUpdate( $this->page, $poutput ); |
443 | | - $u->doUpdate(); |
444 | | - |
445 | | - # Clear the cache... |
446 | | - $this->page->invalidateCache(); |
447 | | - # Might as well save the cache |
448 | | - $parserCache->save( $poutput, $article, $wgUser ); |
449 | | - # Purge squid for this page only |
450 | | - $this->page->purgeSquid(); |
451 | | - |
452 | | - wfProfileOut( __METHOD__ ); |
453 | | - |
454 | | - return true; |
455 | | - } |
456 | | - |
457 | | - /** |
458 | | - * Record a log entry on the action |
459 | | - * @param Title $title |
460 | | - * @param array $dimensions |
461 | | - * @param string $comment |
462 | | - * @param int $revid |
463 | | - * @param bool $approve |
464 | | - */ |
465 | | - function updateLog( $title, $dimensions, $comment, $oldid, $approve ) { |
466 | | - $log = new LogPage( 'review' ); |
467 | | - // ID, accuracy, depth, style |
468 | | - $ratings = array(); |
469 | | - foreach( $dimensions as $quality => $level ) { |
470 | | - $ratings[] = wfMsg( "revreview-$quality" ) . ": " . wfMsg("revreview-$quality-$level"); |
471 | | - } |
472 | | - $rating = ($approve) ? ' [' . implode(', ',$ratings). ']' : ''; |
473 | | - // Append comment with action |
474 | | - // FIXME: do this better |
475 | | - $action = wfMsgExt('review-logaction', array('parsemag'), $oldid ); |
476 | | - if( $approve ) |
477 | | - $comment = ($comment) ? "$action: $comment$rating" : "$action $rating"; |
478 | | - else |
479 | | - $comment = ($comment) ? "$action: $comment" : "$action"; |
480 | | - |
481 | | - if( $approve ) { |
482 | | - $log->addEntry( 'approve', $title, $comment ); |
483 | | - } else { |
484 | | - $log->addEntry( 'unapprove', $title, $comment ); |
485 | | - } |
486 | | - } |
487 | | -} |
488 | | - |
489 | | -class Stableversions extends SpecialPage |
490 | | -{ |
491 | | - |
492 | | - function Stableversions() { |
493 | | - SpecialPage::SpecialPage('Stableversions'); |
494 | | - } |
495 | | - |
496 | | - function execute( $par ) { |
497 | | - global $wgRequest; |
498 | | - |
499 | | - $this->setHeaders(); |
500 | | - // Our target page |
501 | | - $this->page = $wgRequest->getText( 'page' ); |
502 | | - // Revision ID |
503 | | - $this->oldid = $wgRequest->getIntOrNull( 'oldid' ); |
504 | | - |
505 | | - if( $this->oldid ) { |
506 | | - $this->showStableRevision( $wgRequest ); |
507 | | - } else if( $this->page ) { |
508 | | - $this->showStableList( $wgRequest ); |
509 | | - } else { |
510 | | - $this->showForm( $wgRequest ); |
511 | | - } |
512 | | - } |
513 | | - |
514 | | - function showForm( $wgRequest ) { |
515 | | - global $wgOut, $wgTitle, $wgScript; |
516 | | - |
517 | | - $encPage = $this->page; |
518 | | - $encId = $this->oldid; |
519 | | - |
520 | | - $form = "<form name='stableversions' action='$wgScript' method='get'>"; |
521 | | - $form .= "<fieldset><legend>".wfMsg('stableversions-leg1')."</legend>"; |
522 | | - $form .= "<table><tr>"; |
523 | | - $form .= "<td>".Xml::hidden( 'title', $wgTitle->getPrefixedText() )."</td>"; |
524 | | - $form .= "<td>".wfMsgHtml("stableversions-page").":</td>"; |
525 | | - $form .= "<td>".Xml::input('page', 50, $encPage, array( 'id' => 'page' ) )."</td>"; |
526 | | - $form .= "<td>".wfSubmitButton( wfMsgHtml( 'go' ) )."</td>"; |
527 | | - $form .= "</tr></table>"; |
528 | | - $form .= "</fieldset></form>\n"; |
529 | | - |
530 | | - $form .= "<form name='stableversion' action='$wgScript' method='get'>"; |
531 | | - $form .= "<fieldset><legend>".wfMsg('stableversions-leg2')."</legend>"; |
532 | | - $form .= "<table><tr>"; |
533 | | - $form .= "<td>".Xml::hidden( 'title', $wgTitle->getPrefixedDBkey() )."</td>"; |
534 | | - $form .= "<td>".wfMsgHtml("stableversions-rev").":</td>"; |
535 | | - $form .= "<td>".Xml::input('oldid', 15, $encId, array( 'id' => 'oldid' ) )."</td>"; |
536 | | - $form .= "<td>".wfSubmitButton( wfMsgHtml( 'go' ) )."</td>"; |
537 | | - $form .= "</tr></table>"; |
538 | | - $form .= "</fieldset></form>"; |
539 | | - |
540 | | - $wgOut->addHTML( $form ); |
541 | | - } |
542 | | - |
543 | | - function showStableRevision( $frev ) { |
544 | | - global $wgParser, $wgLang, $wgUser, $wgOut, $wgTitle; |
545 | | - |
546 | | - // Get the revision |
547 | | - $frev = FlaggedRevs::getFlaggedRev( $this->oldid ); |
548 | | - // Revision must exists |
549 | | - if( is_null($frev) ) { |
550 | | - $wgOut->showErrorPage( 'notargettitle', 'revnotfoundtext' ); |
551 | | - return; |
552 | | - } |
553 | | - $page = Title::makeTitle( $frev->fr_namespace, $frev->fr_title ); |
554 | | - |
555 | | - $wgOut->setPagetitle( $page->getPrefixedText() ); |
556 | | - |
557 | | - // Modifier instance |
558 | | - $RevFlagging = new FlaggedRevs(); |
559 | | - // Get flags and date |
560 | | - $flags = FlaggedRevs::getFlagsForPageRev( $frev->fr_rev_id ); |
561 | | - $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $frev->fr_timestamp), true ); |
562 | | - // We will be looking at the reviewed revision... |
563 | | - $tag = wfMsgExt('revreview-static', array('parseinline'), urlencode($page->getPrefixedText()), $time, $page->getPrefixedText()); |
564 | | - $tag .= ' <a id="mwrevisiontoggle" style="display:none;" href="javascript:toggleRevRatings()">' . wfMsg('revreview-toggle') . '</a>'; |
565 | | - $tag .= '<span id="mwrevisionratings" style="display:block;">' . |
566 | | - wfMsg('revreview-oldrating') . $RevFlagging->addTagRatings( $flags ) . |
567 | | - '</span>'; |
568 | | - // Parse the text... |
569 | | - $text = $RevFlagging->getFlaggedRevText( $this->oldid ); |
570 | | - $options = ParserOptions::newFromUser($wgUser); |
571 | | - $parserOutput = $RevFlagging->parseStableText( $page, $text, $this->oldid, $options ); |
572 | | - $notes = $RevFlagging->ReviewNotes( $frev ); |
573 | | - // Set the new body HTML, place a tag on top |
574 | | - $wgOut->addHTML('<div id="mwrevisiontag" class="flaggedrevs_notice plainlinks">'.$tag.'</div>' . $parserOutput->getText() . $notes); |
575 | | - // Show stable categories and interwiki links only |
576 | | - $wgOut->mCategoryLinks = array(); |
577 | | - $wgOut->addCategoryLinks( $parserOutput->getCategories() ); |
578 | | - $wgOut->mLanguageLinks = array(); |
579 | | - $wgOut->addLanguageLinks( $parserOutput->getLanguageLinks() ); |
580 | | - } |
581 | | - |
582 | | - function showStableList() { |
583 | | - global $wgOut, $wgUser, $wgLang; |
584 | | - |
585 | | - $skin = $wgUser->getSkin(); |
586 | | - // Must be a valid page/Id |
587 | | - $page = Title::newFromUrl( $this->page ); |
588 | | - if( is_null($page) || !$page->isContentPage() ) { |
589 | | - $wgOut->showErrorPage('notargettitle', 'allpagesbadtitle' ); |
590 | | - return; |
591 | | - } |
592 | | - $article = new Article( $page ); |
593 | | - if( !$article ) { |
594 | | - $wgOut->showErrorPage('notargettitle', 'allpagesbadtitle' ); |
595 | | - return; |
596 | | - } |
597 | | - $pager = new StableRevisionsPager( $this, array(), $page->getNamespace(), $page->getDBkey() ); |
598 | | - if ( $pager->getNumRows() ) { |
599 | | - $wgOut->addHTML( wfMsgExt('stableversions-list', array('parse'), $page->getPrefixedText() ) ); |
600 | | - $wgOut->addHTML( $pager->getNavigationBar() ); |
601 | | - $wgOut->addHTML( "<ul>" . $pager->getBody() . "</ul>" ); |
602 | | - $wgOut->addHTML( $pager->getNavigationBar() ); |
603 | | - } else { |
604 | | - $wgOut->addHTML( wfMsgExt('stableversions-none', array('parse'), $page->getPrefixedText() ) ); |
605 | | - } |
606 | | - } |
607 | | - |
608 | | - function formatRow( $row ) { |
609 | | - global $wgLang, $wgUser; |
610 | | - |
611 | | - static $skin=null; |
612 | | - if( is_null( $skin ) ) |
613 | | - $skin = $wgUser->getSkin(); |
614 | | - |
615 | | - $SV = SpecialPage::getTitleFor( 'Stableversions' ); |
616 | | - $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->rev_timestamp), true ); |
617 | | - $ftime = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->fr_timestamp), true ); |
618 | | - $review = wfMsg( 'stableversions-review', $ftime ); |
619 | | - |
620 | | - $lev = wfMsg('hist-stable'); |
621 | | - if( $row->fr_quality >=1 ) $lev = wfMsg('hist-quality'); |
622 | | - |
623 | | - return '<li>'.$skin->makeKnownLinkObj( $SV, $time, 'oldid='.$row->fr_rev_id ).' ('.$review.') <b>'.$lev.'</b></li>'; |
624 | | - } |
625 | | -} |
626 | | - |
627 | | -/** |
628 | | - * Query to list out stable versions for a page |
629 | | - */ |
630 | | -class StableRevisionsPager extends ReverseChronologicalPager { |
631 | | - public $mForm, $mConds; |
632 | | - |
633 | | - function __construct( $form, $conds = array(), $namespace, $title ) { |
634 | | - $this->mForm = $form; |
635 | | - $this->mConds = $conds; |
636 | | - $this->namespace = $namespace; |
637 | | - $this->title = $title; |
638 | | - parent::__construct(); |
639 | | - } |
640 | | - |
641 | | - function formatRow( $row ) { |
642 | | - $block = new Block; |
643 | | - return $this->mForm->formatRow( $row ); |
644 | | - } |
645 | | - |
646 | | - function getQueryInfo() { |
647 | | - $conds = $this->mConds; |
648 | | - $conds["fr_namespace"] = $this->namespace; |
649 | | - $conds["fr_title"] = $this->title; |
650 | | - $conds[] = "fr_rev_id = rev_id"; |
651 | | - $conds["rev_deleted"] = 0; |
652 | | - return array( |
653 | | - 'tables' => array('flaggedrevs','revision'), |
654 | | - 'fields' => 'fr_rev_id,fr_timestamp,rev_timestamp,fr_quality', |
655 | | - 'conds' => $conds |
656 | | - ); |
657 | | - } |
658 | | - |
659 | | - function getIndexField() { |
660 | | - return 'fr_rev_id'; |
661 | | - } |
662 | | -} |
663 | | - |
664 | | -/** |
665 | | - * Special page to list unreviewed pages |
666 | | - */ |
667 | | -class Unreviewedpages extends SpecialPage |
668 | | -{ |
669 | | - |
670 | | - function Unreviewedpages() { |
671 | | - SpecialPage::SpecialPage('Unreviewedpages'); |
672 | | - } |
673 | | - |
674 | | - function execute( $par ) { |
675 | | - global $wgRequest; |
676 | | - |
677 | | - $this->setHeaders(); |
678 | | - |
679 | | - $this->showList( $wgRequest ); |
680 | | - } |
681 | | - |
682 | | - function showList( $wgRequest ) { |
683 | | - global $wgOut, $wgUser, $wgScript, $wgTitle; |
684 | | - |
685 | | - $skin = $wgUser->getSkin(); |
686 | | - $namespace = $wgRequest->getIntOrNull( 'namespace' ); |
687 | | - $nonquality = $wgRequest->getVal( 'includenonquality' ); |
688 | | - |
689 | | - $action = htmlspecialchars( $wgScript ); |
690 | | - $wgOut->addHTML( "<form action=\"$action\" method=\"get\">\n" . |
691 | | - '<fieldset><legend>' . wfMsg('viewunreviewed') . '</legend>' . |
692 | | - $this->getNamespaceMenu( $namespace ) . "\n" . |
693 | | - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" . |
694 | | - '<p>' . Xml::check( 'includenonquality', $nonquality, array('id' => 'includenonquality') ) . |
695 | | - ' ' . Xml::label( wfMsgHtml("included-nonquality"), 'includenonquality' ) . "</p>\n" . |
696 | | - Xml::hidden( 'title', $wgTitle->getPrefixedText() ) . |
697 | | - "</fieldset></form>"); |
698 | | - |
699 | | - list( $limit, $offset ) = wfCheckLimits(); |
700 | | - |
701 | | - $sdr = new UnreviewedPagesPage( $namespace, $nonquality ); |
702 | | - $sdr->doQuery( $offset, $limit ); |
703 | | - } |
704 | | - |
705 | | - function getNamespaceMenu( $selected=NULL, $allnamespaces = null, $includehidden=false ) { |
706 | | - global $wgContLang, $wgContentNamespaces; |
707 | | - |
708 | | - $selector = "<label for='namespace'>" . wfMsgHtml('namespace') . "</label>"; |
709 | | - if( $selected !== '' ) { |
710 | | - if( is_null( $selected ) ) { |
711 | | - // No namespace selected; let exact match work without hitting Main |
712 | | - $selected = ''; |
713 | | - } else { |
714 | | - // Let input be numeric strings without breaking the empty match. |
715 | | - $selected = intval( $selected ); |
716 | | - } |
717 | | - } |
718 | | - $s = "\n<select id='namespace' name='namespace' class='namespaceselector'>\n"; |
719 | | - $arr = $wgContLang->getFormattedNamespaces(); |
720 | | - if( !is_null($allnamespaces) ) { |
721 | | - $arr = array($allnamespaces => wfMsg('namespacesall')) + $arr; |
722 | | - } |
723 | | - |
724 | | - $s .= "\t" . Xml::element("option", array("value" => "all"), "all") . "\n"; |
725 | | - |
726 | | - foreach ($arr as $index => $name) { |
727 | | - # Content only |
728 | | - if ($index < NS_MAIN || !in_array($index, $wgContentNamespaces) ) continue; |
729 | | - |
730 | | - $name = $index !== 0 ? $name : wfMsg('blanknamespace'); |
731 | | - |
732 | | - if ($index === $selected) { |
733 | | - $s .= "\t" . Xml::element("option", |
734 | | - array("value" => $index, "selected" => "selected"), |
735 | | - $name) . "\n"; |
736 | | - } else { |
737 | | - $s .= "\t" . Xml::element("option", array("value" => $index), $name) . "\n"; |
738 | | - } |
739 | | - } |
740 | | - $s .= "</select>\n"; |
741 | | - return $s; |
742 | | - } |
743 | | -} |
744 | | - |
745 | | -/** |
746 | | - * Query to list out unreviewed pages |
747 | | - */ |
748 | | -class UnreviewedPagesPage extends PageQueryPage { |
749 | | - |
750 | | - function __construct( $namespace=NULL, $nonquality=false ) { |
751 | | - $this->namespace = $namespace; |
752 | | - $this->nonquality = $nonquality; |
753 | | - } |
754 | | - |
755 | | - function getName() { |
756 | | - return 'UnreviewedPages'; |
757 | | - } |
758 | | - |
759 | | - function isExpensive( ) { return true; } |
760 | | - function isSyndicated() { return false; } |
761 | | - |
762 | | - function getPageHeader( ) { |
763 | | - return '<p>'.wfMsg("unreviewed-list")."</p>\n"; |
764 | | - } |
765 | | - |
766 | | - function getSQLText( &$dbr, $namespace, $includenonquality = false ) { |
767 | | - global $wgContentNamespaces; |
768 | | - |
769 | | - list( $page, $flaggedrevs ) = $dbr->tableNamesN( 'page', 'flaggedrevs' ); |
770 | | - |
771 | | - # Must be a content page... |
772 | | - $contentNS = 'page_namespace IN(' . implode(',',$wgContentNamespaces) . ')'; |
773 | | - |
774 | | - $ns = ($namespace !== null) ? "page_namespace=$namespace" : '1 = 1'; |
775 | | - |
776 | | - $where = $includenonquality ? '1 = 1' : 'fr_rev_id IS NULL'; |
777 | | - $having = $includenonquality ? 'MAX(fr_quality) < 1' : '1 = 1'; |
778 | | - |
779 | | - $sql = |
780 | | - "SELECT page_namespace,page_title,page_len AS size |
781 | | - FROM $page |
782 | | - LEFT JOIN $flaggedrevs ON (fr_namespace = page_namespace AND fr_title = page_title) |
783 | | - WHERE page_is_redirect=0 AND $ns AND $contentNS AND ($where) |
784 | | - GROUP BY page_id HAVING $having "; |
785 | | - return $sql; |
786 | | - } |
787 | | - |
788 | | - function getSQL() { |
789 | | - $dbr = wfGetDB( DB_SLAVE ); |
790 | | - return $this->getSQLText( $dbr, $this->namespace, $this->nonquality ); |
791 | | - } |
792 | | - |
793 | | - function getOrder() { |
794 | | - return 'ORDER BY page_id DESC'; |
795 | | - } |
796 | | - |
797 | | - function formatResult( $skin, $result ) { |
798 | | - global $wgLang; |
799 | | - |
800 | | - $fname = 'UnreviewedPagesPage::formatResult'; |
801 | | - $title = Title::makeTitle( $result->page_namespace, $result->page_title ); |
802 | | - $link = $skin->makeKnownLinkObj( $title ); |
803 | | - $stxt = ''; |
804 | | - if (!is_null($size = $result->size)) { |
805 | | - if ($size == 0) |
806 | | - $stxt = ' <small>' . wfMsgHtml('historyempty') . '</small>'; |
807 | | - else |
808 | | - $stxt = ' <small>' . wfMsgHtml('historysize', $wgLang->formatNum( $size ) ) . '</small>'; |
809 | | - } |
810 | | - |
811 | | - return( "{$link} {$stxt}" ); |
812 | | - } |
813 | | -} |
814 | | - |
Index: trunk/extensions/FlaggedRevs/FlaggedRevsPage_body.php |
— | — | @@ -0,0 +1,813 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +#(c) Joerg Baach, Aaron Schulz, 2007 GPL
|
| 5 | +
|
| 6 | +global $IP;
|
| 7 | +require_once( "$IP/includes/LogPage.php" );
|
| 8 | +require_once( "$IP/includes/SpecialLog.php" );
|
| 9 | +
|
| 10 | +class Revisionreview extends SpecialPage
|
| 11 | +{
|
| 12 | +
|
| 13 | + function Revisionreview() {
|
| 14 | + SpecialPage::SpecialPage('Revisionreview', 'review');
|
| 15 | + }
|
| 16 | +
|
| 17 | + function execute( $par ) {
|
| 18 | + global $wgRequest, $wgUser, $wgOut, $wgFlaggedRevComments, $wgFlaggedRevTags;
|
| 19 | +
|
| 20 | + $confirm = $wgRequest->wasPosted() &&
|
| 21 | + $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
|
| 22 | +
|
| 23 | + if( $wgUser->isAllowed( 'review' ) ) {
|
| 24 | + if( $wgUser->isBlocked( !$confirm ) ) {
|
| 25 | + $wgOut->blockedPage();
|
| 26 | + return;
|
| 27 | + }
|
| 28 | + } else {
|
| 29 | + $wgOut->permissionRequired( 'review' );
|
| 30 | + return;
|
| 31 | + }
|
| 32 | +
|
| 33 | + $this->setHeaders();
|
| 34 | + // Our target page
|
| 35 | + $this->target = $wgRequest->getText( 'target' );
|
| 36 | + // Revision ID
|
| 37 | + $this->oldid = $wgRequest->getIntOrNull( 'oldid' );
|
| 38 | + // Must be a valid content page
|
| 39 | + $this->page = Title::newFromUrl( $this->target );
|
| 40 | + if ( !$this->target || !$this->oldid || !$this->page->isContentPage() ) {
|
| 41 | + $wgOut->addHTML( wfMsgExt('revreview-main',array('parse')) );
|
| 42 | + return;
|
| 43 | + }
|
| 44 | + if( is_null($this->page) || is_null($this->oldid) ) {
|
| 45 | + $wgOut->showErrorPage('notargettitle', 'notargettext' );
|
| 46 | + return;
|
| 47 | + }
|
| 48 | + // Check if page is protected
|
| 49 | + if( !$this->page->quickUserCan( 'edit' ) ) {
|
| 50 | + $wgOut->permissionRequired( 'badaccess-group0' );
|
| 51 | + return;
|
| 52 | + }
|
| 53 | + // Special parameter mapping
|
| 54 | + $this->templateParams = $wgRequest->getVal( 'templateParams' );
|
| 55 | + $this->imageParams = $wgRequest->getVal( 'imageParams' );
|
| 56 | + // Log comment
|
| 57 | + $this->comment = $wgRequest->getText( 'wpReason' );
|
| 58 | + // Additional notes
|
| 59 | + $this->notes = ($wgFlaggedRevComments) ? $wgRequest->getText('wpNotes') : '';
|
| 60 | + // Get the revision's current flags, if any
|
| 61 | + $this->oflags = FlaggedRevs::getFlagsForPageRev( $this->oldid );
|
| 62 | + // Get our accuracy/quality dimensions
|
| 63 | + $this->dims = array();
|
| 64 | + $this->upprovedTags = 0;
|
| 65 | + foreach ( array_keys($wgFlaggedRevTags) as $tag ) {
|
| 66 | + $this->dims[$tag] = $wgRequest->getIntOrNull( "wp$tag" );
|
| 67 | + // Must be greater than zero
|
| 68 | + if ( $this->dims[$tag] < 0 ) {
|
| 69 | + $wgOut->showErrorPage('notargettitle', 'notargettext' );
|
| 70 | + return;
|
| 71 | + }
|
| 72 | + if ( $this->dims[$tag]==0 )
|
| 73 | + $this->upprovedTags++;
|
| 74 | + // Check permissions
|
| 75 | + if( !$this->userCan( $tag, $this->oflags[$tag] ) ) {
|
| 76 | + # Users can't take away a status they can't set
|
| 77 | + $wgOut->permissionRequired( 'badaccess-group0' );
|
| 78 | + return;
|
| 79 | + } else if( !$this->userCan( $tag, $this->dims[$tag] ) ) {
|
| 80 | + // Users cannot review to beyond their rights level
|
| 81 | + $wgOut->permissionRequired( 'badaccess-group0' );
|
| 82 | + return;
|
| 83 | + }
|
| 84 | + }
|
| 85 | + // We must at least rate each category as 1, the minimum
|
| 86 | + // Exception: we can rate ALL as unapproved to depreciate a revision
|
| 87 | + $this->isValid = true;
|
| 88 | + if ( $this->upprovedTags && ($this->upprovedTags < count($wgFlaggedRevTags) || !$this->oflags) )
|
| 89 | + $this->isValid = false;
|
| 90 | +
|
| 91 | + if( $this->isValid && $wgRequest->wasPosted() ) {
|
| 92 | + $this->submit( $wgRequest );
|
| 93 | + } else {
|
| 94 | + $this->showRevision( $wgRequest );
|
| 95 | + }
|
| 96 | + }
|
| 97 | +
|
| 98 | + /**
|
| 99 | + * @param string $tag
|
| 100 | + * @param int $val
|
| 101 | + * Returns true if a user can do something
|
| 102 | + */
|
| 103 | + public static function userCan( $tag, $value ) {
|
| 104 | + global $wgFlagRestrictions, $wgUser;
|
| 105 | +
|
| 106 | + if ( !isset($wgFlagRestrictions[$tag]) )
|
| 107 | + return true;
|
| 108 | + // Validators always have full access
|
| 109 | + if ( $wgUser->isAllowed('validate') )
|
| 110 | + return true;
|
| 111 | + // Check if this user has any right that lets him/her set
|
| 112 | + // up to this particular value
|
| 113 | + foreach ( $wgFlagRestrictions[$tag] as $right => $level ) {
|
| 114 | + if ( $value <= $level && $wgUser->isAllowed($right) ) {
|
| 115 | + return true;
|
| 116 | + }
|
| 117 | + }
|
| 118 | + return false;
|
| 119 | + }
|
| 120 | +
|
| 121 | + /**
|
| 122 | + * @param webrequest $request
|
| 123 | + */
|
| 124 | + function showRevision( $request ) {
|
| 125 | + global $wgOut, $wgUser, $wgTitle, $wgFlaggedRevComments, $wgFlaggedRevsOverride,
|
| 126 | + $wgFlaggedRevTags, $wgFlaggedRevValues;
|
| 127 | +
|
| 128 | + if ( !$this->isValid )
|
| 129 | + $wgOut->addWikiText( '<strong>' . wfMsg( 'revreview-toolow' ) . '</strong>' );
|
| 130 | +
|
| 131 | + $wgOut->addWikiText( wfMsg( 'revreview-selected', $this->page->getPrefixedText() ) );
|
| 132 | +
|
| 133 | + $this->skin = $wgUser->getSkin();
|
| 134 | + $rev = Revision::newFromTitle( $this->page, $this->oldid );
|
| 135 | + // Check if rev exists
|
| 136 | + // Do not mess with deleted revisions
|
| 137 | + if( !isset( $rev ) || $rev->mDeleted ) {
|
| 138 | + $wgOut->showErrorPage( 'internalerror', 'notargettitle', 'notargettext' );
|
| 139 | + return;
|
| 140 | + }
|
| 141 | +
|
| 142 | + $wgOut->addHtml( "<ul>" );
|
| 143 | + $wgOut->addHtml( $this->historyLine( $rev ) );
|
| 144 | + $wgOut->addHtml( "</ul>" );
|
| 145 | +
|
| 146 | + if( $wgFlaggedRevsOverride )
|
| 147 | + $wgOut->addWikiText( wfMsg('revreview-text') );
|
| 148 | +
|
| 149 | + $formradios = array();
|
| 150 | + // Dynamically contruct our radio options
|
| 151 | + foreach ( array_keys($wgFlaggedRevTags) as $tag ) {
|
| 152 | + $formradios[$tag] = array();
|
| 153 | + for ($i=0; $i <= $wgFlaggedRevValues; $i++) {
|
| 154 | + $formradios[$tag][] = array( "revreview-$tag-$i", "wp$tag", $i );
|
| 155 | + }
|
| 156 | + }
|
| 157 | + $items = array(
|
| 158 | + wfInputLabel( wfMsgHtml( 'revreview-log' ), 'wpReason', 'wpReason', 60 ),
|
| 159 | + wfSubmitButton( wfMsgHtml( 'revreview-submit' ) ) );
|
| 160 | + $hidden = array(
|
| 161 | + wfHidden( 'wpEditToken', $wgUser->editToken() ),
|
| 162 | + wfHidden( 'target', $this->page->getPrefixedText() ),
|
| 163 | + wfHidden( 'oldid', $this->oldid ) );
|
| 164 | +
|
| 165 | + $action = $wgTitle->escapeLocalUrl( 'action=submit' );
|
| 166 | + $form = "<form name='revisionreview' action='$action' method='post'>";
|
| 167 | + $form .= '<fieldset><legend>' . wfMsgHtml( 'revreview-legend' ) . '</legend><table><tr>';
|
| 168 | + // Dynamically contruct our review types
|
| 169 | + foreach ( array_keys($wgFlaggedRevTags) as $tag ) {
|
| 170 | + $form .= '<td><strong>' . wfMsgHtml( "revreview-$tag" ) . '</strong></td><td width=\'20\'></td>';
|
| 171 | + }
|
| 172 | + $form .= '</tr><tr>';
|
| 173 | + foreach ( $formradios as $set => $ratioset ) {
|
| 174 | + $form .= '<td>';
|
| 175 | + foreach( $ratioset as $item ) {
|
| 176 | + list( $message, $name, $field ) = $item;
|
| 177 | + // Don't give options the user can't set unless its the status quo
|
| 178 | + $attribs = array('id' => $name.$field);
|
| 179 | + if( !$this->userCan($set,$field) )
|
| 180 | + $attribs['disabled'] = 'true';
|
| 181 | + $form .= "<div>";
|
| 182 | + $form .= Xml::radio( $name, $field, ($field==$this->dims[$set]), $attribs );
|
| 183 | + $form .= Xml::label( wfMsg($message), $name.$field );
|
| 184 | + $form .= "</div>\n";
|
| 185 | + }
|
| 186 | + $form .= '</td><td width=\'20\'></td>';
|
| 187 | + }
|
| 188 | + $form .= '</tr></table></fieldset>';
|
| 189 | + // Add box to add live notes to a flagged revision
|
| 190 | + if ( $wgFlaggedRevComments ) {
|
| 191 | + $form .= "<fieldset><legend>" . wfMsgHtml( 'revreview-notes' ) . "</legend>" .
|
| 192 | + "<textarea tabindex='1' name='wpNotes' id='wpNotes' rows='3' cols='80' style='width:100%'>$this->notes</textarea>" .
|
| 193 | + "</fieldset>";
|
| 194 | + }
|
| 195 | +
|
| 196 | + foreach( $items as $item ) {
|
| 197 | + $form .= '<p>' . $item . '</p>';
|
| 198 | + }
|
| 199 | + foreach( $hidden as $item ) {
|
| 200 | + $form .= $item;
|
| 201 | + }
|
| 202 | + // XXX: hack, versioning params
|
| 203 | + $form .= Xml::hidden( 'templateParams', $this->templateParams );
|
| 204 | + $form .= Xml::hidden( 'imageParams', $this->imageParams );
|
| 205 | +
|
| 206 | + $form .= '</form>';
|
| 207 | + $wgOut->addHtml( $form );
|
| 208 | + }
|
| 209 | +
|
| 210 | + /**
|
| 211 | + * @param Revision $rev
|
| 212 | + * @returns string
|
| 213 | + */
|
| 214 | + function historyLine( $rev ) {
|
| 215 | + global $wgContLang;
|
| 216 | + $date = $wgContLang->timeanddate( $rev->getTimestamp() );
|
| 217 | +
|
| 218 | + $difflink = '(' . $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml('diff'),
|
| 219 | + '&diff=' . $rev->getId() . '&oldid=prev' ) . ')';
|
| 220 | +
|
| 221 | + $revlink = $this->skin->makeLinkObj( $this->page, $date, 'oldid=' . $rev->getId() );
|
| 222 | +
|
| 223 | + return
|
| 224 | + "<li> $difflink $revlink " . $this->skin->revUserLink( $rev ) . " " . $this->skin->revComment( $rev ) . "</li>";
|
| 225 | + }
|
| 226 | +
|
| 227 | + function submit( $request ) {
|
| 228 | + global $wgOut, $wgUser;
|
| 229 | +
|
| 230 | + $approved = false;
|
| 231 | + # If all values are set to zero, this has been unapproved
|
| 232 | + foreach( $this->dims as $quality => $value ) {
|
| 233 | + if( $value ) {
|
| 234 | + $approved = true;
|
| 235 | + break;
|
| 236 | + }
|
| 237 | + }
|
| 238 | + // We can only approve actual revisions...
|
| 239 | + if ( $approved ) {
|
| 240 | + $rev = Revision::newFromTitle( $this->page, $this->oldid );
|
| 241 | + // Do not mess with archived/deleted revisions
|
| 242 | + if ( is_null($rev) || $rev->mDeleted ) {
|
| 243 | + $wgOut->showErrorPage( 'internalerror', 'revnotfoundtext' );
|
| 244 | + return;
|
| 245 | + }
|
| 246 | + } else {
|
| 247 | + $frev = FlaggedRevs::getFlaggedRev( $this->oldid );
|
| 248 | + // If we can't find this flagged rev, return to page???
|
| 249 | + if ( is_null($frev) ) {
|
| 250 | + $wgOut->redirect( $this->page->escapeLocalUrl() );
|
| 251 | + return;
|
| 252 | + }
|
| 253 | + }
|
| 254 | +
|
| 255 | + $success = $approved ? $this->approveRevision( $rev, $this->notes ) : $this->unapproveRevision( $frev );
|
| 256 | +
|
| 257 | + // Return to our page
|
| 258 | + if ( $success ) {
|
| 259 | + if( $request->getCheck( 'wpWatchthis' ) ) {
|
| 260 | + $wgUser->addWatch( $this->page );
|
| 261 | + } else {
|
| 262 | + $wgUser->removeWatch( $this->page );
|
| 263 | + }
|
| 264 | + $wgOut->redirect( $this->page->escapeLocalUrl() );
|
| 265 | + } else {
|
| 266 | + $wgOut->showErrorPage( 'internalerror', 'revreview-changed' );
|
| 267 | + }
|
| 268 | + }
|
| 269 | +
|
| 270 | + /**
|
| 271 | + * @param Revision $rev
|
| 272 | + * Adds or updates the flagged revision table for this page/id set
|
| 273 | + */
|
| 274 | + function approveRevision( $rev=NULL, $notes='' ) {
|
| 275 | + global $wgUser, $wgFlaggedRevsWatch, $wgParser;
|
| 276 | +
|
| 277 | + if( is_null($rev) )
|
| 278 | + return false;
|
| 279 | + // Get the page this corresponds to
|
| 280 | + $title = $rev->getTitle();
|
| 281 | +
|
| 282 | + $quality = 0;
|
| 283 | + if ( FlaggedRevs::isQuality($this->dims) ) {
|
| 284 | + $quality = FlaggedRevs::getLCQuality($this->dims);
|
| 285 | + $quality = ($quality > 1) ? $quality : 1;
|
| 286 | + }
|
| 287 | + // Our flags
|
| 288 | + $flagset = array();
|
| 289 | + foreach( $this->dims as $tag => $value ) {
|
| 290 | + $flagset[] = array(
|
| 291 | + 'frt_rev_id' => $rev->getId(),
|
| 292 | + 'frt_dimension' => $tag,
|
| 293 | + 'frt_value' => $value
|
| 294 | + );
|
| 295 | + }
|
| 296 | +
|
| 297 | + // XXX: hack, our template version pointers
|
| 298 | + $tmpset = $templates = array();
|
| 299 | + $templateMap = explode('#',trim($this->templateParams) );
|
| 300 | + foreach( $templateMap as $template ) {
|
| 301 | + if( !$template ) continue;
|
| 302 | +
|
| 303 | + $m = explode('|',$template,2);
|
| 304 | + if( !isset($m[0]) || !isset($m[1]) || !$m[0] ) continue;
|
| 305 | +
|
| 306 | + list($prefixed_text,$rev_id) = $m;
|
| 307 | +
|
| 308 | + if( in_array($prefixed_text,$templates) ) continue; // No dups!
|
| 309 | + $templates[] = $prefixed_text;
|
| 310 | +
|
| 311 | + $tmp_title = Title::newFromText( $prefixed_text ); // Normalize this to be sure...
|
| 312 | + if( is_null($title) ) continue; // Page must exist!
|
| 313 | +
|
| 314 | + $tmpset[] = array(
|
| 315 | + 'ft_rev_id' => $rev->getId(),
|
| 316 | + 'ft_namespace' => $tmp_title->getNamespace(),
|
| 317 | + 'ft_title' => $tmp_title->getDBKey(),
|
| 318 | + 'ft_tmp_rev_id' => $rev_id
|
| 319 | + );
|
| 320 | + }
|
| 321 | + // XXX: hack, our image version pointers
|
| 322 | + $imgset = $images = array();
|
| 323 | + $imageMap = explode('#',trim($this->imageParams) );
|
| 324 | + foreach( $imageMap as $image ) {
|
| 325 | + if( !$image ) continue;
|
| 326 | + $m = explode('|',$image,2);
|
| 327 | +
|
| 328 | + if( !isset($m[0]) || !isset($m[1]) || !$m[0] ) continue;
|
| 329 | +
|
| 330 | + list($dbkey,$timestamp) = $m;
|
| 331 | +
|
| 332 | + if( in_array($dbkey,$images) ) continue; // No dups!
|
| 333 | + $images[] = $dbkey;
|
| 334 | +
|
| 335 | + $img_title = Title::makeTitle( NS_IMAGE, $dbkey ); // Normalize this to be sure...
|
| 336 | + if( is_null($img_title) ) continue; // Page must exist!
|
| 337 | +
|
| 338 | + $imgset[] = array(
|
| 339 | + 'fi_rev_id' => $rev->getId(),
|
| 340 | + 'fi_name' => $img_title->getDBKey(),
|
| 341 | + 'fi_img_timestamp' => $timestamp
|
| 342 | + );
|
| 343 | + }
|
| 344 | +
|
| 345 | + $dbw = wfGetDB( DB_MASTER );
|
| 346 | + $dbw->begin();
|
| 347 | + // Update our versioning pointers
|
| 348 | + if( !empty( $tmpset ) ) {
|
| 349 | + $dbw->replace( 'flaggedtemplates', array( array('ft_rev_id','ft_namespace','ft_title') ), $tmpset,
|
| 350 | + __METHOD__ );
|
| 351 | + }
|
| 352 | + if( !empty( $imgset ) ) {
|
| 353 | + $dbw->replace( 'flaggedimages', array( array('fi_rev_id','fi_name') ), $imgset,
|
| 354 | + __METHOD__ );
|
| 355 | + }
|
| 356 | + // Get the page text and resolve all templates
|
| 357 | + list($fulltext,$complete) = FlaggedRevs::expandText( $rev->getText(), $rev->getTitle(), $rev->getId() );
|
| 358 | + if( !$complete ) {
|
| 359 | + $dbw->rollback(); // All versions must be specified, 0 for none
|
| 360 | + return false;
|
| 361 | + }
|
| 362 | + // Our review entry
|
| 363 | + $revset = array(
|
| 364 | + 'fr_rev_id' => $rev->getId(),
|
| 365 | + 'fr_namespace' => $title->getNamespace(),
|
| 366 | + 'fr_title' => $title->getDBkey(),
|
| 367 | + 'fr_user' => $wgUser->getId(),
|
| 368 | + 'fr_timestamp' => wfTimestampNow(),
|
| 369 | + 'fr_comment' => $notes,
|
| 370 | + 'fr_text' => $fulltext, // Store expanded text for speed
|
| 371 | + 'fr_quality' => $quality
|
| 372 | + );
|
| 373 | + // Update flagged revisions table
|
| 374 | + $dbw->replace( 'flaggedrevs', array( array('fr_rev_id','fr_namespace','fr_title') ), $revset, __METHOD__ );
|
| 375 | + // Set all of our flags
|
| 376 | + $dbw->replace( 'flaggedrevtags', array( array('frt_rev_id','frt_dimension') ), $flagset, __METHOD__ );
|
| 377 | + // Mark as patrolled
|
| 378 | + $dbw->update( 'recentchanges',
|
| 379 | + array( 'rc_patrolled' => 1 ),
|
| 380 | + array( 'rc_this_oldid' => $rev->getId() ),
|
| 381 | + __METHOD__
|
| 382 | + );
|
| 383 | + $dbw->commit();
|
| 384 | +
|
| 385 | + // Update the article review log
|
| 386 | + $this->updateLog( $this->page, $this->dims, $this->comment, $this->oldid, true );
|
| 387 | +
|
| 388 | + $article = new Article( $this->page );
|
| 389 | + // Update the links tables as the stable version may now be the default page...
|
| 390 | + $parserCache =& ParserCache::singleton();
|
| 391 | + $poutput = $parserCache->get( $article, $wgUser );
|
| 392 | + if( $poutput==false ) {
|
| 393 | + $text = $article->getContent();
|
| 394 | + $poutput = $wgParser->parse($text, $article->mTitle, ParserOptions::newFromUser($wgUser));
|
| 395 | + }
|
| 396 | + $u = new LinksUpdate( $this->page, $poutput );
|
| 397 | + $u->doUpdate(); // Will trigger our hook to add stable links too...
|
| 398 | +
|
| 399 | + # Clear the cache...
|
| 400 | + $this->page->invalidateCache();
|
| 401 | + # Might as well save the cache
|
| 402 | + $parserCache->save( $poutput, $article, $wgUser );
|
| 403 | + # Purge squid for this page only
|
| 404 | + $this->page->purgeSquid();
|
| 405 | +
|
| 406 | + return true;
|
| 407 | + }
|
| 408 | +
|
| 409 | + /**
|
| 410 | + * @param Revision $rev
|
| 411 | + * Removes flagged revision data for this page/id set
|
| 412 | + */
|
| 413 | + function unapproveRevision( $row=NULL ) {
|
| 414 | + global $wgUser, $wgFlaggedRevsWatch;
|
| 415 | +
|
| 416 | + if( is_null($row) ) return false;
|
| 417 | +
|
| 418 | + $user = $wgUser->getId();
|
| 419 | +
|
| 420 | + wfProfileIn( __METHOD__ );
|
| 421 | + $dbw = wfGetDB( DB_MASTER );
|
| 422 | + // Delete from table
|
| 423 | + $dbw->delete( 'flaggedrevs', array( 'fr_rev_id' => $row->fr_rev_id ) );
|
| 424 | + // Wipe versioning pointers
|
| 425 | + $dbw->delete( 'flaggedtemplates', array( 'ft_rev_id' => $row->fr_rev_id ) );
|
| 426 | + $dbw->delete( 'flaggedimages', array( 'fi_rev_id' => $row->fr_rev_id ) );
|
| 427 | + // And the flags...
|
| 428 | + $dbw->delete( 'flaggedrevtags', array( 'frt_rev_id' => $row->fr_rev_id ) );
|
| 429 | +
|
| 430 | + // Update the article review log
|
| 431 | + $this->updateLog( $this->page, $this->dims, $this->comment, $this->oldid, false );
|
| 432 | +
|
| 433 | + $article = new Article( $this->page );
|
| 434 | + // Update the links tables as a new stable version
|
| 435 | + // may now be the default page.
|
| 436 | + $parserCache =& ParserCache::singleton();
|
| 437 | + $poutput = $parserCache->get( $article, $wgUser );
|
| 438 | + if ( $poutput==false ) {
|
| 439 | + $text = $article->getContent();
|
| 440 | + $poutput = $wgParser->parse($text, $article->mTitle, ParserOptions::newFromUser($wgUser));
|
| 441 | + }
|
| 442 | + $u = new LinksUpdate( $this->page, $poutput );
|
| 443 | + $u->doUpdate();
|
| 444 | +
|
| 445 | + # Clear the cache...
|
| 446 | + $this->page->invalidateCache();
|
| 447 | + # Might as well save the cache
|
| 448 | + $parserCache->save( $poutput, $article, $wgUser );
|
| 449 | + # Purge squid for this page only
|
| 450 | + $this->page->purgeSquid();
|
| 451 | +
|
| 452 | + wfProfileOut( __METHOD__ );
|
| 453 | +
|
| 454 | + return true;
|
| 455 | + }
|
| 456 | +
|
| 457 | + /**
|
| 458 | + * Record a log entry on the action
|
| 459 | + * @param Title $title
|
| 460 | + * @param array $dimensions
|
| 461 | + * @param string $comment
|
| 462 | + * @param int $revid
|
| 463 | + * @param bool $approve
|
| 464 | + */
|
| 465 | + function updateLog( $title, $dimensions, $comment, $oldid, $approve ) {
|
| 466 | + $log = new LogPage( 'review' );
|
| 467 | + // ID, accuracy, depth, style
|
| 468 | + $ratings = array();
|
| 469 | + foreach( $dimensions as $quality => $level ) {
|
| 470 | + $ratings[] = wfMsg( "revreview-$quality" ) . ": " . wfMsg("revreview-$quality-$level");
|
| 471 | + }
|
| 472 | + $rating = ($approve) ? ' [' . implode(', ',$ratings). ']' : '';
|
| 473 | + // Append comment with action
|
| 474 | + // FIXME: do this better
|
| 475 | + $action = wfMsgExt('review-logaction', array('parsemag'), $oldid );
|
| 476 | + if( $approve )
|
| 477 | + $comment = ($comment) ? "$action: $comment$rating" : "$action $rating";
|
| 478 | + else
|
| 479 | + $comment = ($comment) ? "$action: $comment" : "$action";
|
| 480 | +
|
| 481 | + if( $approve ) {
|
| 482 | + $log->addEntry( 'approve', $title, $comment );
|
| 483 | + } else {
|
| 484 | + $log->addEntry( 'unapprove', $title, $comment );
|
| 485 | + }
|
| 486 | + }
|
| 487 | +}
|
| 488 | +
|
| 489 | +class Stableversions extends SpecialPage
|
| 490 | +{
|
| 491 | +
|
| 492 | + function Stableversions() {
|
| 493 | + SpecialPage::SpecialPage('Stableversions');
|
| 494 | + }
|
| 495 | +
|
| 496 | + function execute( $par ) {
|
| 497 | + global $wgRequest;
|
| 498 | +
|
| 499 | + $this->setHeaders();
|
| 500 | + // Our target page
|
| 501 | + $this->page = $wgRequest->getText( 'page' );
|
| 502 | + // Revision ID
|
| 503 | + $this->oldid = $wgRequest->getIntOrNull( 'oldid' );
|
| 504 | +
|
| 505 | + if( $this->oldid ) {
|
| 506 | + $this->showStableRevision( $wgRequest );
|
| 507 | + } else if( $this->page ) {
|
| 508 | + $this->showStableList( $wgRequest );
|
| 509 | + } else {
|
| 510 | + $this->showForm( $wgRequest );
|
| 511 | + }
|
| 512 | + }
|
| 513 | +
|
| 514 | + function showForm( $wgRequest ) {
|
| 515 | + global $wgOut, $wgTitle, $wgScript;
|
| 516 | +
|
| 517 | + $encPage = $this->page;
|
| 518 | + $encId = $this->oldid;
|
| 519 | +
|
| 520 | + $form = "<form name='stableversions' action='$wgScript' method='get'>";
|
| 521 | + $form .= "<fieldset><legend>".wfMsg('stableversions-leg1')."</legend>";
|
| 522 | + $form .= "<table><tr>";
|
| 523 | + $form .= "<td>".Xml::hidden( 'title', $wgTitle->getPrefixedText() )."</td>";
|
| 524 | + $form .= "<td>".wfMsgHtml("stableversions-page").":</td>";
|
| 525 | + $form .= "<td>".Xml::input('page', 50, $encPage, array( 'id' => 'page' ) )."</td>";
|
| 526 | + $form .= "<td>".wfSubmitButton( wfMsgHtml( 'go' ) )."</td>";
|
| 527 | + $form .= "</tr></table>";
|
| 528 | + $form .= "</fieldset></form>\n";
|
| 529 | +
|
| 530 | + $form .= "<form name='stableversion' action='$wgScript' method='get'>";
|
| 531 | + $form .= "<fieldset><legend>".wfMsg('stableversions-leg2')."</legend>";
|
| 532 | + $form .= "<table><tr>";
|
| 533 | + $form .= "<td>".Xml::hidden( 'title', $wgTitle->getPrefixedDBkey() )."</td>";
|
| 534 | + $form .= "<td>".wfMsgHtml("stableversions-rev").":</td>";
|
| 535 | + $form .= "<td>".Xml::input('oldid', 15, $encId, array( 'id' => 'oldid' ) )."</td>";
|
| 536 | + $form .= "<td>".wfSubmitButton( wfMsgHtml( 'go' ) )."</td>";
|
| 537 | + $form .= "</tr></table>";
|
| 538 | + $form .= "</fieldset></form>";
|
| 539 | +
|
| 540 | + $wgOut->addHTML( $form );
|
| 541 | + }
|
| 542 | +
|
| 543 | + function showStableRevision( $frev ) {
|
| 544 | + global $wgParser, $wgLang, $wgUser, $wgOut, $wgTitle;
|
| 545 | +
|
| 546 | + // Get the revision
|
| 547 | + $frev = FlaggedRevs::getFlaggedRev( $this->oldid );
|
| 548 | + // Revision must exists
|
| 549 | + if( is_null($frev) ) {
|
| 550 | + $wgOut->showErrorPage( 'notargettitle', 'revnotfoundtext' );
|
| 551 | + return;
|
| 552 | + }
|
| 553 | + $page = Title::makeTitle( $frev->fr_namespace, $frev->fr_title );
|
| 554 | +
|
| 555 | + $wgOut->setPagetitle( $page->getPrefixedText() );
|
| 556 | +
|
| 557 | + // Modifier instance
|
| 558 | + $RevFlagging = new FlaggedRevs();
|
| 559 | + // Get flags and date
|
| 560 | + $flags = FlaggedRevs::getFlagsForPageRev( $frev->fr_rev_id );
|
| 561 | + $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $frev->fr_timestamp), true );
|
| 562 | + // We will be looking at the reviewed revision...
|
| 563 | + $tag = wfMsgExt('revreview-static', array('parseinline'), urlencode($page->getPrefixedText()), $time, $page->getPrefixedText());
|
| 564 | + $tag .= ' <a id="mwrevisiontoggle" style="display:none;" href="javascript:toggleRevRatings()">' . wfMsg('revreview-toggle') . '</a>';
|
| 565 | + $tag .= '<span id="mwrevisionratings" style="display:block;">' .
|
| 566 | + wfMsg('revreview-oldrating') . $RevFlagging->addTagRatings( $flags ) .
|
| 567 | + '</span>';
|
| 568 | + // Parse the text...
|
| 569 | + $text = $RevFlagging->getFlaggedRevText( $this->oldid );
|
| 570 | + $options = ParserOptions::newFromUser($wgUser);
|
| 571 | + $parserOutput = $RevFlagging->parseStableText( $page, $text, $this->oldid, $options );
|
| 572 | + $notes = $RevFlagging->ReviewNotes( $frev );
|
| 573 | + // Set the new body HTML, place a tag on top
|
| 574 | + $wgOut->addHTML('<div id="mwrevisiontag" class="flaggedrevs_notice plainlinks">'.$tag.'</div>' . $parserOutput->getText() . $notes);
|
| 575 | + // Show stable categories and interwiki links only
|
| 576 | + $wgOut->mCategoryLinks = array();
|
| 577 | + $wgOut->addCategoryLinks( $parserOutput->getCategories() );
|
| 578 | + $wgOut->mLanguageLinks = array();
|
| 579 | + $wgOut->addLanguageLinks( $parserOutput->getLanguageLinks() );
|
| 580 | + }
|
| 581 | +
|
| 582 | + function showStableList() {
|
| 583 | + global $wgOut, $wgUser, $wgLang;
|
| 584 | +
|
| 585 | + $skin = $wgUser->getSkin();
|
| 586 | + // Must be a valid page/Id
|
| 587 | + $page = Title::newFromUrl( $this->page );
|
| 588 | + if( is_null($page) || !$page->isContentPage() ) {
|
| 589 | + $wgOut->showErrorPage('notargettitle', 'allpagesbadtitle' );
|
| 590 | + return;
|
| 591 | + }
|
| 592 | + $article = new Article( $page );
|
| 593 | + if( !$article ) {
|
| 594 | + $wgOut->showErrorPage('notargettitle', 'allpagesbadtitle' );
|
| 595 | + return;
|
| 596 | + }
|
| 597 | + $pager = new StableRevisionsPager( $this, array(), $page->getNamespace(), $page->getDBkey() );
|
| 598 | + if ( $pager->getNumRows() ) {
|
| 599 | + $wgOut->addHTML( wfMsgExt('stableversions-list', array('parse'), $page->getPrefixedText() ) );
|
| 600 | + $wgOut->addHTML( $pager->getNavigationBar() );
|
| 601 | + $wgOut->addHTML( "<ul>" . $pager->getBody() . "</ul>" );
|
| 602 | + $wgOut->addHTML( $pager->getNavigationBar() );
|
| 603 | + } else {
|
| 604 | + $wgOut->addHTML( wfMsgExt('stableversions-none', array('parse'), $page->getPrefixedText() ) );
|
| 605 | + }
|
| 606 | + }
|
| 607 | +
|
| 608 | + function formatRow( $row ) {
|
| 609 | + global $wgLang, $wgUser;
|
| 610 | +
|
| 611 | + static $skin=null;
|
| 612 | + if( is_null( $skin ) )
|
| 613 | + $skin = $wgUser->getSkin();
|
| 614 | +
|
| 615 | + $SV = SpecialPage::getTitleFor( 'Stableversions' );
|
| 616 | + $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->rev_timestamp), true );
|
| 617 | + $ftime = $wgLang->timeanddate( wfTimestamp(TS_MW, $row->fr_timestamp), true );
|
| 618 | + $review = wfMsg( 'stableversions-review', $ftime );
|
| 619 | +
|
| 620 | + $lev = wfMsg('hist-stable');
|
| 621 | + if( $row->fr_quality >=1 ) $lev = wfMsg('hist-quality');
|
| 622 | +
|
| 623 | + return '<li>'.$skin->makeKnownLinkObj( $SV, $time, 'oldid='.$row->fr_rev_id ).' ('.$review.') <b>'.$lev.'</b></li>';
|
| 624 | + }
|
| 625 | +}
|
| 626 | +
|
| 627 | +/**
|
| 628 | + * Query to list out stable versions for a page
|
| 629 | + */
|
| 630 | +class StableRevisionsPager extends ReverseChronologicalPager {
|
| 631 | + public $mForm, $mConds;
|
| 632 | +
|
| 633 | + function __construct( $form, $conds = array(), $namespace, $title ) {
|
| 634 | + $this->mForm = $form;
|
| 635 | + $this->mConds = $conds;
|
| 636 | + $this->namespace = $namespace;
|
| 637 | + $this->title = $title;
|
| 638 | + parent::__construct();
|
| 639 | + }
|
| 640 | +
|
| 641 | + function formatRow( $row ) {
|
| 642 | + $block = new Block;
|
| 643 | + return $this->mForm->formatRow( $row );
|
| 644 | + }
|
| 645 | +
|
| 646 | + function getQueryInfo() {
|
| 647 | + $conds = $this->mConds;
|
| 648 | + $conds["fr_namespace"] = $this->namespace;
|
| 649 | + $conds["fr_title"] = $this->title;
|
| 650 | + $conds[] = "fr_rev_id = rev_id";
|
| 651 | + $conds["rev_deleted"] = 0;
|
| 652 | + return array(
|
| 653 | + 'tables' => array('flaggedrevs','revision'),
|
| 654 | + 'fields' => 'fr_rev_id,fr_timestamp,rev_timestamp,fr_quality',
|
| 655 | + 'conds' => $conds
|
| 656 | + );
|
| 657 | + }
|
| 658 | +
|
| 659 | + function getIndexField() {
|
| 660 | + return 'fr_rev_id';
|
| 661 | + }
|
| 662 | +}
|
| 663 | +
|
| 664 | +/**
|
| 665 | + * Special page to list unreviewed pages
|
| 666 | + */
|
| 667 | +class Unreviewedpages extends SpecialPage
|
| 668 | +{
|
| 669 | +
|
| 670 | + function Unreviewedpages() {
|
| 671 | + SpecialPage::SpecialPage('Unreviewedpages');
|
| 672 | + }
|
| 673 | +
|
| 674 | + function execute( $par ) {
|
| 675 | + global $wgRequest;
|
| 676 | +
|
| 677 | + $this->setHeaders();
|
| 678 | +
|
| 679 | + $this->showList( $wgRequest );
|
| 680 | + }
|
| 681 | +
|
| 682 | + function showList( $wgRequest ) {
|
| 683 | + global $wgOut, $wgUser, $wgScript, $wgTitle;
|
| 684 | +
|
| 685 | + $skin = $wgUser->getSkin();
|
| 686 | + $namespace = $wgRequest->getIntOrNull( 'namespace' );
|
| 687 | + $nonquality = $wgRequest->getVal( 'includenonquality' );
|
| 688 | +
|
| 689 | + $action = htmlspecialchars( $wgScript );
|
| 690 | + $wgOut->addHTML( "<form action=\"$action\" method=\"get\">\n" .
|
| 691 | + '<fieldset><legend>' . wfMsg('viewunreviewed') . '</legend>' .
|
| 692 | + $this->getNamespaceMenu( $namespace ) . "\n" .
|
| 693 | + Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
|
| 694 | + '<p>' . Xml::check( 'includenonquality', $nonquality, array('id' => 'includenonquality') ) .
|
| 695 | + ' ' . Xml::label( wfMsgHtml("included-nonquality"), 'includenonquality' ) . "</p>\n" .
|
| 696 | + Xml::hidden( 'title', $wgTitle->getPrefixedText() ) .
|
| 697 | + "</fieldset></form>");
|
| 698 | +
|
| 699 | + list( $limit, $offset ) = wfCheckLimits();
|
| 700 | +
|
| 701 | + $sdr = new UnreviewedPagesPage( $namespace, $nonquality );
|
| 702 | + $sdr->doQuery( $offset, $limit );
|
| 703 | + }
|
| 704 | +
|
| 705 | + function getNamespaceMenu( $selected=NULL, $allnamespaces = null, $includehidden=false ) {
|
| 706 | + global $wgContLang, $wgContentNamespaces;
|
| 707 | +
|
| 708 | + $selector = "<label for='namespace'>" . wfMsgHtml('namespace') . "</label>";
|
| 709 | + if( $selected !== '' ) {
|
| 710 | + if( is_null( $selected ) ) {
|
| 711 | + // No namespace selected; let exact match work without hitting Main
|
| 712 | + $selected = '';
|
| 713 | + } else {
|
| 714 | + // Let input be numeric strings without breaking the empty match.
|
| 715 | + $selected = intval( $selected );
|
| 716 | + }
|
| 717 | + }
|
| 718 | + $s = "\n<select id='namespace' name='namespace' class='namespaceselector'>\n";
|
| 719 | + $arr = $wgContLang->getFormattedNamespaces();
|
| 720 | + if( !is_null($allnamespaces) ) {
|
| 721 | + $arr = array($allnamespaces => wfMsg('namespacesall')) + $arr;
|
| 722 | + }
|
| 723 | +
|
| 724 | + $s .= "\t" . Xml::element("option", array("value" => "all"), "all") . "\n";
|
| 725 | +
|
| 726 | + foreach ($arr as $index => $name) {
|
| 727 | + # Content only
|
| 728 | + if ($index < NS_MAIN || !in_array($index, $wgContentNamespaces) ) continue;
|
| 729 | +
|
| 730 | + $name = $index !== 0 ? $name : wfMsg('blanknamespace');
|
| 731 | +
|
| 732 | + if ($index === $selected) {
|
| 733 | + $s .= "\t" . Xml::element("option",
|
| 734 | + array("value" => $index, "selected" => "selected"),
|
| 735 | + $name) . "\n";
|
| 736 | + } else {
|
| 737 | + $s .= "\t" . Xml::element("option", array("value" => $index), $name) . "\n";
|
| 738 | + }
|
| 739 | + }
|
| 740 | + $s .= "</select>\n";
|
| 741 | + return $s;
|
| 742 | + }
|
| 743 | +}
|
| 744 | +
|
| 745 | +/**
|
| 746 | + * Query to list out unreviewed pages
|
| 747 | + */
|
| 748 | +class UnreviewedPagesPage extends PageQueryPage {
|
| 749 | +
|
| 750 | + function __construct( $namespace=NULL, $nonquality=false ) {
|
| 751 | + $this->namespace = $namespace;
|
| 752 | + $this->nonquality = $nonquality;
|
| 753 | + }
|
| 754 | +
|
| 755 | + function getName() {
|
| 756 | + return 'UnreviewedPages';
|
| 757 | + }
|
| 758 | +
|
| 759 | + function isExpensive( ) { return true; }
|
| 760 | + function isSyndicated() { return false; }
|
| 761 | +
|
| 762 | + function getPageHeader( ) {
|
| 763 | + return '<p>'.wfMsg("unreviewed-list")."</p>\n";
|
| 764 | + }
|
| 765 | +
|
| 766 | + function getSQLText( &$dbr, $namespace, $includenonquality = false ) {
|
| 767 | + global $wgContentNamespaces;
|
| 768 | +
|
| 769 | + list( $page, $flaggedrevs ) = $dbr->tableNamesN( 'page', 'flaggedrevs' );
|
| 770 | +
|
| 771 | + # Must be a content page...
|
| 772 | + $contentNS = 'page_namespace IN(' . implode(',',$wgContentNamespaces) . ')';
|
| 773 | +
|
| 774 | + $ns = ($namespace !== null) ? "page_namespace=$namespace" : '1 = 1';
|
| 775 | +
|
| 776 | + $where = $includenonquality ? '1 = 1' : 'fr_rev_id IS NULL';
|
| 777 | + $having = $includenonquality ? 'MAX(fr_quality) < 1' : '1 = 1';
|
| 778 | +
|
| 779 | + $sql =
|
| 780 | + "SELECT page_namespace,page_title,page_len AS size
|
| 781 | + FROM $page
|
| 782 | + LEFT JOIN $flaggedrevs ON (fr_namespace = page_namespace AND fr_title = page_title)
|
| 783 | + WHERE page_is_redirect=0 AND $ns AND $contentNS AND ($where)
|
| 784 | + GROUP BY page_id HAVING $having ";
|
| 785 | + return $sql;
|
| 786 | + }
|
| 787 | +
|
| 788 | + function getSQL() {
|
| 789 | + $dbr = wfGetDB( DB_SLAVE );
|
| 790 | + return $this->getSQLText( $dbr, $this->namespace, $this->nonquality );
|
| 791 | + }
|
| 792 | +
|
| 793 | + function getOrder() {
|
| 794 | + return 'ORDER BY page_id DESC';
|
| 795 | + }
|
| 796 | +
|
| 797 | + function formatResult( $skin, $result ) {
|
| 798 | + global $wgLang;
|
| 799 | +
|
| 800 | + $fname = 'UnreviewedPagesPage::formatResult';
|
| 801 | + $title = Title::makeTitle( $result->page_namespace, $result->page_title );
|
| 802 | + $link = $skin->makeKnownLinkObj( $title );
|
| 803 | + $stxt = '';
|
| 804 | + if (!is_null($size = $result->size)) {
|
| 805 | + if ($size == 0)
|
| 806 | + $stxt = ' <small>' . wfMsgHtml('historyempty') . '</small>';
|
| 807 | + else
|
| 808 | + $stxt = ' <small>' . wfMsgHtml('historysize', $wgLang->formatNum( $size ) ) . '</small>';
|
| 809 | + }
|
| 810 | +
|
| 811 | + return( "{$link} {$stxt}" );
|
| 812 | + }
|
| 813 | +}
|
| 814 | +
|