r58590 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r58589‎ | r58590 | r58591 >
Date:17:55, 5 November 2009
Author:ialex
Status:ok
Tags:
Comment:
svn:eol-style native
Modified paths:
  • /trunk/extensions/FlaggedRevs/FlaggedArticleView.php (modified) (history)
  • /trunk/phase3/t/inc/SearchUpdate.t (modified) (history)

Diff [purge]

Index: trunk/phase3/t/inc/SearchUpdate.t
@@ -1,61 +1,61 @@
2 -#!/usr/bin/env php
3 -<?php
4 -
5 -require 't/Test.php';
6 -
7 -plan( 4 );
8 -
9 -define( 'MEDIAWIKI', 1 );
10 -require 'includes/Defines.php';
11 -require 'includes/ProfilerStub.php';
12 -require 'includes/AutoLoader.php';
13 -require 'LocalSettings.php';
14 -
15 -require 't/DatabaseMock.inc';
16 -
17 -$wgSearchType = 'MockSearch';
18 -
19 -require 'includes/Setup.php';
20 -
21 -
22 -class MockSearch extends SearchEngine {
23 - public static $id;
24 - public static $title;
25 - public static $text;
26 -
27 - public function __construct( $db ) {
28 - }
29 -
30 - public function update( $id, $title, $text ) {
31 - self::$id = $id;
32 - self::$title = $title;
33 - self::$text = $text;
34 - }
35 -}
36 -
37 -function update( $text, $title = 'Test', $id = 1 ) {
38 - $u = new SearchUpdate( $id, $title, $text );
39 - $u->doUpdate();
40 - return array( MockSearch::$title, MockSearch::$text );
41 -}
42 -
43 -function updateText( $text ) {
44 - list( $title, $resultText ) = update( $text );
45 - $resultText = trim( $resultText ); // abstract from some implementation details
46 - return $resultText;
47 -}
48 -
49 -is( updateText( '<div>TeSt</div>' ), 'test', 'HTML stripped, text lowercased' );
50 -
51 -is( updateText( <<<EOT
52 -<table style="color:red; font-size:100px">
53 - <tr class="scary"><td><div>foo</div></td><tr>bar</td></tr>
54 - <tr><td>boz</td><tr>quux</td></tr>
55 -</table>
56 -EOT
57 -), 'foo bar boz quux', 'Stripping HTML tables' );
58 -
59 -is( updateText( 'a > b' ), 'a b', 'Handle unclosed tags' );
60 -
61 -$text = str_pad( "foo <barbarbar \n", 10000, 'x' );
 2+#!/usr/bin/env php
 3+<?php
 4+
 5+require 't/Test.php';
 6+
 7+plan( 4 );
 8+
 9+define( 'MEDIAWIKI', 1 );
 10+require 'includes/Defines.php';
 11+require 'includes/ProfilerStub.php';
 12+require 'includes/AutoLoader.php';
 13+require 'LocalSettings.php';
 14+
 15+require 't/DatabaseMock.inc';
 16+
 17+$wgSearchType = 'MockSearch';
 18+
 19+require 'includes/Setup.php';
 20+
 21+
 22+class MockSearch extends SearchEngine {
 23+ public static $id;
 24+ public static $title;
 25+ public static $text;
 26+
 27+ public function __construct( $db ) {
 28+ }
 29+
 30+ public function update( $id, $title, $text ) {
 31+ self::$id = $id;
 32+ self::$title = $title;
 33+ self::$text = $text;
 34+ }
 35+}
 36+
 37+function update( $text, $title = 'Test', $id = 1 ) {
 38+ $u = new SearchUpdate( $id, $title, $text );
 39+ $u->doUpdate();
 40+ return array( MockSearch::$title, MockSearch::$text );
 41+}
 42+
 43+function updateText( $text ) {
 44+ list( $title, $resultText ) = update( $text );
 45+ $resultText = trim( $resultText ); // abstract from some implementation details
 46+ return $resultText;
 47+}
 48+
 49+is( updateText( '<div>TeSt</div>' ), 'test', 'HTML stripped, text lowercased' );
 50+
 51+is( updateText( <<<EOT
 52+<table style="color:red; font-size:100px">
 53+ <tr class="scary"><td><div>foo</div></td><tr>bar</td></tr>
 54+ <tr><td>boz</td><tr>quux</td></tr>
 55+</table>
 56+EOT
 57+), 'foo bar boz quux', 'Stripping HTML tables' );
 58+
 59+is( updateText( 'a > b' ), 'a b', 'Handle unclosed tags' );
 60+
 61+$text = str_pad( "foo <barbarbar \n", 10000, 'x' );
6262 ok( updateText( $text ) != '', 'Bug 18609' );
\ No newline at end of file
Property changes on: trunk/phase3/t/inc/SearchUpdate.t
___________________________________________________________________
Name: svn:eol-style
6363 + native
Index: trunk/extensions/FlaggedRevs/FlaggedArticleView.php
@@ -1,1522 +1,1522 @@
2 -<?php
3 -
4 -class FlaggedArticleView {
5 - protected $isDiffFromStable = false;
6 - protected $isMultiPageDiff = false;
7 - protected $reviewNotice = '';
8 - protected $reviewNotes = '';
9 - protected $article = null;
10 - protected $loaded = false;
11 -
12 - protected static $instance = null;
13 -
14 - /*
15 - * Get the FlaggedArticleView for this request
16 - */
17 - public static function singleton() {
18 - if( self::$instance == null ) {
19 - self::$instance = new self();
20 - }
21 - return self::$instance;
22 - }
23 - protected function __construct() {}
24 -
25 - /*
26 - * Load the global FlaggedArticle instance
27 - */
28 - protected function load() {
29 - if( !$this->loaded ) {
30 - $this->article = self::globalArticleInstance();
31 - if( $this->article == null ) {
32 - throw new MWException( 'FlaggedArticleViewer has no context article!' );
33 - }
34 - }
35 - }
36 -
37 - /**
38 - * Get the FlaggedArticle instance associated with $wgArticle/$wgTitle,
39 - * or false if there isn't such a title
40 - */
41 - public static function globalArticleInstance() {
42 - global $wgTitle;
43 - if( !empty( $wgTitle ) ) {
44 - return FlaggedArticle::getTitleInstance( $wgTitle );
45 - }
46 - return null;
47 - }
48 -
49 - /**
50 - * Does the config and current URL params allow
51 - * for overriding by stable revisions?
52 - */
53 - public function pageOverride() {
54 - global $wgUser, $wgRequest;
55 - $this->load();
56 - # This only applies to viewing content pages
57 - $action = $wgRequest->getVal( 'action', 'view' );
58 - if( !self::isViewAction($action) || !$this->article->isReviewable() )
59 - return false;
60 - # Does not apply to diffs/old revision...
61 - if( $wgRequest->getVal('oldid') || $wgRequest->getVal('diff') )
62 - return false;
63 - # Explicit requests for a certain stable version handled elsewhere...
64 - if( $wgRequest->getVal('stableid') )
65 - return false;
66 - # Check user preferences
67 - if( $wgUser->getOption('flaggedrevsstable') )
68 - return !( $wgRequest->getIntOrNull('stable') === 0 );
69 - # Get page configuration
70 - $config = $this->article->getVisibilitySettings();
71 - # Does the stable version override the current one?
72 - if( $config['override'] ) {
73 - if( FlaggedRevs::ignoreDefaultVersion() ) {
74 - return ( $wgRequest->getIntOrNull('stable') === 1 );
75 - }
76 - # Viewer sees stable by default
77 - return !( $wgRequest->getIntOrNull('stable') === 0 );
78 - # We are explicity requesting the stable version?
79 - } elseif( $wgRequest->getIntOrNull('stable') === 1 ) {
80 - return true;
81 - }
82 - return false;
83 - }
84 -
85 - /**
86 - * Is this user shown the stable version by default for this page?
87 - * @returns bool
88 - */
89 - public function showStableByDefaultUser() {
90 - $this->load();
91 - $config = $this->article->getVisibilitySettings(); // page configuration
92 - return ( $config['override'] && !FlaggedRevs::ignoreDefaultVersion() );
93 - }
94 -
95 - /**
96 - * Is this user shown the diff-to-stable on edit for this page?
97 - * @returns bool
98 - */
99 - public function showDiffOnEditUser() {
100 - global $wgUser;
101 - $this->load();
102 - return ( $wgUser->isAllowed('review') || $this->showStableByDefaultUser() );
103 - }
104 -
105 - /**
106 - * Is this a view page action?
107 - * @param $action string
108 - * @returns bool
109 - */
110 - protected static function isViewAction( $action ) {
111 - return ( $action == 'view' || $action == 'purge' || $action == 'render' || $action == 'historysubmit' );
112 - }
113 -
114 - /**
115 - * Output review notice
116 - */
117 - protected function displayTag() {
118 - global $wgOut, $wgRequest;
119 - $this->load();
120 - // UI may be limited to unobtrusive patrolling system
121 - if( $wgRequest->getVal('stableid') || !$this->article->limitedUI() ) {
122 - $wgOut->appendSubtitle( $this->reviewNotice );
123 - }
124 - return true;
125 - }
126 -
127 -
128 - /**
129 - * Add a stable link when viewing old versions of an article that
130 - * have been reviewed. (e.g. for &oldid=x urls)
131 - */
132 - public function addStableLink() {
133 - global $wgRequest, $wgOut, $wgLang;
134 - $this->load();
135 - # Only for viewing old versions. UI may be limited to unobtrusive patrolling system.
136 - if( !$wgRequest->getVal('oldid') || $this->article->limitedUI() )
137 - return true;
138 - # We may have nav links like "direction=prev&oldid=x"
139 - $revID = $this->article->getOldIDFromRequest();
140 - $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $revID );
141 - # Give a notice if this rev ID corresponds to a reviewed version...
142 - if( !is_null($frev) ) {
143 - wfLoadExtensionMessages( 'FlaggedRevs' );
144 - $time = $wgLang->date( $frev->getTimestamp(), true );
145 - $flags = $frev->getTags();
146 - $quality = FlaggedRevs::isQuality( $flags );
147 - $msg = $quality ? 'revreview-quality-source' : 'revreview-basic-source';
148 - $tag = wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
149 - # Hide clutter
150 - if( !FlaggedRevs::useSimpleUI() && !empty($flags) ) {
151 - $tag .= " " . FlaggedRevsXML::ratingToggle() .
152 - "<span id='mw-revisionratings' style='display:block;'><br/>" .
153 - wfMsgHtml('revreview-oldrating') .
154 - FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
155 - }
156 - $tag = "<div id='mw-revisiontag-old' class='flaggedrevs_notice plainlinks noprint'>$tag</div>";
157 - $wgOut->addHTML( $tag );
158 - }
159 - return true;
160 - }
161 -
162 - /**
163 - * Replaces a page with the last stable version if possible
164 - * Adds stable version status/info tags and notes
165 - * Adds a quick review form on the bottom if needed
166 - */
167 - public function setPageContent( &$outputDone, &$pcache ) {
168 - global $wgRequest, $wgOut, $wgUser, $wgLang, $wgContLang;
169 - $this->load();
170 - # Only trigger on article view for content pages, not for protect/delete/hist...
171 - $action = $wgRequest->getVal( 'action', 'view' );
172 - if( !self::isViewAction($action) || !$this->article->exists() )
173 - return true;
174 - # Do not clutter up diffs any further and leave archived versions alone...
175 - if( $wgRequest->getVal('diff') || $wgRequest->getVal('oldid') ) {
176 - return true;
177 - }
178 - # Only trigger for reviewable pages
179 - if( !$this->article->isReviewable() ) {
180 - return true;
181 - }
182 - # Load required messages
183 - wfLoadExtensionMessages( 'FlaggedRevs' );
184 - $simpleTag = $old = $stable = false;
185 - $tag = $prot = '';
186 - # Check the newest stable version.
187 - $frev = $srev = $this->article->getStableRev();
188 - $stableId = $frev ? $frev->getRevId() : 0;
189 - # Also, check for any explicitly requested old stable version...
190 - $reqId = $wgRequest->getVal('stableid');
191 - if( $reqId === "best" ) {
192 - $reqId = FlaggedRevs::getPrimeFlaggedRevId( $this->article );
193 - }
194 - if( $stableId && $reqId ) {
195 - # Treat requesting the stable version by ID as &stable=1
196 - if( $reqId != $stableId ) {
197 - $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $reqId, FR_TEXT );
198 - $old = true; // old reviewed version requested by ID
199 - if( !$frev ) {
200 - $wgOut->addWikiText( wfMsg('revreview-invalid') );
201 - $wgOut->returnToMain( false, $this->article->getTitle() );
202 - # Tell MW that parser output is done
203 - $outputDone = true;
204 - $pcache = false;
205 - return true;
206 - }
207 - } else {
208 - $stable = true; // stable version requested by ID
209 - }
210 - }
211 - // Is the page config altered?
212 - if( $this->article->isPageLocked() ) {
213 - $prot = "<span class='fr-icon-locked' title=\"".
214 - wfMsgHtml('revreview-locked-title')."\"></span>";
215 - } elseif( $this->article->isPageUnlocked() ) {
216 - $prot = "<span class='fr-icon-unlocked' title=\"".
217 - wfMsgHtml('revreview-unlocked-title')."\"></span>";
218 - }
219 - // RTL langauges
220 - $rtl = $wgContLang->isRTL() ? " rtl" : "";
221 - // Is there no stable version?
222 - if( is_null($frev) ) {
223 - // Add "no reviewed version" tag, but not for printable output.
224 - if( !$wgOut->isPrintable() ) {
225 - // Simple icon-based UI
226 - if( FlaggedRevs::useSimpleUI() ) {
227 - $msg = $old ? 'revreview-quick-invalid' : 'revreview-quick-none';
228 - $tag .= "{$prot}<span class='fr-icon-current plainlinks'></span>" .
229 - wfMsgExt($msg,array('parseinline'));
230 - $tag = "<div id='mw-revisiontag' class='flaggedrevs_short{$rtl} plainlinks noprint'>$tag</div>";
231 - $this->reviewNotice .= $tag;
232 - // Standard UI
233 - } else {
234 - $msg = $old ? 'revreview-invalid' : 'revreview-noflagged';
235 - $tag = "<div id='mw-revisiontag' class='flaggedrevs_notice plainlinks noprint'>" .
236 - "{$prot}<span class='fr-icon-current plainlinks'></span>" .
237 - wfMsgExt($msg, array('parseinline')) . "</div>";
238 - $this->reviewNotice .= $tag;
239 - }
240 - }
241 - # Show notice bar/icon
242 - $this->displayTag();
243 - return true;
244 - }
245 - # Get flags and date
246 - $time = $wgLang->date( $frev->getTimestamp(), true );
247 - $flags = $frev->getTags();
248 - # Get quality level
249 - $quality = FlaggedRevs::isQuality( $flags );
250 - $pristine = FlaggedRevs::isPristine( $flags );
251 - // Looking at some specific old stable revision ("&stableid=x")
252 - // set to override given the relevant conditions. If the user is
253 - // requesting the stable revision ("&stableid=x"), defer to override
254 - // behavior below, since it is the same as ("&stable=1").
255 - if( $old ) {
256 - $this->showOldReviewedVersion( $srev, $frev, $tag, $prot );
257 - $outputDone = true; # Tell MW that parser output is done
258 - $pcache = false;
259 - // Looking at some specific old revision (&oldid=x) or if FlaggedRevs is not
260 - // set to override given the relevant conditions (like &stable=0).
261 - } elseif( !$stable && !$this->pageOverride() ) {
262 - $this->showRegularVersion( $srev, $tag, $prot );
263 - // The relevant conditions are met to override the page with the stable version.
264 - } else {
265 - $this->showStableVersion( $srev, $tag, $prot );
266 - $outputDone = true; # Tell MW that parser output is done
267 - $pcache = false;
268 - }
269 - # Some checks for which tag CSS to use
270 - if( FlaggedRevs::useSimpleUI() ) $tagClass = 'flaggedrevs_short';
271 - elseif( $simpleTag ) $tagClass = 'flaggedrevs_notice';
272 - elseif( $pristine ) $tagClass = 'flaggedrevs_pristine';
273 - elseif( $quality ) $tagClass = 'flaggedrevs_quality';
274 - else $tagClass = 'flaggedrevs_basic';
275 - # Wrap tag contents in a div
276 - if( $tag != '' ) {
277 - $tag = "<div id='mw-revisiontag' class='{$tagClass}{$rtl} plainlinks noprint'>$tag</div>";
278 - $this->reviewNotice .= $tag;
279 - }
280 - # Show notice bar/icon
281 - $this->displayTag();
282 -
283 - return true;
284 - }
285 -
286 - /**
287 - * @param $srev stable version
288 - * @param $tag review box/bar info
289 - * @param $prot protection notice
290 - * Tag output function must be called by caller
291 - * Parser cache control deferred to caller
292 - */
293 - protected function showRegularVersion( $srev, &$tag, $prot ) {
294 - global $wgUser, $wgOut, $wgLang, $wgRequest;
295 - $this->load();
296 - $flags = $srev->getTags();
297 - $time = $wgLang->date( $srev->getTimestamp(), true );
298 - # Get quality level
299 - $quality = FlaggedRevs::isQuality( $flags );
300 - $pristine = FlaggedRevs::isPristine( $flags );
301 - $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
302 - # Get stable version sync status
303 - $synced = FlaggedRevs::stableVersionIsSynced( $srev, $this->article );
304 - if( $synced ) {
305 - $this->getReviewNotes( $srev ); // Still the same
306 - } else {
307 - $this->maybeShowTopDiff( $srev, $quality ); // user may want diff (via prefs)
308 - }
309 - $pending = '';
310 - # Give notice to newer users if an unreviewed edit was completed...
311 - if( !$synced && $wgRequest->getVal('shownotice') && !$wgUser->isAllowed('review') ) {
312 - $tooltip = wfMsgHtml('revreview-draft-title');
313 - $pending = "{$prot}<span class='fr-icon-current' title=\"{$tooltip}\"></span>" .
314 - wfMsgExt('revreview-edited',array('parseinline'),$srev->getRevId(),$revsSince);
315 - $pending = "<div id='mw-reviewnotice' class='flaggedrevs_preview plainlinks'>$pending</div>";
316 - # Notice should always use subtitle
317 - $this->reviewNotice = $pending;
318 - }
319 - # If they are synced, do special styling
320 - $simpleTag = !$synced;
321 - # Construct some tagging for non-printable outputs. Note that the pending
322 - # notice has all this info already, so don't do this if we added that already.
323 - if( !$wgOut->isPrintable() && !$pending && !($this->article->lowProfileUI() && $synced) ) {
324 - $class = 'fr-icon-current'; // default
325 - $tooltip = 'revreview-draft-title';
326 - // Simple icon-based UI
327 - if( FlaggedRevs::useSimpleUI() ) {
328 - if( $synced ) {
329 - $msg = $quality ? 'revreview-quick-quality-same' : 'revreview-quick-basic-same';
330 - $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
331 - $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
332 - $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
333 - } else {
334 - $msg = $quality ? 'revreview-quick-see-quality' : 'revreview-quick-see-basic';
335 - $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
336 - }
337 - $tooltip = wfMsgHtml($tooltip);
338 - $msgHTML = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>$msgHTML";
339 - $tag .= FlaggedRevsXML::prettyRatingBox( $srev, $msgHTML, $revsSince,
340 - $synced, $synced, false );
341 - // Standard UI
342 - } else {
343 - if( $synced ) {
344 - $msg = $quality ? 'revreview-quality-same' : 'revreview-basic-same';
345 - $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
346 - $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
347 - $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(),
348 - $time, $revsSince );
349 - } else {
350 - $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
351 - $msg .= ($revsSince == 0) ? '-i' : '';
352 - $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(),
353 - $time, $revsSince );
354 - }
355 - $tooltip = wfMsgHtml($tooltip);
356 - $tag .= "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" . $msgHTML;
357 - # Hide clutter
358 - if( !empty($flags) ) {
359 - $tag .= " " . FlaggedRevsXML::ratingToggle();
360 - $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
361 - wfMsgHtml('revreview-oldrating') . FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
362 - }
363 - }
364 - }
365 - # Index the stable version only if it is the default
366 - if( $this->article->showStableByDefault() ) {
367 - $wgOut->setRobotPolicy( 'noindex,nofollow' );
368 - }
369 - }
370 -
371 - /**
372 - * @param $srev stable version
373 - * @param $frev selected flagged revision
374 - * @param $tag review box/bar info
375 - * @param $prot protection notice
376 - * Tag output function must be called by caller
377 - * Parser cache control deferred to caller
378 - */
379 - protected function showOldReviewedVersion( $srev, $frev, &$tag, $prot ) {
380 - global $wgOut, $wgLang;
381 - $this->load();
382 - $flags = $frev->getTags();
383 - $time = $wgLang->date( $frev->getTimestamp(), true );
384 - # Set display revision ID
385 - $wgOut->setRevisionId( $frev->getRevId() );
386 - # Get quality level
387 - $quality = FlaggedRevs::isQuality( $flags );
388 - $pristine = FlaggedRevs::isPristine( $flags );
389 - $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
390 - $text = $frev->getRevText();
391 - $parserOut = FlaggedRevs::parseStableText( $this->article, $text, $frev->getRevId() );
392 - # Construct some tagging for non-printable outputs. Note that the pending
393 - # notice has all this info already, so don't do this if we added that already.
394 - if( !$wgOut->isPrintable() ) {
395 - $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
396 - $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
397 - $tooltip = wfMsgHtml($tooltip);
398 - // Simple icon-based UI
399 - if( FlaggedRevs::useSimpleUI() ) {
400 - $msg = $quality ? 'revreview-quick-quality-old' : 'revreview-quick-basic-old';
401 - $html = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
402 - wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
403 - $tag = FlaggedRevsXML::prettyRatingBox( $frev, $html, $revsSince,
404 - true, false, true );
405 - // Standard UI
406 - } else {
407 - $msg = $quality ? 'revreview-quality-old' : 'revreview-basic-old';
408 - $tag = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
409 - wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
410 - # Hide clutter
411 - if( !empty($flags) ) {
412 - $tag .= " " . FlaggedRevsXML::ratingToggle();
413 - $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
414 - wfMsgHtml('revreview-oldrating') .
415 - FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
416 - }
417 - }
418 - }
419 - # Output HTML
420 - $this->getReviewNotes( $frev );
421 - $wgOut->addParserOutput( $parserOut );
422 - # Index the stable version only
423 - $wgOut->setRobotPolicy( 'noindex,nofollow' );
424 - }
425 -
426 - /**
427 - * @param $srev stable version
428 - * @param $tag review box/bar info
429 - * @param $prot protection notice
430 - * Tag output function must be called by caller
431 - * Parser cache control deferred to caller
432 - */
433 - protected function showStableVersion( $srev, &$tag, $prot ) {
434 - global $wgOut, $wgLang, $wgUser;
435 - $this->load();
436 - $flags = $srev->getTags();
437 - $time = $wgLang->date( $srev->getTimestamp(), true );
438 - # Set display revision ID
439 - $wgOut->setRevisionId( $srev->getRevId() );
440 - # Get quality level
441 - $quality = FlaggedRevs::isQuality( $flags );
442 - $pristine = FlaggedRevs::isPristine( $flags );
443 - # We will be looking at the reviewed revision...
444 - $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
445 - # Get parsed stable version
446 - $parserOut = FlaggedRevs::getPageCache( $this->article, $wgUser );
447 - if( $parserOut == false ) {
448 - $text = $srev->getRevText();
449 - $parserOut = FlaggedRevs::parseStableText( $this->article, $text, $srev->getRevId() );
450 - # Update the stable version cache
451 - FlaggedRevs::updatePageCache( $this->article, $wgUser, $parserOut );
452 - }
453 - $synced = FlaggedRevs::stableVersionIsSynced( $srev, $this->article, $parserOut, null );
454 - # Construct some tagging
455 - if( !$wgOut->isPrintable() && !($this->article->lowProfileUI() && $synced) ) {
456 - $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
457 - $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
458 - $tooltip = wfMsgHtml($tooltip);
459 - // Simple icon-based UI
460 - if( FlaggedRevs::useSimpleUI() ) {
461 - $msg = $quality ? 'revreview-quick-quality' : 'revreview-quick-basic';
462 - # uses messages 'revreview-quick-quality-same', 'revreview-quick-basic-same'
463 - $msg = $synced ? "{$msg}-same" : $msg;
464 - $html = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
465 - wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
466 - $tag = FlaggedRevsXML::prettyRatingBox( $srev, $html, $revsSince, true, $synced );
467 - // Standard UI
468 - } else {
469 - $msg = $quality ? 'revreview-quality' : 'revreview-basic';
470 - if( $synced ) {
471 - # uses messages 'revreview-quality-same', 'revreview-basic-same'
472 - $msg .= '-same';
473 - } elseif( $revsSince == 0 ) {
474 - # uses messages 'revreview-quality-i', 'revreview-basic-i'
475 - $msg .= '-i';
476 - }
477 - $tag = "{$prot}<span class='{$class} plainlinks' title=\"{$tooltip}\"></span>" .
478 - wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $time, $revsSince );
479 - if( !empty($flags) ) {
480 - $tag .= " " . FlaggedRevsXML::ratingToggle();
481 - $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
482 - FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
483 - }
484 - }
485 - }
486 - # Output HTML
487 - $this->getReviewNotes( $srev );
488 - $wgOut->addParserOutput( $parserOut );
489 - }
490 -
491 - /**
492 - * @param FlaggedRevision $srev, stable version
493 - * @param bool $quality, revision is quality
494 - * @returns bool, diff added to output
495 - */
496 - protected function maybeShowTopDiff( $srev, $quality ) {
497 - global $wgUser, $wgOut, $wgMemc;
498 - $this->load();
499 - if( !$wgUser->getBoolOption('flaggedrevsviewdiffs') )
500 - return false; // nothing to do here
501 - if( !$wgUser->isAllowed('review') )
502 - return false; // does not apply to this user
503 - # Diff should only show for the draft
504 - $oldid = $this->article->getOldIDFromRequest();
505 - $latest = $this->article->getLatest();
506 - if( $oldid && $oldid != $latest ) {
507 - return false; // not viewing the draft
508 - }
509 - # Conditions are met to show diff...
510 - wfLoadExtensionMessages( 'FlaggedRevs' ); // load required messages
511 - $leftNote = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
512 - $rClass = FlaggedRevsXML::getQualityColor( false );
513 - $lClass = FlaggedRevsXML::getQualityColor( (int)$quality );
514 - $rightNote = "<span class='$rClass'>[".wfMsgHtml('revreview-draft-title')."]</span>";
515 - $leftNote = "<span class='$lClass'>[".wfMsgHtml($leftNote)."]</span>";
516 - # Fetch the stable and draft revision text
517 - $oText = $srev->getRevText();
518 - if( $oText === false )
519 - return false; // deleted revision or something?
520 - $nText = $this->article->getContent();
521 - if( $nText === false )
522 - return false; // deleted revision or something?
523 - # Build diff at the top of the page
524 - if( strcmp($oText,$nText) !== 0 ) {
525 - $diffEngine = new DifferenceEngine();
526 - $diffEngine->showDiffStyle();
527 - $n = $this->article->getTitle()->countRevisionsBetween( $srev->getRevId(), $latest );
528 - if( $n ) {
529 - $multiNotice = "<tr><td colspan='4' align='center' class='diff-multi'>" .
530 - wfMsgExt( 'diff-multi', array( 'parse' ), $n )."</td></tr>";
531 - } else {
532 - $multiNotice = '';
533 - }
534 - $wgOut->addHTML(
535 - "<div>" .
536 - "<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" .
537 - "<col class='diff-marker' />" .
538 - "<col class='diff-content' />" .
539 - "<col class='diff-marker' />" .
540 - "<col class='diff-content' />" .
541 - "<tr>" .
542 - "<td colspan='2' width='50%' align='center' class='diff-otitle'><b>" .
543 - $leftNote . "</b></td>" .
544 - "<td colspan='2' width='50%' align='center' class='diff-ntitle'><b>" .
545 - $rightNote . "</b></td>" .
546 - "</tr>" .
547 - $multiNotice .
548 - $diffEngine->generateDiffBody( $oText, $nText ) .
549 - "</table>" .
550 - "</div>\n"
551 - );
552 - $this->isDiffFromStable = true;
553 - return true;
554 - }
555 - return false;
556 - }
557 -
558 - /**
559 - * Get the normal and display files for the underlying ImagePage.
560 - * If the a stable version needs to be displayed, this will set $normalFile
561 - * to the current version, and $displayFile to the desired version.
562 - *
563 - * If no stable version is required, the reference parameters will not be set
564 - *
565 - * Depends on $wgRequest
566 - */
567 - public function imagePageFindFile( &$normalFile, &$displayFile ) {
568 - global $wgRequest, $wgArticle;
569 - $this->load();
570 - # Determine timestamp. A reviewed version may have explicitly been requested...
571 - $frev = null;
572 - $time = false;
573 - if( $reqId = $wgRequest->getVal('stableid') ) {
574 - $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $reqId );
575 - } elseif( $this->pageOverride() ) {
576 - $frev = $this->article->getStableRev();
577 - }
578 - if( !is_null($frev) ) {
579 - $time = $frev->getFileTimestamp();
580 - // B/C, may be stored in associated image version metadata table
581 - if( !$time ) {
582 - $dbr = wfGetDB( DB_SLAVE );
583 - $time = $dbr->selectField( 'flaggedimages',
584 - 'fi_img_timestamp',
585 - array( 'fi_rev_id' => $frev->getRevId(),
586 - 'fi_name' => $this->article->getTitle()->getDBkey() ),
587 - __METHOD__
588 - );
589 - }
590 - # NOTE: if not found, this will use the current
591 - $wgArticle = new ImagePage( $this->article->getTitle(), $time );
592 - }
593 - if( !$time ) {
594 - # Try request parameter
595 - $time = $wgRequest->getVal( 'filetimestamp', false );
596 - }
597 -
598 - if( !$time ) {
599 - return; // Use the default behaviour
600 - }
601 -
602 - $title = $this->article->getTitle();
603 - $displayFile = wfFindFile( $title, array( 'time' => $time ) );
604 - # If none found, try current
605 - if( !$displayFile ) {
606 - wfDebug( __METHOD__.": {$title->getPrefixedDBkey()}: $time not found, using current\n" );
607 - $displayFile = wfFindFile( $title );
608 - # If none found, use a valid local placeholder
609 - if( !$displayFile ) {
610 - $displayFile = wfLocalFile( $title ); // fallback to current
611 - }
612 - $normalFile = $displayFile;
613 - # If found, set $normalFile
614 - } else {
615 - wfDebug( __METHOD__.": {$title->getPrefixedDBkey()}: using timestamp $time\n" );
616 - $normalFile = wfFindFile( $title );
617 - }
618 - }
619 -
620 - /**
621 - * Adds latest stable version tag to page when editing
622 - */
623 - public function addToEditView( $editPage ) {
624 - global $wgRequest, $wgOut;
625 - $this->load();
626 - # Must be reviewable. UI may be limited to unobtrusive patrolling system.
627 - if( !$this->article->isReviewable() || $this->article->limitedUI() )
628 - return true;
629 - # Show stabilization log
630 - $this->showStabilityLog();
631 - # Set new body html text as that of now
632 - $tag = $warning = $prot = '';
633 - # Check the newest stable version
634 - $quality = 0;
635 - if( $frev = $this->article->getStableRev() ) {
636 - global $wgLang, $wgUser, $wgFlaggedRevsAutoReview;
637 - # Find out revision id
638 - $revId = $editPage->oldid ?
639 - $editPage->oldid : $this->article->getLatest();
640 - # If this will be autoreviewed, notify the user...
641 - if( !FlaggedRevs::lowProfileUI() && $wgFlaggedRevsAutoReview && $wgUser->isAllowed('review') ) {
642 - # If we are editing some reviewed revision, any changes this user
643 - # makes will be autoreviewed...
644 - $ofrev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $revId );
645 - if( !is_null($ofrev) ) {
646 - wfLoadExtensionMessages( 'FlaggedRevs' );
647 - $msg = ( $revId==$frev->getRevId() ) ? 'revreview-auto-w' : 'revreview-auto-w-old';
648 - $warning = "<div id='mw-autoreviewtag' class='flaggedrevs_warning plainlinks'>" .
649 - wfMsgExt($msg,array('parseinline')) . "</div>";
650 - }
651 - # Let new users know about review procedure a tag
652 - } elseif( !$wgUser->getId() && $this->article->showStableByDefault() ) {
653 - wfLoadExtensionMessages( 'FlaggedRevs' );
654 - $warning = "<div id='mw-editwarningtag' class='flaggedrevs_editnotice plainlinks'>" .
655 - wfMsgExt('revreview-editnotice',array('parseinline')) . "</div>";
656 - }
657 - if( $frev->getRevId() != $revId ) {
658 - wfLoadExtensionMessages( 'FlaggedRevs' );
659 - $time = $wgLang->date( $frev->getTimestamp(), true );
660 - $flags = $frev->getTags();
661 - if( FlaggedRevs::isQuality($flags) ) {
662 - $quality = FlaggedRevs::isPristine($flags) ? 2 : 1;
663 - }
664 - $revsSince = FlaggedRevs::getRevCountSince( $this->article, $frev->getRevId() );
665 - // Is the page config altered?
666 - if( $this->article->isPageLocked() ) {
667 - $prot = "<span class='fr-icon-locked' title=\"".
668 - wfMsgHtml('revreview-locked-title')."\"></span>";
669 - } elseif( $this->article->isPageUnlocked() ) {
670 - $prot = "<span class='fr-icon-unlocked' title=\"".
671 - wfMsgHtml('revreview-unlocked-title')."\"></span>";
672 - }
673 - # Streamlined UI
674 - if( FlaggedRevs::useSimpleUI() ) {
675 - $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
676 - $msg .= ($revsSince == 0) ? '-i' : '';
677 - $tag = "{$prot}<span class='fr-checkbox'></span>" .
678 - wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time, $revsSince );
679 - $tag = "<div id='mw-revisiontag-edit' class='flaggedrevs_editnotice plainlinks'>$tag</div>";
680 - # Standard UI
681 - } else {
682 - $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
683 - $msg .= ($revsSince == 0) ? '-i' : '';
684 - $tag = "{$prot}<span class='fr-checkbox'></span>" .
685 - wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time, $revsSince );
686 - # Hide clutter
687 - if( !empty($flags) ) {
688 - $tag .= " " . FlaggedRevsXML::ratingToggle();
689 - $tag .= '<span id="mw-revisionratings" style="display:block;"><br/>' .
690 - wfMsg('revreview-oldrating') . FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
691 - }
692 - $tag = "<div id='mw-revisiontag-edit' class='flaggedrevs_editnotice plainlinks'>$tag</div>";
693 - }
694 - }
695 - # Output notice and warning for editors
696 - if( $tag || $warning ) {
697 - $wgOut->addHTML( $tag . $warning );
698 - }
699 -
700 - # Show diff to stable, to make things less confusing...
701 - # This can be disabled via user preferences
702 - if( $frev->getRevId() < $revId // changes were made
703 - && $this->showDiffOnEditUser() // stable default and user cannot review
704 - && $wgUser->getBoolOption('flaggedrevseditdiffs') // not disable via prefs
705 - ) {
706 - # Don't show for old revisions, diff, preview, or undo.
707 - if( $editPage->oldid || $editPage->section === "new"
708 - || in_array($editPage->formtype,array('diff','preview')) )
709 - {
710 - return true; // nothing to show here
711 - }
712 -
713 - # Conditions are met to show diff...
714 - wfLoadExtensionMessages( 'FlaggedRevs' ); // load required messages
715 - $leftNote = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
716 - $rClass = FlaggedRevsXML::getQualityColor( false );
717 - $lClass = FlaggedRevsXML::getQualityColor( (int)$quality );
718 - $rightNote = "<span class='$rClass'>[".wfMsgHtml('revreview-draft-title')."]</span>";
719 - $leftNote = "<span class='$lClass'>[".wfMsgHtml($leftNote)."]</span>";
720 - $text = $frev->getRevText();
721 - # Are we editing a section?
722 - $section = ($editPage->section == "") ? false : intval($editPage->section);
723 - if( $section !== false ) {
724 - $text = $this->article->getSection( $text, $section );
725 - }
726 - if( $text !== false && strcmp($text,$editPage->textbox1) !== 0 ) {
727 - $diffEngine = new DifferenceEngine();
728 - $diffEngine->showDiffStyle();
729 - $wgOut->addHTML(
730 - "<div>" .
731 - "<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" .
732 - "<col class='diff-marker' />" .
733 - "<col class='diff-content' />" .
734 - "<col class='diff-marker' />" .
735 - "<col class='diff-content' />" .
736 - "<tr>" .
737 - "<td colspan='2' width='50%' align='center' class='diff-otitle'><b>" .
738 - $leftNote . "</b></td>" .
739 - "<td colspan='2' width='50%' align='center' class='diff-ntitle'><b>" .
740 - $rightNote . "</b></td>" .
741 - "</tr>" .
742 - $diffEngine->generateDiffBody( $text, $editPage->textbox1 ) .
743 - "</table>" .
744 - "</div>\n"
745 - );
746 - }
747 - }
748 - }
749 - return true;
750 - }
751 -
752 - protected function showStabilityLog() {
753 - global $wgOut;
754 - $this->load();
755 - # Only for pages manually made to be stable...
756 - if( $this->article->isPageLocked() ) {
757 - wfLoadExtensionMessages( 'FlaggedRevs' );
758 - $wgOut->addHTML( "<div class='mw-warning-with-logexcerpt'>" );
759 - $wgOut->addWikiMsg( 'revreview-locked' );
760 - LogEventsList::showLogExtract( $wgOut, 'stable',
761 - $this->article->getTitle()->getPrefixedText(), '', array('lim'=>1) );
762 - $wgOut->addHTML( "</div>" );
763 - # ...or unstable
764 - } elseif( $this->article->isPageUnlocked() ) {
765 - wfLoadExtensionMessages( 'FlaggedRevs' );
766 - $wgOut->addHTML( "<div class='mw-warning-with-logexcerpt'>" );
767 - $wgOut->addWikiMsg( 'revreview-unlocked' );
768 - LogEventsList::showLogExtract( $wgOut, 'stable',
769 - $this->article->getTitle()->getPrefixedText(), '', array('lim'=>1) );
770 - $wgOut->addHTML( "</div>" );
771 - }
772 - return true;
773 - }
774 -
775 - /**
776 - * Add unreviewed pages links
777 - */
778 - public function addToCategoryView() {
779 - global $wgOut, $wgUser;
780 - $this->load();
781 - if( !$wgUser->isAllowed( 'review' ) ) {
782 - return true;
783 - }
784 - wfLoadExtensionMessages( 'FlaggedRevs' );
785 - # Load special page names
786 - wfLoadExtensionMessages( 'OldReviewedPages' );
787 - wfLoadExtensionMessages( 'UnreviewedPages' );
788 -
789 - $category = $this->article->getTitle()->getText();
790 -
791 - $unreviewed = SpecialPage::getTitleFor( 'UnreviewedPages' );
792 - $unreviewedLink = $wgUser->getSkin()->makeKnownLinkObj( $unreviewed,
793 - wfMsgHtml('unreviewedpages'), 'category=' . urlencode($category) );
794 -
795 - $oldreviewed = SpecialPage::getTitleFor( 'OldReviewedPages' );
796 - $oldreviewedLink = $wgUser->getSkin()->makeKnownLinkObj( $oldreviewed,
797 - wfMsgHtml('oldreviewedpages'), 'category=' . urlencode($category) );
798 -
799 - $wgOut->appendSubtitle("<span id='mw-category-oldreviewed'>$unreviewedLink / $oldreviewedLink</span>");
800 -
801 - return true;
802 - }
803 -
804 - /**
805 - * Add review form to pages when necessary
806 - */
807 - public function addReviewForm( &$data ) {
808 - global $wgRequest, $wgUser, $wgOut;
809 - $this->load();
810 - # User must have review rights and page must be reviewable
811 - if( !$wgUser->isAllowed('review') || !$this->article->exists() || !$this->article->isReviewable() ) {
812 - return true;
813 - }
814 - # Unobtrusive patrolling UI only shows forms if requested
815 - if( !$wgRequest->getInt('reviewform') && $this->article->limitedUI() ) {
816 - return true;
817 - }
818 - # Avoid multi-page diffs that are useless and misbehave (bug 19327)
819 - if( $this->isMultiPageDiff ) {
820 - return true;
821 - }
822 - # Check action and if page is protected
823 - $action = $wgRequest->getVal( 'action', 'view' );
824 - # Must be view/diff action...
825 - if( !self::isViewAction($action) ) {
826 - return true;
827 - }
828 - # Place the form at the top or bottom as most convenient
829 - $onTop = $wgRequest->getVal('diff') || $this->isDiffFromStable;
830 - $this->addQuickReview( $data, $onTop, false );
831 - return true;
832 - }
833 -
834 - /**
835 - * Add link to stable version setting to protection form
836 - */
837 - public function addVisibilityLink( &$data ) {
838 - global $wgUser, $wgRequest, $wgOut;
839 - $this->load();
840 - if( FlaggedRevs::getProtectionLevels() )
841 - return true; // simple custom levels set for action=protect
842 - # Check only if the title is reviewable
843 - if( !$this->article->isReviewable(true) ) {
844 - return true;
845 - }
846 - $action = $wgRequest->getVal( 'action', 'view' );
847 - if( $action == 'protect' || $action == 'unprotect' ) {
848 - wfLoadExtensionMessages( 'FlaggedRevs' );
849 - wfLoadExtensionMessages( 'Stabilization' ); // Load special page name
850 - $title = SpecialPage::getTitleFor( 'Stabilization' );
851 - # Give a link to the page to configure the stable version
852 - $frev = $this->article->getStableRev();
853 - if( $frev && $frev->getRevId() == $this->article->getLatest() ) {
854 - $wgOut->prependHTML( "<span class='plainlinks'>" .
855 - wfMsgExt( 'revreview-visibility',array('parseinline'),
856 - $title->getPrefixedText() ) . "</span>" );
857 - } elseif( $frev ) {
858 - $wgOut->prependHTML( "<span class='plainlinks'>" .
859 - wfMsgExt( 'revreview-visibility2',array('parseinline'),
860 - $title->getPrefixedText() ) . "</span>" );
861 - } else {
862 - $wgOut->prependHTML( "<span class='plainlinks'>" .
863 - wfMsgExt( 'revreview-visibility3',array('parseinline'),
864 - $title->getPrefixedText() ) . "</span>" );
865 - }
866 - }
867 - return true;
868 - }
869 -
870 - /**
871 - * Modify an array of action links, as used by SkinTemplateNavigation and
872 - * SkinTemplateTabs, to inlude flagged revs UI elements
873 - */
874 - public function setActionTabs( $skin, &$actions ) {
875 - global $wgRequest, $wgUser;
876 - $this->load();
877 - if( FlaggedRevs::getProtectionLevels() ) {
878 - return true; // simple custom levels set for action=protect
879 - }
880 - $title = $this->article->getTitle()->getSubjectPage();
881 - if ( !FlaggedRevs::isPageReviewable( $title ) ) {
882 - return true; // Only reviewable pages need these tabs
883 - }
884 - // Check if we should show a stabilization tab
885 - if (
886 - !$skin->mTitle->isTalkPage() &&
887 - is_array( $actions ) &&
888 - !isset( $actions['protect'] ) &&
889 - !isset( $actions['unprotect'] ) &&
890 - $wgUser->isAllowed( 'stablesettings' ) &&
891 - $title->exists()
892 - ) {
893 - wfLoadExtensionMessages( 'Stabilization' );
894 - $stableTitle = SpecialPage::getTitleFor( 'Stabilization' );
895 - // Add a tab
896 - $actions['default'] = array(
897 - 'class' => false,
898 - 'text' => wfMsg( 'stabilization-tab' ),
899 - 'href' => $stableTitle->getLocalUrl(
900 - 'page=' . $title->getPrefixedUrl()
901 - )
902 - );
903 - }
904 - return true;
905 - }
906 -
907 - /**
908 - * Modify an array of view links, as used by SkinTemplateNavigation and
909 - * SkinTemplateTabs, to inlude flagged revs UI elements
910 - */
911 - public function setViewTabs( $skin, &$views ) {
912 - global $wgRequest, $wgUser, $wgFlaggedRevTabs;
913 - $this->load();
914 -
915 - $title = $this->article->getTitle()->getSubjectPage(); // Get the actual content page
916 - $article = new Article( $title );
917 - $action = $wgRequest->getVal( 'action', 'view' );
918 - $fa = FlaggedArticle::getTitleInstance( $title );
919 - if ( !$fa->isReviewable() || $this->article->limitedUI() ) {
920 - // This isn't a reviewable page or the UI is hidden
921 - return true;
922 - }
923 - $srev = $this->article->getStableRev( $action == 'rollback' ? FR_MASTER : 0 );
924 - if( is_null( $srev ) ) {
925 - return true; // No stable revision exists
926 - }
927 - wfLoadExtensionMessages( 'FlaggedRevs' );
928 - $synced = FlaggedRevs::stableVersionIsSynced( $srev, $article );
929 - // Set draft tab as needed...
930 - if ( !$skin->mTitle->isTalkPage() && !$synced ) {
931 - if ( isset( $views['edit'] ) ) {
932 - if ( $this->article->showStableByDefault() ) {
933 - $views['edit']['text'] = wfMsg('revreview-edit');
934 - }
935 - if ( $this->pageOverride() ) {
936 - $views['edit']['href'] = $title->getLocalUrl( 'action=edit' );
937 - }
938 - }
939 - if ( isset( $views['viewsource'] ) ) {
940 - if ( $this->article->showStableByDefault() ) {
941 - $views['viewsource']['text'] = wfMsg('revreview-source');
942 - }
943 - if ( $this->pageOverride() ) {
944 - $views['viewsource']['href'] = $title->getLocalUrl( 'action=edit' );
945 - }
946 - }
947 - }
948 - if ( !$wgFlaggedRevTabs || $synced ) {
949 - // Exit, since either the stable/draft tabs should not be shown
950 - // or the page is already the most current revision
951 - return true;
952 - }
953 - $tabs = array(
954 - 'stable' => array(
955 - 'text' => wfMsg( 'revreview-stable' ), // unused
956 - 'href' => $title->getLocalUrl( 'stable=1' ),
957 - 'class' => ''
958 - ),
959 - 'current' => array(
960 - 'text' => wfMsg( 'revreview-current' ),
961 - 'href' => $title->getLocalUrl( 'stable=0&redirect=no' ),
962 - 'class' => ''
963 - ),
964 - );
965 - if ( $this->pageOverride() || $wgRequest->getVal( 'stableid' ) ) {
966 - // We are looking a the stable version
967 - $tabs['stable']['class'] = 'selected';
968 - } elseif (
969 - ( self::isViewAction( $action ) || $action == 'edit' ) &&
970 - !$skin->mTitle->isTalkPage()
971 - ) {
972 - // We are looking at the current revision or in edit mode
973 - $tabs['current']['class'] = 'selected';
974 - }
975 - $first = true;
976 - $newViews = array();
977 - foreach ( $views as $tabAction => $data ) {
978 - // Very first tab (page link)
979 - if( $first ) {
980 - if( $synced ) {
981 - // Use existing first tabs when synced
982 - $newViews[$tabAction] = $data;
983 - } else {
984 - // Use split current and stable tabs when not synced
985 - $newViews[$tabAction]['text'] = $data['text']; // keep tab name
986 - $newViews[$tabAction]['href'] = $tabs['stable']['href'];
987 - $newViews[$tabAction]['class'] = $tabs['stable']['class'];
988 - $newViews['current'] = $tabs['current'];
989 - }
990 - $first = false;
991 - } else {
992 - $newViews[$tabAction] = $data;
993 - }
994 - }
995 - // Replaces old tabs with new tabs
996 - $views = $newViews;
997 - return true;
998 - }
999 -
1000 - /**
1001 - * @param FlaggedRevision $frev
1002 - * @return string, revision review notes
1003 - */
1004 - public function getReviewNotes( $frev ) {
1005 - global $wgUser;
1006 - $this->load();
1007 - if( FlaggedRevs::allowComments() && $frev && $frev->getComment() ) {
1008 - wfLoadExtensionMessages( 'FlaggedRevs' );
1009 - $notes = "<br/><div class='flaggedrevs_notes plainlinks'>";
1010 - $notes .= wfMsgExt('revreview-note', array('parseinline'), User::whoIs( $frev->getUser() ) );
1011 - $notes .= '<br/><i>' . $wgUser->getSkin()->formatComment( $frev->getComment() ) . '</i></div>';
1012 - $this->reviewNotes = $notes;
1013 - }
1014 - }
1015 -
1016 - /**
1017 - * When comparing the stable revision to the current after editing a page, show
1018 - * a tag with some explaination for the diff.
1019 - */
1020 - public function addDiffNoticeAndIncludes( $diff, $oldRev, $newRev ) {
1021 - global $wgRequest, $wgUser, $wgOut, $wgMemc;
1022 - $this->load();
1023 - # Page must be reviewable. Exempt printer-friendly output.
1024 - # UI may be limited to unobtrusive patrolling system
1025 - if( $wgOut->isPrintable() || !$this->article->isReviewable() || $this->article->limitedUI() )
1026 - return true;
1027 - # Load required messages
1028 - wfLoadExtensionMessages( 'FlaggedRevs' );
1029 - # Check if this might be the diff to stable. If so, enhance it.
1030 - if( $newRev->isCurrent() && $oldRev ) {
1031 - $article = new Article( $newRev->getTitle() );
1032 - # Try the sync value cache...
1033 - $key = wfMemcKey( 'flaggedrevs', 'includesSynced', $article->getId() );
1034 - $value = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
1035 - $synced = ($value === "true") ? true : false; // default as false to trigger query
1036 - $frev = $this->article->getStableRev();
1037 - if( $frev && $frev->getRevId() == $oldRev->getID() ) {
1038 - global $wgParserCacheExpireTime;
1039 -
1040 - $changeList = array();
1041 - $skin = $wgUser->getSkin();
1042 -
1043 - # Try the cache. Uses format <page ID>-<UNIX timestamp>.
1044 - $key = wfMemcKey( 'stableDiffs', 'templates', $article->getId() );
1045 - $tmpChanges = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
1046 - if( empty($tmpChanges) && !$synced ) {
1047 - $tmpChanges = false; // don't use cache
1048 - }
1049 -
1050 - # Make a list of each changed template...
1051 - if( $tmpChanges === false ) {
1052 - $dbr = wfGetDB( DB_SLAVE );
1053 - // Get templates where the current and stable are not the same revision
1054 - $ret = $dbr->select( array('flaggedtemplates','page','flaggedpages'),
1055 - array( 'ft_namespace', 'ft_title', 'fp_stable','ft_tmp_rev_id', 'page_latest' ),
1056 - array( 'ft_rev_id' => $frev->getRevId(),
1057 - 'page_namespace = ft_namespace',
1058 - 'page_title = ft_title' ),
1059 - __METHOD__,
1060 - array(), /* OPTIONS */
1061 - array( 'flaggedpages' => array('LEFT JOIN','fp_page_id = page_id') )
1062 - );
1063 - $tmpChanges = array();
1064 - while( $row = $dbr->fetchObject( $ret ) ) {
1065 - $title = Title::makeTitleSafe( $row->ft_namespace, $row->ft_title );
1066 - $revIdDraft = $row->page_latest;
1067 - // stable time -> time when reviewed (unless the other is newer)
1068 - $revIdStable = isset($row->fp_stable) && $row->fp_stable >= $row->ft_tmp_rev_id ?
1069 - $row->fp_stable : $row->ft_tmp_rev_id;
1070 - // compare to current
1071 - if( $revIdDraft > $revIdStable ) {
1072 - $tmpChanges[] = $skin->makeKnownLinkObj( $title, $title->getPrefixedText(),
1073 - "diff=cur&oldid={$revIdStable}" );
1074 - }
1075 - }
1076 - $wgMemc->set( $key, FlaggedRevs::makeMemcObj($tmpChanges), $wgParserCacheExpireTime );
1077 - }
1078 - # Add set to list
1079 - if( $tmpChanges )
1080 - $changeList += $tmpChanges;
1081 -
1082 - # Try the cache. Uses format <page ID>-<UNIX timestamp>.
1083 - $key = wfMemcKey( 'stableDiffs', 'images', $article->getId() );
1084 - $imgChanges = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
1085 - if( empty($imgChanges) && !$synced ) {
1086 - $imgChanges = false; // don't use cache
1087 - }
1088 -
1089 - // Get list of each changed image...
1090 - if( $imgChanges === false ) {
1091 - $dbr = wfGetDB( DB_SLAVE );
1092 - // Get images where the current and stable are not the same revision
1093 - $ret = $dbr->select( array('flaggedimages','page','image','flaggedpages','flaggedrevs'),
1094 - array( 'fi_name', 'fi_img_timestamp', 'fr_img_timestamp' ),
1095 - array( 'fi_rev_id' => $frev->getRevId() ),
1096 - __METHOD__,
1097 - array(), /* OPTIONS */
1098 - array( 'page' => array('LEFT JOIN','page_namespace = '. NS_FILE .' AND page_title = fi_name'),
1099 - 'image' => array('LEFT JOIN','img_name = fi_name'),
1100 - 'flaggedpages' => array('LEFT JOIN','fp_page_id = page_id'),
1101 - 'flaggedrevs' => array('LEFT JOIN','fr_page_id = fp_page_id AND fr_rev_id = fp_stable') )
1102 - );
1103 - $imgChanges = array();
1104 - while( $row = $dbr->fetchObject( $ret ) ) {
1105 - $title = Title::makeTitleSafe( NS_FILE, $row->fi_name );
1106 - // stable time -> time when reviewed (unless the other is newer)
1107 - $timestamp = isset($row->fr_img_timestamp) && $row->fr_img_timestamp >= $row->fi_img_timestamp ?
1108 - $row->fr_img_timestamp : $row->fi_img_timestamp;
1109 - // compare to current
1110 - $file = wfFindFile( $title );
1111 - if( $file && $file->getTimestamp() > $timestamp )
1112 - $imgChanges[] = $skin->makeKnownLinkObj( $title, $title->getPrefixedText() );
1113 - }
1114 - $wgMemc->set( $key, FlaggedRevs::makeMemcObj($imgChanges), $wgParserCacheExpireTime );
1115 - }
1116 - if( $imgChanges )
1117 - $changeList += $imgChanges;
1118 -
1119 - # Some important information...
1120 - $notice = '';
1121 - if( count($changeList) > 0 ) {
1122 - $notice = '<br/>' . wfMsgExt('revreview-update-use', array('parseinline'));
1123 - } elseif( !$synced ) {
1124 - $diff->mTitle->invalidateCache(); // bad cache, said they were not synced
1125 - }
1126 -
1127 - # If the user is allowed to review, prompt them!
1128 - if( empty($changeList) && $wgUser->isAllowed('review') ) {
1129 - $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
1130 - wfMsgExt('revreview-update-none', array('parseinline')).$notice.'</div>' );
1131 - } elseif( !empty($changeList) && $wgUser->isAllowed('review') ) {
1132 - $changeList = implode(', ',$changeList);
1133 - $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
1134 - wfMsgExt('revreview-update', array('parseinline')).'&nbsp;'.
1135 - $changeList.$notice.'</div>' );
1136 - } elseif( !empty($changeList) ) {
1137 - $changeList = implode(', ',$changeList);
1138 - $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
1139 - wfMsgExt('revreview-update-includes', array('parseinline')).'&nbsp;'.
1140 - $changeList.$notice.'</div>' );
1141 - }
1142 - # Set flag for review form to tell it to autoselect tag settings from the
1143 - # old revision unless the current one is tagged to.
1144 - if( !FlaggedRevision::newFromTitle( $diff->mTitle, $newRev->getID() ) ) {
1145 - $this->isDiffFromStable = true;
1146 - }
1147 -
1148 - # Set a key to note that someone is viewing this
1149 - if( $wgUser->isAllowed('review') ) {
1150 - $key = wfMemcKey( 'stableDiffs', 'underReview', $oldRev->getID(), $newRev->getID() );
1151 - $wgMemc->set( $key, '1', 10*60 ); // 10 min
1152 - }
1153 - }
1154 - }
1155 - $newRevQ = FlaggedRevs::getRevQuality( $newRev->getPage(), $newRev->getId() );
1156 - $oldRevQ = $oldRev ? FlaggedRevs::getRevQuality( $newRev->getPage(), $oldRev->getId() ) : false;
1157 - # Diff between two revisions
1158 - if( $oldRev ) {
1159 - $wgOut->addHTML( "<table class='fr-diff-ratings'><tr>" );
1160 -
1161 - $class = FlaggedRevsXML::getQualityColor( $oldRevQ );
1162 - if( $oldRevQ !== false ) {
1163 - $msg = $oldRevQ ? 'hist-quality' : 'hist-stable';
1164 - } else {
1165 - $msg = 'hist-draft';
1166 - }
1167 - $wgOut->addHTML( "<td width='50%' align='center'>" );
1168 - $wgOut->addHTML( "<span class='$class'><b>[" . wfMsgHtml( $msg ) . "]</b></span>" );
1169 -
1170 - $class = FlaggedRevsXML::getQualityColor( $newRevQ );
1171 - if( $newRevQ !== false ) {
1172 - $msg = $newRevQ ? 'hist-quality' : 'hist-stable';
1173 - } else {
1174 - $msg = 'hist-draft';
1175 - }
1176 - $wgOut->addHTML( "</td><td width='50%' align='center'>" );
1177 - $wgOut->addHTML( "<span class='$class'><b>[" . wfMsgHtml( $msg ) . "]</b></span>" );
1178 -
1179 - $wgOut->addHTML( '</td></tr></table>' );
1180 - # New page "diffs" - just one rev
1181 - } else {
1182 - if( $newRevQ !== false ) {
1183 - $msg = $newRevQ ? 'hist-quality' : 'hist-stable';
1184 - } else {
1185 - $msg = 'hist-draft';
1186 - }
1187 - $wgOut->addHTML( "<table class='fr-diff-ratings'><tr><td class='fr-$msg' align='center'>" );
1188 - $wgOut->addHTML( "<b>[" . wfMsgHtml( $msg ) . "]</b>" );
1189 - $wgOut->addHTML( '</td></tr></table>' );
1190 - }
1191 - return true;
1192 - }
1193 -
1194 - /**
1195 - * Set $this->isDiffFromStable and $this->isMultiPageDiff fields
1196 - */
1197 - public function setViewFlags( $diff, $oldRev, $newRev ) {
1198 - $this->load();
1199 - if( $newRev && $oldRev ) {
1200 - // Is this a diff between two pages?
1201 - if( $newRev->getPage() != $oldRev->getPage() ) {
1202 - $this->isMultiPageDiff = true;
1203 - // Is there a stable version?
1204 - } else if( $this->article->isReviewable() ) {
1205 - $frev = $this->article->getStableRev();
1206 - // Is this a diff of the draft rev against the stable rev?
1207 - if( $frev && $frev->getRevId() == $oldRev->getId() && $newRev->isCurrent() ) {
1208 - $this->isDiffFromStable = true;
1209 - }
1210 - }
1211 - }
1212 - return true;
1213 - }
1214 -
1215 - /**
1216 - * Add a link to patrol non-reviewable pages.
1217 - * Also add a diff-to-stable for other pages if possible.
1218 - */
1219 - public function addDiffLink( $diff, $oldRev, $newRev ) {
1220 - global $wgUser, $wgOut;
1221 - $this->load();
1222 - // Is there a stable version?
1223 - if( $newRev && $oldRev && $this->article->isReviewable() ) {
1224 - $frev = $this->article->getStableRev();
1225 - # Give a link to the diff-to-stable if needed
1226 - if( $frev && !$this->isDiffFromStable ) {
1227 - $article = new Article( $newRev->getTitle() );
1228 - # Is the stable revision using the same revision as the current?
1229 - if( $article->getLatest() != $frev->getRevId() ) {
1230 - wfLoadExtensionMessages( 'FlaggedRevs' );
1231 - $patrol = '(' . $wgUser->getSkin()->makeKnownLinkObj( $newRev->getTitle(),
1232 - wfMsgHtml( 'review-diff2stable' ), "oldid={$frev->getRevId()}&diff=cur&diffonly=0" ) . ')';
1233 - $wgOut->addHTML( "<div class='fr-diff-to-stable' align='center'>$patrol</div>" );
1234 - }
1235 - }
1236 - }
1237 - return true;
1238 - }
1239 -
1240 - /**
1241 - * Redirect users out to review the changes to the stable version.
1242 - * Only for people who can review and for pages that have a stable version.
1243 - */
1244 - public function injectReviewDiffURLParams( &$sectionAnchor, &$extraQuery ) {
1245 - global $wgUser, $wgReviewChangesAfterEdit;
1246 - $this->load();
1247 - # Don't show this for pages that are not reviewable
1248 - if( !$this->article->isReviewable() || $this->article->getTitle()->isTalkPage() )
1249 - return true;
1250 - # We may want to skip some UI elements
1251 - if( $this->article->limitedUI() ) return true;
1252 - # Get the stable version, from master
1253 - $frev = $this->article->getStableRev( FR_MASTER );
1254 - if( !$frev )
1255 - return true;
1256 - $latest = $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
1257 - // If we are supposed to review after edit, and it was not autoreviewed,
1258 - // and the user can actually make new stable version, take us to the diff...
1259 - if( $wgReviewChangesAfterEdit && $frev && $latest > $frev->getRevId() && $frev->userCanSetFlags() ) {
1260 - $extraQuery .= $extraQuery ? '&' : '';
1261 - $extraQuery .= "oldid={$frev->getRevId()}&diff=cur&diffonly=0"; // override diff-only
1262 - // ...otherwise, go to the current revision after completing an edit.
1263 - } else {
1264 - if( $frev && $latest != $frev->getRevId() ) {
1265 - $extraQuery .= "stable=0";
1266 - if( !$wgUser->isAllowed('review') && $this->article->showStableByDefault() ) {
1267 - $extraQuery .= "&shownotice=1";
1268 - }
1269 - }
1270 - }
1271 - return true;
1272 - }
1273 -
1274 - /**
1275 - * Add a hidden revision ID field to edit form.
1276 - * Needed for autoreview so it can select the flags from said revision.
1277 - */
1278 - public function addRevisionIDField( $editPage, $out ) {
1279 - global $wgRequest;
1280 - $this->load();
1281 - # Find out revision id
1282 - if( $this->article->mRevision ) {
1283 - $revId = $this->article->mRevision->mId;
1284 - } else {
1285 - $latest = $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
1286 - $revId = $latest;
1287 - wfDebug( 'FlaggedArticle::addRevisionIDField - ID not specified, assumed current' );
1288 - }
1289 - # If undoing a few consecutive top edits, we know the base ID
1290 - if( $undo = $wgRequest->getIntOrNull('undo') ) {
1291 - $undoAfter = $wgRequest->getIntOrNull('undoafter');
1292 - $latest = isset($latest) ?
1293 - $latest : $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
1294 - if( $undoAfter && $undo == $this->article->getLatest() ) {
1295 - $revId = $undoAfter;
1296 - }
1297 - }
1298 - $out->addHTML( "\n" . Xml::hidden( 'baseRevId', $revId ) );
1299 - $out->addHTML( "\n" . Xml::hidden( 'undidRev',
1300 - empty($editPage->undidRev) ? 0 : $editPage->undidRev )
1301 - );
1302 - return true;
1303 - }
1304 -
1305 - /**
1306 - * Adds brief review notes to a page.
1307 - * @param OutputPage $out
1308 - */
1309 - public function addReviewNotes( &$data ) {
1310 - $this->load();
1311 - if( $this->reviewNotes ) {
1312 - $data .= $this->reviewNotes;
1313 - }
1314 - return true;
1315 - }
1316 -
1317 - /**
1318 - * Adds a brief review form to a page.
1319 - * @param string $data
1320 - * @param bool $top
1321 - * @param bool hide
1322 - * @param bool $top, should this form always go on top?
1323 - */
1324 - public function addQuickReview( &$data, $top = false, $hide = false ) {
1325 - global $wgOut, $wgUser, $wgRequest;
1326 - $this->load();
1327 - # Get the revision being displayed
1328 - $id = $wgOut->getRevisionId();
1329 - if( !$id ) {
1330 - if( !$this->isDiffFromStable ) {
1331 - return false; // only safe to assume current if diff-to-stable
1332 - } else {
1333 - $rev = Revision::newFromTitle( $this->article->getTitle() );
1334 - $id = $rev->getId();
1335 - }
1336 - } else {
1337 - $rev = Revision::newFromTitle( $this->article->getTitle(), $id );
1338 - }
1339 - # Load required messages
1340 - wfLoadExtensionMessages( 'FlaggedRevs' );
1341 - # Must be a valid non-printable output and revision must be public
1342 - if( $wgOut->isPrintable() || !$rev || $rev->isDeleted(Revision::DELETED_TEXT) ) {
1343 - return false;
1344 - }
1345 - $useCurrent = false;
1346 - if( !isset($wgOut->mTemplateIds) || !isset($wgOut->fr_ImageSHA1Keys) ) {
1347 - $useCurrent = true;
1348 - }
1349 - $skin = $wgUser->getSkin();
1350 -
1351 - $config = $this->article->getVisibilitySettings();
1352 - # Variable for sites with no flags, otherwise discarded
1353 - $approve = $wgRequest->getBool('wpApprove');
1354 - # See if the version being displayed is flagged...
1355 - $oldFlags = $this->article->getFlagsForRevision( $id );
1356 - # If we are reviewing updates to a page, start off with the stable revision's
1357 - # flags. Otherwise, we just fill them in with the selected revision's flags.
1358 - if( $this->isDiffFromStable ) {
1359 - $srev = $this->article->getStableRev();
1360 - $flags = $srev->getTags();
1361 - # Check if user is allowed to renew the stable version.
1362 - # If not, then get the flags for the new revision itself.
1363 - if( !RevisionReview::userCanSetFlags( $oldFlags ) ) {
1364 - $flags = $oldFlags;
1365 - }
1366 - $encNotes = $srev->getComment();
1367 - } else {
1368 - $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $id );
1369 - $flags = $oldFlags;
1370 - $encNotes = $frev ? $frev->getComment() : ""; // pre-fill notes
1371 - }
1372 -
1373 - $reviewTitle = SpecialPage::getTitleFor( 'RevisionReview' );
1374 - $action = $reviewTitle->getLocalUrl( 'action=submit' );
1375 - $params = array( 'method' => 'post', 'action' => $action, 'id' => 'mw-reviewform' );
1376 - if( $hide ) {
1377 - $params['class'] = 'fr-hiddenform';
1378 - }
1379 - $form = Xml::openElement( 'form', $params );
1380 - $form .= Xml::openElement( 'fieldset', array('class' => 'flaggedrevs_reviewform noprint') );
1381 - $form .= "<legend><strong>" . wfMsgHtml( 'revreview-flag', $id ) . "</strong></legend>\n";
1382 -
1383 - # Show explanatory text
1384 - if( !FlaggedRevs::lowProfileUI() ) {
1385 - $msg = FlaggedRevs::showStableByDefault() ? 'revreview-text' : 'revreview-text2';
1386 - $form .= wfMsgExt( $msg, array('parse') );
1387 - }
1388 -
1389 - # Current user has too few rights to change at least one flag, thus entire form disabled
1390 - $uneditable = !$this->article->getTitle()->quickUserCan('edit');
1391 - $disabled = !RevisionReview::userCanSetFlags( $flags ) || $uneditable;
1392 - if( $disabled ) {
1393 - $form .= Xml::openElement( 'div', array('class' => 'fr-rating-controls-disabled',
1394 - 'id' => 'fr-rating-controls-disabled') );
1395 - $toggle = array( 'disabled' => "disabled" );
1396 - } else {
1397 - $form .= Xml::openElement( 'div', array('class' => 'fr-rating-controls',
1398 - 'id' => 'fr-rating-controls') );
1399 - $toggle = array();
1400 - }
1401 - # Add main checkboxes/selects
1402 - $form .= Xml::openElement( 'span', array('id' => 'mw-ratingselects') );
1403 - $form .= FlaggedRevsXML::ratingInputs( $flags, $config, $disabled );
1404 - $form .= Xml::closeElement( 'span' );
1405 -
1406 - if( FlaggedRevs::allowComments() && $wgUser->isAllowed( 'validate' ) ) {
1407 - $form .= "<div id='mw-notebox'>\n";
1408 - $form .= "<p>".wfMsgHtml( 'revreview-notes' ) . "</p>\n";
1409 - $form .= Xml::openElement( 'textarea', array('name' => 'wpNotes', 'id' => 'wpNotes',
1410 - 'class' => 'fr-notes-box', 'rows' => '2', 'cols' => '80') ) .
1411 - htmlspecialchars( $encNotes ) .
1412 - Xml::closeElement('textarea') . "\n";
1413 - $form .= "</div>\n";
1414 - }
1415 - # Get versions of templates/files used
1416 - $imageParams = $templateParams = $fileVersion = '';
1417 - if( $useCurrent ) {
1418 - # Get parsed current version
1419 - $parserCache = ParserCache::singleton();
1420 - $article = $this->article;
1421 - $currentOutput = $parserCache->get( $article, $wgUser );
1422 - if( $currentOutput == false ) {
1423 - global $wgParser, $wgEnableParserCache;
1424 - $text = $article->getContent();
1425 - $title = $article->getTitle();
1426 - $options = FlaggedRevs::makeParserOptions();
1427 - $currentOutput = $wgParser->parse( $text, $title, $options );
1428 - # Might as well save the cache while we're at it
1429 - if( $wgEnableParserCache )
1430 - $parserCache->save( $currentOutput, $article, $wgUser );
1431 - }
1432 - $templateIDs = $currentOutput->mTemplateIds;
1433 - $imageSHA1Keys = $currentOutput->fr_ImageSHA1Keys;
1434 - } else {
1435 - $templateIDs = $wgOut->mTemplateIds;
1436 - $imageSHA1Keys = $wgOut->fr_ImageSHA1Keys;
1437 - }
1438 - list($templateParams,$imageParams,$fileVersion) =
1439 - FlaggedRevs::getIncludeParams( $this->article, $templateIDs, $imageSHA1Keys );
1440 -
1441 - $form .= Xml::openElement( 'span', array('style' => 'white-space: nowrap;') );
1442 - # Hide comment if needed
1443 - if( !$disabled ) {
1444 - if( count(FlaggedRevs::getDimensions()) > 1 )
1445 - $form .= "<br/>"; // Don't put too much on one line
1446 - $form .= "<span id='mw-commentbox' style='clear:both'>" .
1447 - Xml::inputLabel( wfMsg('revreview-log'), 'wpReason', 'wpReason', 40, '',
1448 - array('class' => 'fr-comment-box') ) . "&nbsp;&nbsp;&nbsp;</span>";
1449 - }
1450 - $form .= Xml::submitButton( wfMsg('revreview-submit'),
1451 - array(
1452 - 'id' => 'submitreview', 'accesskey' => wfMsg('revreview-ak-review'),
1453 - 'title' => wfMsg('revreview-tt-review').' ['.wfMsg('revreview-ak-review').']'
1454 - ) + $toggle
1455 - );
1456 - $form .= Xml::closeElement( 'span' );
1457 -
1458 - $form .= Xml::closeElement( 'div' ) . "\n";
1459 -
1460 - # Show stability log if there is anything interesting...
1461 - if( $this->article->isPageLocked() ) {
1462 - $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, LogEventsList::NO_ACTION_LINK );
1463 - $pager = new LogPager( $loglist, 'stable', '', $this->article->getTitle()->getPrefixedDBKey() );
1464 - $pager->mLimit = 1; // top item
1465 - if( ($logBody = $pager->getBody()) ) {
1466 - $form .= "<div><ul style='list-style:none; margin: 0;'>$logBody</ul></div>";
1467 - }
1468 - }
1469 -
1470 - # Hidden params
1471 - $form .= Xml::hidden( 'title', $reviewTitle->getPrefixedText() ) . "\n";
1472 - $form .= Xml::hidden( 'target', $this->article->getTitle()->getPrefixedDBKey() ) . "\n";
1473 - $form .= Xml::hidden( 'oldid', $id ) . "\n";
1474 - $form .= Xml::hidden( 'action', 'submit') . "\n";
1475 - $form .= Xml::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n";
1476 - # Add review parameters
1477 - $form .= Xml::hidden( 'templateParams', $templateParams ) . "\n";
1478 - $form .= Xml::hidden( 'imageParams', $imageParams ) . "\n";
1479 - $form .= Xml::hidden( 'fileVersion', $fileVersion ) . "\n";
1480 - # Pass this in if given; useful for new page patrol
1481 - $form .= Xml::hidden( 'rcid', $wgRequest->getVal('rcid') ) . "\n";
1482 - # Special token to discourage fiddling...
1483 - $checkCode = RevisionReview::validationKey( $templateParams, $imageParams, $fileVersion, $id );
1484 - $form .= Xml::hidden( 'validatedParams', $checkCode ) . "\n";
1485 -
1486 - $form .= Xml::closeElement( 'fieldset' );
1487 - $form .= Xml::closeElement( 'form' );
1488 - # Place form at the correct position specified by $top
1489 - if( $top ) {
1490 - $wgOut->prependHTML( $form );
1491 - } else {
1492 - $data .= $form;
1493 - }
1494 - return true;
1495 - }
1496 -
1497 - /**
1498 - * Updates parser cache output to included needed versioning params.
1499 - */
1500 - public function maybeUpdateMainCache( &$outputDone, &$pcache ) {
1501 - global $wgUser, $wgRequest;
1502 - $this->load();
1503 -
1504 - $action = $wgRequest->getVal( 'action', 'view' );
1505 - if( $action == 'purge' )
1506 - return true; // already purging!
1507 - # Only trigger on article view for content pages, not for protect/delete/hist
1508 - if( !self::isViewAction($action) || !$wgUser->isAllowed( 'review' ) )
1509 - return true;
1510 - if( !$this->article->exists() || !$this->article->isReviewable() )
1511 - return true;
1512 -
1513 - $parserCache = ParserCache::singleton();
1514 - $parserOut = $parserCache->get( $this->article, $wgUser );
1515 - if( $parserOut ) {
1516 - # Clear older, incomplete, cached versions
1517 - # We need the IDs of templates and timestamps of images used
1518 - if( !isset($parserOut->fr_newestTemplateID) || !isset($parserOut->fr_newestImageTime) )
1519 - $this->article->getTitle()->invalidateCache();
1520 - }
1521 - return true;
1522 - }
1523 -}
 2+<?php
 3+
 4+class FlaggedArticleView {
 5+ protected $isDiffFromStable = false;
 6+ protected $isMultiPageDiff = false;
 7+ protected $reviewNotice = '';
 8+ protected $reviewNotes = '';
 9+ protected $article = null;
 10+ protected $loaded = false;
 11+
 12+ protected static $instance = null;
 13+
 14+ /*
 15+ * Get the FlaggedArticleView for this request
 16+ */
 17+ public static function singleton() {
 18+ if( self::$instance == null ) {
 19+ self::$instance = new self();
 20+ }
 21+ return self::$instance;
 22+ }
 23+ protected function __construct() {}
 24+
 25+ /*
 26+ * Load the global FlaggedArticle instance
 27+ */
 28+ protected function load() {
 29+ if( !$this->loaded ) {
 30+ $this->article = self::globalArticleInstance();
 31+ if( $this->article == null ) {
 32+ throw new MWException( 'FlaggedArticleViewer has no context article!' );
 33+ }
 34+ }
 35+ }
 36+
 37+ /**
 38+ * Get the FlaggedArticle instance associated with $wgArticle/$wgTitle,
 39+ * or false if there isn't such a title
 40+ */
 41+ public static function globalArticleInstance() {
 42+ global $wgTitle;
 43+ if( !empty( $wgTitle ) ) {
 44+ return FlaggedArticle::getTitleInstance( $wgTitle );
 45+ }
 46+ return null;
 47+ }
 48+
 49+ /**
 50+ * Does the config and current URL params allow
 51+ * for overriding by stable revisions?
 52+ */
 53+ public function pageOverride() {
 54+ global $wgUser, $wgRequest;
 55+ $this->load();
 56+ # This only applies to viewing content pages
 57+ $action = $wgRequest->getVal( 'action', 'view' );
 58+ if( !self::isViewAction($action) || !$this->article->isReviewable() )
 59+ return false;
 60+ # Does not apply to diffs/old revision...
 61+ if( $wgRequest->getVal('oldid') || $wgRequest->getVal('diff') )
 62+ return false;
 63+ # Explicit requests for a certain stable version handled elsewhere...
 64+ if( $wgRequest->getVal('stableid') )
 65+ return false;
 66+ # Check user preferences
 67+ if( $wgUser->getOption('flaggedrevsstable') )
 68+ return !( $wgRequest->getIntOrNull('stable') === 0 );
 69+ # Get page configuration
 70+ $config = $this->article->getVisibilitySettings();
 71+ # Does the stable version override the current one?
 72+ if( $config['override'] ) {
 73+ if( FlaggedRevs::ignoreDefaultVersion() ) {
 74+ return ( $wgRequest->getIntOrNull('stable') === 1 );
 75+ }
 76+ # Viewer sees stable by default
 77+ return !( $wgRequest->getIntOrNull('stable') === 0 );
 78+ # We are explicity requesting the stable version?
 79+ } elseif( $wgRequest->getIntOrNull('stable') === 1 ) {
 80+ return true;
 81+ }
 82+ return false;
 83+ }
 84+
 85+ /**
 86+ * Is this user shown the stable version by default for this page?
 87+ * @returns bool
 88+ */
 89+ public function showStableByDefaultUser() {
 90+ $this->load();
 91+ $config = $this->article->getVisibilitySettings(); // page configuration
 92+ return ( $config['override'] && !FlaggedRevs::ignoreDefaultVersion() );
 93+ }
 94+
 95+ /**
 96+ * Is this user shown the diff-to-stable on edit for this page?
 97+ * @returns bool
 98+ */
 99+ public function showDiffOnEditUser() {
 100+ global $wgUser;
 101+ $this->load();
 102+ return ( $wgUser->isAllowed('review') || $this->showStableByDefaultUser() );
 103+ }
 104+
 105+ /**
 106+ * Is this a view page action?
 107+ * @param $action string
 108+ * @returns bool
 109+ */
 110+ protected static function isViewAction( $action ) {
 111+ return ( $action == 'view' || $action == 'purge' || $action == 'render' || $action == 'historysubmit' );
 112+ }
 113+
 114+ /**
 115+ * Output review notice
 116+ */
 117+ protected function displayTag() {
 118+ global $wgOut, $wgRequest;
 119+ $this->load();
 120+ // UI may be limited to unobtrusive patrolling system
 121+ if( $wgRequest->getVal('stableid') || !$this->article->limitedUI() ) {
 122+ $wgOut->appendSubtitle( $this->reviewNotice );
 123+ }
 124+ return true;
 125+ }
 126+
 127+
 128+ /**
 129+ * Add a stable link when viewing old versions of an article that
 130+ * have been reviewed. (e.g. for &oldid=x urls)
 131+ */
 132+ public function addStableLink() {
 133+ global $wgRequest, $wgOut, $wgLang;
 134+ $this->load();
 135+ # Only for viewing old versions. UI may be limited to unobtrusive patrolling system.
 136+ if( !$wgRequest->getVal('oldid') || $this->article->limitedUI() )
 137+ return true;
 138+ # We may have nav links like "direction=prev&oldid=x"
 139+ $revID = $this->article->getOldIDFromRequest();
 140+ $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $revID );
 141+ # Give a notice if this rev ID corresponds to a reviewed version...
 142+ if( !is_null($frev) ) {
 143+ wfLoadExtensionMessages( 'FlaggedRevs' );
 144+ $time = $wgLang->date( $frev->getTimestamp(), true );
 145+ $flags = $frev->getTags();
 146+ $quality = FlaggedRevs::isQuality( $flags );
 147+ $msg = $quality ? 'revreview-quality-source' : 'revreview-basic-source';
 148+ $tag = wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
 149+ # Hide clutter
 150+ if( !FlaggedRevs::useSimpleUI() && !empty($flags) ) {
 151+ $tag .= " " . FlaggedRevsXML::ratingToggle() .
 152+ "<span id='mw-revisionratings' style='display:block;'><br/>" .
 153+ wfMsgHtml('revreview-oldrating') .
 154+ FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
 155+ }
 156+ $tag = "<div id='mw-revisiontag-old' class='flaggedrevs_notice plainlinks noprint'>$tag</div>";
 157+ $wgOut->addHTML( $tag );
 158+ }
 159+ return true;
 160+ }
 161+
 162+ /**
 163+ * Replaces a page with the last stable version if possible
 164+ * Adds stable version status/info tags and notes
 165+ * Adds a quick review form on the bottom if needed
 166+ */
 167+ public function setPageContent( &$outputDone, &$pcache ) {
 168+ global $wgRequest, $wgOut, $wgUser, $wgLang, $wgContLang;
 169+ $this->load();
 170+ # Only trigger on article view for content pages, not for protect/delete/hist...
 171+ $action = $wgRequest->getVal( 'action', 'view' );
 172+ if( !self::isViewAction($action) || !$this->article->exists() )
 173+ return true;
 174+ # Do not clutter up diffs any further and leave archived versions alone...
 175+ if( $wgRequest->getVal('diff') || $wgRequest->getVal('oldid') ) {
 176+ return true;
 177+ }
 178+ # Only trigger for reviewable pages
 179+ if( !$this->article->isReviewable() ) {
 180+ return true;
 181+ }
 182+ # Load required messages
 183+ wfLoadExtensionMessages( 'FlaggedRevs' );
 184+ $simpleTag = $old = $stable = false;
 185+ $tag = $prot = '';
 186+ # Check the newest stable version.
 187+ $frev = $srev = $this->article->getStableRev();
 188+ $stableId = $frev ? $frev->getRevId() : 0;
 189+ # Also, check for any explicitly requested old stable version...
 190+ $reqId = $wgRequest->getVal('stableid');
 191+ if( $reqId === "best" ) {
 192+ $reqId = FlaggedRevs::getPrimeFlaggedRevId( $this->article );
 193+ }
 194+ if( $stableId && $reqId ) {
 195+ # Treat requesting the stable version by ID as &stable=1
 196+ if( $reqId != $stableId ) {
 197+ $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $reqId, FR_TEXT );
 198+ $old = true; // old reviewed version requested by ID
 199+ if( !$frev ) {
 200+ $wgOut->addWikiText( wfMsg('revreview-invalid') );
 201+ $wgOut->returnToMain( false, $this->article->getTitle() );
 202+ # Tell MW that parser output is done
 203+ $outputDone = true;
 204+ $pcache = false;
 205+ return true;
 206+ }
 207+ } else {
 208+ $stable = true; // stable version requested by ID
 209+ }
 210+ }
 211+ // Is the page config altered?
 212+ if( $this->article->isPageLocked() ) {
 213+ $prot = "<span class='fr-icon-locked' title=\"".
 214+ wfMsgHtml('revreview-locked-title')."\"></span>";
 215+ } elseif( $this->article->isPageUnlocked() ) {
 216+ $prot = "<span class='fr-icon-unlocked' title=\"".
 217+ wfMsgHtml('revreview-unlocked-title')."\"></span>";
 218+ }
 219+ // RTL langauges
 220+ $rtl = $wgContLang->isRTL() ? " rtl" : "";
 221+ // Is there no stable version?
 222+ if( is_null($frev) ) {
 223+ // Add "no reviewed version" tag, but not for printable output.
 224+ if( !$wgOut->isPrintable() ) {
 225+ // Simple icon-based UI
 226+ if( FlaggedRevs::useSimpleUI() ) {
 227+ $msg = $old ? 'revreview-quick-invalid' : 'revreview-quick-none';
 228+ $tag .= "{$prot}<span class='fr-icon-current plainlinks'></span>" .
 229+ wfMsgExt($msg,array('parseinline'));
 230+ $tag = "<div id='mw-revisiontag' class='flaggedrevs_short{$rtl} plainlinks noprint'>$tag</div>";
 231+ $this->reviewNotice .= $tag;
 232+ // Standard UI
 233+ } else {
 234+ $msg = $old ? 'revreview-invalid' : 'revreview-noflagged';
 235+ $tag = "<div id='mw-revisiontag' class='flaggedrevs_notice plainlinks noprint'>" .
 236+ "{$prot}<span class='fr-icon-current plainlinks'></span>" .
 237+ wfMsgExt($msg, array('parseinline')) . "</div>";
 238+ $this->reviewNotice .= $tag;
 239+ }
 240+ }
 241+ # Show notice bar/icon
 242+ $this->displayTag();
 243+ return true;
 244+ }
 245+ # Get flags and date
 246+ $time = $wgLang->date( $frev->getTimestamp(), true );
 247+ $flags = $frev->getTags();
 248+ # Get quality level
 249+ $quality = FlaggedRevs::isQuality( $flags );
 250+ $pristine = FlaggedRevs::isPristine( $flags );
 251+ // Looking at some specific old stable revision ("&stableid=x")
 252+ // set to override given the relevant conditions. If the user is
 253+ // requesting the stable revision ("&stableid=x"), defer to override
 254+ // behavior below, since it is the same as ("&stable=1").
 255+ if( $old ) {
 256+ $this->showOldReviewedVersion( $srev, $frev, $tag, $prot );
 257+ $outputDone = true; # Tell MW that parser output is done
 258+ $pcache = false;
 259+ // Looking at some specific old revision (&oldid=x) or if FlaggedRevs is not
 260+ // set to override given the relevant conditions (like &stable=0).
 261+ } elseif( !$stable && !$this->pageOverride() ) {
 262+ $this->showRegularVersion( $srev, $tag, $prot );
 263+ // The relevant conditions are met to override the page with the stable version.
 264+ } else {
 265+ $this->showStableVersion( $srev, $tag, $prot );
 266+ $outputDone = true; # Tell MW that parser output is done
 267+ $pcache = false;
 268+ }
 269+ # Some checks for which tag CSS to use
 270+ if( FlaggedRevs::useSimpleUI() ) $tagClass = 'flaggedrevs_short';
 271+ elseif( $simpleTag ) $tagClass = 'flaggedrevs_notice';
 272+ elseif( $pristine ) $tagClass = 'flaggedrevs_pristine';
 273+ elseif( $quality ) $tagClass = 'flaggedrevs_quality';
 274+ else $tagClass = 'flaggedrevs_basic';
 275+ # Wrap tag contents in a div
 276+ if( $tag != '' ) {
 277+ $tag = "<div id='mw-revisiontag' class='{$tagClass}{$rtl} plainlinks noprint'>$tag</div>";
 278+ $this->reviewNotice .= $tag;
 279+ }
 280+ # Show notice bar/icon
 281+ $this->displayTag();
 282+
 283+ return true;
 284+ }
 285+
 286+ /**
 287+ * @param $srev stable version
 288+ * @param $tag review box/bar info
 289+ * @param $prot protection notice
 290+ * Tag output function must be called by caller
 291+ * Parser cache control deferred to caller
 292+ */
 293+ protected function showRegularVersion( $srev, &$tag, $prot ) {
 294+ global $wgUser, $wgOut, $wgLang, $wgRequest;
 295+ $this->load();
 296+ $flags = $srev->getTags();
 297+ $time = $wgLang->date( $srev->getTimestamp(), true );
 298+ # Get quality level
 299+ $quality = FlaggedRevs::isQuality( $flags );
 300+ $pristine = FlaggedRevs::isPristine( $flags );
 301+ $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
 302+ # Get stable version sync status
 303+ $synced = FlaggedRevs::stableVersionIsSynced( $srev, $this->article );
 304+ if( $synced ) {
 305+ $this->getReviewNotes( $srev ); // Still the same
 306+ } else {
 307+ $this->maybeShowTopDiff( $srev, $quality ); // user may want diff (via prefs)
 308+ }
 309+ $pending = '';
 310+ # Give notice to newer users if an unreviewed edit was completed...
 311+ if( !$synced && $wgRequest->getVal('shownotice') && !$wgUser->isAllowed('review') ) {
 312+ $tooltip = wfMsgHtml('revreview-draft-title');
 313+ $pending = "{$prot}<span class='fr-icon-current' title=\"{$tooltip}\"></span>" .
 314+ wfMsgExt('revreview-edited',array('parseinline'),$srev->getRevId(),$revsSince);
 315+ $pending = "<div id='mw-reviewnotice' class='flaggedrevs_preview plainlinks'>$pending</div>";
 316+ # Notice should always use subtitle
 317+ $this->reviewNotice = $pending;
 318+ }
 319+ # If they are synced, do special styling
 320+ $simpleTag = !$synced;
 321+ # Construct some tagging for non-printable outputs. Note that the pending
 322+ # notice has all this info already, so don't do this if we added that already.
 323+ if( !$wgOut->isPrintable() && !$pending && !($this->article->lowProfileUI() && $synced) ) {
 324+ $class = 'fr-icon-current'; // default
 325+ $tooltip = 'revreview-draft-title';
 326+ // Simple icon-based UI
 327+ if( FlaggedRevs::useSimpleUI() ) {
 328+ if( $synced ) {
 329+ $msg = $quality ? 'revreview-quick-quality-same' : 'revreview-quick-basic-same';
 330+ $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
 331+ $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 332+ $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
 333+ } else {
 334+ $msg = $quality ? 'revreview-quick-see-quality' : 'revreview-quick-see-basic';
 335+ $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
 336+ }
 337+ $tooltip = wfMsgHtml($tooltip);
 338+ $msgHTML = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>$msgHTML";
 339+ $tag .= FlaggedRevsXML::prettyRatingBox( $srev, $msgHTML, $revsSince,
 340+ $synced, $synced, false );
 341+ // Standard UI
 342+ } else {
 343+ if( $synced ) {
 344+ $msg = $quality ? 'revreview-quality-same' : 'revreview-basic-same';
 345+ $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
 346+ $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 347+ $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(),
 348+ $time, $revsSince );
 349+ } else {
 350+ $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
 351+ $msg .= ($revsSince == 0) ? '-i' : '';
 352+ $msgHTML = wfMsgExt( $msg, array('parseinline'), $srev->getRevId(),
 353+ $time, $revsSince );
 354+ }
 355+ $tooltip = wfMsgHtml($tooltip);
 356+ $tag .= "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" . $msgHTML;
 357+ # Hide clutter
 358+ if( !empty($flags) ) {
 359+ $tag .= " " . FlaggedRevsXML::ratingToggle();
 360+ $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
 361+ wfMsgHtml('revreview-oldrating') . FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
 362+ }
 363+ }
 364+ }
 365+ # Index the stable version only if it is the default
 366+ if( $this->article->showStableByDefault() ) {
 367+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
 368+ }
 369+ }
 370+
 371+ /**
 372+ * @param $srev stable version
 373+ * @param $frev selected flagged revision
 374+ * @param $tag review box/bar info
 375+ * @param $prot protection notice
 376+ * Tag output function must be called by caller
 377+ * Parser cache control deferred to caller
 378+ */
 379+ protected function showOldReviewedVersion( $srev, $frev, &$tag, $prot ) {
 380+ global $wgOut, $wgLang;
 381+ $this->load();
 382+ $flags = $frev->getTags();
 383+ $time = $wgLang->date( $frev->getTimestamp(), true );
 384+ # Set display revision ID
 385+ $wgOut->setRevisionId( $frev->getRevId() );
 386+ # Get quality level
 387+ $quality = FlaggedRevs::isQuality( $flags );
 388+ $pristine = FlaggedRevs::isPristine( $flags );
 389+ $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
 390+ $text = $frev->getRevText();
 391+ $parserOut = FlaggedRevs::parseStableText( $this->article, $text, $frev->getRevId() );
 392+ # Construct some tagging for non-printable outputs. Note that the pending
 393+ # notice has all this info already, so don't do this if we added that already.
 394+ if( !$wgOut->isPrintable() ) {
 395+ $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
 396+ $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 397+ $tooltip = wfMsgHtml($tooltip);
 398+ // Simple icon-based UI
 399+ if( FlaggedRevs::useSimpleUI() ) {
 400+ $msg = $quality ? 'revreview-quick-quality-old' : 'revreview-quick-basic-old';
 401+ $html = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
 402+ wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
 403+ $tag = FlaggedRevsXML::prettyRatingBox( $frev, $html, $revsSince,
 404+ true, false, true );
 405+ // Standard UI
 406+ } else {
 407+ $msg = $quality ? 'revreview-quality-old' : 'revreview-basic-old';
 408+ $tag = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
 409+ wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time );
 410+ # Hide clutter
 411+ if( !empty($flags) ) {
 412+ $tag .= " " . FlaggedRevsXML::ratingToggle();
 413+ $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
 414+ wfMsgHtml('revreview-oldrating') .
 415+ FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
 416+ }
 417+ }
 418+ }
 419+ # Output HTML
 420+ $this->getReviewNotes( $frev );
 421+ $wgOut->addParserOutput( $parserOut );
 422+ # Index the stable version only
 423+ $wgOut->setRobotPolicy( 'noindex,nofollow' );
 424+ }
 425+
 426+ /**
 427+ * @param $srev stable version
 428+ * @param $tag review box/bar info
 429+ * @param $prot protection notice
 430+ * Tag output function must be called by caller
 431+ * Parser cache control deferred to caller
 432+ */
 433+ protected function showStableVersion( $srev, &$tag, $prot ) {
 434+ global $wgOut, $wgLang, $wgUser;
 435+ $this->load();
 436+ $flags = $srev->getTags();
 437+ $time = $wgLang->date( $srev->getTimestamp(), true );
 438+ # Set display revision ID
 439+ $wgOut->setRevisionId( $srev->getRevId() );
 440+ # Get quality level
 441+ $quality = FlaggedRevs::isQuality( $flags );
 442+ $pristine = FlaggedRevs::isPristine( $flags );
 443+ # We will be looking at the reviewed revision...
 444+ $revsSince = FlaggedRevs::getRevCountSince( $this->article, $srev->getRevId() );
 445+ # Get parsed stable version
 446+ $parserOut = FlaggedRevs::getPageCache( $this->article, $wgUser );
 447+ if( $parserOut == false ) {
 448+ $text = $srev->getRevText();
 449+ $parserOut = FlaggedRevs::parseStableText( $this->article, $text, $srev->getRevId() );
 450+ # Update the stable version cache
 451+ FlaggedRevs::updatePageCache( $this->article, $wgUser, $parserOut );
 452+ }
 453+ $synced = FlaggedRevs::stableVersionIsSynced( $srev, $this->article, $parserOut, null );
 454+ # Construct some tagging
 455+ if( !$wgOut->isPrintable() && !($this->article->lowProfileUI() && $synced) ) {
 456+ $class = $quality ? 'fr-icon-quality' : 'fr-icon-stable';
 457+ $tooltip = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 458+ $tooltip = wfMsgHtml($tooltip);
 459+ // Simple icon-based UI
 460+ if( FlaggedRevs::useSimpleUI() ) {
 461+ $msg = $quality ? 'revreview-quick-quality' : 'revreview-quick-basic';
 462+ # uses messages 'revreview-quick-quality-same', 'revreview-quick-basic-same'
 463+ $msg = $synced ? "{$msg}-same" : $msg;
 464+ $html = "{$prot}<span class='{$class}' title=\"{$tooltip}\"></span>" .
 465+ wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $revsSince );
 466+ $tag = FlaggedRevsXML::prettyRatingBox( $srev, $html, $revsSince, true, $synced );
 467+ // Standard UI
 468+ } else {
 469+ $msg = $quality ? 'revreview-quality' : 'revreview-basic';
 470+ if( $synced ) {
 471+ # uses messages 'revreview-quality-same', 'revreview-basic-same'
 472+ $msg .= '-same';
 473+ } elseif( $revsSince == 0 ) {
 474+ # uses messages 'revreview-quality-i', 'revreview-basic-i'
 475+ $msg .= '-i';
 476+ }
 477+ $tag = "{$prot}<span class='{$class} plainlinks' title=\"{$tooltip}\"></span>" .
 478+ wfMsgExt( $msg, array('parseinline'), $srev->getRevId(), $time, $revsSince );
 479+ if( !empty($flags) ) {
 480+ $tag .= " " . FlaggedRevsXML::ratingToggle();
 481+ $tag .= "<span id='mw-revisionratings' style='display:block;'><br/>" .
 482+ FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
 483+ }
 484+ }
 485+ }
 486+ # Output HTML
 487+ $this->getReviewNotes( $srev );
 488+ $wgOut->addParserOutput( $parserOut );
 489+ }
 490+
 491+ /**
 492+ * @param FlaggedRevision $srev, stable version
 493+ * @param bool $quality, revision is quality
 494+ * @returns bool, diff added to output
 495+ */
 496+ protected function maybeShowTopDiff( $srev, $quality ) {
 497+ global $wgUser, $wgOut, $wgMemc;
 498+ $this->load();
 499+ if( !$wgUser->getBoolOption('flaggedrevsviewdiffs') )
 500+ return false; // nothing to do here
 501+ if( !$wgUser->isAllowed('review') )
 502+ return false; // does not apply to this user
 503+ # Diff should only show for the draft
 504+ $oldid = $this->article->getOldIDFromRequest();
 505+ $latest = $this->article->getLatest();
 506+ if( $oldid && $oldid != $latest ) {
 507+ return false; // not viewing the draft
 508+ }
 509+ # Conditions are met to show diff...
 510+ wfLoadExtensionMessages( 'FlaggedRevs' ); // load required messages
 511+ $leftNote = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 512+ $rClass = FlaggedRevsXML::getQualityColor( false );
 513+ $lClass = FlaggedRevsXML::getQualityColor( (int)$quality );
 514+ $rightNote = "<span class='$rClass'>[".wfMsgHtml('revreview-draft-title')."]</span>";
 515+ $leftNote = "<span class='$lClass'>[".wfMsgHtml($leftNote)."]</span>";
 516+ # Fetch the stable and draft revision text
 517+ $oText = $srev->getRevText();
 518+ if( $oText === false )
 519+ return false; // deleted revision or something?
 520+ $nText = $this->article->getContent();
 521+ if( $nText === false )
 522+ return false; // deleted revision or something?
 523+ # Build diff at the top of the page
 524+ if( strcmp($oText,$nText) !== 0 ) {
 525+ $diffEngine = new DifferenceEngine();
 526+ $diffEngine->showDiffStyle();
 527+ $n = $this->article->getTitle()->countRevisionsBetween( $srev->getRevId(), $latest );
 528+ if( $n ) {
 529+ $multiNotice = "<tr><td colspan='4' align='center' class='diff-multi'>" .
 530+ wfMsgExt( 'diff-multi', array( 'parse' ), $n )."</td></tr>";
 531+ } else {
 532+ $multiNotice = '';
 533+ }
 534+ $wgOut->addHTML(
 535+ "<div>" .
 536+ "<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" .
 537+ "<col class='diff-marker' />" .
 538+ "<col class='diff-content' />" .
 539+ "<col class='diff-marker' />" .
 540+ "<col class='diff-content' />" .
 541+ "<tr>" .
 542+ "<td colspan='2' width='50%' align='center' class='diff-otitle'><b>" .
 543+ $leftNote . "</b></td>" .
 544+ "<td colspan='2' width='50%' align='center' class='diff-ntitle'><b>" .
 545+ $rightNote . "</b></td>" .
 546+ "</tr>" .
 547+ $multiNotice .
 548+ $diffEngine->generateDiffBody( $oText, $nText ) .
 549+ "</table>" .
 550+ "</div>\n"
 551+ );
 552+ $this->isDiffFromStable = true;
 553+ return true;
 554+ }
 555+ return false;
 556+ }
 557+
 558+ /**
 559+ * Get the normal and display files for the underlying ImagePage.
 560+ * If the a stable version needs to be displayed, this will set $normalFile
 561+ * to the current version, and $displayFile to the desired version.
 562+ *
 563+ * If no stable version is required, the reference parameters will not be set
 564+ *
 565+ * Depends on $wgRequest
 566+ */
 567+ public function imagePageFindFile( &$normalFile, &$displayFile ) {
 568+ global $wgRequest, $wgArticle;
 569+ $this->load();
 570+ # Determine timestamp. A reviewed version may have explicitly been requested...
 571+ $frev = null;
 572+ $time = false;
 573+ if( $reqId = $wgRequest->getVal('stableid') ) {
 574+ $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $reqId );
 575+ } elseif( $this->pageOverride() ) {
 576+ $frev = $this->article->getStableRev();
 577+ }
 578+ if( !is_null($frev) ) {
 579+ $time = $frev->getFileTimestamp();
 580+ // B/C, may be stored in associated image version metadata table
 581+ if( !$time ) {
 582+ $dbr = wfGetDB( DB_SLAVE );
 583+ $time = $dbr->selectField( 'flaggedimages',
 584+ 'fi_img_timestamp',
 585+ array( 'fi_rev_id' => $frev->getRevId(),
 586+ 'fi_name' => $this->article->getTitle()->getDBkey() ),
 587+ __METHOD__
 588+ );
 589+ }
 590+ # NOTE: if not found, this will use the current
 591+ $wgArticle = new ImagePage( $this->article->getTitle(), $time );
 592+ }
 593+ if( !$time ) {
 594+ # Try request parameter
 595+ $time = $wgRequest->getVal( 'filetimestamp', false );
 596+ }
 597+
 598+ if( !$time ) {
 599+ return; // Use the default behaviour
 600+ }
 601+
 602+ $title = $this->article->getTitle();
 603+ $displayFile = wfFindFile( $title, array( 'time' => $time ) );
 604+ # If none found, try current
 605+ if( !$displayFile ) {
 606+ wfDebug( __METHOD__.": {$title->getPrefixedDBkey()}: $time not found, using current\n" );
 607+ $displayFile = wfFindFile( $title );
 608+ # If none found, use a valid local placeholder
 609+ if( !$displayFile ) {
 610+ $displayFile = wfLocalFile( $title ); // fallback to current
 611+ }
 612+ $normalFile = $displayFile;
 613+ # If found, set $normalFile
 614+ } else {
 615+ wfDebug( __METHOD__.": {$title->getPrefixedDBkey()}: using timestamp $time\n" );
 616+ $normalFile = wfFindFile( $title );
 617+ }
 618+ }
 619+
 620+ /**
 621+ * Adds latest stable version tag to page when editing
 622+ */
 623+ public function addToEditView( $editPage ) {
 624+ global $wgRequest, $wgOut;
 625+ $this->load();
 626+ # Must be reviewable. UI may be limited to unobtrusive patrolling system.
 627+ if( !$this->article->isReviewable() || $this->article->limitedUI() )
 628+ return true;
 629+ # Show stabilization log
 630+ $this->showStabilityLog();
 631+ # Set new body html text as that of now
 632+ $tag = $warning = $prot = '';
 633+ # Check the newest stable version
 634+ $quality = 0;
 635+ if( $frev = $this->article->getStableRev() ) {
 636+ global $wgLang, $wgUser, $wgFlaggedRevsAutoReview;
 637+ # Find out revision id
 638+ $revId = $editPage->oldid ?
 639+ $editPage->oldid : $this->article->getLatest();
 640+ # If this will be autoreviewed, notify the user...
 641+ if( !FlaggedRevs::lowProfileUI() && $wgFlaggedRevsAutoReview && $wgUser->isAllowed('review') ) {
 642+ # If we are editing some reviewed revision, any changes this user
 643+ # makes will be autoreviewed...
 644+ $ofrev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $revId );
 645+ if( !is_null($ofrev) ) {
 646+ wfLoadExtensionMessages( 'FlaggedRevs' );
 647+ $msg = ( $revId==$frev->getRevId() ) ? 'revreview-auto-w' : 'revreview-auto-w-old';
 648+ $warning = "<div id='mw-autoreviewtag' class='flaggedrevs_warning plainlinks'>" .
 649+ wfMsgExt($msg,array('parseinline')) . "</div>";
 650+ }
 651+ # Let new users know about review procedure a tag
 652+ } elseif( !$wgUser->getId() && $this->article->showStableByDefault() ) {
 653+ wfLoadExtensionMessages( 'FlaggedRevs' );
 654+ $warning = "<div id='mw-editwarningtag' class='flaggedrevs_editnotice plainlinks'>" .
 655+ wfMsgExt('revreview-editnotice',array('parseinline')) . "</div>";
 656+ }
 657+ if( $frev->getRevId() != $revId ) {
 658+ wfLoadExtensionMessages( 'FlaggedRevs' );
 659+ $time = $wgLang->date( $frev->getTimestamp(), true );
 660+ $flags = $frev->getTags();
 661+ if( FlaggedRevs::isQuality($flags) ) {
 662+ $quality = FlaggedRevs::isPristine($flags) ? 2 : 1;
 663+ }
 664+ $revsSince = FlaggedRevs::getRevCountSince( $this->article, $frev->getRevId() );
 665+ // Is the page config altered?
 666+ if( $this->article->isPageLocked() ) {
 667+ $prot = "<span class='fr-icon-locked' title=\"".
 668+ wfMsgHtml('revreview-locked-title')."\"></span>";
 669+ } elseif( $this->article->isPageUnlocked() ) {
 670+ $prot = "<span class='fr-icon-unlocked' title=\"".
 671+ wfMsgHtml('revreview-unlocked-title')."\"></span>";
 672+ }
 673+ # Streamlined UI
 674+ if( FlaggedRevs::useSimpleUI() ) {
 675+ $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
 676+ $msg .= ($revsSince == 0) ? '-i' : '';
 677+ $tag = "{$prot}<span class='fr-checkbox'></span>" .
 678+ wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time, $revsSince );
 679+ $tag = "<div id='mw-revisiontag-edit' class='flaggedrevs_editnotice plainlinks'>$tag</div>";
 680+ # Standard UI
 681+ } else {
 682+ $msg = $quality ? 'revreview-newest-quality' : 'revreview-newest-basic';
 683+ $msg .= ($revsSince == 0) ? '-i' : '';
 684+ $tag = "{$prot}<span class='fr-checkbox'></span>" .
 685+ wfMsgExt( $msg, array('parseinline'), $frev->getRevId(), $time, $revsSince );
 686+ # Hide clutter
 687+ if( !empty($flags) ) {
 688+ $tag .= " " . FlaggedRevsXML::ratingToggle();
 689+ $tag .= '<span id="mw-revisionratings" style="display:block;"><br/>' .
 690+ wfMsg('revreview-oldrating') . FlaggedRevsXML::addTagRatings( $flags ) . '</span>';
 691+ }
 692+ $tag = "<div id='mw-revisiontag-edit' class='flaggedrevs_editnotice plainlinks'>$tag</div>";
 693+ }
 694+ }
 695+ # Output notice and warning for editors
 696+ if( $tag || $warning ) {
 697+ $wgOut->addHTML( $tag . $warning );
 698+ }
 699+
 700+ # Show diff to stable, to make things less confusing...
 701+ # This can be disabled via user preferences
 702+ if( $frev->getRevId() < $revId // changes were made
 703+ && $this->showDiffOnEditUser() // stable default and user cannot review
 704+ && $wgUser->getBoolOption('flaggedrevseditdiffs') // not disable via prefs
 705+ ) {
 706+ # Don't show for old revisions, diff, preview, or undo.
 707+ if( $editPage->oldid || $editPage->section === "new"
 708+ || in_array($editPage->formtype,array('diff','preview')) )
 709+ {
 710+ return true; // nothing to show here
 711+ }
 712+
 713+ # Conditions are met to show diff...
 714+ wfLoadExtensionMessages( 'FlaggedRevs' ); // load required messages
 715+ $leftNote = $quality ? 'revreview-quality-title' : 'revreview-stable-title';
 716+ $rClass = FlaggedRevsXML::getQualityColor( false );
 717+ $lClass = FlaggedRevsXML::getQualityColor( (int)$quality );
 718+ $rightNote = "<span class='$rClass'>[".wfMsgHtml('revreview-draft-title')."]</span>";
 719+ $leftNote = "<span class='$lClass'>[".wfMsgHtml($leftNote)."]</span>";
 720+ $text = $frev->getRevText();
 721+ # Are we editing a section?
 722+ $section = ($editPage->section == "") ? false : intval($editPage->section);
 723+ if( $section !== false ) {
 724+ $text = $this->article->getSection( $text, $section );
 725+ }
 726+ if( $text !== false && strcmp($text,$editPage->textbox1) !== 0 ) {
 727+ $diffEngine = new DifferenceEngine();
 728+ $diffEngine->showDiffStyle();
 729+ $wgOut->addHTML(
 730+ "<div>" .
 731+ "<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" .
 732+ "<col class='diff-marker' />" .
 733+ "<col class='diff-content' />" .
 734+ "<col class='diff-marker' />" .
 735+ "<col class='diff-content' />" .
 736+ "<tr>" .
 737+ "<td colspan='2' width='50%' align='center' class='diff-otitle'><b>" .
 738+ $leftNote . "</b></td>" .
 739+ "<td colspan='2' width='50%' align='center' class='diff-ntitle'><b>" .
 740+ $rightNote . "</b></td>" .
 741+ "</tr>" .
 742+ $diffEngine->generateDiffBody( $text, $editPage->textbox1 ) .
 743+ "</table>" .
 744+ "</div>\n"
 745+ );
 746+ }
 747+ }
 748+ }
 749+ return true;
 750+ }
 751+
 752+ protected function showStabilityLog() {
 753+ global $wgOut;
 754+ $this->load();
 755+ # Only for pages manually made to be stable...
 756+ if( $this->article->isPageLocked() ) {
 757+ wfLoadExtensionMessages( 'FlaggedRevs' );
 758+ $wgOut->addHTML( "<div class='mw-warning-with-logexcerpt'>" );
 759+ $wgOut->addWikiMsg( 'revreview-locked' );
 760+ LogEventsList::showLogExtract( $wgOut, 'stable',
 761+ $this->article->getTitle()->getPrefixedText(), '', array('lim'=>1) );
 762+ $wgOut->addHTML( "</div>" );
 763+ # ...or unstable
 764+ } elseif( $this->article->isPageUnlocked() ) {
 765+ wfLoadExtensionMessages( 'FlaggedRevs' );
 766+ $wgOut->addHTML( "<div class='mw-warning-with-logexcerpt'>" );
 767+ $wgOut->addWikiMsg( 'revreview-unlocked' );
 768+ LogEventsList::showLogExtract( $wgOut, 'stable',
 769+ $this->article->getTitle()->getPrefixedText(), '', array('lim'=>1) );
 770+ $wgOut->addHTML( "</div>" );
 771+ }
 772+ return true;
 773+ }
 774+
 775+ /**
 776+ * Add unreviewed pages links
 777+ */
 778+ public function addToCategoryView() {
 779+ global $wgOut, $wgUser;
 780+ $this->load();
 781+ if( !$wgUser->isAllowed( 'review' ) ) {
 782+ return true;
 783+ }
 784+ wfLoadExtensionMessages( 'FlaggedRevs' );
 785+ # Load special page names
 786+ wfLoadExtensionMessages( 'OldReviewedPages' );
 787+ wfLoadExtensionMessages( 'UnreviewedPages' );
 788+
 789+ $category = $this->article->getTitle()->getText();
 790+
 791+ $unreviewed = SpecialPage::getTitleFor( 'UnreviewedPages' );
 792+ $unreviewedLink = $wgUser->getSkin()->makeKnownLinkObj( $unreviewed,
 793+ wfMsgHtml('unreviewedpages'), 'category=' . urlencode($category) );
 794+
 795+ $oldreviewed = SpecialPage::getTitleFor( 'OldReviewedPages' );
 796+ $oldreviewedLink = $wgUser->getSkin()->makeKnownLinkObj( $oldreviewed,
 797+ wfMsgHtml('oldreviewedpages'), 'category=' . urlencode($category) );
 798+
 799+ $wgOut->appendSubtitle("<span id='mw-category-oldreviewed'>$unreviewedLink / $oldreviewedLink</span>");
 800+
 801+ return true;
 802+ }
 803+
 804+ /**
 805+ * Add review form to pages when necessary
 806+ */
 807+ public function addReviewForm( &$data ) {
 808+ global $wgRequest, $wgUser, $wgOut;
 809+ $this->load();
 810+ # User must have review rights and page must be reviewable
 811+ if( !$wgUser->isAllowed('review') || !$this->article->exists() || !$this->article->isReviewable() ) {
 812+ return true;
 813+ }
 814+ # Unobtrusive patrolling UI only shows forms if requested
 815+ if( !$wgRequest->getInt('reviewform') && $this->article->limitedUI() ) {
 816+ return true;
 817+ }
 818+ # Avoid multi-page diffs that are useless and misbehave (bug 19327)
 819+ if( $this->isMultiPageDiff ) {
 820+ return true;
 821+ }
 822+ # Check action and if page is protected
 823+ $action = $wgRequest->getVal( 'action', 'view' );
 824+ # Must be view/diff action...
 825+ if( !self::isViewAction($action) ) {
 826+ return true;
 827+ }
 828+ # Place the form at the top or bottom as most convenient
 829+ $onTop = $wgRequest->getVal('diff') || $this->isDiffFromStable;
 830+ $this->addQuickReview( $data, $onTop, false );
 831+ return true;
 832+ }
 833+
 834+ /**
 835+ * Add link to stable version setting to protection form
 836+ */
 837+ public function addVisibilityLink( &$data ) {
 838+ global $wgUser, $wgRequest, $wgOut;
 839+ $this->load();
 840+ if( FlaggedRevs::getProtectionLevels() )
 841+ return true; // simple custom levels set for action=protect
 842+ # Check only if the title is reviewable
 843+ if( !$this->article->isReviewable(true) ) {
 844+ return true;
 845+ }
 846+ $action = $wgRequest->getVal( 'action', 'view' );
 847+ if( $action == 'protect' || $action == 'unprotect' ) {
 848+ wfLoadExtensionMessages( 'FlaggedRevs' );
 849+ wfLoadExtensionMessages( 'Stabilization' ); // Load special page name
 850+ $title = SpecialPage::getTitleFor( 'Stabilization' );
 851+ # Give a link to the page to configure the stable version
 852+ $frev = $this->article->getStableRev();
 853+ if( $frev && $frev->getRevId() == $this->article->getLatest() ) {
 854+ $wgOut->prependHTML( "<span class='plainlinks'>" .
 855+ wfMsgExt( 'revreview-visibility',array('parseinline'),
 856+ $title->getPrefixedText() ) . "</span>" );
 857+ } elseif( $frev ) {
 858+ $wgOut->prependHTML( "<span class='plainlinks'>" .
 859+ wfMsgExt( 'revreview-visibility2',array('parseinline'),
 860+ $title->getPrefixedText() ) . "</span>" );
 861+ } else {
 862+ $wgOut->prependHTML( "<span class='plainlinks'>" .
 863+ wfMsgExt( 'revreview-visibility3',array('parseinline'),
 864+ $title->getPrefixedText() ) . "</span>" );
 865+ }
 866+ }
 867+ return true;
 868+ }
 869+
 870+ /**
 871+ * Modify an array of action links, as used by SkinTemplateNavigation and
 872+ * SkinTemplateTabs, to inlude flagged revs UI elements
 873+ */
 874+ public function setActionTabs( $skin, &$actions ) {
 875+ global $wgRequest, $wgUser;
 876+ $this->load();
 877+ if( FlaggedRevs::getProtectionLevels() ) {
 878+ return true; // simple custom levels set for action=protect
 879+ }
 880+ $title = $this->article->getTitle()->getSubjectPage();
 881+ if ( !FlaggedRevs::isPageReviewable( $title ) ) {
 882+ return true; // Only reviewable pages need these tabs
 883+ }
 884+ // Check if we should show a stabilization tab
 885+ if (
 886+ !$skin->mTitle->isTalkPage() &&
 887+ is_array( $actions ) &&
 888+ !isset( $actions['protect'] ) &&
 889+ !isset( $actions['unprotect'] ) &&
 890+ $wgUser->isAllowed( 'stablesettings' ) &&
 891+ $title->exists()
 892+ ) {
 893+ wfLoadExtensionMessages( 'Stabilization' );
 894+ $stableTitle = SpecialPage::getTitleFor( 'Stabilization' );
 895+ // Add a tab
 896+ $actions['default'] = array(
 897+ 'class' => false,
 898+ 'text' => wfMsg( 'stabilization-tab' ),
 899+ 'href' => $stableTitle->getLocalUrl(
 900+ 'page=' . $title->getPrefixedUrl()
 901+ )
 902+ );
 903+ }
 904+ return true;
 905+ }
 906+
 907+ /**
 908+ * Modify an array of view links, as used by SkinTemplateNavigation and
 909+ * SkinTemplateTabs, to inlude flagged revs UI elements
 910+ */
 911+ public function setViewTabs( $skin, &$views ) {
 912+ global $wgRequest, $wgUser, $wgFlaggedRevTabs;
 913+ $this->load();
 914+
 915+ $title = $this->article->getTitle()->getSubjectPage(); // Get the actual content page
 916+ $article = new Article( $title );
 917+ $action = $wgRequest->getVal( 'action', 'view' );
 918+ $fa = FlaggedArticle::getTitleInstance( $title );
 919+ if ( !$fa->isReviewable() || $this->article->limitedUI() ) {
 920+ // This isn't a reviewable page or the UI is hidden
 921+ return true;
 922+ }
 923+ $srev = $this->article->getStableRev( $action == 'rollback' ? FR_MASTER : 0 );
 924+ if( is_null( $srev ) ) {
 925+ return true; // No stable revision exists
 926+ }
 927+ wfLoadExtensionMessages( 'FlaggedRevs' );
 928+ $synced = FlaggedRevs::stableVersionIsSynced( $srev, $article );
 929+ // Set draft tab as needed...
 930+ if ( !$skin->mTitle->isTalkPage() && !$synced ) {
 931+ if ( isset( $views['edit'] ) ) {
 932+ if ( $this->article->showStableByDefault() ) {
 933+ $views['edit']['text'] = wfMsg('revreview-edit');
 934+ }
 935+ if ( $this->pageOverride() ) {
 936+ $views['edit']['href'] = $title->getLocalUrl( 'action=edit' );
 937+ }
 938+ }
 939+ if ( isset( $views['viewsource'] ) ) {
 940+ if ( $this->article->showStableByDefault() ) {
 941+ $views['viewsource']['text'] = wfMsg('revreview-source');
 942+ }
 943+ if ( $this->pageOverride() ) {
 944+ $views['viewsource']['href'] = $title->getLocalUrl( 'action=edit' );
 945+ }
 946+ }
 947+ }
 948+ if ( !$wgFlaggedRevTabs || $synced ) {
 949+ // Exit, since either the stable/draft tabs should not be shown
 950+ // or the page is already the most current revision
 951+ return true;
 952+ }
 953+ $tabs = array(
 954+ 'stable' => array(
 955+ 'text' => wfMsg( 'revreview-stable' ), // unused
 956+ 'href' => $title->getLocalUrl( 'stable=1' ),
 957+ 'class' => ''
 958+ ),
 959+ 'current' => array(
 960+ 'text' => wfMsg( 'revreview-current' ),
 961+ 'href' => $title->getLocalUrl( 'stable=0&redirect=no' ),
 962+ 'class' => ''
 963+ ),
 964+ );
 965+ if ( $this->pageOverride() || $wgRequest->getVal( 'stableid' ) ) {
 966+ // We are looking a the stable version
 967+ $tabs['stable']['class'] = 'selected';
 968+ } elseif (
 969+ ( self::isViewAction( $action ) || $action == 'edit' ) &&
 970+ !$skin->mTitle->isTalkPage()
 971+ ) {
 972+ // We are looking at the current revision or in edit mode
 973+ $tabs['current']['class'] = 'selected';
 974+ }
 975+ $first = true;
 976+ $newViews = array();
 977+ foreach ( $views as $tabAction => $data ) {
 978+ // Very first tab (page link)
 979+ if( $first ) {
 980+ if( $synced ) {
 981+ // Use existing first tabs when synced
 982+ $newViews[$tabAction] = $data;
 983+ } else {
 984+ // Use split current and stable tabs when not synced
 985+ $newViews[$tabAction]['text'] = $data['text']; // keep tab name
 986+ $newViews[$tabAction]['href'] = $tabs['stable']['href'];
 987+ $newViews[$tabAction]['class'] = $tabs['stable']['class'];
 988+ $newViews['current'] = $tabs['current'];
 989+ }
 990+ $first = false;
 991+ } else {
 992+ $newViews[$tabAction] = $data;
 993+ }
 994+ }
 995+ // Replaces old tabs with new tabs
 996+ $views = $newViews;
 997+ return true;
 998+ }
 999+
 1000+ /**
 1001+ * @param FlaggedRevision $frev
 1002+ * @return string, revision review notes
 1003+ */
 1004+ public function getReviewNotes( $frev ) {
 1005+ global $wgUser;
 1006+ $this->load();
 1007+ if( FlaggedRevs::allowComments() && $frev && $frev->getComment() ) {
 1008+ wfLoadExtensionMessages( 'FlaggedRevs' );
 1009+ $notes = "<br/><div class='flaggedrevs_notes plainlinks'>";
 1010+ $notes .= wfMsgExt('revreview-note', array('parseinline'), User::whoIs( $frev->getUser() ) );
 1011+ $notes .= '<br/><i>' . $wgUser->getSkin()->formatComment( $frev->getComment() ) . '</i></div>';
 1012+ $this->reviewNotes = $notes;
 1013+ }
 1014+ }
 1015+
 1016+ /**
 1017+ * When comparing the stable revision to the current after editing a page, show
 1018+ * a tag with some explaination for the diff.
 1019+ */
 1020+ public function addDiffNoticeAndIncludes( $diff, $oldRev, $newRev ) {
 1021+ global $wgRequest, $wgUser, $wgOut, $wgMemc;
 1022+ $this->load();
 1023+ # Page must be reviewable. Exempt printer-friendly output.
 1024+ # UI may be limited to unobtrusive patrolling system
 1025+ if( $wgOut->isPrintable() || !$this->article->isReviewable() || $this->article->limitedUI() )
 1026+ return true;
 1027+ # Load required messages
 1028+ wfLoadExtensionMessages( 'FlaggedRevs' );
 1029+ # Check if this might be the diff to stable. If so, enhance it.
 1030+ if( $newRev->isCurrent() && $oldRev ) {
 1031+ $article = new Article( $newRev->getTitle() );
 1032+ # Try the sync value cache...
 1033+ $key = wfMemcKey( 'flaggedrevs', 'includesSynced', $article->getId() );
 1034+ $value = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
 1035+ $synced = ($value === "true") ? true : false; // default as false to trigger query
 1036+ $frev = $this->article->getStableRev();
 1037+ if( $frev && $frev->getRevId() == $oldRev->getID() ) {
 1038+ global $wgParserCacheExpireTime;
 1039+
 1040+ $changeList = array();
 1041+ $skin = $wgUser->getSkin();
 1042+
 1043+ # Try the cache. Uses format <page ID>-<UNIX timestamp>.
 1044+ $key = wfMemcKey( 'stableDiffs', 'templates', $article->getId() );
 1045+ $tmpChanges = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
 1046+ if( empty($tmpChanges) && !$synced ) {
 1047+ $tmpChanges = false; // don't use cache
 1048+ }
 1049+
 1050+ # Make a list of each changed template...
 1051+ if( $tmpChanges === false ) {
 1052+ $dbr = wfGetDB( DB_SLAVE );
 1053+ // Get templates where the current and stable are not the same revision
 1054+ $ret = $dbr->select( array('flaggedtemplates','page','flaggedpages'),
 1055+ array( 'ft_namespace', 'ft_title', 'fp_stable','ft_tmp_rev_id', 'page_latest' ),
 1056+ array( 'ft_rev_id' => $frev->getRevId(),
 1057+ 'page_namespace = ft_namespace',
 1058+ 'page_title = ft_title' ),
 1059+ __METHOD__,
 1060+ array(), /* OPTIONS */
 1061+ array( 'flaggedpages' => array('LEFT JOIN','fp_page_id = page_id') )
 1062+ );
 1063+ $tmpChanges = array();
 1064+ while( $row = $dbr->fetchObject( $ret ) ) {
 1065+ $title = Title::makeTitleSafe( $row->ft_namespace, $row->ft_title );
 1066+ $revIdDraft = $row->page_latest;
 1067+ // stable time -> time when reviewed (unless the other is newer)
 1068+ $revIdStable = isset($row->fp_stable) && $row->fp_stable >= $row->ft_tmp_rev_id ?
 1069+ $row->fp_stable : $row->ft_tmp_rev_id;
 1070+ // compare to current
 1071+ if( $revIdDraft > $revIdStable ) {
 1072+ $tmpChanges[] = $skin->makeKnownLinkObj( $title, $title->getPrefixedText(),
 1073+ "diff=cur&oldid={$revIdStable}" );
 1074+ }
 1075+ }
 1076+ $wgMemc->set( $key, FlaggedRevs::makeMemcObj($tmpChanges), $wgParserCacheExpireTime );
 1077+ }
 1078+ # Add set to list
 1079+ if( $tmpChanges )
 1080+ $changeList += $tmpChanges;
 1081+
 1082+ # Try the cache. Uses format <page ID>-<UNIX timestamp>.
 1083+ $key = wfMemcKey( 'stableDiffs', 'images', $article->getId() );
 1084+ $imgChanges = FlaggedRevs::getMemcValue( $wgMemc->get($key), $article );
 1085+ if( empty($imgChanges) && !$synced ) {
 1086+ $imgChanges = false; // don't use cache
 1087+ }
 1088+
 1089+ // Get list of each changed image...
 1090+ if( $imgChanges === false ) {
 1091+ $dbr = wfGetDB( DB_SLAVE );
 1092+ // Get images where the current and stable are not the same revision
 1093+ $ret = $dbr->select( array('flaggedimages','page','image','flaggedpages','flaggedrevs'),
 1094+ array( 'fi_name', 'fi_img_timestamp', 'fr_img_timestamp' ),
 1095+ array( 'fi_rev_id' => $frev->getRevId() ),
 1096+ __METHOD__,
 1097+ array(), /* OPTIONS */
 1098+ array( 'page' => array('LEFT JOIN','page_namespace = '. NS_FILE .' AND page_title = fi_name'),
 1099+ 'image' => array('LEFT JOIN','img_name = fi_name'),
 1100+ 'flaggedpages' => array('LEFT JOIN','fp_page_id = page_id'),
 1101+ 'flaggedrevs' => array('LEFT JOIN','fr_page_id = fp_page_id AND fr_rev_id = fp_stable') )
 1102+ );
 1103+ $imgChanges = array();
 1104+ while( $row = $dbr->fetchObject( $ret ) ) {
 1105+ $title = Title::makeTitleSafe( NS_FILE, $row->fi_name );
 1106+ // stable time -> time when reviewed (unless the other is newer)
 1107+ $timestamp = isset($row->fr_img_timestamp) && $row->fr_img_timestamp >= $row->fi_img_timestamp ?
 1108+ $row->fr_img_timestamp : $row->fi_img_timestamp;
 1109+ // compare to current
 1110+ $file = wfFindFile( $title );
 1111+ if( $file && $file->getTimestamp() > $timestamp )
 1112+ $imgChanges[] = $skin->makeKnownLinkObj( $title, $title->getPrefixedText() );
 1113+ }
 1114+ $wgMemc->set( $key, FlaggedRevs::makeMemcObj($imgChanges), $wgParserCacheExpireTime );
 1115+ }
 1116+ if( $imgChanges )
 1117+ $changeList += $imgChanges;
 1118+
 1119+ # Some important information...
 1120+ $notice = '';
 1121+ if( count($changeList) > 0 ) {
 1122+ $notice = '<br/>' . wfMsgExt('revreview-update-use', array('parseinline'));
 1123+ } elseif( !$synced ) {
 1124+ $diff->mTitle->invalidateCache(); // bad cache, said they were not synced
 1125+ }
 1126+
 1127+ # If the user is allowed to review, prompt them!
 1128+ if( empty($changeList) && $wgUser->isAllowed('review') ) {
 1129+ $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
 1130+ wfMsgExt('revreview-update-none', array('parseinline')).$notice.'</div>' );
 1131+ } elseif( !empty($changeList) && $wgUser->isAllowed('review') ) {
 1132+ $changeList = implode(', ',$changeList);
 1133+ $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
 1134+ wfMsgExt('revreview-update', array('parseinline')).'&nbsp;'.
 1135+ $changeList.$notice.'</div>' );
 1136+ } elseif( !empty($changeList) ) {
 1137+ $changeList = implode(', ',$changeList);
 1138+ $wgOut->addHTML( "<div id='mw-difftostable' class='flaggedrevs_diffnotice plainlinks'>" .
 1139+ wfMsgExt('revreview-update-includes', array('parseinline')).'&nbsp;'.
 1140+ $changeList.$notice.'</div>' );
 1141+ }
 1142+ # Set flag for review form to tell it to autoselect tag settings from the
 1143+ # old revision unless the current one is tagged to.
 1144+ if( !FlaggedRevision::newFromTitle( $diff->mTitle, $newRev->getID() ) ) {
 1145+ $this->isDiffFromStable = true;
 1146+ }
 1147+
 1148+ # Set a key to note that someone is viewing this
 1149+ if( $wgUser->isAllowed('review') ) {
 1150+ $key = wfMemcKey( 'stableDiffs', 'underReview', $oldRev->getID(), $newRev->getID() );
 1151+ $wgMemc->set( $key, '1', 10*60 ); // 10 min
 1152+ }
 1153+ }
 1154+ }
 1155+ $newRevQ = FlaggedRevs::getRevQuality( $newRev->getPage(), $newRev->getId() );
 1156+ $oldRevQ = $oldRev ? FlaggedRevs::getRevQuality( $newRev->getPage(), $oldRev->getId() ) : false;
 1157+ # Diff between two revisions
 1158+ if( $oldRev ) {
 1159+ $wgOut->addHTML( "<table class='fr-diff-ratings'><tr>" );
 1160+
 1161+ $class = FlaggedRevsXML::getQualityColor( $oldRevQ );
 1162+ if( $oldRevQ !== false ) {
 1163+ $msg = $oldRevQ ? 'hist-quality' : 'hist-stable';
 1164+ } else {
 1165+ $msg = 'hist-draft';
 1166+ }
 1167+ $wgOut->addHTML( "<td width='50%' align='center'>" );
 1168+ $wgOut->addHTML( "<span class='$class'><b>[" . wfMsgHtml( $msg ) . "]</b></span>" );
 1169+
 1170+ $class = FlaggedRevsXML::getQualityColor( $newRevQ );
 1171+ if( $newRevQ !== false ) {
 1172+ $msg = $newRevQ ? 'hist-quality' : 'hist-stable';
 1173+ } else {
 1174+ $msg = 'hist-draft';
 1175+ }
 1176+ $wgOut->addHTML( "</td><td width='50%' align='center'>" );
 1177+ $wgOut->addHTML( "<span class='$class'><b>[" . wfMsgHtml( $msg ) . "]</b></span>" );
 1178+
 1179+ $wgOut->addHTML( '</td></tr></table>' );
 1180+ # New page "diffs" - just one rev
 1181+ } else {
 1182+ if( $newRevQ !== false ) {
 1183+ $msg = $newRevQ ? 'hist-quality' : 'hist-stable';
 1184+ } else {
 1185+ $msg = 'hist-draft';
 1186+ }
 1187+ $wgOut->addHTML( "<table class='fr-diff-ratings'><tr><td class='fr-$msg' align='center'>" );
 1188+ $wgOut->addHTML( "<b>[" . wfMsgHtml( $msg ) . "]</b>" );
 1189+ $wgOut->addHTML( '</td></tr></table>' );
 1190+ }
 1191+ return true;
 1192+ }
 1193+
 1194+ /**
 1195+ * Set $this->isDiffFromStable and $this->isMultiPageDiff fields
 1196+ */
 1197+ public function setViewFlags( $diff, $oldRev, $newRev ) {
 1198+ $this->load();
 1199+ if( $newRev && $oldRev ) {
 1200+ // Is this a diff between two pages?
 1201+ if( $newRev->getPage() != $oldRev->getPage() ) {
 1202+ $this->isMultiPageDiff = true;
 1203+ // Is there a stable version?
 1204+ } else if( $this->article->isReviewable() ) {
 1205+ $frev = $this->article->getStableRev();
 1206+ // Is this a diff of the draft rev against the stable rev?
 1207+ if( $frev && $frev->getRevId() == $oldRev->getId() && $newRev->isCurrent() ) {
 1208+ $this->isDiffFromStable = true;
 1209+ }
 1210+ }
 1211+ }
 1212+ return true;
 1213+ }
 1214+
 1215+ /**
 1216+ * Add a link to patrol non-reviewable pages.
 1217+ * Also add a diff-to-stable for other pages if possible.
 1218+ */
 1219+ public function addDiffLink( $diff, $oldRev, $newRev ) {
 1220+ global $wgUser, $wgOut;
 1221+ $this->load();
 1222+ // Is there a stable version?
 1223+ if( $newRev && $oldRev && $this->article->isReviewable() ) {
 1224+ $frev = $this->article->getStableRev();
 1225+ # Give a link to the diff-to-stable if needed
 1226+ if( $frev && !$this->isDiffFromStable ) {
 1227+ $article = new Article( $newRev->getTitle() );
 1228+ # Is the stable revision using the same revision as the current?
 1229+ if( $article->getLatest() != $frev->getRevId() ) {
 1230+ wfLoadExtensionMessages( 'FlaggedRevs' );
 1231+ $patrol = '(' . $wgUser->getSkin()->makeKnownLinkObj( $newRev->getTitle(),
 1232+ wfMsgHtml( 'review-diff2stable' ), "oldid={$frev->getRevId()}&diff=cur&diffonly=0" ) . ')';
 1233+ $wgOut->addHTML( "<div class='fr-diff-to-stable' align='center'>$patrol</div>" );
 1234+ }
 1235+ }
 1236+ }
 1237+ return true;
 1238+ }
 1239+
 1240+ /**
 1241+ * Redirect users out to review the changes to the stable version.
 1242+ * Only for people who can review and for pages that have a stable version.
 1243+ */
 1244+ public function injectReviewDiffURLParams( &$sectionAnchor, &$extraQuery ) {
 1245+ global $wgUser, $wgReviewChangesAfterEdit;
 1246+ $this->load();
 1247+ # Don't show this for pages that are not reviewable
 1248+ if( !$this->article->isReviewable() || $this->article->getTitle()->isTalkPage() )
 1249+ return true;
 1250+ # We may want to skip some UI elements
 1251+ if( $this->article->limitedUI() ) return true;
 1252+ # Get the stable version, from master
 1253+ $frev = $this->article->getStableRev( FR_MASTER );
 1254+ if( !$frev )
 1255+ return true;
 1256+ $latest = $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
 1257+ // If we are supposed to review after edit, and it was not autoreviewed,
 1258+ // and the user can actually make new stable version, take us to the diff...
 1259+ if( $wgReviewChangesAfterEdit && $frev && $latest > $frev->getRevId() && $frev->userCanSetFlags() ) {
 1260+ $extraQuery .= $extraQuery ? '&' : '';
 1261+ $extraQuery .= "oldid={$frev->getRevId()}&diff=cur&diffonly=0"; // override diff-only
 1262+ // ...otherwise, go to the current revision after completing an edit.
 1263+ } else {
 1264+ if( $frev && $latest != $frev->getRevId() ) {
 1265+ $extraQuery .= "stable=0";
 1266+ if( !$wgUser->isAllowed('review') && $this->article->showStableByDefault() ) {
 1267+ $extraQuery .= "&shownotice=1";
 1268+ }
 1269+ }
 1270+ }
 1271+ return true;
 1272+ }
 1273+
 1274+ /**
 1275+ * Add a hidden revision ID field to edit form.
 1276+ * Needed for autoreview so it can select the flags from said revision.
 1277+ */
 1278+ public function addRevisionIDField( $editPage, $out ) {
 1279+ global $wgRequest;
 1280+ $this->load();
 1281+ # Find out revision id
 1282+ if( $this->article->mRevision ) {
 1283+ $revId = $this->article->mRevision->mId;
 1284+ } else {
 1285+ $latest = $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
 1286+ $revId = $latest;
 1287+ wfDebug( 'FlaggedArticle::addRevisionIDField - ID not specified, assumed current' );
 1288+ }
 1289+ # If undoing a few consecutive top edits, we know the base ID
 1290+ if( $undo = $wgRequest->getIntOrNull('undo') ) {
 1291+ $undoAfter = $wgRequest->getIntOrNull('undoafter');
 1292+ $latest = isset($latest) ?
 1293+ $latest : $this->article->getTitle()->getLatestRevID(GAID_FOR_UPDATE);
 1294+ if( $undoAfter && $undo == $this->article->getLatest() ) {
 1295+ $revId = $undoAfter;
 1296+ }
 1297+ }
 1298+ $out->addHTML( "\n" . Xml::hidden( 'baseRevId', $revId ) );
 1299+ $out->addHTML( "\n" . Xml::hidden( 'undidRev',
 1300+ empty($editPage->undidRev) ? 0 : $editPage->undidRev )
 1301+ );
 1302+ return true;
 1303+ }
 1304+
 1305+ /**
 1306+ * Adds brief review notes to a page.
 1307+ * @param OutputPage $out
 1308+ */
 1309+ public function addReviewNotes( &$data ) {
 1310+ $this->load();
 1311+ if( $this->reviewNotes ) {
 1312+ $data .= $this->reviewNotes;
 1313+ }
 1314+ return true;
 1315+ }
 1316+
 1317+ /**
 1318+ * Adds a brief review form to a page.
 1319+ * @param string $data
 1320+ * @param bool $top
 1321+ * @param bool hide
 1322+ * @param bool $top, should this form always go on top?
 1323+ */
 1324+ public function addQuickReview( &$data, $top = false, $hide = false ) {
 1325+ global $wgOut, $wgUser, $wgRequest;
 1326+ $this->load();
 1327+ # Get the revision being displayed
 1328+ $id = $wgOut->getRevisionId();
 1329+ if( !$id ) {
 1330+ if( !$this->isDiffFromStable ) {
 1331+ return false; // only safe to assume current if diff-to-stable
 1332+ } else {
 1333+ $rev = Revision::newFromTitle( $this->article->getTitle() );
 1334+ $id = $rev->getId();
 1335+ }
 1336+ } else {
 1337+ $rev = Revision::newFromTitle( $this->article->getTitle(), $id );
 1338+ }
 1339+ # Load required messages
 1340+ wfLoadExtensionMessages( 'FlaggedRevs' );
 1341+ # Must be a valid non-printable output and revision must be public
 1342+ if( $wgOut->isPrintable() || !$rev || $rev->isDeleted(Revision::DELETED_TEXT) ) {
 1343+ return false;
 1344+ }
 1345+ $useCurrent = false;
 1346+ if( !isset($wgOut->mTemplateIds) || !isset($wgOut->fr_ImageSHA1Keys) ) {
 1347+ $useCurrent = true;
 1348+ }
 1349+ $skin = $wgUser->getSkin();
 1350+
 1351+ $config = $this->article->getVisibilitySettings();
 1352+ # Variable for sites with no flags, otherwise discarded
 1353+ $approve = $wgRequest->getBool('wpApprove');
 1354+ # See if the version being displayed is flagged...
 1355+ $oldFlags = $this->article->getFlagsForRevision( $id );
 1356+ # If we are reviewing updates to a page, start off with the stable revision's
 1357+ # flags. Otherwise, we just fill them in with the selected revision's flags.
 1358+ if( $this->isDiffFromStable ) {
 1359+ $srev = $this->article->getStableRev();
 1360+ $flags = $srev->getTags();
 1361+ # Check if user is allowed to renew the stable version.
 1362+ # If not, then get the flags for the new revision itself.
 1363+ if( !RevisionReview::userCanSetFlags( $oldFlags ) ) {
 1364+ $flags = $oldFlags;
 1365+ }
 1366+ $encNotes = $srev->getComment();
 1367+ } else {
 1368+ $frev = FlaggedRevision::newFromTitle( $this->article->getTitle(), $id );
 1369+ $flags = $oldFlags;
 1370+ $encNotes = $frev ? $frev->getComment() : ""; // pre-fill notes
 1371+ }
 1372+
 1373+ $reviewTitle = SpecialPage::getTitleFor( 'RevisionReview' );
 1374+ $action = $reviewTitle->getLocalUrl( 'action=submit' );
 1375+ $params = array( 'method' => 'post', 'action' => $action, 'id' => 'mw-reviewform' );
 1376+ if( $hide ) {
 1377+ $params['class'] = 'fr-hiddenform';
 1378+ }
 1379+ $form = Xml::openElement( 'form', $params );
 1380+ $form .= Xml::openElement( 'fieldset', array('class' => 'flaggedrevs_reviewform noprint') );
 1381+ $form .= "<legend><strong>" . wfMsgHtml( 'revreview-flag', $id ) . "</strong></legend>\n";
 1382+
 1383+ # Show explanatory text
 1384+ if( !FlaggedRevs::lowProfileUI() ) {
 1385+ $msg = FlaggedRevs::showStableByDefault() ? 'revreview-text' : 'revreview-text2';
 1386+ $form .= wfMsgExt( $msg, array('parse') );
 1387+ }
 1388+
 1389+ # Current user has too few rights to change at least one flag, thus entire form disabled
 1390+ $uneditable = !$this->article->getTitle()->quickUserCan('edit');
 1391+ $disabled = !RevisionReview::userCanSetFlags( $flags ) || $uneditable;
 1392+ if( $disabled ) {
 1393+ $form .= Xml::openElement( 'div', array('class' => 'fr-rating-controls-disabled',
 1394+ 'id' => 'fr-rating-controls-disabled') );
 1395+ $toggle = array( 'disabled' => "disabled" );
 1396+ } else {
 1397+ $form .= Xml::openElement( 'div', array('class' => 'fr-rating-controls',
 1398+ 'id' => 'fr-rating-controls') );
 1399+ $toggle = array();
 1400+ }
 1401+ # Add main checkboxes/selects
 1402+ $form .= Xml::openElement( 'span', array('id' => 'mw-ratingselects') );
 1403+ $form .= FlaggedRevsXML::ratingInputs( $flags, $config, $disabled );
 1404+ $form .= Xml::closeElement( 'span' );
 1405+
 1406+ if( FlaggedRevs::allowComments() && $wgUser->isAllowed( 'validate' ) ) {
 1407+ $form .= "<div id='mw-notebox'>\n";
 1408+ $form .= "<p>".wfMsgHtml( 'revreview-notes' ) . "</p>\n";
 1409+ $form .= Xml::openElement( 'textarea', array('name' => 'wpNotes', 'id' => 'wpNotes',
 1410+ 'class' => 'fr-notes-box', 'rows' => '2', 'cols' => '80') ) .
 1411+ htmlspecialchars( $encNotes ) .
 1412+ Xml::closeElement('textarea') . "\n";
 1413+ $form .= "</div>\n";
 1414+ }
 1415+ # Get versions of templates/files used
 1416+ $imageParams = $templateParams = $fileVersion = '';
 1417+ if( $useCurrent ) {
 1418+ # Get parsed current version
 1419+ $parserCache = ParserCache::singleton();
 1420+ $article = $this->article;
 1421+ $currentOutput = $parserCache->get( $article, $wgUser );
 1422+ if( $currentOutput == false ) {
 1423+ global $wgParser, $wgEnableParserCache;
 1424+ $text = $article->getContent();
 1425+ $title = $article->getTitle();
 1426+ $options = FlaggedRevs::makeParserOptions();
 1427+ $currentOutput = $wgParser->parse( $text, $title, $options );
 1428+ # Might as well save the cache while we're at it
 1429+ if( $wgEnableParserCache )
 1430+ $parserCache->save( $currentOutput, $article, $wgUser );
 1431+ }
 1432+ $templateIDs = $currentOutput->mTemplateIds;
 1433+ $imageSHA1Keys = $currentOutput->fr_ImageSHA1Keys;
 1434+ } else {
 1435+ $templateIDs = $wgOut->mTemplateIds;
 1436+ $imageSHA1Keys = $wgOut->fr_ImageSHA1Keys;
 1437+ }
 1438+ list($templateParams,$imageParams,$fileVersion) =
 1439+ FlaggedRevs::getIncludeParams( $this->article, $templateIDs, $imageSHA1Keys );
 1440+
 1441+ $form .= Xml::openElement( 'span', array('style' => 'white-space: nowrap;') );
 1442+ # Hide comment if needed
 1443+ if( !$disabled ) {
 1444+ if( count(FlaggedRevs::getDimensions()) > 1 )
 1445+ $form .= "<br/>"; // Don't put too much on one line
 1446+ $form .= "<span id='mw-commentbox' style='clear:both'>" .
 1447+ Xml::inputLabel( wfMsg('revreview-log'), 'wpReason', 'wpReason', 40, '',
 1448+ array('class' => 'fr-comment-box') ) . "&nbsp;&nbsp;&nbsp;</span>";
 1449+ }
 1450+ $form .= Xml::submitButton( wfMsg('revreview-submit'),
 1451+ array(
 1452+ 'id' => 'submitreview', 'accesskey' => wfMsg('revreview-ak-review'),
 1453+ 'title' => wfMsg('revreview-tt-review').' ['.wfMsg('revreview-ak-review').']'
 1454+ ) + $toggle
 1455+ );
 1456+ $form .= Xml::closeElement( 'span' );
 1457+
 1458+ $form .= Xml::closeElement( 'div' ) . "\n";
 1459+
 1460+ # Show stability log if there is anything interesting...
 1461+ if( $this->article->isPageLocked() ) {
 1462+ $loglist = new LogEventsList( $wgUser->getSkin(), $wgOut, LogEventsList::NO_ACTION_LINK );
 1463+ $pager = new LogPager( $loglist, 'stable', '', $this->article->getTitle()->getPrefixedDBKey() );
 1464+ $pager->mLimit = 1; // top item
 1465+ if( ($logBody = $pager->getBody()) ) {
 1466+ $form .= "<div><ul style='list-style:none; margin: 0;'>$logBody</ul></div>";
 1467+ }
 1468+ }
 1469+
 1470+ # Hidden params
 1471+ $form .= Xml::hidden( 'title', $reviewTitle->getPrefixedText() ) . "\n";
 1472+ $form .= Xml::hidden( 'target', $this->article->getTitle()->getPrefixedDBKey() ) . "\n";
 1473+ $form .= Xml::hidden( 'oldid', $id ) . "\n";
 1474+ $form .= Xml::hidden( 'action', 'submit') . "\n";
 1475+ $form .= Xml::hidden( 'wpEditToken', $wgUser->editToken() ) . "\n";
 1476+ # Add review parameters
 1477+ $form .= Xml::hidden( 'templateParams', $templateParams ) . "\n";
 1478+ $form .= Xml::hidden( 'imageParams', $imageParams ) . "\n";
 1479+ $form .= Xml::hidden( 'fileVersion', $fileVersion ) . "\n";
 1480+ # Pass this in if given; useful for new page patrol
 1481+ $form .= Xml::hidden( 'rcid', $wgRequest->getVal('rcid') ) . "\n";
 1482+ # Special token to discourage fiddling...
 1483+ $checkCode = RevisionReview::validationKey( $templateParams, $imageParams, $fileVersion, $id );
 1484+ $form .= Xml::hidden( 'validatedParams', $checkCode ) . "\n";
 1485+
 1486+ $form .= Xml::closeElement( 'fieldset' );
 1487+ $form .= Xml::closeElement( 'form' );
 1488+ # Place form at the correct position specified by $top
 1489+ if( $top ) {
 1490+ $wgOut->prependHTML( $form );
 1491+ } else {
 1492+ $data .= $form;
 1493+ }
 1494+ return true;
 1495+ }
 1496+
 1497+ /**
 1498+ * Updates parser cache output to included needed versioning params.
 1499+ */
 1500+ public function maybeUpdateMainCache( &$outputDone, &$pcache ) {
 1501+ global $wgUser, $wgRequest;
 1502+ $this->load();
 1503+
 1504+ $action = $wgRequest->getVal( 'action', 'view' );
 1505+ if( $action == 'purge' )
 1506+ return true; // already purging!
 1507+ # Only trigger on article view for content pages, not for protect/delete/hist
 1508+ if( !self::isViewAction($action) || !$wgUser->isAllowed( 'review' ) )
 1509+ return true;
 1510+ if( !$this->article->exists() || !$this->article->isReviewable() )
 1511+ return true;
 1512+
 1513+ $parserCache = ParserCache::singleton();
 1514+ $parserOut = $parserCache->get( $this->article, $wgUser );
 1515+ if( $parserOut ) {
 1516+ # Clear older, incomplete, cached versions
 1517+ # We need the IDs of templates and timestamps of images used
 1518+ if( !isset($parserOut->fr_newestTemplateID) || !isset($parserOut->fr_newestImageTime) )
 1519+ $this->article->getTitle()->invalidateCache();
 1520+ }
 1521+ return true;
 1522+ }
 1523+}
Property changes on: trunk/extensions/FlaggedRevs/FlaggedArticleView.php
___________________________________________________________________
Name: svn:eol-style
15241524 + native

Status & tagging log