Index: trunk/extensions/FlaggedRevs/maintenance/updateTracking.inc |
— | — | @@ -7,11 +7,11 @@ |
8 | 8 | |
9 | 9 | $db = wfGetDB( DB_MASTER ); |
10 | 10 | |
11 | | - if( $start === null ) { |
| 11 | + if ( $start === null ) { |
12 | 12 | $start = $db->selectField( 'revision', 'MIN(rev_id)', false, __FUNCTION__ ); |
13 | 13 | } |
14 | 14 | $end = $db->selectField( 'revision', 'MAX(rev_id)', false, __FUNCTION__ ); |
15 | | - if( is_null( $start ) || is_null( $end ) ) { |
| 15 | + if ( is_null( $start ) || is_null( $end ) ) { |
16 | 16 | echo "...revision table seems to be empty.\n"; |
17 | 17 | return; |
18 | 18 | } |
— | — | @@ -21,7 +21,7 @@ |
22 | 22 | $blockEnd = $start + $BATCH_SIZE - 1; |
23 | 23 | $count = 0; |
24 | 24 | $changed = 0; |
25 | | - while( $blockEnd <= $end ) { |
| 25 | + while ( $blockEnd <= $end ) { |
26 | 26 | echo "...doing fr_rev_id from $blockStart to $blockEnd\n"; |
27 | 27 | $cond = "rev_id BETWEEN $blockStart AND $blockEnd |
28 | 28 | AND fr_page_id = rev_page AND fr_rev_id = rev_id AND page_id = rev_page"; |
— | — | @@ -32,17 +32,17 @@ |
33 | 33 | ); |
34 | 34 | $db->begin(); |
35 | 35 | # Go through and clean up missing items, as well as correct fr_quality... |
36 | | - foreach( $res as $row ) { |
| 36 | + foreach ( $res as $row ) { |
37 | 37 | $tags = FlaggedRevision::expandRevisionTags( $row->fr_tags ); |
38 | 38 | # Quality rating levels may have changed due to config tweaks... |
39 | | - if( FlaggedRevs::isPristine( $tags ) ) { |
| 39 | + if ( FlaggedRevs::isPristine( $tags ) ) { |
40 | 40 | $quality = 2; |
41 | 41 | } else { |
42 | 42 | $quality = FlaggedRevs::isQuality( $tags ) ? 1 : 0; |
43 | 43 | } |
44 | 44 | $time = $sha1 = $file = null; |
45 | 45 | # Check for file version to see if it's stored the old way... |
46 | | - if( !$row->fr_img_name && $row->page_namespace == NS_IMAGE ) { |
| 46 | + if ( !$row->fr_img_name && $row->page_namespace == NS_IMAGE ) { |
47 | 47 | $irow = $db->selectRow( 'flaggedimages', |
48 | 48 | array( 'fi_img_timestamp', 'fi_img_sha1' ), |
49 | 49 | array( 'fi_rev_id' => $row->fr_rev_id, |
— | — | @@ -52,7 +52,7 @@ |
53 | 53 | $sha1 = $irow ? $irow->fi_img_sha1 : null; |
54 | 54 | $file = $irow ? $row->page_title : null; |
55 | 55 | # Fill in from current if broken |
56 | | - if( !$irow ) { |
| 56 | + if ( !$irow ) { |
57 | 57 | $crow = $db->selectRow( 'image', |
58 | 58 | array( 'img_timestamp', 'img_sha1' ), |
59 | 59 | array( 'img_name' => $row->page_title ), |
— | — | @@ -62,12 +62,12 @@ |
63 | 63 | $file = $crow ? $row->page_title : null; |
64 | 64 | } |
65 | 65 | # Leave it alone if already set |
66 | | - } elseif( $row->fr_img_name && $row->page_namespace == NS_IMAGE ) { |
| 66 | + } elseif ( $row->fr_img_name && $row->page_namespace == NS_IMAGE ) { |
67 | 67 | $time = $row->fr_img_timestamp; |
68 | 68 | $sha1 = $row->fr_img_sha1; |
69 | 69 | $file = $row->fr_img_name; |
70 | 70 | } |
71 | | - if( $quality != $row->fr_quality |
| 71 | + if ( $quality != $row->fr_quality |
72 | 72 | || $file != $row->fr_img_name |
73 | 73 | || $sha1 != $row->fr_img_sha1 |
74 | 74 | || $time != $row->fr_img_timestamp ) |
— | — | @@ -101,11 +101,11 @@ |
102 | 102 | |
103 | 103 | $db = wfGetDB( DB_MASTER ); |
104 | 104 | |
105 | | - if( $start === null ) { |
| 105 | + if ( $start === null ) { |
106 | 106 | $start = $db->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); |
107 | 107 | } |
108 | 108 | $end = $db->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); |
109 | | - if( is_null( $start ) || is_null( $end ) ) { |
| 109 | + if ( is_null( $start ) || is_null( $end ) ) { |
110 | 110 | echo "...flaggedpages table seems to be empty.\n"; |
111 | 111 | return; |
112 | 112 | } |
— | — | @@ -114,37 +114,44 @@ |
115 | 115 | $blockStart = $start; |
116 | 116 | $blockEnd = $start + $BATCH_SIZE - 1; |
117 | 117 | $count = $deleted = $fixed = 0; |
118 | | - while( $blockEnd <= $end ) { |
| 118 | + while ( $blockEnd <= $end ) { |
119 | 119 | echo "...doing page_id from $blockStart to $blockEnd\n"; |
120 | 120 | $cond = "page_id BETWEEN $blockStart AND $blockEnd"; |
121 | 121 | $res = $db->select( 'page', array('page_id','page_namespace','page_title','page_latest'), |
122 | 122 | $cond, __FUNCTION__ ); |
123 | 123 | # Go through and update the de-normalized references... |
124 | 124 | $db->begin(); |
125 | | - foreach( $res as $row ) { |
| 125 | + foreach ( $res as $row ) { |
126 | 126 | $title = Title::newFromRow( $row ); |
127 | | - $article = new Article( $title ); |
128 | | - # Replaces new fields into flaggedpages |
| 127 | + $article = new FlaggedArticle( $title ); |
| 128 | + $oldFrev = FlaggedRevision::newFromStable( $title, FR_MASTER ); |
129 | 129 | $frev = FlaggedRevision::determineStable( $title, FR_MASTER ); |
130 | 130 | # Update fp_stable, fp_quality, and fp_reviewed |
131 | | - if( $frev ) { |
132 | | - FlaggedRevs::updateStableVersion( $article, $frev, $row->page_latest ); |
| 131 | + if ( $frev ) { |
| 132 | + $article->updateStableVersion( $frev, $row->page_latest ); |
| 133 | + $changed = ( !$oldFrev || $oldFrev->getRevId() != $frev->getRevId() ); |
133 | 134 | # Somethings broke? Delete the row... |
134 | 135 | } else { |
135 | | - FlaggedRevs::clearTrackingRows( $row->page_id ); |
136 | | - if( $db->affectedRows() > 0 ) $deleted++; |
| 136 | + $article->clearStableVersion(); |
| 137 | + if ( $db->affectedRows() > 0 ) $deleted++; |
| 138 | + $changed = (bool)$oldFrev; |
137 | 139 | } |
138 | 140 | # Get the latest revision |
139 | 141 | $revRow = $db->selectRow( 'revision', '*', |
140 | 142 | array('rev_page' => $row->page_id), __FUNCTION__, |
141 | 143 | array('ORDER BY' => 'rev_timestamp DESC') ); |
142 | 144 | # Correct page_latest if needed (import/files made plenty of bad rows) |
143 | | - if( $revRow ) { |
| 145 | + if ( $revRow ) { |
144 | 146 | $revision = new Revision( $revRow ); |
145 | | - if( $article->updateIfNewerOn( $db, $revision ) ) { |
| 147 | + if ( $article->updateIfNewerOn( $db, $revision ) ) { |
146 | 148 | $fixed++; |
147 | 149 | } |
148 | 150 | } |
| 151 | + if ( $changed ) { |
| 152 | + # Lazily rebuild dependancies on next parse (we invalidate below) |
| 153 | + FlaggedRevs::clearStableOnlyDeps( $title ); |
| 154 | + $title->invalidateCache(); |
| 155 | + } |
149 | 156 | $count++; |
150 | 157 | } |
151 | 158 | $db->freeResult( $res ); |
— | — | @@ -172,11 +179,11 @@ |
173 | 180 | |
174 | 181 | $db = wfGetDB( DB_MASTER ); |
175 | 182 | |
176 | | - if( $start === null ) { |
| 183 | + if ( $start === null ) { |
177 | 184 | $start = $db->selectField( 'flaggedimages', 'MIN(fi_rev_id)', false, __FUNCTION__ ); |
178 | 185 | } |
179 | 186 | $end = $db->selectField( 'flaggedimages', 'MAX(fi_rev_id)', false, __FUNCTION__ ); |
180 | | - if( is_null( $start ) || is_null( $end ) ) { |
| 187 | + if ( is_null( $start ) || is_null( $end ) ) { |
181 | 188 | echo "...flaggedimages table seems to be empty.\n"; |
182 | 189 | return; |
183 | 190 | } |
— | — | @@ -185,7 +192,7 @@ |
186 | 193 | $blockStart = $start; |
187 | 194 | $blockEnd = $start + $BATCH_SIZE - 1; |
188 | 195 | $nulled = 0; |
189 | | - while( $blockEnd <= $end ) { |
| 196 | + while ( $blockEnd <= $end ) { |
190 | 197 | echo "...doing fi_rev_id from $blockStart to $blockEnd\n"; |
191 | 198 | $cond = "fi_rev_id BETWEEN $blockStart AND $blockEnd"; |
192 | 199 | $db->begin(); |
— | — | @@ -195,7 +202,7 @@ |
196 | 203 | array( $cond, "fi_img_timestamp = '' OR LOCATE( '\\0', fi_img_timestamp )" ), |
197 | 204 | __FUNCTION__ |
198 | 205 | ); |
199 | | - if( $db->affectedRows() > 0 ) { |
| 206 | + if ( $db->affectedRows() > 0 ) { |
200 | 207 | $nulled += $db->affectedRows(); |
201 | 208 | } |
202 | 209 | $db->commit(); |
Index: trunk/extensions/FlaggedRevs/FlaggedArticle.php |
— | — | @@ -6,6 +6,7 @@ |
7 | 7 | */ |
8 | 8 | class FlaggedArticle extends Article { |
9 | 9 | /* Process cache variables */ |
| 10 | + protected $stable = 0; |
10 | 11 | protected $stableRev = null; |
11 | 12 | protected $revsArePending = null; |
12 | 13 | protected $pendingRevCount = null; |
— | — | @@ -14,8 +15,6 @@ |
15 | 16 | |
16 | 17 | protected $imagePage = null; // for file pages |
17 | 18 | |
18 | | - protected $stabilityDataLoaded = false; |
19 | | - |
20 | 19 | /** |
21 | 20 | * Get a FlaggedArticle for a given title |
22 | 21 | * @param Title |
— | — | @@ -43,14 +42,14 @@ |
44 | 43 | * @return void |
45 | 44 | */ |
46 | 45 | public function clear() { |
| 46 | + $this->stable = 0; |
47 | 47 | $this->stableRev = null; |
48 | 48 | $this->revsArePending = null; |
49 | 49 | $this->pendingRevCount = null; |
50 | 50 | $this->pageConfig = null; |
| 51 | + $this->syncedInTracking = null; |
51 | 52 | $this->imagePage = null; |
52 | | - |
53 | | - $this->stabilityDataLoaded = false; |
54 | | - parent::clear(); |
| 53 | + parent::clear(); // call super! |
55 | 54 | } |
56 | 55 | |
57 | 56 | /** |
— | — | @@ -59,11 +58,11 @@ |
60 | 59 | * @return mixed (File/false) |
61 | 60 | */ |
62 | 61 | public function getFile() { |
63 | | - if ( $this->getTitle()->getNamespace() != NS_FILE ) { |
| 62 | + if ( $this->mTitle->getNamespace() != NS_FILE ) { |
64 | 63 | return false; // not a file page |
65 | 64 | } |
66 | 65 | if ( is_null( $this->imagePage ) ) { |
67 | | - $this->imagePage = new ImagePage( $this->getTitle() ); |
| 66 | + $this->imagePage = new ImagePage( $this->mTitle ); |
68 | 67 | } |
69 | 68 | return $this->imagePage->getFile(); |
70 | 69 | } |
— | — | @@ -74,22 +73,20 @@ |
75 | 74 | * @return mixed (File/false) |
76 | 75 | */ |
77 | 76 | public function getDisplayedFile() { |
78 | | - if ( $this->getTitle()->getNamespace() != NS_FILE ) { |
| 77 | + if ( $this->mTitle->getNamespace() != NS_FILE ) { |
79 | 78 | return false; // not a file page |
80 | 79 | } |
81 | 80 | if ( is_null( $this->imagePage ) ) { |
82 | | - $this->imagePage = new ImagePage( $this->getTitle() ); |
| 81 | + $this->imagePage = new ImagePage( $this->mTitle ); |
83 | 82 | } |
84 | 83 | return $this->imagePage->getDisplayedFile(); |
85 | 84 | } |
86 | 85 | |
87 | 86 | /** |
88 | 87 | * Is the stable version shown by default for this page? |
89 | | - * @param int $flags, FR_MASTER |
90 | 88 | * @return bool |
91 | 89 | */ |
92 | | - public function isStableShownByDefault( $flags = 0 ) { |
93 | | - $this->loadFlaggedRevsData( $flags ); |
| 90 | + public function isStableShownByDefault() { |
94 | 91 | if ( !$this->isReviewable() ) { |
95 | 92 | return false; // no stable versions can exist |
96 | 93 | } |
— | — | @@ -99,11 +96,9 @@ |
100 | 97 | |
101 | 98 | /** |
102 | 99 | * Do edits have to be reviewed before being shown by default (going live)? |
103 | | - * @param int $flags, FR_MASTER |
104 | 100 | * @return bool |
105 | 101 | */ |
106 | | - public function editsRequireReview( $flags = 0 ) { |
107 | | - $this->loadFlaggedRevsData( $flags ); |
| 102 | + public function editsRequireReview() { |
108 | 103 | return ( |
109 | 104 | $this->isReviewable() && // reviewable page |
110 | 105 | $this->isStableShownByDefault() && // and stable versions override |
— | — | @@ -113,24 +108,28 @@ |
114 | 109 | |
115 | 110 | /** |
116 | 111 | * Are edits to this page currently pending? |
117 | | - * @param int $flags, FR_MASTER |
118 | 112 | * @return bool |
119 | 113 | */ |
120 | | - public function revsArePending( $flags = 0 ) { |
121 | | - $this->loadFlaggedRevsData( $flags ); |
| 114 | + public function revsArePending() { |
| 115 | + if ( !$this->mDataLoaded ) { |
| 116 | + $this->loadPageData(); |
| 117 | + } |
122 | 118 | return $this->revsArePending; |
123 | 119 | } |
124 | 120 | |
125 | 121 | /** |
126 | 122 | * Get number of revs since the stable revision |
127 | 123 | * Note: slower than revsArePending() |
128 | | - * @param int $flags FR_MASTER |
| 124 | + * @param int $flags FR_MASTER (be sure to use loadFromDB( FR_MASTER ) if set) |
129 | 125 | * @return int |
130 | 126 | */ |
131 | 127 | public function getPendingRevCount( $flags = 0 ) { |
132 | 128 | global $wgMemc, $wgParserCacheExpireTime; |
133 | | - $this->loadFlaggedRevsData( $flags ); |
134 | | - if ( !( $flags & FR_MASTER ) && $this->pendingRevCount !== null ) { |
| 129 | + if ( !$this->mDataLoaded ) { |
| 130 | + $this->loadPageData(); |
| 131 | + } |
| 132 | + # Pending count deferred even after page data load |
| 133 | + if ( $this->pendingRevCount !== null ) { |
135 | 134 | return $this->pendingRevCount; // use process cache |
136 | 135 | } |
137 | 136 | $srev = $this->getStableRev(); |
— | — | @@ -185,7 +184,7 @@ |
186 | 185 | if ( $this->revsArePending() ) { |
187 | 186 | return false; |
188 | 187 | # Stable file revision must be the same as the current |
189 | | - } elseif ( $this->getTitle()->getNamespace() == NS_FILE ) { |
| 188 | + } elseif ( $this->mTitle->getNamespace() == NS_FILE ) { |
190 | 189 | $file = $this->getFile(); // current upload version |
191 | 190 | if ( $file && $file->getTimestamp() > $srev->getFileTimestamp() ) { |
192 | 191 | return false; |
— | — | @@ -251,11 +250,10 @@ |
252 | 251 | |
253 | 252 | /** |
254 | 253 | * Is this article reviewable? |
255 | | - * @param int $flags, FR_MASTER |
256 | 254 | * @return bool |
257 | 255 | */ |
258 | | - public function isReviewable( $flags = 0 ) { |
259 | | - if ( !FlaggedRevs::inReviewNamespace( $this->getTitle() ) ) { |
| 256 | + public function isReviewable() { |
| 257 | + if ( !FlaggedRevs::inReviewNamespace( $this->mTitle ) ) { |
260 | 258 | return false; |
261 | 259 | } |
262 | 260 | # Check if flagging is disabled for this page via config |
— | — | @@ -268,105 +266,276 @@ |
269 | 267 | |
270 | 268 | /** |
271 | 269 | * Is this page in patrollable? |
272 | | - * @param int $flags, FR_MASTER |
273 | 270 | * @return bool |
274 | 271 | */ |
275 | | - public function isPatrollable( $flags = 0 ) { |
276 | | - if ( !FlaggedRevs::inPatrolNamespace( $this->getTitle() ) ) { |
| 272 | + public function isPatrollable() { |
| 273 | + if ( !FlaggedRevs::inPatrolNamespace( $this->mTitle ) ) { |
277 | 274 | return false; |
278 | 275 | } |
279 | | - return !$this->isReviewable( $flags ); // pages that are reviewable are not patrollable |
| 276 | + return !$this->isReviewable(); // pages that are reviewable are not patrollable |
280 | 277 | } |
281 | 278 | |
282 | 279 | /** |
283 | 280 | * Get the stable revision ID |
284 | | - * @param int $flags |
285 | 281 | * @return int |
286 | 282 | */ |
287 | | - public function getStable( $flags = 0 ) { |
288 | | - $srev = $this->getStableRev( $flags ); |
289 | | - return $srev ? $srev->getRevId() : 0; |
| 283 | + public function getStable() { |
| 284 | + if ( !$this->mDataLoaded ) { |
| 285 | + $this->loadPageData(); |
| 286 | + } |
| 287 | + return (int)$this->stable; |
290 | 288 | } |
291 | 289 | |
292 | 290 | /** |
293 | 291 | * Get the stable revision |
294 | | - * @param int $flags |
295 | 292 | * @return mixed (FlaggedRevision/null) |
296 | 293 | */ |
297 | | - public function getStableRev( $flags = 0 ) { |
298 | | - $this->loadFlaggedRevsData( $flags ); |
| 294 | + public function getStableRev() { |
| 295 | + if ( !$this->mDataLoaded ) { |
| 296 | + $this->loadPageData(); |
| 297 | + } |
| 298 | + # Stable rev deferred even after page data load |
| 299 | + if ( $this->stableRev === null ) { |
| 300 | + $srev = FlaggedRevision::newFromTitle( $this->mTitle, $this->stable ); |
| 301 | + $this->stableRev = $srev ? $srev : false; // cache negative hits too |
| 302 | + } |
299 | 303 | return $this->stableRev ? $this->stableRev : null; // false => null |
300 | 304 | } |
301 | 305 | |
302 | 306 | /** |
303 | 307 | * Get visiblity restrictions on page |
304 | | - * @param int $flags, FR_MASTER |
305 | 308 | * @return Array (select,override) |
306 | 309 | */ |
307 | | - public function getStabilitySettings( $flags = 0 ) { |
308 | | - $this->loadFlaggedRevsData( $flags ); |
| 310 | + public function getStabilitySettings() { |
| 311 | + if ( !$this->mDataLoaded ) { |
| 312 | + $this->loadPageData(); |
| 313 | + } |
309 | 314 | return $this->pageConfig; |
310 | 315 | } |
311 | 316 | |
| 317 | + /* |
| 318 | + * Get the fp_reviewed value for this page |
| 319 | + * @return bool |
| 320 | + */ |
| 321 | + public function syncedInTracking() { |
| 322 | + if ( !$this->mDataLoaded ) { |
| 323 | + $this->loadPageData(); |
| 324 | + } |
| 325 | + return $this->syncedInTracking; |
| 326 | + } |
| 327 | + |
312 | 328 | /** |
313 | | - * Get a DB row of the stable version and page config of a title. |
314 | | - * @param Title $title, page title |
315 | | - * @param int $flags FR_MASTER |
| 329 | + * Fetch a page record with the given conditions |
| 330 | + * @param $dbr Database object |
| 331 | + * @param $conditions Array |
| 332 | + * @return mixed Database result resource, or false on failure |
316 | 333 | */ |
317 | | - protected function loadFlaggedRevsData( $flags = 0 ) { |
318 | | - if ( $this->stabilityDataLoaded && !( $flags & FR_MASTER ) ) { |
319 | | - return; // no need to reload everything |
320 | | - } |
321 | | - $this->stabilityDataLoaded = true; |
322 | | - |
323 | | - $this->pageConfig = FlaggedPageConfig::getDefaultVisibilitySettings(); // default |
324 | | - $this->stableRev = false; // false => "found nothing" |
325 | | - $this->revsArePending = false; |
326 | | - $this->pendingRevCount = null; // defer this one |
327 | | - |
328 | | - if ( !FlaggedRevs::inReviewNamespace( $this->getTitle() ) ) { |
329 | | - return; // short-circuit |
330 | | - } |
331 | | - # User master/slave as appropriate... |
332 | | - $db = ( $flags & FR_MASTER ) ? |
333 | | - wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE ); |
334 | | - $row = $db->selectRow( |
335 | | - array( 'page', 'flaggedpages', 'flaggedrevs', 'flaggedpage_config' ), |
336 | | - array_merge( FlaggedRevision::selectFields(), |
| 334 | + protected function pageData( $dbr, $conditions ) { |
| 335 | + $row = $dbr->selectRow( |
| 336 | + array( 'page', 'flaggedpages', 'flaggedpage_config' ), |
| 337 | + array_merge( |
| 338 | + Article::selectFields(), |
337 | 339 | FlaggedPageConfig::selectFields(), |
338 | | - array( 'fp_pending_since', 'fp_reviewed' ) ), |
339 | | - array( 'page_id' => $this->getID() ), |
| 340 | + array( 'fp_pending_since', 'fp_stable', 'fp_reviewed' ) ), |
| 341 | + $conditions, |
340 | 342 | __METHOD__, |
341 | 343 | array(), |
342 | 344 | array( |
343 | | - 'flaggedpages' => array( 'LEFT JOIN', 'fp_page_id = page_id' ), |
344 | | - 'flaggedrevs' => array( 'LEFT JOIN', |
345 | | - 'fr_page_id = fp_page_id AND fr_rev_id = fp_stable' ), |
| 345 | + 'flaggedpages' => array( 'LEFT JOIN', 'fp_page_id = page_id' ), |
346 | 346 | 'flaggedpage_config' => array( 'LEFT JOIN', 'fpc_page_id = page_id' ) ) |
347 | 347 | ); |
348 | | - if ( !$row ) { |
349 | | - return; // no page found at all |
| 348 | + return $row; |
| 349 | + } |
| 350 | + |
| 351 | + /** |
| 352 | + * Set the page field data loaded from some source |
| 353 | + * @param $data Database row object or "fromdb" |
| 354 | + * @return void |
| 355 | + */ |
| 356 | + public function loadPageData( $data = 'fromdb' ) { |
| 357 | + $this->mDataLoaded = true; // sanity |
| 358 | + # Fetch data from DB as needed... |
| 359 | + if ( $data === 'fromdb' ) { |
| 360 | + $data = $this->pageDataFromTitle( wfGetDB( DB_SLAVE ), $this->mTitle ); |
350 | 361 | } |
351 | | - if ( $row->fpc_override !== null ) { // page config row found |
352 | | - $this->pageConfig = FlaggedPageConfig::getVisibilitySettingsFromRow( $row ); |
| 362 | + # Load in primary page data... |
| 363 | + parent::loadPageData( $data /* Row obj */ ); |
| 364 | + # Load in FlaggedRevs page data... |
| 365 | + $this->stable = 0; // 0 => "found nothing" |
| 366 | + $this->stableRev = null; // defer this one... |
| 367 | + $this->revsArePending = false; // false => "found nothing" or "none pending" |
| 368 | + $this->pendingRevCount = null; // defer this one... |
| 369 | + $this->pageConfig = FlaggedPageConfig::getDefaultVisibilitySettings(); // default |
| 370 | + $this->syncedInTracking = true; // false => "unreviewed" or "synced" |
| 371 | + # Load in Row data if the page exists... |
| 372 | + if ( $data ) { |
| 373 | + if ( $data->fpc_override !== null ) { // page config row found |
| 374 | + $this->pageConfig = FlaggedPageConfig::getVisibilitySettingsFromRow( $data ); |
| 375 | + } |
| 376 | + if ( $data->fp_stable !== null ) { // stable rev found |
| 377 | + $this->stable = (int)$data->fp_stable; |
| 378 | + $this->revsArePending = ( $data->fp_pending_since !== null ); // revs await review |
| 379 | + $this->syncedInTracking = (bool)$data->fp_reviewed; |
| 380 | + } |
353 | 381 | } |
354 | | - if ( $row->fr_rev_id !== null ) { // stable rev row found |
355 | | - // Page may not reviewable, which implies no stable version |
356 | | - if ( !FlaggedRevs::useOnlyIfProtected() || $this->pageConfig['override'] ) { |
357 | | - $this->stableRev = new FlaggedRevision( $row ); |
| 382 | + } |
| 383 | + |
| 384 | + /** |
| 385 | + * Set the page field data loaded from the DB |
| 386 | + * @param int $flags FR_MASTER |
| 387 | + * @param $data Database row object or "fromdb" |
| 388 | + */ |
| 389 | + public function loadFromDB( $flags = 0 ) { |
| 390 | + $db = ( $flags & FR_MASTER ) ? |
| 391 | + wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE ); |
| 392 | + $this->loadPageData( $this->pageDataFromTitle( $db, $this->mTitle ) ); |
| 393 | + } |
| 394 | + |
| 395 | + /** |
| 396 | + * Updates the flagging tracking tables for this page |
| 397 | + * @param FlaggedRevision $srev The new stable version |
| 398 | + * @param mixed $latest The latest rev ID (optional) |
| 399 | + * @return bool Updates were done |
| 400 | + */ |
| 401 | + public function updateStableVersion( FlaggedRevision $srev, $latest = null ) { |
| 402 | + $rev = $srev->getRevision(); |
| 403 | + if ( !$this->exists() || !$rev ) { |
| 404 | + return false; // no bogus entries |
| 405 | + } |
| 406 | + # Get the latest revision ID if not set |
| 407 | + if ( !$latest ) { |
| 408 | + $latest = $this->mTitle->getLatestRevID( Title::GAID_FOR_UPDATE ); |
| 409 | + } |
| 410 | + $dbw = wfGetDB( DB_MASTER ); |
| 411 | + # Get the highest quality revision (not necessarily this one)... |
| 412 | + if ( $srev->getQuality() === FlaggedRevs::highestReviewTier() ) { |
| 413 | + $maxQuality = $srev->getQuality(); // save a query |
| 414 | + } else { |
| 415 | + $maxQuality = $dbw->selectField( array( 'flaggedrevs', 'revision' ), |
| 416 | + 'fr_quality', |
| 417 | + array( 'fr_page_id' => $this->getId(), |
| 418 | + 'rev_id = fr_rev_id', |
| 419 | + 'rev_page = fr_page_id', |
| 420 | + 'rev_deleted & ' . Revision::DELETED_TEXT => 0 |
| 421 | + ), |
| 422 | + __METHOD__, |
| 423 | + array( 'ORDER BY' => 'fr_quality DESC', 'LIMIT' => 1 ) |
| 424 | + ); |
| 425 | + $maxQuality = max( $maxQuality, $srev->getQuality() ); // sanity |
| 426 | + } |
| 427 | + # Get the timestamp of the first edit after the stable version (if any)... |
| 428 | + $nextTimestamp = null; |
| 429 | + if ( $rev->getId() != $latest ) { |
| 430 | + $timestamp = $dbw->timestamp( $rev->getTimestamp() ); |
| 431 | + $nextEditTS = $dbw->selectField( 'revision', |
| 432 | + 'rev_timestamp', |
| 433 | + array( |
| 434 | + 'rev_page' => $this->getId(), |
| 435 | + "rev_timestamp > " . $dbw->addQuotes( $timestamp ) ), |
| 436 | + __METHOD__, |
| 437 | + array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 ) |
| 438 | + ); |
| 439 | + if ( $nextEditTS ) { // sanity check |
| 440 | + $nextTimestamp = $nextEditTS; |
358 | 441 | } |
359 | 442 | } |
360 | | - $this->revsArePending = ( $row->fp_pending_since !== null ); // revs await review |
361 | | - $this->syncedInTracking = (bool)$row->fp_reviewed; |
| 443 | + # Get the new page sync status... |
| 444 | + $synced = !( |
| 445 | + $nextTimestamp !== null || // edits pending |
| 446 | + $srev->findPendingTemplateChanges() || // template changes pending |
| 447 | + $srev->findPendingFileChanges( 'noForeign' ) // file changes pending |
| 448 | + ); |
| 449 | + # Alter table metadata |
| 450 | + $dbw->replace( 'flaggedpages', |
| 451 | + array( 'fp_page_id' ), |
| 452 | + array( |
| 453 | + 'fp_page_id' => $this->getId(), |
| 454 | + 'fp_stable' => $rev->getId(), |
| 455 | + 'fp_reviewed' => $synced ? 1 : 0, |
| 456 | + 'fp_quality' => ( $maxQuality === false ) ? null : $maxQuality, |
| 457 | + 'fp_pending_since' => $dbw->timestampOrNull( $nextTimestamp ) |
| 458 | + ), |
| 459 | + __METHOD__ |
| 460 | + ); |
| 461 | + # Update pending edit tracking table |
| 462 | + self::updatePendingList( $this->getId(), $latest ); |
| 463 | + return true; |
362 | 464 | } |
363 | 465 | |
364 | | - /* |
365 | | - * Get the fp_reviewed value for this page |
366 | | - * @param int $flags FR_MASTER |
367 | | - * @return bool |
| 466 | + /** |
| 467 | + * Updates the flagging tracking tables for this page |
| 468 | + * @return void |
368 | 469 | */ |
369 | | - public function syncedInTracking( $flags = 0 ) { |
370 | | - $this->loadFlaggedRevsData( $flags ); |
371 | | - return $this->syncedInTracking; |
| 470 | + public function clearStableVersion() { |
| 471 | + if ( !$this->exists() ) { |
| 472 | + return; // nothing to do |
| 473 | + } |
| 474 | + $dbw = wfGetDB( DB_MASTER ); |
| 475 | + $dbw->delete( 'flaggedpages', |
| 476 | + array( 'fp_page_id' => $this->getId() ), __METHOD__ ); |
| 477 | + $dbw->delete( 'flaggedpage_pending', |
| 478 | + array( 'fpp_page_id' => $this->getId() ), __METHOD__ ); |
372 | 479 | } |
| 480 | + |
| 481 | + /** |
| 482 | + * Updates the flaggedpage_pending table |
| 483 | + * @param int $pageId Page ID |
| 484 | + * @abstract int $latest Latest revision |
| 485 | + * @return void |
| 486 | + */ |
| 487 | + protected static function updatePendingList( $pageId, $latest ) { |
| 488 | + $data = array(); |
| 489 | + $level = FlaggedRevs::highestReviewTier(); |
| 490 | + # Update pending times for each level, going from highest to lowest |
| 491 | + $dbw = wfGetDB( DB_MASTER ); |
| 492 | + $higherLevelId = 0; |
| 493 | + $higherLevelTS = ''; |
| 494 | + while ( $level >= 0 ) { |
| 495 | + # Get the latest revision of this level... |
| 496 | + $row = $dbw->selectRow( array( 'flaggedrevs', 'revision' ), |
| 497 | + array( 'fr_rev_id', 'rev_timestamp' ), |
| 498 | + array( 'fr_page_id' => $pageId, |
| 499 | + 'fr_quality' => $level, |
| 500 | + 'rev_id = fr_rev_id', |
| 501 | + 'rev_page = fr_page_id', |
| 502 | + 'rev_deleted & ' . Revision::DELETED_TEXT => 0, |
| 503 | + 'rev_id > ' . intval( $higherLevelId ) |
| 504 | + ), |
| 505 | + __METHOD__, |
| 506 | + array( 'ORDER BY' => 'fr_rev_id DESC', 'LIMIT' => 1 ) |
| 507 | + ); |
| 508 | + # If there is a revision of this level, track it... |
| 509 | + # Revisions reviewed to one level count as reviewed |
| 510 | + # at the lower levels (i.e. quality -> checked). |
| 511 | + if ( $row ) { |
| 512 | + $id = $row->fr_rev_id; |
| 513 | + $ts = $row->rev_timestamp; |
| 514 | + } else { |
| 515 | + $id = $higherLevelId; // use previous (quality -> checked) |
| 516 | + $ts = $higherLevelTS; // use previous (quality -> checked) |
| 517 | + } |
| 518 | + # Get edits that actually are pending... |
| 519 | + if ( $id && $latest > $id ) { |
| 520 | + # Get the timestamp of the edit after this version (if any) |
| 521 | + $nextTimestamp = $dbw->selectField( 'revision', |
| 522 | + 'rev_timestamp', |
| 523 | + array( 'rev_page' => $pageId, "rev_timestamp > " . $dbw->addQuotes( $ts ) ), |
| 524 | + __METHOD__, |
| 525 | + array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 ) |
| 526 | + ); |
| 527 | + $data[] = array( |
| 528 | + 'fpp_page_id' => $pageId, |
| 529 | + 'fpp_quality' => $level, |
| 530 | + 'fpp_rev_id' => $id, |
| 531 | + 'fpp_pending_since' => $nextTimestamp |
| 532 | + ); |
| 533 | + $higherLevelId = $id; |
| 534 | + $higherLevelTS = $ts; |
| 535 | + } |
| 536 | + $level--; |
| 537 | + } |
| 538 | + # Clear any old junk, and insert new rows |
| 539 | + $dbw->delete( 'flaggedpage_pending', array( 'fpp_page_id' => $pageId ), __METHOD__ ); |
| 540 | + $dbw->insert( 'flaggedpage_pending', $data, __METHOD__ ); |
| 541 | + } |
373 | 542 | } |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.class.php |
— | — | @@ -171,6 +171,20 @@ |
172 | 172 | } |
173 | 173 | |
174 | 174 | /** |
| 175 | + * Get the highest review tier that is enabled |
| 176 | + * @returns int One of FR_PRISTINE,FR_QUALITY,FR_CHECKED |
| 177 | + */ |
| 178 | + public static function highestReviewTier() { |
| 179 | + self::load(); |
| 180 | + if ( self::$pristineVersions ) { |
| 181 | + return FR_PRISTINE; |
| 182 | + } elseif ( self::$qualityVersions ) { |
| 183 | + return FR_QUALITY; |
| 184 | + } |
| 185 | + return FR_CHECKED; |
| 186 | + } |
| 187 | + |
| 188 | + /** |
175 | 189 | * Allow auto-review edits directly to the stable version by reviewers? |
176 | 190 | * @returns bool |
177 | 191 | */ |
— | — | @@ -720,19 +734,17 @@ |
721 | 735 | if ( $sv === null ) { // optional |
722 | 736 | $sv = FlaggedRevision::determineStable( $title, FR_MASTER ); |
723 | 737 | } |
| 738 | + $article = new FlaggedArticle( $title ); |
724 | 739 | if ( !$sv ) { |
725 | 740 | # Empty flaggedrevs data for this page if there is no stable version |
726 | | - self::clearTrackingRows( $title->getArticleID() ); |
| 741 | + $article->clearStableVersion(); |
727 | 742 | # Check if pages using this need to be refreshed... |
728 | 743 | if ( FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE ) { |
729 | 744 | $changed = (bool)$oldSv; |
730 | 745 | } |
731 | 746 | } else { |
732 | | - $article = new Article( $title ); |
733 | 747 | # Update flagged page related fields |
734 | | - FlaggedRevs::updateStableVersion( $article, $sv ); |
735 | | - # Lazily rebuild dependancies on next parse (we invalidate below) |
736 | | - FlaggedRevs::clearStableOnlyDeps( $title ); |
| 748 | + $article->updateStableVersion( $sv ); |
737 | 749 | # Check if pages using this need to be invalidated/purged... |
738 | 750 | if ( FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE ) { |
739 | 751 | $changed = ( |
— | — | @@ -743,6 +755,8 @@ |
744 | 756 | ); |
745 | 757 | } |
746 | 758 | } |
| 759 | + # Lazily rebuild dependancies on next parse (we invalidate below) |
| 760 | + FlaggedRevs::clearStableOnlyDeps( $title ); |
747 | 761 | # Clear page cache |
748 | 762 | $title->invalidateCache(); |
749 | 763 | self::purgeSquid( $title ); |
— | — | @@ -759,143 +773,6 @@ |
760 | 774 | } |
761 | 775 | |
762 | 776 | /** |
763 | | - * @param Article $article |
764 | | - * @param FlaggedRevision $srev, the new stable version |
765 | | - * @param mixed $latest, the latest rev ID (optional) |
766 | | - * Updates the tracking tables and pending edit count cache. Called on edit. |
767 | | - */ |
768 | | - public static function updateStableVersion( |
769 | | - Article $article, FlaggedRevision $srev, $latest = null |
770 | | - ) { |
771 | | - $rev = $srev->getRevision(); |
772 | | - if ( !$rev || !$article->getId() ) { |
773 | | - return true; // no bogus entries |
774 | | - } |
775 | | - # Get the latest revision ID if not set |
776 | | - if ( !$latest ) { |
777 | | - $latest = $article->getTitle()->getLatestRevID( Title::GAID_FOR_UPDATE ); |
778 | | - } |
779 | | - # Get the highest quality revision (not necessarily this one) |
780 | | - $dbw = wfGetDB( DB_MASTER ); |
781 | | - $maxQuality = $dbw->selectField( array( 'flaggedrevs', 'revision' ), |
782 | | - 'fr_quality', |
783 | | - array( 'fr_page_id' => $article->getId(), |
784 | | - 'rev_id = fr_rev_id', |
785 | | - 'rev_page = fr_page_id', |
786 | | - 'rev_deleted & ' . Revision::DELETED_TEXT => 0 |
787 | | - ), |
788 | | - __METHOD__, |
789 | | - array( 'ORDER BY' => 'fr_quality DESC', 'LIMIT' => 1 ) |
790 | | - ); |
791 | | - # Get the timestamp of the first edit after the stable version (if any)... |
792 | | - $nextTimestamp = null; |
793 | | - if ( $rev->getId() != $latest ) { |
794 | | - $timestamp = $dbw->timestamp( $rev->getTimestamp() ); |
795 | | - $nextEditTS = $dbw->selectField( 'revision', |
796 | | - 'rev_timestamp', |
797 | | - array( |
798 | | - 'rev_page' => $article->getId(), |
799 | | - "rev_timestamp > " . $dbw->addQuotes( $timestamp ) ), |
800 | | - __METHOD__, |
801 | | - array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 ) |
802 | | - ); |
803 | | - if ( $nextEditTS ) { // sanity check |
804 | | - $nextTimestamp = $nextEditTS; |
805 | | - } |
806 | | - } |
807 | | - # Get the new page sync status... |
808 | | - $synced = !( |
809 | | - $nextTimestamp !== null || // edits pending |
810 | | - $srev->findPendingTemplateChanges() || // template changes pending |
811 | | - $srev->findPendingFileChanges( 'noForeign' ) // file changes pending |
812 | | - ); |
813 | | - # Alter table metadata |
814 | | - $dbw->replace( 'flaggedpages', |
815 | | - array( 'fp_page_id' ), |
816 | | - array( |
817 | | - 'fp_page_id' => $article->getId(), |
818 | | - 'fp_stable' => $rev->getId(), |
819 | | - 'fp_reviewed' => $synced ? 1 : 0, |
820 | | - 'fp_quality' => ( $maxQuality === false ) ? null : $maxQuality, |
821 | | - 'fp_pending_since' => $dbw->timestampOrNull( $nextTimestamp ) |
822 | | - ), |
823 | | - __METHOD__ |
824 | | - ); |
825 | | - # Update pending edit tracking table |
826 | | - self::updatePendingList( $article, $latest ); |
827 | | - return true; |
828 | | - } |
829 | | - |
830 | | - /** |
831 | | - * @param Article $article |
832 | | - * @param mixed $latest, the latest rev ID (optional) |
833 | | - * Updates the flaggedpage_pending table |
834 | | - */ |
835 | | - public static function updatePendingList( Article $article, $latest = null ) { |
836 | | - $data = array(); |
837 | | - $level = self::pristineVersions() ? FR_PRISTINE : FR_QUALITY; |
838 | | - if ( !self::qualityVersions() ) { |
839 | | - $level = FR_CHECKED; |
840 | | - } |
841 | | - # Get the latest revision ID if not set |
842 | | - if ( !$latest ) { |
843 | | - $latest = $article->getTitle()->getLatestRevID( Title::GAID_FOR_UPDATE ); |
844 | | - } |
845 | | - $pageId = $article->getId(); |
846 | | - # Update pending times for each level, going from highest to lowest |
847 | | - $dbw = wfGetDB( DB_MASTER ); |
848 | | - $higherLevelId = 0; |
849 | | - $higherLevelTS = ''; |
850 | | - while ( $level >= 0 ) { |
851 | | - # Get the latest revision of this level... |
852 | | - $row = $dbw->selectRow( array( 'flaggedrevs', 'revision' ), |
853 | | - array( 'fr_rev_id', 'rev_timestamp' ), |
854 | | - array( 'fr_page_id' => $pageId, |
855 | | - 'fr_quality' => $level, |
856 | | - 'rev_id = fr_rev_id', |
857 | | - 'rev_page = fr_page_id', |
858 | | - 'rev_deleted & ' . Revision::DELETED_TEXT => 0, |
859 | | - 'rev_id > ' . intval( $higherLevelId ) |
860 | | - ), |
861 | | - __METHOD__, |
862 | | - array( 'ORDER BY' => 'fr_rev_id DESC', 'LIMIT' => 1 ) |
863 | | - ); |
864 | | - # If there is a revision of this level, track it... |
865 | | - # Revisions reviewed to one level count as reviewed |
866 | | - # at the lower levels (i.e. quality -> checked). |
867 | | - if ( $row ) { |
868 | | - $id = $row->fr_rev_id; |
869 | | - $ts = $row->rev_timestamp; |
870 | | - } else { |
871 | | - $id = $higherLevelId; // use previous (quality -> checked) |
872 | | - $ts = $higherLevelTS; // use previous (quality -> checked) |
873 | | - } |
874 | | - # Get edits that actually are pending... |
875 | | - if ( $id && $latest > $id ) { |
876 | | - # Get the timestamp of the edit after this version (if any) |
877 | | - $nextTimestamp = $dbw->selectField( 'revision', |
878 | | - 'rev_timestamp', |
879 | | - array( 'rev_page' => $pageId, "rev_timestamp > " . $dbw->addQuotes( $ts ) ), |
880 | | - __METHOD__, |
881 | | - array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 ) |
882 | | - ); |
883 | | - $data[] = array( |
884 | | - 'fpp_page_id' => $pageId, |
885 | | - 'fpp_quality' => $level, |
886 | | - 'fpp_rev_id' => $id, |
887 | | - 'fpp_pending_since' => $nextTimestamp |
888 | | - ); |
889 | | - $higherLevelId = $id; |
890 | | - $higherLevelTS = $ts; |
891 | | - } |
892 | | - $level--; |
893 | | - } |
894 | | - # Clear any old junk, and insert new rows |
895 | | - $dbw->delete( 'flaggedpage_pending', array( 'fpp_page_id' => $pageId ), __METHOD__ ); |
896 | | - $dbw->insert( 'flaggedpage_pending', $data, __METHOD__ ); |
897 | | - } |
898 | | - |
899 | | - /** |
900 | 777 | * Do cache updates for when the stable version of a page changed. |
901 | 778 | * Invalidates/purges pages that include the given page. |
902 | 779 | * @param Title $title |
Index: trunk/extensions/FlaggedRevs/business/PageStabilityForm.php |
— | — | @@ -224,26 +224,36 @@ |
225 | 225 | $changed = FlaggedPageConfig::setStabilitySettings( $this->page, $this->getNewConfig() ); |
226 | 226 | # Log if this actually changed anything... |
227 | 227 | if ( $changed ) { |
| 228 | + $article = new FlaggedArticle( $this->page ); |
| 229 | + if ( FlaggedRevs::useOnlyIfProtected() ) { |
| 230 | + # Config may have changed to allow stable versions, so refresh |
| 231 | + # the tracking table to account for any hidden reviewed versions... |
| 232 | + $frev = FlaggedRevision::determineStable( $this->page, FR_MASTER ); |
| 233 | + if ( $frev ) { |
| 234 | + $article->updateStableVersion( $frev ); |
| 235 | + } else { |
| 236 | + $article->clearStableVersion(); |
| 237 | + } |
| 238 | + } |
228 | 239 | # Update logs and make a null edit |
229 | | - $nullRev = $this->updateLogsAndHistory(); |
230 | | - if ( $this->reviewThis ) { |
231 | | - # Null edit may have been auto-reviewed already |
232 | | - $frev = FlaggedRevision::newFromTitle( |
233 | | - $this->page, $nullRev->getId(), FR_MASTER ); |
234 | | - # Check if this null edit is to be reviewed... |
235 | | - if ( !$frev ) { |
236 | | - $flags = null; |
237 | | - $article = new Article( $this->page ); |
238 | | - # Review this revision of the page... |
239 | | - $ok = FlaggedRevs::autoReviewEdit( |
240 | | - $article, $this->user, $nullRev, $flags, true ); |
241 | | - if ( $ok ) { |
242 | | - FlaggedRevs::markRevisionPatrolled( $nullRev ); // reviewed -> patrolled |
243 | | - } |
| 240 | + $nullRev = $this->updateLogsAndHistory( $article ); |
| 241 | + # Null edit may have been auto-reviewed already |
| 242 | + $frev = FlaggedRevision::newFromTitle( $this->page, $nullRev->getId(), FR_MASTER ); |
| 243 | + $updatesDone = (bool)$frev; // stableVersionUpdates() already called? |
| 244 | + # Check if this null edit is to be reviewed... |
| 245 | + if ( $this->reviewThis && !$frev ) { |
| 246 | + $flags = null; |
| 247 | + # Review this revision of the page... |
| 248 | + $ok = FlaggedRevs::autoReviewEdit( $article, $this->user, $nullRev, $flags, true ); |
| 249 | + if ( $ok ) { |
| 250 | + FlaggedRevs::markRevisionPatrolled( $nullRev ); // reviewed -> patrolled |
| 251 | + $updatesDone = true; // stableVersionUpdates() already called |
244 | 252 | } |
245 | 253 | } |
246 | | - # Update page and tracking tables and clear cache |
247 | | - FlaggedRevs::stableVersionUpdates( $this->page ); |
| 254 | + # Update page and tracking tables and clear cache. |
| 255 | + if ( !$updatesDone ) { |
| 256 | + FlaggedRevs::stableVersionUpdates( $this->page ); |
| 257 | + } |
248 | 258 | } |
249 | 259 | # Apply watchlist checkbox value (may be NULL) |
250 | 260 | $this->updateWatchlist(); |
— | — | @@ -258,24 +268,12 @@ |
259 | 269 | * (b) Add a null edit like the log entry |
260 | 270 | * @return Revision |
261 | 271 | */ |
262 | | - protected function updateLogsAndHistory() { |
| 272 | + protected function updateLogsAndHistory( FlaggedArticle $article ) { |
263 | 273 | global $wgContLang; |
264 | | - $article = new Article( $this->page ); |
265 | 274 | $newConfig = $this->getNewConfig(); |
266 | 275 | $oldConfig = $this->getOldConfig(); |
267 | 276 | $reason = $this->getReason(); |
268 | 277 | |
269 | | - if ( FlaggedRevs::useOnlyIfProtected() ) { |
270 | | - # Config may have changed to allow stable versions, so refresh |
271 | | - # the tracking table to account for any hidden reviewed versions... |
272 | | - $frev = FlaggedRevision::determineStable( $this->page, FR_MASTER ); |
273 | | - if ( $frev ) { |
274 | | - FlaggedRevs::updateStableVersion( $article, $frev ); |
275 | | - } else { |
276 | | - FlaggedRevs::clearTrackingRows( $article->getId() ); |
277 | | - } |
278 | | - } |
279 | | - |
280 | 278 | # Insert stability log entry... |
281 | 279 | FlaggedRevsLog::updateStabilityLog( $this->page, $newConfig, $oldConfig, $reason ); |
282 | 280 | |
Index: trunk/extensions/FlaggedRevs/FlaggedRevision.php |
— | — | @@ -26,7 +26,7 @@ |
27 | 27 | private $mStableFiles; |
28 | 28 | |
29 | 29 | /** |
30 | | - * @param mixed $row (DB row or array) |
| 30 | + * @param Row|array $row (DB row or array) |
31 | 31 | * @return void |
32 | 32 | */ |
33 | 33 | public function __construct( $row ) { |
— | — | @@ -38,6 +38,8 @@ |
39 | 39 | $this->mTags = self::expandRevisionTags( strval( $row->fr_tags ) ); |
40 | 40 | $this->mFlags = explode( ',', $row->fr_flags ); |
41 | 41 | $this->mUser = intval( $row->fr_user ); |
| 42 | + # Base Revision object |
| 43 | + $this->mRevision = new Revision( $row ); |
42 | 44 | # Image page revision relevant params |
43 | 45 | $this->mFileName = $row->fr_img_name ? $row->fr_img_name : null; |
44 | 46 | $this->mFileSha1 = $row->fr_img_sha1 ? $row->fr_img_sha1 : null; |
— | — | @@ -76,7 +78,7 @@ |
77 | 79 | * @param Title $title |
78 | 80 | * @param int $revId |
79 | 81 | * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
80 | | - * @return mixed FlaggedRevision (null on failure) |
| 82 | + * @return FlaggedRevision|null (null on failure) |
81 | 83 | */ |
82 | 84 | public static function newFromTitle( Title $title, $revId, $flags = 0 ) { |
83 | 85 | if ( !FlaggedRevs::inReviewNamespace( $title ) ) { |
— | — | @@ -92,13 +94,15 @@ |
93 | 95 | $db = wfGetDB( DB_SLAVE ); |
94 | 96 | $pageId = $title->getArticleID(); |
95 | 97 | } |
96 | | - if ( !$pageId ) { |
| 98 | + if ( !$pageId || !$revId ) { |
97 | 99 | return null; // short-circuit query |
98 | 100 | } |
99 | 101 | # Skip deleted revisions |
100 | | - $row = $db->selectRow( array( 'flaggedrevs', 'revision' ), |
| 102 | + $row = $db->selectRow( |
| 103 | + array( 'flaggedrevs', 'revision' ), |
101 | 104 | self::selectFields(), |
102 | | - array( 'fr_page_id' => $pageId, |
| 105 | + array( |
| 106 | + 'fr_page_id' => $pageId, |
103 | 107 | 'fr_rev_id' => $revId, |
104 | 108 | 'rev_id = fr_rev_id', |
105 | 109 | 'rev_page = fr_page_id', |
— | — | @@ -120,7 +124,7 @@ |
121 | 125 | * Get a FlaggedRevision of the stable version of a title. |
122 | 126 | * @param Title $title, page title |
123 | 127 | * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
124 | | - * @return mixed FlaggedRevision (null on failure) |
| 128 | + * @return FlaggedRevision|null (null on failure) |
125 | 129 | */ |
126 | 130 | public static function newFromStable( Title $title, $flags = 0 ) { |
127 | 131 | if ( !FlaggedRevs::inReviewNamespace( $title ) ) { |
— | — | @@ -141,21 +145,23 @@ |
142 | 146 | } |
143 | 147 | # Check tracking tables |
144 | 148 | $row = $db->selectRow( |
145 | | - array( 'flaggedpages', 'flaggedrevs' ), |
| 149 | + array( 'flaggedpages', 'flaggedrevs', 'revision' ), |
146 | 150 | self::selectFields(), |
147 | | - array( 'fp_page_id' => $pageId, |
| 151 | + array( |
| 152 | + 'fp_page_id' => $pageId, |
148 | 153 | 'fr_page_id = fp_page_id', |
149 | | - 'fr_rev_id = fp_stable' |
| 154 | + 'fr_rev_id = fp_stable', |
| 155 | + 'rev_id = fr_rev_id' |
150 | 156 | ), |
151 | 157 | __METHOD__, |
152 | 158 | $options |
153 | 159 | ); |
154 | | - if ( !$row ) { |
155 | | - return null; |
| 160 | + if ( $row ) { |
| 161 | + $frev = new self( $row ); |
| 162 | + $frev->mTitle = $title; |
| 163 | + return $frev; |
156 | 164 | } |
157 | | - $frev = new self( $row ); |
158 | | - $frev->mTitle = $title; |
159 | | - return $frev; |
| 165 | + return null; |
160 | 166 | } |
161 | 167 | |
162 | 168 | /** |
— | — | @@ -165,7 +171,7 @@ |
166 | 172 | * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
167 | 173 | * @param array $config, optional page config (use to skip queries) |
168 | 174 | * @param string $precedence (latest,quality,pristine) |
169 | | - * @return mixed FlaggedRevision (null on failure) |
| 175 | + * @return FlaggedRevision|null (null on failure) |
170 | 176 | */ |
171 | 177 | public static function determineStable( |
172 | 178 | Title $title, $flags = 0, $config = array(), $precedence = 'latest' |
— | — | @@ -194,13 +200,12 @@ |
195 | 201 | return null; // page is not reviewable; no stable version |
196 | 202 | } |
197 | 203 | $row = null; |
198 | | - $columns = self::selectFields(); |
199 | 204 | $options['ORDER BY'] = 'fr_rev_id DESC'; |
200 | 205 | # Look for the latest pristine revision... |
201 | 206 | if ( FlaggedRevs::pristineVersions() && $precedence !== 'latest' ) { |
202 | 207 | $prow = $db->selectRow( |
203 | 208 | array( 'flaggedrevs', 'revision' ), |
204 | | - $columns, |
| 209 | + self::selectFields(), |
205 | 210 | array( 'fr_page_id' => $pageId, |
206 | 211 | 'fr_quality = ' . FR_PRISTINE, |
207 | 212 | 'rev_id = fr_rev_id', |
— | — | @@ -221,7 +226,7 @@ |
222 | 227 | $newerClause = $row ? "fr_rev_id > {$row->fr_rev_id}" : "1 = 1"; |
223 | 228 | $qrow = $db->selectRow( |
224 | 229 | array( 'flaggedrevs', 'revision' ), |
225 | | - $columns, |
| 230 | + self::selectFields(), |
226 | 231 | array( 'fr_page_id' => $pageId, |
227 | 232 | 'fr_quality = ' . FR_QUALITY, |
228 | 233 | $newerClause, |
— | — | @@ -238,7 +243,7 @@ |
239 | 244 | if ( !$row ) { |
240 | 245 | $row = $db->selectRow( |
241 | 246 | array( 'flaggedrevs', 'revision' ), |
242 | | - $columns, |
| 247 | + self::selectFields(), |
243 | 248 | array( 'fr_page_id' => $pageId, |
244 | 249 | 'rev_id = fr_rev_id', |
245 | 250 | 'rev_page = fr_page_id', |
— | — | @@ -321,12 +326,14 @@ |
322 | 327 | } |
323 | 328 | |
324 | 329 | /** |
325 | | - * @return Array basic select fields for FlaggedRevision DB row |
| 330 | + * Get select fields for FlaggedRevision DB row (flaggedrevs/revision tables) |
| 331 | + * @return Array |
326 | 332 | */ |
327 | 333 | public static function selectFields() { |
328 | | - return array( |
329 | | - 'fr_rev_id', 'fr_page_id', 'fr_user', 'fr_timestamp', 'fr_quality', |
330 | | - 'fr_tags', 'fr_flags', 'fr_img_name', 'fr_img_sha1', 'fr_img_timestamp', |
| 334 | + return array_merge( |
| 335 | + Revision::selectFields(), |
| 336 | + array( 'fr_rev_id', 'fr_page_id', 'fr_user', 'fr_timestamp', 'fr_quality', |
| 337 | + 'fr_tags', 'fr_flags', 'fr_img_name', 'fr_img_sha1', 'fr_img_timestamp' ) |
331 | 338 | ); |
332 | 339 | } |
333 | 340 | |
— | — | @@ -730,7 +737,7 @@ |
731 | 738 | |
732 | 739 | /** |
733 | 740 | * Get text of the corresponding revision |
734 | | - * @return mixed (string/false) revision timestamp in MW format |
| 741 | + * @return string|false revision timestamp in MW format |
735 | 742 | */ |
736 | 743 | public function getRevText() { |
737 | 744 | # Get corresponding revision |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.hooks.php |
— | — | @@ -204,8 +204,9 @@ |
205 | 205 | Title $otitle, Title $ntitle, $user, $pageId |
206 | 206 | ) { |
207 | 207 | $fa = FlaggedArticle::getTitleInstance( $ntitle ); |
| 208 | + $fa->loadFromDB( FR_MASTER ); |
208 | 209 | // Re-validate NS/config (new title may not be reviewable) |
209 | | - if ( $fa->isReviewable( FR_MASTER ) ) { |
| 210 | + if ( $fa->isReviewable() ) { |
210 | 211 | // Moved from non-reviewable to reviewable NS? |
211 | 212 | // Auto-review such edits like new pages... |
212 | 213 | if ( !FlaggedRevs::inReviewNamespace( $otitle ) |
— | — | @@ -485,7 +486,8 @@ |
486 | 487 | global $wgRequest; |
487 | 488 | # Edit must be non-null, to a reviewable page, with $user set |
488 | 489 | $fa = FlaggedArticle::getArticleInstance( $article ); |
489 | | - if ( !$rev || !$user || !$fa->isReviewable( FR_MASTER ) ) { |
| 490 | + $fa->loadFromDB( FR_MASTER ); |
| 491 | + if ( !$rev || !$user || !$fa->isReviewable() ) { |
490 | 492 | return true; |
491 | 493 | } |
492 | 494 | $title = $article->getTitle(); // convenience |
— | — | @@ -556,7 +558,7 @@ |
557 | 559 | # (a) this is a rollback to the stable version |
558 | 560 | # (b) this is a self-reversion to the stable version |
559 | 561 | # These are subcases of making a new revision based on an old, reviewed, revision. |
560 | | - } elseif ( FlaggedRevs::autoReviewEdits() && $fa->getStableRev( FR_MASTER ) ) { |
| 562 | + } elseif ( FlaggedRevs::autoReviewEdits() && $fa->getStableRev() ) { |
561 | 563 | $srev = $fa->getStableRev(); |
562 | 564 | # Check for rollbacks... |
563 | 565 | $reviewableChange = ( |
— | — | @@ -660,7 +662,8 @@ |
661 | 663 | return true; |
662 | 664 | } |
663 | 665 | $fa = FlaggedArticle::getArticleInstance( $article ); |
664 | | - if ( !$fa->isReviewable( FR_MASTER ) ) { |
| 666 | + $fa->loadFromDB( FR_MASTER ); |
| 667 | + if ( !$fa->isReviewable() ) { |
665 | 668 | return true; // page is not reviewable |
666 | 669 | } |
667 | 670 | $title = $article->getTitle(); // convenience |
— | — | @@ -724,8 +727,9 @@ |
725 | 728 | return true; |
726 | 729 | } |
727 | 730 | $fa = FlaggedArticle::getTitleInstance( $rc->getTitle() ); |
| 731 | + $fa->loadFromDB( FR_MASTER ); |
728 | 732 | // Is the page reviewable? |
729 | | - if ( $fa->isReviewable( FR_MASTER ) ) { |
| 733 | + if ( $fa->isReviewable() ) { |
730 | 734 | $revId = $rc->mAttribs['rc_this_oldid']; |
731 | 735 | $quality = FlaggedRevs::getRevQuality( |
732 | 736 | $rc->mAttribs['rc_cur_id'], $revId, FR_MASTER ); |
Index: trunk/extensions/FlaggedRevs/presentation/FlaggedArticleView.php |
— | — | @@ -1597,8 +1597,9 @@ |
1598 | 1598 | public function injectPostEditURLParams( &$sectionAnchor, &$extraQuery ) { |
1599 | 1599 | global $wgUser; |
1600 | 1600 | $this->load(); |
| 1601 | + $this->article->loadFromDB( FR_MASTER ); |
1601 | 1602 | # Get the stable version from the master |
1602 | | - $frev = $this->article->getStableRev( FR_MASTER ); |
| 1603 | + $frev = $this->article->getStableRev(); |
1603 | 1604 | if ( !$frev || !$this->article->revsArePending() ) { |
1604 | 1605 | return true; // only for pages with pending edits |
1605 | 1606 | } |