Index: trunk/extensions/FlaggedRevs/FlaggedArticle.php |
— | — | @@ -279,6 +279,16 @@ |
280 | 280 | } |
281 | 281 | |
282 | 282 | /** |
| 283 | + * Get the stable revision ID |
| 284 | + * @param int $flags |
| 285 | + * @return int |
| 286 | + */ |
| 287 | + public function getStable( $flags = 0 ) { |
| 288 | + $srev = $this->getStableRev( $flags ); |
| 289 | + return $srev ? $srev->getRevId() : 0; |
| 290 | + } |
| 291 | + |
| 292 | + /** |
283 | 293 | * Get the stable revision |
284 | 294 | * @param int $flags |
285 | 295 | * @return mixed (FlaggedRevision/null) |
— | — | @@ -286,29 +296,15 @@ |
287 | 297 | public function getStableRev( $flags = 0 ) { |
288 | 298 | # Cached results available? |
289 | 299 | if ( $this->stableRev === null || ( $flags & FR_MASTER ) ) { |
290 | | - $srev = null; |
291 | | - if ( $this->isReviewable( $flags ) ) { // short-circuit if not reviewable |
292 | | - $srev = FlaggedRevision::newFromStable( $this->getTitle(), $flags ); |
293 | | - } |
294 | | - $this->stableRev = $srev ? $srev : false; // false => "found nothing" |
| 300 | + $this->loadStableRevAndConfig(); |
295 | 301 | } |
296 | 302 | if ( $this->stableRev ) { |
297 | 303 | return $this->stableRev; |
298 | 304 | } |
299 | | - return null; |
| 305 | + return null; // false => null |
300 | 306 | } |
301 | 307 | |
302 | 308 | /** |
303 | | - * Get the stable revision ID |
304 | | - * @param int $flags |
305 | | - * @return int |
306 | | - */ |
307 | | - public function getStable( $flags = 0 ) { |
308 | | - $srev = $this->getStableRev( $flags ); |
309 | | - return $srev ? $srev->getRevId() : 0; |
310 | | - } |
311 | | - |
312 | | - /** |
313 | 309 | * Get visiblity restrictions on page |
314 | 310 | * @param int $flags, FR_MASTER |
315 | 311 | * @return array (select,override) |
— | — | @@ -317,7 +313,48 @@ |
318 | 314 | if ( !( $flags & FR_MASTER ) && $this->pageConfig !== null ) { |
319 | 315 | return $this->pageConfig; // use process cache |
320 | 316 | } |
321 | | - $this->pageConfig = FlaggedRevs::getPageStabilitySettings( $this->getTitle(), $flags ); |
| 317 | + $this->loadStableRevAndConfig(); |
322 | 318 | return $this->pageConfig; |
323 | 319 | } |
| 320 | + |
| 321 | + /** |
| 322 | + * Get a DB row of the stable version and page config of a title. |
| 323 | + * @param Title $title, page title |
| 324 | + * @param int $flags FR_MASTER |
| 325 | + */ |
| 326 | + protected function loadStableRevAndConfig( $flags = 0 ) { |
| 327 | + $this->stableRev = false; // false => "found nothing" |
| 328 | + $this->pageConfig = FlaggedRevs::getDefaultVisibilitySettings(); // default |
| 329 | + if ( !FlaggedRevs::inReviewNamespace( $this->getTitle() ) ) { |
| 330 | + return; // short-circuit |
| 331 | + } |
| 332 | + # User master/slave as appropriate... |
| 333 | + $db = ( $flags & FR_MASTER ) ? |
| 334 | + wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE ); |
| 335 | + $row = $db->selectRow( |
| 336 | + array( 'page', 'flaggedpages', 'flaggedrevs', 'flaggedpage_config' ), |
| 337 | + array_merge( FlaggedRevision::selectFields(), |
| 338 | + array( 'fpc_override', 'fpc_level', 'fpc_expiry' ) ), |
| 339 | + array( 'page_id' => $this->getID() ), |
| 340 | + __METHOD__, |
| 341 | + array(), |
| 342 | + 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' ), |
| 346 | + 'flaggedpage_config' => array( 'LEFT JOIN', 'fpc_page_id = page_id' ) ) |
| 347 | + ); |
| 348 | + if ( !$row ) { |
| 349 | + return; // no page found at all |
| 350 | + } |
| 351 | + if ( $row->fpc_override !== null ) { // page config row found |
| 352 | + $this->pageConfig = FlaggedRevs::getVisibilitySettingsFromRow( $row ); |
| 353 | + } |
| 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 ); |
| 358 | + } |
| 359 | + } |
| 360 | + } |
324 | 361 | } |
Index: trunk/extensions/FlaggedRevs/FlaggedRevs.class.php |
— | — | @@ -967,6 +967,13 @@ |
968 | 968 | array( 'fpc_page_id' => $title->getArticleID() ), |
969 | 969 | __METHOD__ |
970 | 970 | ); |
| 971 | + return self::getVisibilitySettingsFromRow( $row ); |
| 972 | + } |
| 973 | + |
| 974 | + /** |
| 975 | + * Get page configuration settings from a DB row |
| 976 | + */ |
| 977 | + public static function getVisibilitySettingsFromRow( $row ) { |
971 | 978 | if ( $row ) { |
972 | 979 | # This code should be refactored, now that it's being used more generally. |
973 | 980 | $expiry = Block::decodeExpiry( $row->fpc_expiry ); |
— | — | @@ -974,7 +981,6 @@ |
975 | 982 | if ( !$expiry || $expiry < wfTimestampNow() ) { |
976 | 983 | $row = null; // expired |
977 | 984 | self::purgeExpiredConfigurations(); |
978 | | - self::stableVersionUpdates( $title ); // re-find stable version |
979 | 985 | } |
980 | 986 | } |
981 | 987 | // Is there a non-expired row? |
— | — | @@ -1059,36 +1065,54 @@ |
1060 | 1066 | * The stable version of pages may change and invalidation may be required. |
1061 | 1067 | */ |
1062 | 1068 | public static function purgeExpiredConfigurations() { |
| 1069 | + if ( wfReadOnly() ) return; |
| 1070 | + |
1063 | 1071 | $dbw = wfGetDB( DB_MASTER ); |
1064 | | - $pageIds = array(); |
1065 | | - $pagesClearTracking = array(); |
1066 | 1072 | $config = self::getDefaultVisibilitySettings(); // config is to be reset |
1067 | 1073 | $encCutoff = $dbw->addQuotes( $dbw->timestamp() ); |
1068 | | - $ret = $dbw->select( 'flaggedpage_config', |
1069 | | - array( 'fpc_page_id' ), |
1070 | | - array( 'fpc_expiry < ' . $encCutoff ), |
| 1074 | + $ret = $dbw->select( |
| 1075 | + array( 'flaggedpage_config', 'page' ), |
| 1076 | + array( 'fpc_page_id', 'page_namespace', 'page_title' ), |
| 1077 | + array( 'page_id = fpc_page_id', 'fpc_expiry < ' . $encCutoff ), |
1071 | 1078 | __METHOD__ |
1072 | 1079 | // array( 'FOR UPDATE' ) |
1073 | 1080 | ); |
1074 | | - foreach( $ret as $row ) { |
1075 | | - // If FlaggedRevs got "turned off" for this page (due to not |
1076 | | - // having the stable version as the default), then clear it |
1077 | | - // from the tracking tables... |
1078 | | - if ( !$config['override'] && self::useOnlyIfProtected() ) { |
| 1081 | + $pagesClearConfig = array(); |
| 1082 | + $pagesClearTracking = $titlesClearTracking = array(); |
| 1083 | + foreach ( $ret as $row ) { |
| 1084 | + # If FlaggedRevs got "turned off" (in protection config) |
| 1085 | + # for this page, then clear it from the tracking tables... |
| 1086 | + if ( self::useOnlyIfProtected() && !$config['override'] ) { |
1079 | 1087 | $pagesClearTracking[] = $row->fpc_page_id; // no stable version |
| 1088 | + $titlesClearTracking[] = Title::newFromRow( $row ); // no stable version |
1080 | 1089 | } |
1081 | | - $pageIds[] = $row->fpc_page_id; // page with expired config |
| 1090 | + $pagesClearConfig[] = $row->fpc_page_id; // page with expired config |
1082 | 1091 | } |
1083 | | - // Clear the expired config for these pages |
1084 | | - if ( count( $pageIds ) ) { |
| 1092 | + # Clear the expired config for these pages... |
| 1093 | + if ( count( $pagesClearConfig ) ) { |
1085 | 1094 | $dbw->delete( 'flaggedpage_config', |
1086 | | - array( 'fpc_page_id' => $pageIds, 'fpc_expiry < ' . $encCutoff ), |
1087 | | - __METHOD__ ); |
| 1095 | + array( 'fpc_page_id' => $pagesClearConfig, 'fpc_expiry < ' . $encCutoff ), |
| 1096 | + __METHOD__ |
| 1097 | + ); |
1088 | 1098 | } |
1089 | | - // Clear the tracking rows where needed |
| 1099 | + # Clear the tracking rows and update page_touched for the |
| 1100 | + # pages in $pagesClearConfig that do now have a stable version... |
1090 | 1101 | if ( count( $pagesClearTracking ) ) { |
1091 | 1102 | self::clearTrackingRows( $pagesClearTracking ); |
| 1103 | + $dbw->update( 'page', |
| 1104 | + array( 'page_touched' => $dbw->timestamp() ), |
| 1105 | + array( 'page_id' => $pagesClearTracking ), |
| 1106 | + __METHOD__ |
| 1107 | + ); |
1092 | 1108 | } |
| 1109 | + # Also, clear their squid caches and purge other pages that use this page. |
| 1110 | + # NOTE: all of these updates are deferred via $wgDeferredUpdateList. |
| 1111 | + foreach ( $titlesClearTracking as $title ) { |
| 1112 | + self::purgeSquid( $title ); |
| 1113 | + if ( FlaggedRevs::inclusionSetting() == FR_INCLUDES_STABLE ) { |
| 1114 | + FlaggedRevs::HTMLCacheUpdates( $title ); // purge pages that use this page |
| 1115 | + } |
| 1116 | + } |
1093 | 1117 | } |
1094 | 1118 | |
1095 | 1119 | # ################ Other utility functions ################# |
Index: trunk/extensions/FlaggedRevs/FlaggedRevision.php |
— | — | @@ -80,30 +80,29 @@ |
81 | 81 | * Note: will return NULL if the revision is deleted. |
82 | 82 | * @param Title $title |
83 | 83 | * @param int $revId |
84 | | - * @param int $flags FR_MASTER |
| 84 | + * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
85 | 85 | * @return mixed FlaggedRevision (null on failure) |
86 | 86 | */ |
87 | 87 | public static function newFromTitle( Title $title, $revId, $flags = 0 ) { |
88 | 88 | if ( !FlaggedRevs::inReviewNamespace( $title ) ) { |
89 | 89 | return null; // short-circuit |
90 | 90 | } |
91 | | - $columns = self::selectFields(); |
92 | 91 | $options = array(); |
93 | | - # User master/slave as appropriate |
| 92 | + # User master/slave as appropriate... |
94 | 93 | if ( $flags & FR_FOR_UPDATE || $flags & FR_MASTER ) { |
95 | 94 | $db = wfGetDB( DB_MASTER ); |
96 | 95 | if ( $flags & FR_FOR_UPDATE ) $options[] = 'FOR UPDATE'; |
| 96 | + $pageId = $title->getArticleID( Title::GAID_FOR_UPDATE ); |
97 | 97 | } else { |
98 | 98 | $db = wfGetDB( DB_SLAVE ); |
| 99 | + $pageId = $title->getArticleID(); |
99 | 100 | } |
100 | | - $pageId = $title->getArticleID( $flags & FR_FOR_UPDATE ? Title::GAID_FOR_UPDATE : 0 ); |
101 | | - # Short-circuit query |
102 | 101 | if ( !$pageId ) { |
103 | | - return null; |
| 102 | + return null; // short-circuit query |
104 | 103 | } |
105 | 104 | # Skip deleted revisions |
106 | 105 | $row = $db->selectRow( array( 'flaggedrevs', 'revision' ), |
107 | | - $columns, |
| 106 | + self::selectFields(), |
108 | 107 | array( 'fr_page_id' => $pageId, |
109 | 108 | 'fr_rev_id' => $revId, |
110 | 109 | 'rev_id = fr_rev_id', |
— | — | @@ -125,30 +124,30 @@ |
126 | 125 | /** |
127 | 126 | * Get a FlaggedRevision of the stable version of a title. |
128 | 127 | * @param Title $title, page title |
129 | | - * @param int $flags FR_MASTER |
| 128 | + * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
130 | 129 | * @return mixed FlaggedRevision (null on failure) |
131 | 130 | */ |
132 | 131 | public static function newFromStable( Title $title, $flags = 0 ) { |
133 | 132 | if ( !FlaggedRevs::inReviewNamespace( $title ) ) { |
134 | 133 | return null; // short-circuit |
135 | 134 | } |
136 | | - $columns = self::selectFields(); |
137 | 135 | $options = array(); |
138 | | - $pageId = $title->getArticleID( $flags & FR_MASTER ? Title::GAID_FOR_UPDATE : 0 ); |
139 | | - if ( !$pageId ) { |
140 | | - return null; // short-circuit query |
141 | | - } |
142 | | - # User master/slave as appropriate |
| 136 | + # User master/slave as appropriate... |
143 | 137 | if ( $flags & FR_FOR_UPDATE || $flags & FR_MASTER ) { |
144 | 138 | $db = wfGetDB( DB_MASTER ); |
145 | 139 | if ( $flags & FR_FOR_UPDATE ) $options[] = 'FOR UPDATE'; |
| 140 | + $pageId = $title->getArticleID( Title::GAID_FOR_UPDATE ); |
146 | 141 | } else { |
147 | 142 | $db = wfGetDB( DB_SLAVE ); |
| 143 | + $pageId = $title->getArticleID(); |
148 | 144 | } |
| 145 | + if ( !$pageId ) { |
| 146 | + return null; // short-circuit query |
| 147 | + } |
149 | 148 | # Check tracking tables |
150 | 149 | $row = $db->selectRow( |
151 | 150 | array( 'flaggedpages', 'flaggedrevs' ), |
152 | | - $columns, |
| 151 | + self::selectFields(), |
153 | 152 | array( 'fp_page_id' => $pageId, |
154 | 153 | 'fr_page_id = fp_page_id', |
155 | 154 | 'fr_rev_id = fp_stable' |
— | — | @@ -168,7 +167,7 @@ |
169 | 168 | * Get a FlaggedRevision of the stable version of a title. |
170 | 169 | * Skips tracking tables to figure out new stable version. |
171 | 170 | * @param Title $title, page title |
172 | | - * @param int $flags FR_MASTER |
| 171 | + * @param int $flags (FR_MASTER, FR_FOR_UPDATE) |
173 | 172 | * @param array $config, optional page config (use to skip queries) |
174 | 173 | * @param string $precedence (latest,quality,pristine) |
175 | 174 | * @return mixed FlaggedRevision (null on failure) |
— | — | @@ -179,19 +178,19 @@ |
180 | 179 | if ( !FlaggedRevs::inReviewNamespace( $title ) ) { |
181 | 180 | return null; // short-circuit |
182 | 181 | } |
183 | | - $columns = self::selectFields(); |
184 | 182 | $options = array(); |
185 | | - $pageId = $title->getArticleID( $flags & FR_FOR_UPDATE ? Title::GAID_FOR_UPDATE : 0 ); |
186 | | - if ( !$pageId ) { |
187 | | - return null; // short-circuit query |
188 | | - } |
189 | | - # User master/slave as appropriate |
| 183 | + # User master/slave as appropriate... |
190 | 184 | if ( $flags & FR_FOR_UPDATE || $flags & FR_MASTER ) { |
191 | 185 | $db = wfGetDB( DB_MASTER ); |
192 | 186 | if ( $flags & FR_FOR_UPDATE ) $options[] = 'FOR UPDATE'; |
| 187 | + $pageId = $title->getArticleID( Title::GAID_FOR_UPDATE ); |
193 | 188 | } else { |
194 | 189 | $db = wfGetDB( DB_SLAVE ); |
| 190 | + $pageId = $title->getArticleID(); |
195 | 191 | } |
| 192 | + if ( !$pageId ) { |
| 193 | + return null; // short-circuit query |
| 194 | + } |
196 | 195 | # Get visiblity settings... |
197 | 196 | if ( empty( $config ) ) { |
198 | 197 | $config = FlaggedRevs::getPageStabilitySettings( $title, $flags ); |
— | — | @@ -200,6 +199,7 @@ |
201 | 200 | return null; // page is not reviewable; no stable version |
202 | 201 | } |
203 | 202 | $row = null; |
| 203 | + $columns = self::selectFields(); |
204 | 204 | $options['ORDER BY'] = 'fr_rev_id DESC'; |
205 | 205 | # Look for the latest pristine revision... |
206 | 206 | if ( FlaggedRevs::pristineVersions() && $precedence !== 'latest' ) { |
— | — | @@ -331,9 +331,9 @@ |
332 | 332 | } |
333 | 333 | |
334 | 334 | /** |
335 | | - * @return Array basic select fields (not including text/text flags) |
| 335 | + * @return Array basic select fields for FlaggedRevision DB row |
336 | 336 | */ |
337 | | - protected static function selectFields() { |
| 337 | + public static function selectFields() { |
338 | 338 | return array( |
339 | 339 | 'fr_rev_id', 'fr_page_id', 'fr_user', 'fr_timestamp', |
340 | 340 | 'fr_comment', 'fr_quality', 'fr_tags', 'fr_img_name', |