Index: trunk/phase3/includes/FormOptions.php |
— | — | @@ -7,11 +7,11 @@ |
8 | 8 | */ |
9 | 9 | |
10 | 10 | class FormOptions implements ArrayAccess { |
11 | | - const AUTO = -1; //! Automatically detects simple data types |
| 11 | + const AUTO = -1; // ! Automatically detects simple data types |
12 | 12 | const STRING = 0; |
13 | 13 | const INT = 1; |
14 | 14 | const BOOL = 2; |
15 | | - const INTNULL = 3; //! Useful for namespace selector |
| 15 | + const INTNULL = 3; // ! Useful for namespace selector |
16 | 16 | |
17 | 17 | protected $options = array(); |
18 | 18 | |
— | — | @@ -34,15 +34,15 @@ |
35 | 35 | |
36 | 36 | public function delete( $name ) { |
37 | 37 | $this->validateName( $name, true ); |
38 | | - unset($this->options[$name]); |
| 38 | + unset( $this->options[$name] ); |
39 | 39 | } |
40 | 40 | |
41 | 41 | public static function guessType( $data ) { |
42 | | - if ( is_bool($data) ) { |
| 42 | + if ( is_bool( $data ) ) { |
43 | 43 | return self::BOOL; |
44 | | - } elseif( is_int($data) ) { |
| 44 | + } elseif ( is_int( $data ) ) { |
45 | 45 | return self::INT; |
46 | | - } elseif( is_string($data) ) { |
| 46 | + } elseif ( is_string( $data ) ) { |
47 | 47 | return self::STRING; |
48 | 48 | } else { |
49 | 49 | throw new MWException( 'Unsupported datatype' ); |
— | — | @@ -52,7 +52,7 @@ |
53 | 53 | # Handling values |
54 | 54 | |
55 | 55 | public function validateName( $name, $strict = false ) { |
56 | | - if ( !isset($this->options[$name]) ) { |
| 56 | + if ( !isset( $this->options[$name] ) ) { |
57 | 57 | if ( $strict ) { |
58 | 58 | throw new MWException( "Invalid option $name" ); |
59 | 59 | } else { |
— | — | @@ -64,6 +64,7 @@ |
65 | 65 | |
66 | 66 | public function setValue( $name, $value, $force = false ) { |
67 | 67 | $this->validateName( $name, true ); |
| 68 | + |
68 | 69 | if ( !$force && $value === $this->options[$name]['default'] ) { |
69 | 70 | // null default values as unchanged |
70 | 71 | $this->options[$name]['value'] = null; |
— | — | @@ -74,6 +75,7 @@ |
75 | 76 | |
76 | 77 | public function getValue( $name ) { |
77 | 78 | $this->validateName( $name, true ); |
| 79 | + |
78 | 80 | return $this->getValueReal( $this->options[$name] ); |
79 | 81 | } |
80 | 82 | |
— | — | @@ -93,16 +95,19 @@ |
94 | 96 | public function consumeValue( $name ) { |
95 | 97 | $this->validateName( $name, true ); |
96 | 98 | $this->options[$name]['consumed'] = true; |
| 99 | + |
97 | 100 | return $this->getValueReal( $this->options[$name] ); |
98 | 101 | } |
99 | 102 | |
100 | 103 | public function consumeValues( /*Array*/ $names ) { |
101 | 104 | $out = array(); |
| 105 | + |
102 | 106 | foreach ( $names as $name ) { |
103 | 107 | $this->validateName( $name, true ); |
104 | 108 | $this->options[$name]['consumed'] = true; |
105 | 109 | $out[] = $this->getValueReal( $this->options[$name] ); |
106 | 110 | } |
| 111 | + |
107 | 112 | return $out; |
108 | 113 | } |
109 | 114 | |
— | — | @@ -111,8 +116,9 @@ |
112 | 117 | public function validateIntBounds( $name, $min, $max ) { |
113 | 118 | $this->validateName( $name, true ); |
114 | 119 | |
115 | | - if ( $this->options[$name]['type'] !== self::INT ) |
| 120 | + if ( $this->options[$name]['type'] !== self::INT ) { |
116 | 121 | throw new MWException( "Option $name is not of type int" ); |
| 122 | + } |
117 | 123 | |
118 | 124 | $value = $this->getValueReal( $this->options[$name] ); |
119 | 125 | $value = max( $min, min( $max, $value ) ); |
— | — | @@ -124,6 +130,7 @@ |
125 | 131 | |
126 | 132 | public function getUnconsumedValues( $all = false ) { |
127 | 133 | $values = array(); |
| 134 | + |
128 | 135 | foreach ( $this->options as $name => $data ) { |
129 | 136 | if ( !$data['consumed'] ) { |
130 | 137 | if ( $all || $data['value'] !== null ) { |
— | — | @@ -131,24 +138,29 @@ |
132 | 139 | } |
133 | 140 | } |
134 | 141 | } |
| 142 | + |
135 | 143 | return $values; |
136 | 144 | } |
137 | 145 | |
138 | 146 | public function getChangedValues() { |
139 | 147 | $values = array(); |
| 148 | + |
140 | 149 | foreach ( $this->options as $name => $data ) { |
141 | 150 | if ( $data['value'] !== null ) { |
142 | 151 | $values[$name] = $data['value']; |
143 | 152 | } |
144 | 153 | } |
| 154 | + |
145 | 155 | return $values; |
146 | 156 | } |
147 | 157 | |
148 | 158 | public function getAllValues() { |
149 | 159 | $values = array(); |
| 160 | + |
150 | 161 | foreach ( $this->options as $name => $data ) { |
151 | 162 | $values[$name] = $this->getValueReal( $data ); |
152 | 163 | } |
| 164 | + |
153 | 165 | return $values; |
154 | 166 | } |
155 | 167 | |
— | — | @@ -156,7 +168,7 @@ |
157 | 169 | |
158 | 170 | public function fetchValuesFromRequest( WebRequest $r, $values = false ) { |
159 | 171 | if ( !$values ) { |
160 | | - $values = array_keys($this->options); |
| 172 | + $values = array_keys( $this->options ); |
161 | 173 | } |
162 | 174 | |
163 | 175 | foreach ( $values as $name ) { |
— | — | @@ -184,7 +196,7 @@ |
185 | 197 | |
186 | 198 | /* ArrayAccess methods */ |
187 | 199 | public function offsetExists( $name ) { |
188 | | - return isset($this->options[$name]); |
| 200 | + return isset( $this->options[$name] ); |
189 | 201 | } |
190 | 202 | |
191 | 203 | public function offsetGet( $name ) { |
— | — | @@ -198,5 +210,4 @@ |
199 | 211 | public function offsetUnset( $name ) { |
200 | 212 | $this->delete( $name ); |
201 | 213 | } |
202 | | - |
203 | 214 | } |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -83,10 +83,14 @@ |
84 | 84 | * @return mixed Title object, or null if this page is not a redirect |
85 | 85 | */ |
86 | 86 | public function getRedirectTarget() { |
87 | | - if ( !$this->mTitle || !$this->mTitle->isRedirect() ) |
| 87 | + if ( !$this->mTitle || !$this->mTitle->isRedirect() ) { |
88 | 88 | return null; |
89 | | - if ( !is_null( $this->mRedirectTarget ) ) |
| 89 | + } |
| 90 | + |
| 91 | + if ( !is_null( $this->mRedirectTarget ) ) { |
90 | 92 | return $this->mRedirectTarget; |
| 93 | + } |
| 94 | + |
91 | 95 | # Query the redirect table |
92 | 96 | $dbr = wfGetDB( DB_SLAVE ); |
93 | 97 | $row = $dbr->selectRow( 'redirect', |
— | — | @@ -94,9 +98,11 @@ |
95 | 99 | array( 'rd_from' => $this->getID() ), |
96 | 100 | __METHOD__ |
97 | 101 | ); |
| 102 | + |
98 | 103 | if ( $row ) { |
99 | 104 | return $this->mRedirectTarget = Title::makeTitle( $row->rd_namespace, $row->rd_title ); |
100 | 105 | } |
| 106 | + |
101 | 107 | # This page doesn't have an entry in the redirect table |
102 | 108 | return $this->mRedirectTarget = $this->insertRedirect(); |
103 | 109 | } |
— | — | @@ -109,9 +115,11 @@ |
110 | 116 | */ |
111 | 117 | public function insertRedirect() { |
112 | 118 | $retval = Title::newFromRedirect( $this->getContent() ); |
| 119 | + |
113 | 120 | if ( !$retval ) { |
114 | 121 | return null; |
115 | 122 | } |
| 123 | + |
116 | 124 | $dbw = wfGetDB( DB_MASTER ); |
117 | 125 | $dbw->replace( 'redirect', array( 'rd_from' ), |
118 | 126 | array( |
— | — | @@ -121,6 +129,7 @@ |
122 | 130 | ), |
123 | 131 | __METHOD__ |
124 | 132 | ); |
| 133 | + |
125 | 134 | return $retval; |
126 | 135 | } |
127 | 136 | |
— | — | @@ -131,6 +140,7 @@ |
132 | 141 | */ |
133 | 142 | public function followRedirect() { |
134 | 143 | $text = $this->getContent(); |
| 144 | + |
135 | 145 | return $this->followRedirectText( $text ); |
136 | 146 | } |
137 | 147 | |
— | — | @@ -143,6 +153,7 @@ |
144 | 154 | public function followRedirectText( $text ) { |
145 | 155 | $rt = Title::newFromRedirectRecurse( $text ); // recurse through to only get the final target |
146 | 156 | # process if title object is valid and not special:userlogout |
| 157 | + |
147 | 158 | if ( $rt ) { |
148 | 159 | if ( $rt->getInterwiki() != '' ) { |
149 | 160 | if ( $rt->isLocal() ) { |
— | — | @@ -166,9 +177,11 @@ |
167 | 178 | return $rt->getFullURL(); |
168 | 179 | } |
169 | 180 | } |
| 181 | + |
170 | 182 | return $rt; |
171 | 183 | } |
172 | 184 | } |
| 185 | + |
173 | 186 | // No or invalid redirect |
174 | 187 | return false; |
175 | 188 | } |
— | — | @@ -213,7 +226,9 @@ |
214 | 227 | */ |
215 | 228 | public function getContent() { |
216 | 229 | global $wgUser, $wgContLang, $wgOut, $wgMessageCache; |
| 230 | + |
217 | 231 | wfProfileIn( __METHOD__ ); |
| 232 | + |
218 | 233 | if ( $this->getID() === 0 ) { |
219 | 234 | # If this is a MediaWiki:x message, then load the messages |
220 | 235 | # and return the message value for x. |
— | — | @@ -222,16 +237,19 @@ |
223 | 238 | list( $message, $lang ) = $wgMessageCache->figureMessage( $wgContLang->lcfirst( $this->mTitle->getText() ) ); |
224 | 239 | $wgMessageCache->loadAllMessages( $lang ); |
225 | 240 | $text = wfMsgGetKey( $message, false, $lang, false ); |
| 241 | + |
226 | 242 | if ( wfEmptyMsg( $message, $text ) ) |
227 | 243 | $text = ''; |
228 | 244 | } else { |
229 | 245 | $text = wfMsgExt( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon', 'parsemag' ); |
230 | 246 | } |
231 | 247 | wfProfileOut( __METHOD__ ); |
| 248 | + |
232 | 249 | return $text; |
233 | 250 | } else { |
234 | 251 | $this->loadContent(); |
235 | 252 | wfProfileOut( __METHOD__ ); |
| 253 | + |
236 | 254 | return $this->mContent; |
237 | 255 | } |
238 | 256 | } |
— | — | @@ -246,8 +264,10 @@ |
247 | 265 | if ( $this->mContentLoaded && $this->mOldId == 0 ) { |
248 | 266 | return $this->mContent; |
249 | 267 | } |
| 268 | + |
250 | 269 | $rev = Revision::newFromTitle( $this->mTitle ); |
251 | 270 | $text = $rev ? $rev->getRawText() : false; |
| 271 | + |
252 | 272 | return $text; |
253 | 273 | } |
254 | 274 | |
— | — | @@ -265,6 +285,7 @@ |
266 | 286 | */ |
267 | 287 | public function getSection( $text, $section ) { |
268 | 288 | global $wgParser; |
| 289 | + |
269 | 290 | return $wgParser->getSection( $text, $section ); |
270 | 291 | } |
271 | 292 | |
— | — | @@ -280,13 +301,18 @@ |
281 | 302 | $undo_text = $undo->getText(); |
282 | 303 | $undoafter_text = $undoafter->getText(); |
283 | 304 | $cur_text = $this->getContent(); |
| 305 | + |
284 | 306 | if ( $cur_text == $undo_text ) { |
285 | 307 | # No use doing a merge if it's just a straight revert. |
286 | 308 | return $undoafter_text; |
287 | 309 | } |
| 310 | + |
288 | 311 | $undone_text = ''; |
289 | | - if ( !wfMerge( $undo_text, $undoafter_text, $cur_text, $undone_text ) ) |
| 312 | + |
| 313 | + if ( !wfMerge( $undo_text, $undoafter_text, $cur_text, $undone_text ) ) { |
290 | 314 | return false; |
| 315 | + } |
| 316 | + |
291 | 317 | return $undone_text; |
292 | 318 | } |
293 | 319 | |
— | — | @@ -298,6 +324,7 @@ |
299 | 325 | if ( is_null( $this->mOldId ) ) { |
300 | 326 | $this->mOldId = $this->getOldIDFromRequest(); |
301 | 327 | } |
| 328 | + |
302 | 329 | return $this->mOldId; |
303 | 330 | } |
304 | 331 | |
— | — | @@ -308,13 +335,16 @@ |
309 | 336 | */ |
310 | 337 | public function getOldIDFromRequest() { |
311 | 338 | global $wgRequest; |
| 339 | + |
312 | 340 | $this->mRedirectUrl = false; |
| 341 | + |
313 | 342 | $oldid = $wgRequest->getVal( 'oldid' ); |
| 343 | + |
314 | 344 | if ( isset( $oldid ) ) { |
315 | 345 | $oldid = intval( $oldid ); |
316 | 346 | if ( $wgRequest->getVal( 'direction' ) == 'next' ) { |
317 | 347 | $nextid = $this->mTitle->getNextRevisionID( $oldid ); |
318 | | - if ( $nextid ) { |
| 348 | + if ( $nextid ) { |
319 | 349 | $oldid = $nextid; |
320 | 350 | } else { |
321 | 351 | $this->mRedirectUrl = $this->mTitle->getFullURL( 'redirect=no' ); |
— | — | @@ -326,9 +356,11 @@ |
327 | 357 | } |
328 | 358 | } |
329 | 359 | } |
| 360 | + |
330 | 361 | if ( !$oldid ) { |
331 | 362 | $oldid = 0; |
332 | 363 | } |
| 364 | + |
333 | 365 | return $oldid; |
334 | 366 | } |
335 | 367 | |
— | — | @@ -336,18 +368,22 @@ |
337 | 369 | * Load the revision (including text) into this object |
338 | 370 | */ |
339 | 371 | function loadContent() { |
340 | | - if ( $this->mContentLoaded ) return; |
| 372 | + if ( $this->mContentLoaded ) { |
| 373 | + return; |
| 374 | + } |
| 375 | + |
341 | 376 | wfProfileIn( __METHOD__ ); |
| 377 | + |
342 | 378 | # Query variables :P |
343 | 379 | $oldid = $this->getOldID(); |
344 | 380 | # Pre-fill content with error message so that if something |
345 | 381 | # fails we'll have something telling us what we intended. |
346 | 382 | $this->mOldId = $oldid; |
347 | 383 | $this->fetchContent( $oldid ); |
| 384 | + |
348 | 385 | wfProfileOut( __METHOD__ ); |
349 | 386 | } |
350 | 387 | |
351 | | - |
352 | 388 | /** |
353 | 389 | * Fetch a page record with the given conditions |
354 | 390 | * @param $dbr Database object |
— | — | @@ -368,21 +404,25 @@ |
369 | 405 | 'page_latest', |
370 | 406 | 'page_len', |
371 | 407 | ); |
| 408 | + |
372 | 409 | wfRunHooks( 'ArticlePageDataBefore', array( &$this, &$fields ) ); |
| 410 | + |
373 | 411 | $row = $dbr->selectRow( |
374 | 412 | 'page', |
375 | 413 | $fields, |
376 | 414 | $conditions, |
377 | 415 | __METHOD__ |
378 | 416 | ); |
| 417 | + |
379 | 418 | wfRunHooks( 'ArticlePageDataAfter', array( &$this, &$row ) ); |
| 419 | + |
380 | 420 | return $row ; |
381 | 421 | } |
382 | 422 | |
383 | 423 | /** |
384 | 424 | * Fetch a page record matching the Title object's namespace and title |
385 | 425 | * using a sanitized title string |
386 | | - * |
| 426 | + * |
387 | 427 | * @param $dbr Database object |
388 | 428 | * @param $title Title object |
389 | 429 | * @return mixed Database result resource, or false on failure |
— | — | @@ -416,6 +456,7 @@ |
417 | 457 | } |
418 | 458 | |
419 | 459 | $lc = LinkCache::singleton(); |
| 460 | + |
420 | 461 | if ( $data ) { |
421 | 462 | $lc->addGoodLinkObj( $data->page_id, $this->mTitle, $data->page_len, $data->page_is_redirect ); |
422 | 463 | |
— | — | @@ -435,13 +476,13 @@ |
436 | 477 | $this->mTitle->mArticleID = 0; |
437 | 478 | } |
438 | 479 | |
439 | | - $this->mDataLoaded = true; |
| 480 | + $this->mDataLoaded = true; |
440 | 481 | } |
441 | 482 | |
442 | 483 | /** |
443 | 484 | * Get text of an article from database |
444 | 485 | * Does *NOT* follow redirects. |
445 | | - * |
| 486 | + * |
446 | 487 | * @param $oldid Int: 0 for whatever the latest revision is |
447 | 488 | * @return mixed string containing article contents, or false if null |
448 | 489 | */ |
— | — | @@ -464,20 +505,25 @@ |
465 | 506 | wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" ); |
466 | 507 | return false; |
467 | 508 | } |
| 509 | + |
468 | 510 | $data = $this->pageDataFromId( $dbr, $revision->getPage() ); |
| 511 | + |
469 | 512 | if ( !$data ) { |
470 | 513 | wfDebug( __METHOD__ . " failed to get page data linked to revision id $oldid\n" ); |
471 | 514 | return false; |
472 | 515 | } |
| 516 | + |
473 | 517 | $this->mTitle = Title::makeTitle( $data->page_namespace, $data->page_title ); |
474 | 518 | $this->loadPageData( $data ); |
475 | 519 | } else { |
476 | 520 | if ( !$this->mDataLoaded ) { |
477 | 521 | $data = $this->pageDataFromTitle( $dbr, $this->mTitle ); |
| 522 | + |
478 | 523 | if ( !$data ) { |
479 | 524 | wfDebug( __METHOD__ . " failed to find page data for title " . $this->mTitle->getPrefixedText() . "\n" ); |
480 | 525 | return false; |
481 | 526 | } |
| 527 | + |
482 | 528 | $this->loadPageData( $data ); |
483 | 529 | } |
484 | 530 | $revision = Revision::newFromId( $this->mLatest ); |
— | — | @@ -541,6 +587,7 @@ |
542 | 588 | $options = 'FOR UPDATE'; |
543 | 589 | } |
544 | 590 | } |
| 591 | + |
545 | 592 | return $options; |
546 | 593 | } |
547 | 594 | |
— | — | @@ -580,6 +627,7 @@ |
581 | 628 | public function getCount() { |
582 | 629 | if ( -1 == $this->mCounter ) { |
583 | 630 | $id = $this->getID(); |
| 631 | + |
584 | 632 | if ( $id == 0 ) { |
585 | 633 | $this->mCounter = 0; |
586 | 634 | } else { |
— | — | @@ -592,11 +640,12 @@ |
593 | 641 | ); |
594 | 642 | } |
595 | 643 | } |
| 644 | + |
596 | 645 | return $this->mCounter; |
597 | 646 | } |
598 | 647 | |
599 | 648 | /** |
600 | | - * Determine whether a page would be suitable for being counted as an |
| 649 | + * Determine whether a page would be suitable for being counted as an |
601 | 650 | * article in the site_stats table based on the title & its content |
602 | 651 | * |
603 | 652 | * @param $text String: text to analyze |
— | — | @@ -606,6 +655,7 @@ |
607 | 656 | global $wgUseCommaCount; |
608 | 657 | |
609 | 658 | $token = $wgUseCommaCount ? ',' : '[['; |
| 659 | + |
610 | 660 | return $this->mTitle->isContentPage() && !$this->isRedirect( $text ) && in_string( $token, $text ); |
611 | 661 | } |
612 | 662 | |
— | — | @@ -620,12 +670,14 @@ |
621 | 671 | if ( $this->mDataLoaded ) { |
622 | 672 | return $this->mIsRedirect; |
623 | 673 | } |
| 674 | + |
624 | 675 | // Apparently loadPageData was never called |
625 | 676 | $this->loadContent(); |
626 | 677 | $titleObj = Title::newFromRedirectRecurse( $this->fetchContent() ); |
627 | 678 | } else { |
628 | 679 | $titleObj = Title::newFromRedirect( $text ); |
629 | 680 | } |
| 681 | + |
630 | 682 | return $titleObj !== null; |
631 | 683 | } |
632 | 684 | |
— | — | @@ -639,6 +691,7 @@ |
640 | 692 | if ( $this->getOldID() == 0 ) { |
641 | 693 | return true; |
642 | 694 | } |
| 695 | + |
643 | 696 | return $this->exists() && isset( $this->mRevision ) && $this->mRevision->isCurrent(); |
644 | 697 | } |
645 | 698 | |
— | — | @@ -647,12 +700,15 @@ |
648 | 701 | * This isn't necessary for all uses, so it's only done if needed. |
649 | 702 | */ |
650 | 703 | protected function loadLastEdit() { |
651 | | - if ( -1 != $this->mUser ) |
| 704 | + if ( -1 != $this->mUser ) { |
652 | 705 | return; |
| 706 | + } |
653 | 707 | |
654 | 708 | # New or non-existent articles have no user information |
655 | 709 | $id = $this->getID(); |
656 | | - if ( 0 == $id ) return; |
| 710 | + if ( 0 == $id ) { |
| 711 | + return; |
| 712 | + } |
657 | 713 | |
658 | 714 | $this->mLastRevision = Revision::loadFromPageId( wfGetDB( DB_MASTER ), $id ); |
659 | 715 | if ( !is_null( $this->mLastRevision ) ) { |
— | — | @@ -664,7 +720,7 @@ |
665 | 721 | $this->mRevIdFetched = $this->mLastRevision->getId(); |
666 | 722 | } |
667 | 723 | } |
668 | | - |
| 724 | + |
669 | 725 | /** |
670 | 726 | * @return string GMT timestamp of last article revision |
671 | 727 | **/ |
— | — | @@ -674,6 +730,7 @@ |
675 | 731 | if ( !$this->mTimestamp ) { |
676 | 732 | $this->loadLastEdit(); |
677 | 733 | } |
| 734 | + |
678 | 735 | return wfTimestamp( TS_MW, $this->mTimestamp ); |
679 | 736 | } |
680 | 737 | |
— | — | @@ -682,6 +739,7 @@ |
683 | 740 | */ |
684 | 741 | public function getUser() { |
685 | 742 | $this->loadLastEdit(); |
| 743 | + |
686 | 744 | return $this->mUser; |
687 | 745 | } |
688 | 746 | |
— | — | @@ -690,6 +748,7 @@ |
691 | 749 | */ |
692 | 750 | public function getUserText() { |
693 | 751 | $this->loadLastEdit(); |
| 752 | + |
694 | 753 | return $this->mUserText; |
695 | 754 | } |
696 | 755 | |
— | — | @@ -698,16 +757,18 @@ |
699 | 758 | */ |
700 | 759 | public function getComment() { |
701 | 760 | $this->loadLastEdit(); |
| 761 | + |
702 | 762 | return $this->mComment; |
703 | 763 | } |
704 | 764 | |
705 | 765 | /** |
706 | 766 | * Returns true if last revision was marked as "minor edit" |
707 | | - * |
| 767 | + * |
708 | 768 | * @return boolean Minor edit indicator for the last article revision. |
709 | 769 | */ |
710 | 770 | public function getMinorEdit() { |
711 | 771 | $this->loadLastEdit(); |
| 772 | + |
712 | 773 | return $this->mMinorEdit; |
713 | 774 | } |
714 | 775 | |
— | — | @@ -718,6 +779,7 @@ |
719 | 780 | */ |
720 | 781 | public function getRevIdFetched() { |
721 | 782 | $this->loadLastEdit(); |
| 783 | + |
722 | 784 | return $this->mRevIdFetched; |
723 | 785 | } |
724 | 786 | |
— | — | @@ -727,7 +789,7 @@ |
728 | 790 | * @return UserArrayFromResult object with User objects of article contributors for requested range |
729 | 791 | */ |
730 | 792 | public function getContributors( $limit = 0, $offset = 0 ) { |
731 | | - # XXX: this is expensive; cache this info somewhere. |
| 793 | + # FIXME: this is expensive; cache this info somewhere. |
732 | 794 | |
733 | 795 | $dbr = wfGetDB( DB_SLAVE ); |
734 | 796 | $revTable = $dbr->tableName( 'revision' ); |
— | — | @@ -736,6 +798,7 @@ |
737 | 799 | $pageId = $this->getId(); |
738 | 800 | |
739 | 801 | $user = $this->getUser(); |
| 802 | + |
740 | 803 | if ( $user ) { |
741 | 804 | $excludeCond = "AND rev_user != $user"; |
742 | 805 | } else { |
— | — | @@ -753,8 +816,9 @@ |
754 | 817 | GROUP BY rev_user, rev_user_text |
755 | 818 | ORDER BY timestamp DESC"; |
756 | 819 | |
757 | | - if ( $limit > 0 ) |
| 820 | + if ( $limit > 0 ) { |
758 | 821 | $sql = $dbr->limitResult( $sql, $limit, $offset ); |
| 822 | + } |
759 | 823 | |
760 | 824 | $sql .= ' ' . $this->getSelectOptions(); |
761 | 825 | $res = $dbr->query( $sql, __METHOD__ ); |
— | — | @@ -786,13 +850,16 @@ |
787 | 851 | # Try client and file cache |
788 | 852 | if ( $oldid === 0 && $this->checkTouched() ) { |
789 | 853 | global $wgUseETag; |
| 854 | + |
790 | 855 | if ( $wgUseETag ) { |
791 | 856 | $wgOut->setETag( $parserCache->getETag( $this, $parserOptions ) ); |
792 | 857 | } |
| 858 | + |
793 | 859 | # Is is client cached? |
794 | 860 | if ( $wgOut->checkLastModified( $this->getTouched() ) ) { |
795 | 861 | wfDebug( __METHOD__ . ": done 304\n" ); |
796 | 862 | wfProfileOut( __METHOD__ ); |
| 863 | + |
797 | 864 | return; |
798 | 865 | # Try file cache |
799 | 866 | } else if ( $wgUseFileCache && $this->tryFileCache() ) { |
— | — | @@ -801,6 +868,7 @@ |
802 | 869 | $wgOut->disable(); |
803 | 870 | $this->viewUpdates(); |
804 | 871 | wfProfileOut( __METHOD__ ); |
| 872 | + |
805 | 873 | return; |
806 | 874 | } |
807 | 875 | } |
— | — | @@ -810,6 +878,7 @@ |
811 | 879 | $wgOut->redirect( $this->mRedirectUrl ); |
812 | 880 | wfDebug( __METHOD__ . ": redirecting due to oldid\n" ); |
813 | 881 | wfProfileOut( __METHOD__ ); |
| 882 | + |
814 | 883 | return; |
815 | 884 | } |
816 | 885 | |
— | — | @@ -822,6 +891,7 @@ |
823 | 892 | wfDebug( __METHOD__ . ": showing diff page\n" ); |
824 | 893 | $this->showDiffPage(); |
825 | 894 | wfProfileOut( __METHOD__ ); |
| 895 | + |
826 | 896 | return; |
827 | 897 | } |
828 | 898 | |
— | — | @@ -840,16 +910,17 @@ |
841 | 911 | $pass = 0; |
842 | 912 | $outputDone = false; |
843 | 913 | $this->mParserOutput = false; |
| 914 | + |
844 | 915 | while ( !$outputDone && ++$pass ) { |
845 | 916 | switch( $pass ) { |
846 | 917 | case 1: |
847 | 918 | wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) ); |
848 | 919 | break; |
849 | | - |
850 | 920 | case 2: |
851 | 921 | # Try the parser cache |
852 | 922 | if ( $useParserCache ) { |
853 | 923 | $this->mParserOutput = $parserCache->get( $this, $parserOptions ); |
| 924 | + |
854 | 925 | if ( $this->mParserOutput !== false ) { |
855 | 926 | wfDebug( __METHOD__ . ": showing parser cache contents\n" ); |
856 | 927 | $wgOut->addParserOutput( $this->mParserOutput ); |
— | — | @@ -860,7 +931,6 @@ |
861 | 932 | } |
862 | 933 | } |
863 | 934 | break; |
864 | | - |
865 | 935 | case 3: |
866 | 936 | $text = $this->getContent(); |
867 | 937 | if ( $text === false || $this->getID() == 0 ) { |
— | — | @@ -883,11 +953,13 @@ |
884 | 954 | # Are we looking at an old revision |
885 | 955 | if ( $oldid && !is_null( $this->mRevision ) ) { |
886 | 956 | $this->setOldSubtitle( $oldid ); |
| 957 | + |
887 | 958 | if ( !$this->showDeletedRevisionHeader() ) { |
888 | 959 | wfDebug( __METHOD__ . ": cannot view deleted revision\n" ); |
889 | 960 | wfProfileOut( __METHOD__ ); |
890 | 961 | return; |
891 | 962 | } |
| 963 | + |
892 | 964 | # If this "old" version is the current, then try the parser cache... |
893 | 965 | if ( $oldid === $this->getLatest() && $this->useParserCache( false ) ) { |
894 | 966 | $this->mParserOutput = $parserCache->get( $this, $parserOptions ); |
— | — | @@ -923,7 +995,6 @@ |
924 | 996 | $outputDone = true; |
925 | 997 | } |
926 | 998 | break; |
927 | | - |
928 | 999 | case 4: |
929 | 1000 | # Run the parse, protected by a pool counter |
930 | 1001 | wfDebug( __METHOD__ . ": doing uncached parse\n" ); |
— | — | @@ -941,7 +1012,6 @@ |
942 | 1013 | $outputDone = true; |
943 | 1014 | } |
944 | 1015 | break; |
945 | | - |
946 | 1016 | # Should be unreachable, but just in case... |
947 | 1017 | default: |
948 | 1018 | break 2; |
— | — | @@ -951,6 +1021,7 @@ |
952 | 1022 | # Adjust the title if it was set by displaytitle, -{T|}- or language conversion |
953 | 1023 | if ( $this->mParserOutput ) { |
954 | 1024 | $titleText = $this->mParserOutput->getTitleText(); |
| 1025 | + |
955 | 1026 | if ( strval( $titleText ) !== '' ) { |
956 | 1027 | $wgOut->setPageTitle( $titleText ); |
957 | 1028 | } |
— | — | @@ -1012,7 +1083,9 @@ |
1013 | 1084 | */ |
1014 | 1085 | public function showCssOrJsPage() { |
1015 | 1086 | global $wgOut; |
| 1087 | + |
1016 | 1088 | $wgOut->addHTML( wfMsgExt( 'clearyourcache', 'parse' ) ); |
| 1089 | + |
1017 | 1090 | // Give hooks a chance to customise the output |
1018 | 1091 | if ( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->mTitle, $wgOut ) ) ) { |
1019 | 1092 | // Wrap the whole lot in a <pre> and don't parse |
— | — | @@ -1033,6 +1106,7 @@ |
1034 | 1107 | public function getRobotPolicyForView() { |
1035 | 1108 | wfDeprecated( __METHOD__ ); |
1036 | 1109 | $policy = $this->getRobotPolicy( 'view' ); |
| 1110 | + |
1037 | 1111 | return $policy['index'] . ',' . $policy['follow']; |
1038 | 1112 | } |
1039 | 1113 | |
— | — | @@ -1043,34 +1117,42 @@ |
1044 | 1118 | * TODO: actions other than 'view' |
1045 | 1119 | */ |
1046 | 1120 | public function getRobotPolicy( $action ) { |
1047 | | - |
1048 | 1121 | global $wgOut, $wgArticleRobotPolicies, $wgNamespaceRobotPolicies; |
1049 | 1122 | global $wgDefaultRobotPolicy, $wgRequest; |
1050 | 1123 | |
1051 | 1124 | $ns = $this->mTitle->getNamespace(); |
| 1125 | + |
1052 | 1126 | if ( $ns == NS_USER || $ns == NS_USER_TALK ) { |
1053 | 1127 | # Don't index user and user talk pages for blocked users (bug 11443) |
1054 | 1128 | if ( !$this->mTitle->isSubpage() ) { |
1055 | 1129 | $block = new Block(); |
1056 | 1130 | if ( $block->load( $this->mTitle->getText() ) ) { |
1057 | | - return array( 'index' => 'noindex', |
1058 | | - 'follow' => 'nofollow' ); |
| 1131 | + return array( |
| 1132 | + 'index' => 'noindex', |
| 1133 | + 'follow' => 'nofollow' |
| 1134 | + ); |
1059 | 1135 | } |
1060 | 1136 | } |
1061 | 1137 | } |
1062 | 1138 | |
1063 | 1139 | if ( $this->getID() === 0 || $this->getOldID() ) { |
1064 | 1140 | # Non-articles (special pages etc), and old revisions |
1065 | | - return array( 'index' => 'noindex', |
1066 | | - 'follow' => 'nofollow' ); |
| 1141 | + return array( |
| 1142 | + 'index' => 'noindex', |
| 1143 | + 'follow' => 'nofollow' |
| 1144 | + ); |
1067 | 1145 | } elseif ( $wgOut->isPrintable() ) { |
1068 | 1146 | # Discourage indexing of printable versions, but encourage following |
1069 | | - return array( 'index' => 'noindex', |
1070 | | - 'follow' => 'follow' ); |
| 1147 | + return array( |
| 1148 | + 'index' => 'noindex', |
| 1149 | + 'follow' => 'follow' |
| 1150 | + ); |
1071 | 1151 | } elseif ( $wgRequest->getInt( 'curid' ) ) { |
1072 | 1152 | # For ?curid=x urls, disallow indexing |
1073 | | - return array( 'index' => 'noindex', |
1074 | | - 'follow' => 'follow' ); |
| 1153 | + return array( |
| 1154 | + 'index' => 'noindex', |
| 1155 | + 'follow' => 'follow' |
| 1156 | + ); |
1075 | 1157 | } |
1076 | 1158 | |
1077 | 1159 | # Otherwise, construct the policy based on the various config variables. |
— | — | @@ -1078,24 +1160,29 @@ |
1079 | 1161 | |
1080 | 1162 | if ( isset( $wgNamespaceRobotPolicies[$ns] ) ) { |
1081 | 1163 | # Honour customised robot policies for this namespace |
1082 | | - $policy = array_merge( $policy, |
1083 | | - self::formatRobotPolicy( $wgNamespaceRobotPolicies[$ns] ) ); |
| 1164 | + $policy = array_merge( |
| 1165 | + $policy, |
| 1166 | + self::formatRobotPolicy( $wgNamespaceRobotPolicies[$ns] ) |
| 1167 | + ); |
1084 | 1168 | } |
1085 | 1169 | if ( $this->mTitle->canUseNoindex() && is_object( $this->mParserOutput ) && $this->mParserOutput->getIndexPolicy() ) { |
1086 | 1170 | # __INDEX__ and __NOINDEX__ magic words, if allowed. Incorporates |
1087 | 1171 | # a final sanity check that we have really got the parser output. |
1088 | | - $policy = array_merge( $policy, |
1089 | | - array( 'index' => $this->mParserOutput->getIndexPolicy() ) ); |
| 1172 | + $policy = array_merge( |
| 1173 | + $policy, |
| 1174 | + array( 'index' => $this->mParserOutput->getIndexPolicy() ) |
| 1175 | + ); |
1090 | 1176 | } |
1091 | 1177 | |
1092 | 1178 | if ( isset( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) ) { |
1093 | 1179 | # (bug 14900) site config can override user-defined __INDEX__ or __NOINDEX__ |
1094 | | - $policy = array_merge( $policy, |
1095 | | - self::formatRobotPolicy( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) ); |
| 1180 | + $policy = array_merge( |
| 1181 | + $policy, |
| 1182 | + self::formatRobotPolicy( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) |
| 1183 | + ); |
1096 | 1184 | } |
1097 | 1185 | |
1098 | 1186 | return $policy; |
1099 | | - |
1100 | 1187 | } |
1101 | 1188 | |
1102 | 1189 | /** |
— | — | @@ -1123,6 +1210,7 @@ |
1124 | 1211 | $arr['follow'] = $var; |
1125 | 1212 | } |
1126 | 1213 | } |
| 1214 | + |
1127 | 1215 | return $arr; |
1128 | 1216 | } |
1129 | 1217 | |
— | — | @@ -1138,6 +1226,7 @@ |
1139 | 1227 | |
1140 | 1228 | $rdfrom = $wgRequest->getVal( 'rdfrom' ); |
1141 | 1229 | $sk = $wgUser->getSkin(); |
| 1230 | + |
1142 | 1231 | if ( isset( $this->mRedirectedFrom ) ) { |
1143 | 1232 | // This is an internally redirected page view. |
1144 | 1233 | // We'll need a backlink to the source page for navigation. |
— | — | @@ -1149,6 +1238,7 @@ |
1150 | 1239 | array( 'redirect' => 'no' ), |
1151 | 1240 | array( 'known', 'noclasses' ) |
1152 | 1241 | ); |
| 1242 | + |
1153 | 1243 | $s = wfMsgExt( 'redirectedfrom', array( 'parseinline', 'replaceafter' ), $redir ); |
1154 | 1244 | $wgOut->setSubtitle( $s ); |
1155 | 1245 | |
— | — | @@ -1162,6 +1252,7 @@ |
1163 | 1253 | $wgOut->addLink( array( 'rel' => 'canonical', |
1164 | 1254 | 'href' => $this->mTitle->getLocalURL() ) |
1165 | 1255 | ); |
| 1256 | + |
1166 | 1257 | return true; |
1167 | 1258 | } |
1168 | 1259 | } elseif ( $rdfrom ) { |
— | — | @@ -1171,9 +1262,11 @@ |
1172 | 1263 | $redir = $sk->makeExternalLink( $rdfrom, $rdfrom ); |
1173 | 1264 | $s = wfMsgExt( 'redirectedfrom', array( 'parseinline', 'replaceafter' ), $redir ); |
1174 | 1265 | $wgOut->setSubtitle( $s ); |
| 1266 | + |
1175 | 1267 | return true; |
1176 | 1268 | } |
1177 | 1269 | } |
| 1270 | + |
1178 | 1271 | return false; |
1179 | 1272 | } |
1180 | 1273 | |
— | — | @@ -1183,6 +1276,7 @@ |
1184 | 1277 | */ |
1185 | 1278 | public function showNamespaceHeader() { |
1186 | 1279 | global $wgOut; |
| 1280 | + |
1187 | 1281 | if ( $this->mTitle->isTalkPage() ) { |
1188 | 1282 | $msg = wfMsgNoTrans( 'talkpageheader' ); |
1189 | 1283 | if ( $msg !== '-' && !wfEmptyMsg( 'talkpageheader', $msg ) ) { |
— | — | @@ -1196,6 +1290,7 @@ |
1197 | 1291 | */ |
1198 | 1292 | public function showViewFooter() { |
1199 | 1293 | global $wgOut, $wgUseTrackbacks, $wgRequest; |
| 1294 | + |
1200 | 1295 | # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page |
1201 | 1296 | if ( $this->mTitle->getNamespace() == NS_USER_TALK && IP::isValid( $this->mTitle->getText() ) ) { |
1202 | 1297 | $wgOut->addWikiMsg( 'anontalkpagetext' ); |
— | — | @@ -1218,6 +1313,7 @@ |
1219 | 1314 | */ |
1220 | 1315 | public function showPatrolFooter() { |
1221 | 1316 | global $wgOut, $wgRequest, $wgUser; |
| 1317 | + |
1222 | 1318 | $rcid = $wgRequest->getVal( 'rcid' ); |
1223 | 1319 | |
1224 | 1320 | if ( !$rcid || !$this->mTitle->exists() || !$this->mTitle->quickUserCan( 'patrol' ) ) { |
— | — | @@ -1258,6 +1354,7 @@ |
1259 | 1355 | $rootPart = $parts[0]; |
1260 | 1356 | $user = User::newFromName( $rootPart, false /* allow IP users*/ ); |
1261 | 1357 | $ip = User::isIP( $rootPart ); |
| 1358 | + |
1262 | 1359 | if ( !$user->isLoggedIn() && !$ip ) { # User does not exist |
1263 | 1360 | $wgOut->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>", |
1264 | 1361 | array( 'userpage-userdoesnotexist-view', $rootPart ) ); |
— | — | @@ -1278,7 +1375,9 @@ |
1279 | 1376 | ); |
1280 | 1377 | } |
1281 | 1378 | } |
| 1379 | + |
1282 | 1380 | wfRunHooks( 'ShowMissingArticle', array( $this ) ); |
| 1381 | + |
1283 | 1382 | # Show delete and move logs |
1284 | 1383 | LogEventsList::showLogExtract( $wgOut, array( 'delete', 'move' ), $this->mTitle->getPrefixedText(), '', |
1285 | 1384 | array( 'lim' => 10, |
— | — | @@ -1301,36 +1400,42 @@ |
1302 | 1401 | $editErrors = $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ); |
1303 | 1402 | $errors = array_merge( $createErrors, $editErrors ); |
1304 | 1403 | |
1305 | | - if ( !count( $errors ) ) |
| 1404 | + if ( !count( $errors ) ) { |
1306 | 1405 | $text = wfMsgNoTrans( 'noarticletext' ); |
1307 | | - else |
| 1406 | + } else { |
1308 | 1407 | $text = wfMsgNoTrans( 'noarticletext-nopermission' ); |
| 1408 | + } |
1309 | 1409 | } |
1310 | 1410 | $text = "<div class='noarticletext'>\n$text\n</div>"; |
| 1411 | + |
1311 | 1412 | if ( !$this->hasViewableContent() ) { |
1312 | 1413 | // If there's no backing content, send a 404 Not Found |
1313 | 1414 | // for better machine handling of broken links. |
1314 | 1415 | $wgRequest->response()->header( "HTTP/1.x 404 Not Found" ); |
1315 | 1416 | } |
| 1417 | + |
1316 | 1418 | $wgOut->addWikiText( $text ); |
1317 | 1419 | } |
1318 | 1420 | |
1319 | 1421 | /** |
1320 | 1422 | * If the revision requested for view is deleted, check permissions. |
1321 | 1423 | * Send either an error message or a warning header to $wgOut. |
1322 | | - * |
| 1424 | + * |
1323 | 1425 | * @return boolean true if the view is allowed, false if not. |
1324 | 1426 | */ |
1325 | 1427 | public function showDeletedRevisionHeader() { |
1326 | 1428 | global $wgOut, $wgRequest; |
| 1429 | + |
1327 | 1430 | if ( !$this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) { |
1328 | 1431 | // Not deleted |
1329 | 1432 | return true; |
1330 | 1433 | } |
| 1434 | + |
1331 | 1435 | // If the user is not allowed to see it... |
1332 | 1436 | if ( !$this->mRevision->userCan( Revision::DELETED_TEXT ) ) { |
1333 | 1437 | $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", |
1334 | 1438 | 'rev-deleted-text-permission' ); |
| 1439 | + |
1335 | 1440 | return false; |
1336 | 1441 | // If the user needs to confirm that they want to see it... |
1337 | 1442 | } else if ( $wgRequest->getInt( 'unhide' ) != 1 ) { |
— | — | @@ -1341,12 +1446,14 @@ |
1342 | 1447 | 'rev-suppressed-text-unhide' : 'rev-deleted-text-unhide'; |
1343 | 1448 | $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", |
1344 | 1449 | array( $msg, $link ) ); |
| 1450 | + |
1345 | 1451 | return false; |
1346 | 1452 | // We are allowed to see... |
1347 | 1453 | } else { |
1348 | 1454 | $msg = $this->mRevision->isDeleted( Revision::DELETED_RESTRICTED ) ? |
1349 | 1455 | 'rev-suppressed-text-view' : 'rev-deleted-text-view'; |
1350 | 1456 | $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", $msg ); |
| 1457 | + |
1351 | 1458 | return true; |
1352 | 1459 | } |
1353 | 1460 | } |
— | — | @@ -1372,11 +1479,14 @@ |
1373 | 1480 | */ |
1374 | 1481 | public function doViewParse() { |
1375 | 1482 | global $wgOut; |
| 1483 | + |
1376 | 1484 | $oldid = $this->getOldID(); |
1377 | 1485 | $useParserCache = $this->useParserCache( $oldid ); |
1378 | 1486 | $parserOptions = clone $this->getParserOptions(); |
| 1487 | + |
1379 | 1488 | # Render printable version, use printable version cache |
1380 | 1489 | $parserOptions->setIsPrintable( $wgOut->isPrintable() ); |
| 1490 | + |
1381 | 1491 | # Don't show section-edit links on old revisions... this way lies madness. |
1382 | 1492 | $parserOptions->setEditSection( $this->isCurrent() ); |
1383 | 1493 | $useParserCache = $this->useParserCache( $oldid ); |
— | — | @@ -1392,11 +1502,13 @@ |
1393 | 1503 | * @return boolean |
1394 | 1504 | */ |
1395 | 1505 | public function tryDirtyCache() { |
| 1506 | + |
1396 | 1507 | global $wgOut; |
1397 | 1508 | $parserCache = ParserCache::singleton(); |
1398 | 1509 | $options = $this->getParserOptions(); |
1399 | 1510 | $options->setIsPrintable( $wgOut->isPrintable() ); |
1400 | 1511 | $output = $parserCache->getDirty( $this, $options ); |
| 1512 | + |
1401 | 1513 | if ( $output ) { |
1402 | 1514 | wfDebug( __METHOD__ . ": sending dirty output\n" ); |
1403 | 1515 | wfDebugLog( 'dirty', "dirty output " . $parserCache->getKey( $this, $options ) . "\n" ); |
— | — | @@ -1404,10 +1516,12 @@ |
1405 | 1517 | $this->mParserOutput = $output; |
1406 | 1518 | $wgOut->addParserOutput( $output ); |
1407 | 1519 | $wgOut->addHTML( "<!-- parser cache is expired, sending anyway due to pool overload-->\n" ); |
| 1520 | + |
1408 | 1521 | return true; |
1409 | 1522 | } else { |
1410 | 1523 | wfDebugLog( 'dirty', "dirty missing\n" ); |
1411 | 1524 | wfDebug( __METHOD__ . ": no dirty cache\n" ); |
| 1525 | + |
1412 | 1526 | return false; |
1413 | 1527 | } |
1414 | 1528 | } |
— | — | @@ -1418,6 +1532,7 @@ |
1419 | 1533 | */ |
1420 | 1534 | public function showPoolError( $status ) { |
1421 | 1535 | global $wgOut; |
| 1536 | + |
1422 | 1537 | $wgOut->clearHTML(); // for release() errors |
1423 | 1538 | $wgOut->enableClientCache( false ); |
1424 | 1539 | $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
— | — | @@ -1430,7 +1545,7 @@ |
1431 | 1546 | |
1432 | 1547 | /** |
1433 | 1548 | * View redirect |
1434 | | - * |
| 1549 | + * |
1435 | 1550 | * @param $target Title object or Array of destination(s) to redirect |
1436 | 1551 | * @param $appendSubtitle Boolean [optional] |
1437 | 1552 | * @param $forceKnown Boolean: should the image be shown as a bluelink regardless of existence? |
— | — | @@ -1438,10 +1553,12 @@ |
1439 | 1554 | */ |
1440 | 1555 | public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) { |
1441 | 1556 | global $wgOut, $wgContLang, $wgStylePath, $wgUser; |
| 1557 | + |
1442 | 1558 | # Display redirect |
1443 | 1559 | if ( !is_array( $target ) ) { |
1444 | 1560 | $target = array( $target ); |
1445 | 1561 | } |
| 1562 | + |
1446 | 1563 | $imageDir = $wgContLang->getDir(); |
1447 | 1564 | $imageUrl = $wgStylePath . '/common/images/redirect' . $imageDir . '.png'; |
1448 | 1565 | $imageUrl2 = $wgStylePath . '/common/images/nextredirect' . $imageDir . '.png'; |
— | — | @@ -1450,9 +1567,11 @@ |
1451 | 1568 | if ( $appendSubtitle ) { |
1452 | 1569 | $wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) ); |
1453 | 1570 | } |
| 1571 | + |
1454 | 1572 | $sk = $wgUser->getSkin(); |
1455 | 1573 | // the loop prepends the arrow image before the link, so the first case needs to be outside |
1456 | 1574 | $title = array_shift( $target ); |
| 1575 | + |
1457 | 1576 | if ( $forceKnown ) { |
1458 | 1577 | $link = $sk->link( |
1459 | 1578 | $title, |
— | — | @@ -1464,7 +1583,8 @@ |
1465 | 1584 | } else { |
1466 | 1585 | $link = $sk->link( $title, htmlspecialchars( $title->getFullText() ) ); |
1467 | 1586 | } |
1468 | | - // automatically append redirect=no to each link, since most of them are redirect pages themselves |
| 1587 | + |
| 1588 | + // Automatically append redirect=no to each link, since most of them are redirect pages themselves. |
1469 | 1589 | foreach ( $target as $rt ) { |
1470 | 1590 | if ( $forceKnown ) { |
1471 | 1591 | $link .= '<img src="' . $imageUrl2 . '" alt="' . $alt2 . ' " />' |
— | — | @@ -1480,9 +1600,9 @@ |
1481 | 1601 | . $sk->link( $rt, htmlspecialchars( $rt->getFullText() ) ); |
1482 | 1602 | } |
1483 | 1603 | } |
| 1604 | + |
1484 | 1605 | return '<img src="' . $imageUrl . '" alt="#REDIRECT " />' . |
1485 | 1606 | '<span class="redirectText">' . $link . '</span>'; |
1486 | | - |
1487 | 1607 | } |
1488 | 1608 | |
1489 | 1609 | /** |
— | — | @@ -1490,21 +1610,27 @@ |
1491 | 1611 | */ |
1492 | 1612 | public function addTrackbacks() { |
1493 | 1613 | global $wgOut, $wgUser; |
| 1614 | + |
1494 | 1615 | $dbr = wfGetDB( DB_SLAVE ); |
1495 | 1616 | $tbs = $dbr->select( 'trackbacks', |
1496 | 1617 | array( 'tb_id', 'tb_title', 'tb_url', 'tb_ex', 'tb_name' ), |
1497 | 1618 | array( 'tb_page' => $this->getID() ) |
1498 | 1619 | ); |
1499 | | - if ( !$dbr->numRows( $tbs ) ) return; |
1500 | 1620 | |
| 1621 | + if ( !$dbr->numRows( $tbs ) ) { |
| 1622 | + return; |
| 1623 | + } |
| 1624 | + |
1501 | 1625 | $tbtext = ""; |
1502 | 1626 | while ( $o = $dbr->fetchObject( $tbs ) ) { |
1503 | 1627 | $rmvtxt = ""; |
| 1628 | + |
1504 | 1629 | if ( $wgUser->isAllowed( 'trackback' ) ) { |
1505 | 1630 | $delurl = $this->mTitle->getFullURL( "action=deletetrackback&tbid=" . |
1506 | 1631 | $o->tb_id . "&token=" . urlencode( $wgUser->editToken() ) ); |
1507 | 1632 | $rmvtxt = wfMsg( 'trackbackremove', htmlspecialchars( $delurl ) ); |
1508 | 1633 | } |
| 1634 | + |
1509 | 1635 | $tbtext .= "\n"; |
1510 | 1636 | $tbtext .= wfMsg( strlen( $o->tb_ex ) ? 'trackbackexcerpt' : 'trackback', |
1511 | 1637 | $o->tb_title, |
— | — | @@ -1513,6 +1639,7 @@ |
1514 | 1640 | $o->tb_name, |
1515 | 1641 | $rmvtxt ); |
1516 | 1642 | } |
| 1643 | + |
1517 | 1644 | $wgOut->wrapWikiMsg( "<div id='mw_trackbacks'>\n$1\n</div>\n", array( 'trackbackbox', $tbtext ) ); |
1518 | 1645 | } |
1519 | 1646 | |
— | — | @@ -1521,14 +1648,18 @@ |
1522 | 1649 | */ |
1523 | 1650 | public function deletetrackback() { |
1524 | 1651 | global $wgUser, $wgRequest, $wgOut; |
| 1652 | + |
1525 | 1653 | if ( !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ) ) ) { |
1526 | 1654 | $wgOut->addWikiMsg( 'sessionfailure' ); |
| 1655 | + |
1527 | 1656 | return; |
1528 | 1657 | } |
1529 | 1658 | |
1530 | 1659 | $permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser ); |
| 1660 | + |
1531 | 1661 | if ( count( $permission_errors ) ) { |
1532 | 1662 | $wgOut->showPermissionsErrorPage( $permission_errors ); |
| 1663 | + |
1533 | 1664 | return; |
1534 | 1665 | } |
1535 | 1666 | |
— | — | @@ -1538,13 +1669,14 @@ |
1539 | 1670 | $wgOut->addWikiMsg( 'trackbackdeleteok' ); |
1540 | 1671 | $this->mTitle->invalidateCache(); |
1541 | 1672 | } |
1542 | | - |
| 1673 | + |
1543 | 1674 | /** |
1544 | 1675 | * Handle action=render |
1545 | 1676 | */ |
1546 | 1677 | |
1547 | 1678 | public function render() { |
1548 | 1679 | global $wgOut; |
| 1680 | + |
1549 | 1681 | $wgOut->setArticleBodyOnly( true ); |
1550 | 1682 | $this->view(); |
1551 | 1683 | } |
— | — | @@ -1554,6 +1686,7 @@ |
1555 | 1687 | */ |
1556 | 1688 | public function purge() { |
1557 | 1689 | global $wgUser, $wgRequest, $wgOut; |
| 1690 | + |
1558 | 1691 | if ( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) { |
1559 | 1692 | if ( wfRunHooks( 'ArticlePurge', array( &$this ) ) ) { |
1560 | 1693 | $this->doPurge(); |
— | — | @@ -1578,6 +1711,7 @@ |
1579 | 1712 | */ |
1580 | 1713 | public function doPurge() { |
1581 | 1714 | global $wgUseSquid; |
| 1715 | + |
1582 | 1716 | // Invalidate the cache |
1583 | 1717 | $this->mTitle->invalidateCache(); |
1584 | 1718 | |
— | — | @@ -1590,13 +1724,16 @@ |
1591 | 1725 | $update = SquidUpdate::newSimplePurge( $this->mTitle ); |
1592 | 1726 | $update->doUpdate(); |
1593 | 1727 | } |
| 1728 | + |
1594 | 1729 | if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { |
1595 | 1730 | global $wgMessageCache; |
| 1731 | + |
1596 | 1732 | if ( $this->getID() == 0 ) { |
1597 | 1733 | $text = false; |
1598 | 1734 | } else { |
1599 | 1735 | $text = $this->getRawText(); |
1600 | 1736 | } |
| 1737 | + |
1601 | 1738 | $wgMessageCache->replace( $this->mTitle->getDBkey(), $text ); |
1602 | 1739 | } |
1603 | 1740 | } |
— | — | @@ -1631,11 +1768,13 @@ |
1632 | 1769 | ), __METHOD__, 'IGNORE' ); |
1633 | 1770 | |
1634 | 1771 | $affected = $dbw->affectedRows(); |
| 1772 | + |
1635 | 1773 | if ( $affected ) { |
1636 | 1774 | $newid = $dbw->insertId(); |
1637 | 1775 | $this->mTitle->resetArticleId( $newid ); |
1638 | 1776 | } |
1639 | 1777 | wfProfileOut( __METHOD__ ); |
| 1778 | + |
1640 | 1779 | return $affected ? $newid : false; |
1641 | 1780 | } |
1642 | 1781 | |
— | — | @@ -1661,6 +1800,7 @@ |
1662 | 1801 | $rt = Title::newFromRedirect( $text ); |
1663 | 1802 | |
1664 | 1803 | $conditions = array( 'page_id' => $this->getId() ); |
| 1804 | + |
1665 | 1805 | if ( !is_null( $lastRevision ) ) { |
1666 | 1806 | # An extra check against threads stepping on each other |
1667 | 1807 | $conditions['page_latest'] = $lastRevision; |
— | — | @@ -1702,6 +1842,7 @@ |
1703 | 1843 | // Update/Insert if we don't know if the last revision was a redirect or not |
1704 | 1844 | // Delete if changing from redirect to non-redirect |
1705 | 1845 | $isRedirect = !is_null( $redirectTitle ); |
| 1846 | + |
1706 | 1847 | if ( $isRedirect || is_null( $lastRevIsRedirect ) || $lastRevIsRedirect !== $isRedirect ) { |
1707 | 1848 | wfProfileIn( __METHOD__ ); |
1708 | 1849 | if ( $isRedirect ) { |
— | — | @@ -1717,12 +1858,15 @@ |
1718 | 1859 | $where = array( 'rd_from' => $this->getId() ); |
1719 | 1860 | $dbw->delete( 'redirect', $where, __METHOD__ ); |
1720 | 1861 | } |
| 1862 | + |
1721 | 1863 | if ( $this->getTitle()->getNamespace() == NS_FILE ) { |
1722 | 1864 | RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $this->getTitle() ); |
1723 | 1865 | } |
1724 | 1866 | wfProfileOut( __METHOD__ ); |
| 1867 | + |
1725 | 1868 | return ( $dbw->affectedRows() != 0 ); |
1726 | 1869 | } |
| 1870 | + |
1727 | 1871 | return true; |
1728 | 1872 | } |
1729 | 1873 | |
— | — | @@ -1732,10 +1876,11 @@ |
1733 | 1877 | * |
1734 | 1878 | * @param $dbw Database object |
1735 | 1879 | * @param $revision Revision object |
1736 | | - * @return mixed |
| 1880 | + * @return mixed |
1737 | 1881 | */ |
1738 | 1882 | public function updateIfNewerOn( &$dbw, $revision ) { |
1739 | 1883 | wfProfileIn( __METHOD__ ); |
| 1884 | + |
1740 | 1885 | $row = $dbw->selectRow( |
1741 | 1886 | array( 'revision', 'page' ), |
1742 | 1887 | array( 'rev_id', 'rev_timestamp', 'page_is_redirect' ), |
— | — | @@ -1743,6 +1888,7 @@ |
1744 | 1889 | 'page_id' => $this->getId(), |
1745 | 1890 | 'page_latest=rev_id' ), |
1746 | 1891 | __METHOD__ ); |
| 1892 | + |
1747 | 1893 | if ( $row ) { |
1748 | 1894 | if ( wfTimestamp( TS_MW, $row->rev_timestamp ) >= $revision->getTimestamp() ) { |
1749 | 1895 | wfProfileOut( __METHOD__ ); |
— | — | @@ -1755,7 +1901,9 @@ |
1756 | 1902 | $prev = 0; |
1757 | 1903 | $lastRevIsRedirect = null; |
1758 | 1904 | } |
| 1905 | + |
1759 | 1906 | $ret = $this->updateRevisionOn( $dbw, $revision, $prev, $lastRevIsRedirect ); |
| 1907 | + |
1760 | 1908 | wfProfileOut( __METHOD__ ); |
1761 | 1909 | return $ret; |
1762 | 1910 | } |
— | — | @@ -1769,6 +1917,7 @@ |
1770 | 1918 | */ |
1771 | 1919 | public function replaceSection( $section, $text, $summary = '', $edittime = null ) { |
1772 | 1920 | wfProfileIn( __METHOD__ ); |
| 1921 | + |
1773 | 1922 | if ( strval( $section ) == '' ) { |
1774 | 1923 | // Whole-page edit; let the whole text through |
1775 | 1924 | } else { |
— | — | @@ -1778,11 +1927,13 @@ |
1779 | 1928 | $dbw = wfGetDB( DB_MASTER ); |
1780 | 1929 | $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime ); |
1781 | 1930 | } |
| 1931 | + |
1782 | 1932 | if ( !$rev ) { |
1783 | 1933 | wfDebug( "Article::replaceSection asked for bogus section (page: " . |
1784 | 1934 | $this->getId() . "; section: $section; edittime: $edittime)\n" ); |
1785 | 1935 | return null; |
1786 | 1936 | } |
| 1937 | + |
1787 | 1938 | $oldtext = $rev->getText(); |
1788 | 1939 | |
1789 | 1940 | if ( $section == 'new' ) { |
— | — | @@ -1794,9 +1945,11 @@ |
1795 | 1946 | } else { |
1796 | 1947 | # Replacing an existing section; roll out the big guns |
1797 | 1948 | global $wgParser; |
| 1949 | + |
1798 | 1950 | $text = $wgParser->replaceSection( $oldtext, $section, $text ); |
1799 | 1951 | } |
1800 | 1952 | } |
| 1953 | + |
1801 | 1954 | wfProfileOut( __METHOD__ ); |
1802 | 1955 | return $text; |
1803 | 1956 | } |
— | — | @@ -1812,7 +1965,6 @@ |
1813 | 1966 | ( $bot ? EDIT_FORCE_BOT : 0 ); |
1814 | 1967 | |
1815 | 1968 | $this->doEdit( $text, $summary, $flags, false, null, $watchthis, $comment, '', true ); |
1816 | | - |
1817 | 1969 | } |
1818 | 1970 | |
1819 | 1971 | /** |
— | — | @@ -1824,6 +1976,7 @@ |
1825 | 1977 | ( $forceBot ? EDIT_FORCE_BOT : 0 ); |
1826 | 1978 | |
1827 | 1979 | $status = $this->doEdit( $text, $summary, $flags, false, null, $watchthis, false, $sectionanchor, true ); |
| 1980 | + |
1828 | 1981 | if ( !$status->isOK() ) { |
1829 | 1982 | return false; |
1830 | 1983 | } |
— | — | @@ -1847,6 +2000,7 @@ |
1848 | 2001 | |
1849 | 2002 | return $flags; |
1850 | 2003 | } |
| 2004 | + |
1851 | 2005 | /** |
1852 | 2006 | * Article::doEdit() |
1853 | 2007 | * |
— | — | @@ -1919,7 +2073,7 @@ |
1920 | 2074 | $this->loadPageData(); |
1921 | 2075 | |
1922 | 2076 | $flags = $this->checkFlags( $flags ); |
1923 | | - |
| 2077 | + |
1924 | 2078 | # If this is a comment, add the summary as headline |
1925 | 2079 | if ( $comment && $summary != "" ) { |
1926 | 2080 | $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $summary ) . "\n\n" . $text; |
— | — | @@ -1930,9 +2084,11 @@ |
1931 | 2085 | { |
1932 | 2086 | wfDebug( __METHOD__ . ": ArticleSave hook aborted save!\n" ); |
1933 | 2087 | wfProfileOut( __METHOD__ ); |
| 2088 | + |
1934 | 2089 | if ( $status->isOK() ) { |
1935 | 2090 | $status->fatal( 'edit-hook-aborted' ); |
1936 | 2091 | } |
| 2092 | + |
1937 | 2093 | return $status; |
1938 | 2094 | } |
1939 | 2095 | |
— | — | @@ -1959,6 +2115,7 @@ |
1960 | 2116 | if ( $flags & EDIT_UPDATE ) { |
1961 | 2117 | # Update article, but only if changed. |
1962 | 2118 | $status->value['new'] = false; |
| 2119 | + |
1963 | 2120 | # Make sure the revision is either completely inserted or not inserted at all |
1964 | 2121 | if ( !$wgDBtransactions ) { |
1965 | 2122 | $userAbort = ignore_user_abort( true ); |
— | — | @@ -1977,6 +2134,7 @@ |
1978 | 2135 | # Article gone missing |
1979 | 2136 | wfDebug( __METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n" ); |
1980 | 2137 | $status->fatal( 'edit-gone-missing' ); |
| 2138 | + |
1981 | 2139 | wfProfileOut( __METHOD__ ); |
1982 | 2140 | return $status; |
1983 | 2141 | } |
— | — | @@ -1989,7 +2147,7 @@ |
1990 | 2148 | 'parent_id' => $this->mLatest, |
1991 | 2149 | 'user' => $user->getId(), |
1992 | 2150 | 'user_text' => $user->getName(), |
1993 | | - ) ); |
| 2151 | + ) ); |
1994 | 2152 | |
1995 | 2153 | $dbw->begin(); |
1996 | 2154 | $revisionId = $revision->insertOn( $dbw ); |
— | — | @@ -2006,10 +2164,12 @@ |
2007 | 2165 | if ( !$ok ) { |
2008 | 2166 | /* Belated edit conflict! Run away!! */ |
2009 | 2167 | $status->fatal( 'edit-conflict' ); |
| 2168 | + |
2010 | 2169 | # Delete the invalid revision if the DB is not transactional |
2011 | 2170 | if ( !$wgDBtransactions ) { |
2012 | 2171 | $dbw->delete( 'revision', array( 'rev_id' => $revisionId ), __METHOD__ ); |
2013 | 2172 | } |
| 2173 | + |
2014 | 2174 | $revisionId = 0; |
2015 | 2175 | $dbw->rollback(); |
2016 | 2176 | } else { |
— | — | @@ -2024,6 +2184,7 @@ |
2025 | 2185 | $this->mLatest, $this->getTimestamp(), $bot, '', $oldsize, $newsize, |
2026 | 2186 | $revisionId, $patrolled |
2027 | 2187 | ); |
| 2188 | + |
2028 | 2189 | # Log auto-patrolled edits |
2029 | 2190 | if ( $patrolled ) { |
2030 | 2191 | PatrolLog::record( $rc, true ); |
— | — | @@ -2045,6 +2206,7 @@ |
2046 | 2207 | if ( !$wgDBtransactions ) { |
2047 | 2208 | ignore_user_abort( $userAbort ); |
2048 | 2209 | } |
| 2210 | + |
2049 | 2211 | // Now that ignore_user_abort is restored, we can respond to fatal errors |
2050 | 2212 | if ( !$status->isOK() ) { |
2051 | 2213 | wfProfileOut( __METHOD__ ); |
— | — | @@ -2075,6 +2237,7 @@ |
2076 | 2238 | if ( $newid === false ) { |
2077 | 2239 | $dbw->rollback(); |
2078 | 2240 | $status->fatal( 'edit-already-exists' ); |
| 2241 | + |
2079 | 2242 | wfProfileOut( __METHOD__ ); |
2080 | 2243 | return $status; |
2081 | 2244 | } |
— | — | @@ -2096,14 +2259,17 @@ |
2097 | 2260 | $this->updateRevisionOn( $dbw, $revision, 0 ); |
2098 | 2261 | |
2099 | 2262 | wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) ); |
| 2263 | + |
2100 | 2264 | # Update recentchanges |
2101 | 2265 | if ( !( $flags & EDIT_SUPPRESS_RC ) ) { |
2102 | 2266 | global $wgUseRCPatrol, $wgUseNPPatrol; |
| 2267 | + |
2103 | 2268 | # Mark as patrolled if the user can do so |
2104 | 2269 | $patrolled = ( $wgUseRCPatrol || $wgUseNPPatrol ) && $this->mTitle->userCan( 'autopatrol' ); |
2105 | 2270 | # Add RC row to the DB |
2106 | 2271 | $rc = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot, |
2107 | 2272 | '', strlen( $text ), $revisionId, $patrolled ); |
| 2273 | + |
2108 | 2274 | # Log auto-patrolled edits |
2109 | 2275 | if ( $patrolled ) { |
2110 | 2276 | PatrolLog::record( $rc, true ); |
— | — | @@ -2133,7 +2299,7 @@ |
2134 | 2300 | wfRunHooks( 'ArticleSaveComplete', array( &$this, &$user, $text, $summary, |
2135 | 2301 | $flags & EDIT_MINOR, &$watchthis, null, &$flags, $revision, &$status, $baseRevId, |
2136 | 2302 | &$redirect) ); |
2137 | | - |
| 2303 | + |
2138 | 2304 | # Watch or unwatch the page |
2139 | 2305 | if ( $watchthis === true ) { |
2140 | 2306 | if ( !$this->mTitle->userIsWatching() ) { |
— | — | @@ -2148,10 +2314,12 @@ |
2149 | 2315 | $dbw->commit(); |
2150 | 2316 | } |
2151 | 2317 | } |
2152 | | - |
| 2318 | + |
2153 | 2319 | # Give extensions a chance to modify URL query on update |
2154 | | - $extraQuery = ''; |
| 2320 | + $extraQuery = ''; |
| 2321 | + |
2155 | 2322 | wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this, &$sectionanchor, &$extraQuery ) ); |
| 2323 | + |
2156 | 2324 | if ( $redirect ) { |
2157 | 2325 | if ( $sectionanchor || $extraQuery ) { |
2158 | 2326 | $this->doRedirect( $this->isRedirect( $text ), $sectionanchor, $extraQuery ); |
— | — | @@ -2159,9 +2327,9 @@ |
2160 | 2328 | $this->doRedirect( $this->isRedirect( $text ) ); |
2161 | 2329 | } |
2162 | 2330 | } |
2163 | | - |
| 2331 | + |
2164 | 2332 | wfProfileOut( __METHOD__ ); |
2165 | | - |
| 2333 | + |
2166 | 2334 | return $status; |
2167 | 2335 | } |
2168 | 2336 | |
— | — | @@ -2183,6 +2351,7 @@ |
2184 | 2352 | */ |
2185 | 2353 | public function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) { |
2186 | 2354 | global $wgOut; |
| 2355 | + |
2187 | 2356 | if ( $noRedir ) { |
2188 | 2357 | $query = 'redirect=no'; |
2189 | 2358 | if ( $extraQuery ) |
— | — | @@ -2190,6 +2359,7 @@ |
2191 | 2360 | } else { |
2192 | 2361 | $query = $extraQuery; |
2193 | 2362 | } |
| 2363 | + |
2194 | 2364 | $wgOut->redirect( $this->mTitle->getFullURL( $query ) . $sectionAnchor ); |
2195 | 2365 | } |
2196 | 2366 | |
— | — | @@ -2198,11 +2368,13 @@ |
2199 | 2369 | */ |
2200 | 2370 | public function markpatrolled() { |
2201 | 2371 | global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUseNPPatrol, $wgUser; |
| 2372 | + |
2202 | 2373 | $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2203 | 2374 | |
2204 | 2375 | # If we haven't been given an rc_id value, we can't do anything |
2205 | 2376 | $rcid = (int) $wgRequest->getVal( 'rcid' ); |
2206 | 2377 | $rc = RecentChange::newFromId( $rcid ); |
| 2378 | + |
2207 | 2379 | if ( is_null( $rc ) ) { |
2208 | 2380 | $wgOut->showErrorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' ); |
2209 | 2381 | return; |
— | — | @@ -2217,6 +2389,7 @@ |
2218 | 2390 | |
2219 | 2391 | if ( in_array( array( 'rcpatroldisabled' ), $errors ) ) { |
2220 | 2392 | $wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' ); |
| 2393 | + |
2221 | 2394 | return; |
2222 | 2395 | } |
2223 | 2396 | |
— | — | @@ -2229,11 +2402,13 @@ |
2230 | 2403 | $wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) ); |
2231 | 2404 | $wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' ); |
2232 | 2405 | $wgOut->returnToMain( false, $return ); |
| 2406 | + |
2233 | 2407 | return; |
2234 | 2408 | } |
2235 | 2409 | |
2236 | 2410 | if ( !empty( $errors ) ) { |
2237 | 2411 | $wgOut->showPermissionsErrorPage( $errors ); |
| 2412 | + |
2238 | 2413 | return; |
2239 | 2414 | } |
2240 | 2415 | |
— | — | @@ -2248,19 +2423,23 @@ |
2249 | 2424 | */ |
2250 | 2425 | public function watch() { |
2251 | 2426 | global $wgUser, $wgOut; |
| 2427 | + |
2252 | 2428 | if ( $wgUser->isAnon() ) { |
2253 | 2429 | $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' ); |
2254 | 2430 | return; |
2255 | 2431 | } |
| 2432 | + |
2256 | 2433 | if ( wfReadOnly() ) { |
2257 | 2434 | $wgOut->readOnlyPage(); |
2258 | 2435 | return; |
2259 | 2436 | } |
| 2437 | + |
2260 | 2438 | if ( $this->doWatch() ) { |
2261 | 2439 | $wgOut->setPagetitle( wfMsg( 'addedwatch' ) ); |
2262 | 2440 | $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2263 | 2441 | $wgOut->addWikiMsg( 'addedwatchtext', $this->mTitle->getPrefixedText() ); |
2264 | 2442 | } |
| 2443 | + |
2265 | 2444 | $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() ); |
2266 | 2445 | } |
2267 | 2446 | |
— | — | @@ -2270,13 +2449,16 @@ |
2271 | 2450 | */ |
2272 | 2451 | public function doWatch() { |
2273 | 2452 | global $wgUser; |
| 2453 | + |
2274 | 2454 | if ( $wgUser->isAnon() ) { |
2275 | 2455 | return false; |
2276 | 2456 | } |
| 2457 | + |
2277 | 2458 | if ( wfRunHooks( 'WatchArticle', array( &$wgUser, &$this ) ) ) { |
2278 | 2459 | $wgUser->addWatch( $this->mTitle ); |
2279 | 2460 | return wfRunHooks( 'WatchArticleComplete', array( &$wgUser, &$this ) ); |
2280 | 2461 | } |
| 2462 | + |
2281 | 2463 | return false; |
2282 | 2464 | } |
2283 | 2465 | |
— | — | @@ -2285,19 +2467,23 @@ |
2286 | 2468 | */ |
2287 | 2469 | public function unwatch() { |
2288 | 2470 | global $wgUser, $wgOut; |
| 2471 | + |
2289 | 2472 | if ( $wgUser->isAnon() ) { |
2290 | 2473 | $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' ); |
2291 | 2474 | return; |
2292 | 2475 | } |
| 2476 | + |
2293 | 2477 | if ( wfReadOnly() ) { |
2294 | 2478 | $wgOut->readOnlyPage(); |
2295 | 2479 | return; |
2296 | 2480 | } |
| 2481 | + |
2297 | 2482 | if ( $this->doUnwatch() ) { |
2298 | 2483 | $wgOut->setPagetitle( wfMsg( 'removedwatch' ) ); |
2299 | 2484 | $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
2300 | 2485 | $wgOut->addWikiMsg( 'removedwatchtext', $this->mTitle->getPrefixedText() ); |
2301 | 2486 | } |
| 2487 | + |
2302 | 2488 | $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() ); |
2303 | 2489 | } |
2304 | 2490 | |
— | — | @@ -2307,13 +2493,16 @@ |
2308 | 2494 | */ |
2309 | 2495 | public function doUnwatch() { |
2310 | 2496 | global $wgUser; |
| 2497 | + |
2311 | 2498 | if ( $wgUser->isAnon() ) { |
2312 | 2499 | return false; |
2313 | 2500 | } |
| 2501 | + |
2314 | 2502 | if ( wfRunHooks( 'UnwatchArticle', array( &$wgUser, &$this ) ) ) { |
2315 | 2503 | $wgUser->removeWatch( $this->mTitle ); |
2316 | 2504 | return wfRunHooks( 'UnwatchArticleComplete', array( &$wgUser, &$this ) ); |
2317 | 2505 | } |
| 2506 | + |
2318 | 2507 | return false; |
2319 | 2508 | } |
2320 | 2509 | |
— | — | @@ -2347,6 +2536,7 @@ |
2348 | 2537 | $restrictionTypes = $this->mTitle->getRestrictionTypes(); |
2349 | 2538 | |
2350 | 2539 | $id = $this->mTitle->getArticleID(); |
| 2540 | + |
2351 | 2541 | if ( $id <= 0 ) { |
2352 | 2542 | wfDebug( "updateRestrictions failed: $id <= 0\n" ); |
2353 | 2543 | return false; |
— | — | @@ -2374,6 +2564,7 @@ |
2375 | 2565 | $current = array(); |
2376 | 2566 | $updated = Article::flattenRestrictions( $limit ); |
2377 | 2567 | $changed = false; |
| 2568 | + |
2378 | 2569 | foreach ( $restrictionTypes as $action ) { |
2379 | 2570 | if ( isset( $expiry[$action] ) ) { |
2380 | 2571 | # Get current restrictions on $action |
— | — | @@ -2381,6 +2572,7 @@ |
2382 | 2573 | $current[$action] = implode( '', $aLimits ); |
2383 | 2574 | # Are any actual restrictions being dealt with here? |
2384 | 2575 | $aRChanged = count( $aLimits ) || !empty( $limit[$action] ); |
| 2576 | + |
2385 | 2577 | # If something changed, we need to log it. Checking $aRChanged |
2386 | 2578 | # assures that "unprotecting" a page that is not protected does |
2387 | 2579 | # not log just because the expiry was "changed". |
— | — | @@ -2399,36 +2591,42 @@ |
2400 | 2592 | # If nothing's changed, do nothing |
2401 | 2593 | if ( $changed ) { |
2402 | 2594 | if ( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) { |
2403 | | - |
2404 | 2595 | $dbw = wfGetDB( DB_MASTER ); |
2405 | 2596 | |
2406 | 2597 | # Prepare a null revision to be added to the history |
2407 | 2598 | $modified = $current != '' && $protect; |
| 2599 | + |
2408 | 2600 | if ( $protect ) { |
2409 | 2601 | $comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle'; |
2410 | 2602 | } else { |
2411 | 2603 | $comment_type = 'unprotectedarticle'; |
2412 | 2604 | } |
| 2605 | + |
2413 | 2606 | $comment = $wgContLang->ucfirst( wfMsgForContent( $comment_type, $this->mTitle->getPrefixedText() ) ); |
2414 | 2607 | |
2415 | 2608 | # Only restrictions with the 'protect' right can cascade... |
2416 | 2609 | # Otherwise, people who cannot normally protect can "protect" pages via transclusion |
2417 | 2610 | $editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' ); |
| 2611 | + |
2418 | 2612 | # The schema allows multiple restrictions |
2419 | | - if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) |
| 2613 | + if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) { |
2420 | 2614 | $cascade = false; |
| 2615 | + } |
| 2616 | + |
2421 | 2617 | $cascade_description = ''; |
| 2618 | + |
2422 | 2619 | if ( $cascade ) { |
2423 | 2620 | $cascade_description = ' [' . wfMsgForContent( 'protect-summary-cascade' ) . ']'; |
2424 | 2621 | } |
2425 | 2622 | |
2426 | | - if ( $reason ) |
| 2623 | + if ( $reason ) { |
2427 | 2624 | $comment .= ": $reason"; |
| 2625 | + } |
2428 | 2626 | |
2429 | 2627 | $editComment = $comment; |
2430 | 2628 | $encodedExpiry = array(); |
2431 | 2629 | $protect_description = ''; |
2432 | | - foreach ( $limit as $action => $restrictions ) { |
| 2630 | + foreach ( $limit as $action => $restrictions ) { |
2433 | 2631 | if ( !isset( $expiry[$action] ) ) |
2434 | 2632 | $expiry[$action] = 'infinite'; |
2435 | 2633 | |
— | — | @@ -2443,15 +2641,20 @@ |
2444 | 2642 | } else { |
2445 | 2643 | $protect_description .= wfMsgForContent( 'protect-expiry-indefinite' ); |
2446 | 2644 | } |
| 2645 | + |
2447 | 2646 | $protect_description .= ') '; |
2448 | 2647 | } |
2449 | 2648 | } |
2450 | 2649 | $protect_description = trim( $protect_description ); |
2451 | 2650 | |
2452 | | - if ( $protect_description && $protect ) |
| 2651 | + if ( $protect_description && $protect ) { |
2453 | 2652 | $editComment .= " ($protect_description)"; |
2454 | | - if ( $cascade ) |
| 2653 | + } |
| 2654 | + |
| 2655 | + if ( $cascade ) { |
2455 | 2656 | $editComment .= "$cascade_description"; |
| 2657 | + } |
| 2658 | + |
2456 | 2659 | # Update restrictions table |
2457 | 2660 | foreach ( $limit as $action => $restrictions ) { |
2458 | 2661 | if ( $restrictions != '' ) { |
— | — | @@ -2460,7 +2663,10 @@ |
2461 | 2664 | 'pr_type' => $action, |
2462 | 2665 | 'pr_level' => $restrictions, |
2463 | 2666 | 'pr_cascade' => ( $cascade && $action == 'edit' ) ? 1 : 0, |
2464 | | - 'pr_expiry' => $encodedExpiry[$action] ), __METHOD__ ); |
| 2667 | + 'pr_expiry' => $encodedExpiry[$action] |
| 2668 | + ), |
| 2669 | + __METHOD__ |
| 2670 | + ); |
2465 | 2671 | } else { |
2466 | 2672 | $dbw->delete( 'page_restrictions', array( 'pr_page' => $id, |
2467 | 2673 | 'pr_type' => $action ), __METHOD__ ); |
— | — | @@ -2494,7 +2700,6 @@ |
2495 | 2701 | } else { |
2496 | 2702 | $log->addEntry( 'unprotect', $this->mTitle, $reason ); |
2497 | 2703 | } |
2498 | | - |
2499 | 2704 | } # End hook |
2500 | 2705 | } # End "changed" check |
2501 | 2706 | |
— | — | @@ -2511,38 +2716,46 @@ |
2512 | 2717 | if ( !is_array( $limit ) ) { |
2513 | 2718 | throw new MWException( 'Article::flattenRestrictions given non-array restriction set' ); |
2514 | 2719 | } |
| 2720 | + |
2515 | 2721 | $bits = array(); |
2516 | 2722 | ksort( $limit ); |
| 2723 | + |
2517 | 2724 | foreach ( $limit as $action => $restrictions ) { |
2518 | 2725 | if ( $restrictions != '' ) { |
2519 | 2726 | $bits[] = "$action=$restrictions"; |
2520 | 2727 | } |
2521 | 2728 | } |
| 2729 | + |
2522 | 2730 | return implode( ':', $bits ); |
2523 | 2731 | } |
2524 | 2732 | |
2525 | 2733 | /** |
2526 | 2734 | * Auto-generates a deletion reason |
2527 | | - * |
| 2735 | + * |
2528 | 2736 | * @param &$hasHistory Boolean: whether the page has a history |
2529 | 2737 | * @return mixed String containing deletion reason or empty string, or boolean false |
2530 | 2738 | * if no revision occurred |
2531 | 2739 | */ |
2532 | 2740 | public function generateReason( &$hasHistory ) { |
2533 | 2741 | global $wgContLang; |
| 2742 | + |
2534 | 2743 | $dbw = wfGetDB( DB_MASTER ); |
2535 | 2744 | // Get the last revision |
2536 | 2745 | $rev = Revision::newFromTitle( $this->mTitle ); |
2537 | | - if ( is_null( $rev ) ) |
| 2746 | + |
| 2747 | + if ( is_null( $rev ) ) { |
2538 | 2748 | return false; |
| 2749 | + } |
2539 | 2750 | |
2540 | 2751 | // Get the article's contents |
2541 | 2752 | $contents = $rev->getText(); |
2542 | 2753 | $blank = false; |
| 2754 | + |
2543 | 2755 | // If the page is blank, use the text from the previous revision, |
2544 | 2756 | // which can only be blank if there's a move/import/protect dummy revision involved |
2545 | 2757 | if ( $contents == '' ) { |
2546 | 2758 | $prev = $rev->getPrevious(); |
| 2759 | + |
2547 | 2760 | if ( $prev ) { |
2548 | 2761 | $contents = $prev->getText(); |
2549 | 2762 | $blank = true; |
— | — | @@ -2556,12 +2769,15 @@ |
2557 | 2770 | __METHOD__, |
2558 | 2771 | array( 'LIMIT' => 20 ) |
2559 | 2772 | ); |
2560 | | - if ( $res === false ) |
| 2773 | + |
| 2774 | + if ( $res === false ) { |
2561 | 2775 | // This page has no revisions, which is very weird |
2562 | 2776 | return false; |
| 2777 | + } |
2563 | 2778 | |
2564 | 2779 | $hasHistory = ( $res->numRows() > 1 ); |
2565 | 2780 | $row = $dbw->fetchObject( $res ); |
| 2781 | + |
2566 | 2782 | if ( $row ) { // $row is false if the only contributor is hidden |
2567 | 2783 | $onlyAuthor = $row->rev_user_text; |
2568 | 2784 | // Try to find a second contributor |
— | — | @@ -2574,6 +2790,7 @@ |
2575 | 2791 | } else { |
2576 | 2792 | $onlyAuthor = false; |
2577 | 2793 | } |
| 2794 | + |
2578 | 2795 | $dbw->freeResult( $res ); |
2579 | 2796 | |
2580 | 2797 | // Generate the summary with a '$1' placeholder |
— | — | @@ -2582,10 +2799,11 @@ |
2583 | 2800 | // blank. It's just not our lucky day |
2584 | 2801 | $reason = wfMsgForContent( 'exbeforeblank', '$1' ); |
2585 | 2802 | } else { |
2586 | | - if ( $onlyAuthor ) |
| 2803 | + if ( $onlyAuthor ) { |
2587 | 2804 | $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor ); |
2588 | | - else |
| 2805 | + } else { |
2589 | 2806 | $reason = wfMsgForContent( 'excontent', '$1' ); |
| 2807 | + } |
2590 | 2808 | } |
2591 | 2809 | |
2592 | 2810 | if ( $reason == '-' ) { |
— | — | @@ -2603,6 +2821,7 @@ |
2604 | 2822 | $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents ); |
2605 | 2823 | // Now replace the '$1' placeholder |
2606 | 2824 | $reason = str_replace( '$1', $contents, $reason ); |
| 2825 | + |
2607 | 2826 | return $reason; |
2608 | 2827 | } |
2609 | 2828 | |
— | — | @@ -2627,6 +2846,7 @@ |
2628 | 2847 | } elseif ( $reason == 'other' ) { |
2629 | 2848 | $reason = $this->DeleteReason; |
2630 | 2849 | } |
| 2850 | + |
2631 | 2851 | # Flag to hide all contents of the archived revisions |
2632 | 2852 | $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed( 'suppressrevision' ); |
2633 | 2853 | |
— | — | @@ -2635,6 +2855,7 @@ |
2636 | 2856 | # Read-only check... |
2637 | 2857 | if ( wfReadOnly() ) { |
2638 | 2858 | $wgOut->readOnlyPage(); |
| 2859 | + |
2639 | 2860 | return; |
2640 | 2861 | } |
2641 | 2862 | |
— | — | @@ -2643,6 +2864,7 @@ |
2644 | 2865 | |
2645 | 2866 | if ( count( $permission_errors ) > 0 ) { |
2646 | 2867 | $wgOut->showPermissionsErrorPage( $permission_errors ); |
| 2868 | + |
2647 | 2869 | return; |
2648 | 2870 | } |
2649 | 2871 | |
— | — | @@ -2666,6 +2888,7 @@ |
2667 | 2889 | 'delete', |
2668 | 2890 | $this->mTitle->getPrefixedText() |
2669 | 2891 | ); |
| 2892 | + |
2670 | 2893 | return; |
2671 | 2894 | } |
2672 | 2895 | |
— | — | @@ -2673,28 +2896,35 @@ |
2674 | 2897 | $bigHistory = $this->isBigDeletion(); |
2675 | 2898 | if ( $bigHistory && !$this->mTitle->userCan( 'bigdelete' ) ) { |
2676 | 2899 | global $wgLang, $wgDeleteRevisionsLimit; |
| 2900 | + |
2677 | 2901 | $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n", |
2678 | 2902 | array( 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); |
| 2903 | + |
2679 | 2904 | return; |
2680 | 2905 | } |
2681 | 2906 | |
2682 | 2907 | if ( $confirm ) { |
2683 | 2908 | $this->doDelete( $reason, $suppress ); |
| 2909 | + |
2684 | 2910 | if ( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) { |
2685 | 2911 | $this->doWatch(); |
2686 | 2912 | } elseif ( $this->mTitle->userIsWatching() ) { |
2687 | 2913 | $this->doUnwatch(); |
2688 | 2914 | } |
| 2915 | + |
2689 | 2916 | return; |
2690 | 2917 | } |
2691 | 2918 | |
2692 | 2919 | // Generate deletion reason |
2693 | 2920 | $hasHistory = false; |
2694 | | - if ( !$reason ) $reason = $this->generateReason( $hasHistory ); |
| 2921 | + if ( !$reason ) { |
| 2922 | + $reason = $this->generateReason( $hasHistory ); |
| 2923 | + } |
2695 | 2924 | |
2696 | 2925 | // If the page has a history, insert a warning |
2697 | 2926 | if ( $hasHistory && !$confirm ) { |
2698 | 2927 | global $wgLang; |
| 2928 | + |
2699 | 2929 | $skin = $wgUser->getSkin(); |
2700 | 2930 | $revisions = $this->estimateRevisionCount(); |
2701 | 2931 | $wgOut->addHTML( '<strong class="mw-delete-warning-revisions">' . |
— | — | @@ -2702,8 +2932,10 @@ |
2703 | 2933 | wfMsgHtml( 'word-separator' ) . $skin->historyLink() . |
2704 | 2934 | '</strong>' |
2705 | 2935 | ); |
| 2936 | + |
2706 | 2937 | if ( $bigHistory ) { |
2707 | 2938 | global $wgDeleteRevisionsLimit; |
| 2939 | + |
2708 | 2940 | $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n", |
2709 | 2941 | array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) ); |
2710 | 2942 | } |
— | — | @@ -2717,10 +2949,13 @@ |
2718 | 2950 | */ |
2719 | 2951 | public function isBigDeletion() { |
2720 | 2952 | global $wgDeleteRevisionsLimit; |
| 2953 | + |
2721 | 2954 | if ( $wgDeleteRevisionsLimit ) { |
2722 | 2955 | $revCount = $this->estimateRevisionCount(); |
| 2956 | + |
2723 | 2957 | return $revCount > $wgDeleteRevisionsLimit; |
2724 | 2958 | } |
| 2959 | + |
2725 | 2960 | return false; |
2726 | 2961 | } |
2727 | 2962 | |
— | — | @@ -2729,6 +2964,7 @@ |
2730 | 2965 | */ |
2731 | 2966 | public function estimateRevisionCount() { |
2732 | 2967 | $dbr = wfGetDB( DB_SLAVE ); |
| 2968 | + |
2733 | 2969 | // For an exact count... |
2734 | 2970 | // return $dbr->selectField( 'revision', 'COUNT(*)', |
2735 | 2971 | // array( 'rev_page' => $this->getId() ), __METHOD__ ); |
— | — | @@ -2748,6 +2984,7 @@ |
2749 | 2985 | // If that doesn't have the latest revision, try the master |
2750 | 2986 | $continue = 2; |
2751 | 2987 | $db = wfGetDB( DB_SLAVE ); |
| 2988 | + |
2752 | 2989 | do { |
2753 | 2990 | $res = $db->select( array( 'page', 'revision' ), |
2754 | 2991 | array( 'rev_id', 'rev_user_text' ), |
— | — | @@ -2760,11 +2997,14 @@ |
2761 | 2998 | 'LIMIT' => $num |
2762 | 2999 | ) ) |
2763 | 3000 | ); |
| 3001 | + |
2764 | 3002 | if ( !$res ) { |
2765 | 3003 | wfProfileOut( __METHOD__ ); |
2766 | 3004 | return array(); |
2767 | 3005 | } |
| 3006 | + |
2768 | 3007 | $row = $db->fetchObject( $res ); |
| 3008 | + |
2769 | 3009 | if ( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) { |
2770 | 3010 | $db = wfGetDB( DB_MASTER ); |
2771 | 3011 | $continue--; |
— | — | @@ -2774,9 +3014,11 @@ |
2775 | 3015 | } while ( $continue ); |
2776 | 3016 | |
2777 | 3017 | $authors = array( $row->rev_user_text ); |
| 3018 | + |
2778 | 3019 | while ( $row = $db->fetchObject( $res ) ) { |
2779 | 3020 | $authors[] = $row->rev_user_text; |
2780 | 3021 | } |
| 3022 | + |
2781 | 3023 | wfProfileOut( __METHOD__ ); |
2782 | 3024 | return $authors; |
2783 | 3025 | } |
— | — | @@ -2845,6 +3087,7 @@ |
2846 | 3088 | ) ) . |
2847 | 3089 | "</td> |
2848 | 3090 | </tr>"; |
| 3091 | + |
2849 | 3092 | # Disallow watching if user is not logged in |
2850 | 3093 | if ( $wgUser->isLoggedIn() ) { |
2851 | 3094 | $form .= " |
— | — | @@ -2856,6 +3099,7 @@ |
2857 | 3100 | "</td> |
2858 | 3101 | </tr>"; |
2859 | 3102 | } |
| 3103 | + |
2860 | 3104 | $form .= " |
2861 | 3105 | $suppress |
2862 | 3106 | <tr> |
— | — | @@ -2896,6 +3140,7 @@ |
2897 | 3141 | */ |
2898 | 3142 | public function doDelete( $reason, $suppress = false ) { |
2899 | 3143 | global $wgOut, $wgUser; |
| 3144 | + |
2900 | 3145 | $id = $this->mTitle->getArticleID( GAID_FOR_UPDATE ); |
2901 | 3146 | |
2902 | 3147 | $error = ''; |
— | — | @@ -2921,7 +3166,9 @@ |
2922 | 3167 | wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() ) |
2923 | 3168 | ) |
2924 | 3169 | ); |
| 3170 | + |
2925 | 3171 | $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) ); |
| 3172 | + |
2926 | 3173 | LogEventsList::showLogExtract( |
2927 | 3174 | $wgOut, |
2928 | 3175 | 'delete', |
— | — | @@ -3016,6 +3263,7 @@ |
3017 | 3264 | # Now that it's safely backed up, delete it |
3018 | 3265 | $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ ); |
3019 | 3266 | $ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy |
| 3267 | + |
3020 | 3268 | if ( !$ok ) { |
3021 | 3269 | $dbw->rollback(); |
3022 | 3270 | return false; |
— | — | @@ -3024,9 +3272,11 @@ |
3025 | 3273 | # Fix category table counts |
3026 | 3274 | $cats = array(); |
3027 | 3275 | $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ ); |
| 3276 | + |
3028 | 3277 | foreach ( $res as $row ) { |
3029 | 3278 | $cats [] = $row->cl_to; |
3030 | 3279 | } |
| 3280 | + |
3031 | 3281 | $this->updateCategoryCounts( array(), $cats ); |
3032 | 3282 | |
3033 | 3283 | # If using cascading deletes, we can skip some explicit deletes |
— | — | @@ -3102,6 +3352,7 @@ |
3103 | 3353 | */ |
3104 | 3354 | public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) { |
3105 | 3355 | global $wgUser; |
| 3356 | + |
3106 | 3357 | $resultDetails = null; |
3107 | 3358 | |
3108 | 3359 | # Check permissions |
— | — | @@ -3109,15 +3360,18 @@ |
3110 | 3361 | $rollbackErrors = $this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser ); |
3111 | 3362 | $errors = array_merge( $editErrors, wfArrayDiff2( $rollbackErrors, $editErrors ) ); |
3112 | 3363 | |
3113 | | - if ( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) ) |
| 3364 | + if ( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) ) { |
3114 | 3365 | $errors[] = array( 'sessionfailure' ); |
| 3366 | + } |
3115 | 3367 | |
3116 | 3368 | if ( $wgUser->pingLimiter( 'rollback' ) || $wgUser->pingLimiter() ) { |
3117 | 3369 | $errors[] = array( 'actionthrottledtext' ); |
3118 | 3370 | } |
| 3371 | + |
3119 | 3372 | # If there were errors, bail out now |
3120 | | - if ( !empty( $errors ) ) |
| 3373 | + if ( !empty( $errors ) ) { |
3121 | 3374 | return $errors; |
| 3375 | + } |
3122 | 3376 | |
3123 | 3377 | return $this->commitRollback( $fromP, $summary, $bot, $resultDetails ); |
3124 | 3378 | } |
— | — | @@ -3133,6 +3387,7 @@ |
3134 | 3388 | */ |
3135 | 3389 | public function commitRollback( $fromP, $summary, $bot, &$resultDetails ) { |
3136 | 3390 | global $wgUseRCPatrol, $wgUser, $wgLang; |
| 3391 | + |
3137 | 3392 | $dbw = wfGetDB( DB_MASTER ); |
3138 | 3393 | |
3139 | 3394 | if ( wfReadOnly() ) { |
— | — | @@ -3168,7 +3423,7 @@ |
3169 | 3424 | "rev_user != {$user} OR rev_user_text != {$user_text}" |
3170 | 3425 | ), __METHOD__, |
3171 | 3426 | array( 'USE INDEX' => 'page_timestamp', |
3172 | | - 'ORDER BY' => 'rev_timestamp DESC' ) |
| 3427 | + 'ORDER BY' => 'rev_timestamp DESC' ) |
3173 | 3428 | ); |
3174 | 3429 | if ( $s === false ) { |
3175 | 3430 | # No one else ever edited this page |
— | — | @@ -3183,6 +3438,7 @@ |
3184 | 3439 | # Mark all reverted edits as bot |
3185 | 3440 | $set['rc_bot'] = 1; |
3186 | 3441 | } |
| 3442 | + |
3187 | 3443 | if ( $wgUseRCPatrol ) { |
3188 | 3444 | # Mark all reverted edits as patrolled |
3189 | 3445 | $set['rc_patrolled'] = 1; |
— | — | @@ -3219,11 +3475,14 @@ |
3220 | 3476 | # Save |
3221 | 3477 | $flags = EDIT_UPDATE; |
3222 | 3478 | |
3223 | | - if ( $wgUser->isAllowed( 'minoredit' ) ) |
| 3479 | + if ( $wgUser->isAllowed( 'minoredit' ) ) { |
3224 | 3480 | $flags |= EDIT_MINOR; |
| 3481 | + } |
3225 | 3482 | |
3226 | | - if ( $bot && ( $wgUser->isAllowed( 'markbotedits' ) || $wgUser->isAllowed( 'bot' ) ) ) |
| 3483 | + if ( $bot && ( $wgUser->isAllowed( 'markbotedits' ) || $wgUser->isAllowed( 'bot' ) ) ) { |
3227 | 3484 | $flags |= EDIT_FORCE_BOT; |
| 3485 | + } |
| 3486 | + |
3228 | 3487 | # Actually store the edit |
3229 | 3488 | $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId() ); |
3230 | 3489 | if ( !empty( $status->value['revision'] ) ) { |
— | — | @@ -3240,6 +3499,7 @@ |
3241 | 3500 | 'target' => $target, |
3242 | 3501 | 'newid' => $revId |
3243 | 3502 | ); |
| 3503 | + |
3244 | 3504 | return array(); |
3245 | 3505 | } |
3246 | 3506 | |
— | — | @@ -3248,6 +3508,7 @@ |
3249 | 3509 | */ |
3250 | 3510 | public function rollback() { |
3251 | 3511 | global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol; |
| 3512 | + |
3252 | 3513 | $details = null; |
3253 | 3514 | |
3254 | 3515 | $result = $this->doRollback( |
— | — | @@ -3262,26 +3523,31 @@ |
3263 | 3524 | $wgOut->rateLimited(); |
3264 | 3525 | return; |
3265 | 3526 | } |
| 3527 | + |
3266 | 3528 | if ( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) { |
3267 | 3529 | $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) ); |
3268 | 3530 | $errArray = $result[0]; |
3269 | 3531 | $errMsg = array_shift( $errArray ); |
3270 | 3532 | $wgOut->addWikiMsgArray( $errMsg, $errArray ); |
| 3533 | + |
3271 | 3534 | if ( isset( $details['current'] ) ) { |
3272 | 3535 | $current = $details['current']; |
| 3536 | + |
3273 | 3537 | if ( $current->getComment() != '' ) { |
3274 | 3538 | $wgOut->addWikiMsgArray( 'editcomment', array( |
3275 | 3539 | $wgUser->getSkin()->formatComment( $current->getComment() ) ), array( 'replaceafter' ) ); |
3276 | 3540 | } |
3277 | 3541 | } |
| 3542 | + |
3278 | 3543 | return; |
3279 | 3544 | } |
| 3545 | + |
3280 | 3546 | # Display permissions errors before read-only message -- there's no |
3281 | 3547 | # point in misleading the user into thinking the inability to rollback |
3282 | 3548 | # is only temporary. |
3283 | 3549 | if ( !empty( $result ) && $result !== array( array( 'readonlytext' ) ) ) { |
3284 | | - # array_diff is completely broken for arrays of arrays, sigh. Re- |
3285 | | - # move any 'readonlytext' error manually. |
| 3550 | + # array_diff is completely broken for arrays of arrays, sigh. |
| 3551 | + # Remove any 'readonlytext' error manually. |
3286 | 3552 | $out = array(); |
3287 | 3553 | foreach ( $result as $error ) { |
3288 | 3554 | if ( $error != array( 'readonlytext' ) ) { |
— | — | @@ -3289,10 +3555,13 @@ |
3290 | 3556 | } |
3291 | 3557 | } |
3292 | 3558 | $wgOut->showPermissionsErrorPage( $out ); |
| 3559 | + |
3293 | 3560 | return; |
3294 | 3561 | } |
| 3562 | + |
3295 | 3563 | if ( $result == array( array( 'readonlytext' ) ) ) { |
3296 | 3564 | $wgOut->readOnlyPage(); |
| 3565 | + |
3297 | 3566 | return; |
3298 | 3567 | } |
3299 | 3568 | |
— | — | @@ -3301,12 +3570,14 @@ |
3302 | 3571 | $newId = $details['newid']; |
3303 | 3572 | $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) ); |
3304 | 3573 | $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
| 3574 | + |
3305 | 3575 | if ( $current->getUserText() === '' ) { |
3306 | 3576 | $old = wfMsg( 'rev-deleted-user' ); |
3307 | 3577 | } else { |
3308 | 3578 | $old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() ) |
3309 | 3579 | . $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() ); |
3310 | 3580 | } |
| 3581 | + |
3311 | 3582 | $new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() ) |
3312 | 3583 | . $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() ); |
3313 | 3584 | $wgOut->addHTML( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) ); |
— | — | @@ -3318,7 +3589,6 @@ |
3319 | 3590 | } |
3320 | 3591 | } |
3321 | 3592 | |
3322 | | - |
3323 | 3593 | /** |
3324 | 3594 | * Do standard deferred updates after page view |
3325 | 3595 | */ |
— | — | @@ -3327,12 +3597,14 @@ |
3328 | 3598 | if ( wfReadOnly() ) { |
3329 | 3599 | return; |
3330 | 3600 | } |
| 3601 | + |
3331 | 3602 | # Don't update page view counters on views from bot users (bug 14044) |
3332 | 3603 | if ( !$wgDisableCounters && !$wgUser->isAllowed( 'bot' ) && $this->getID() ) { |
3333 | 3604 | Article::incViewCount( $this->getID() ); |
3334 | 3605 | $u = new SiteStatsUpdate( 1, 0, 0 ); |
3335 | 3606 | array_push( $wgDeferredUpdateList, $u ); |
3336 | 3607 | } |
| 3608 | + |
3337 | 3609 | # Update newtalk / watchlist notification status |
3338 | 3610 | $wgUser->clearNotification( $this->mTitle ); |
3339 | 3611 | } |
— | — | @@ -3346,7 +3618,9 @@ |
3347 | 3619 | // Already prepared |
3348 | 3620 | return $this->mPreparedEdit; |
3349 | 3621 | } |
| 3622 | + |
3350 | 3623 | global $wgParser; |
| 3624 | + |
3351 | 3625 | $edit = (object)array(); |
3352 | 3626 | $edit->revid = $revid; |
3353 | 3627 | $edit->newText = $text; |
— | — | @@ -3354,7 +3628,9 @@ |
3355 | 3629 | $options = $this->getParserOptions(); |
3356 | 3630 | $edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $options, true, true, $revid ); |
3357 | 3631 | $edit->oldText = $this->getContent(); |
| 3632 | + |
3358 | 3633 | $this->mPreparedEdit = $edit; |
| 3634 | + |
3359 | 3635 | return $edit; |
3360 | 3636 | } |
3361 | 3637 | |
— | — | @@ -3405,10 +3681,12 @@ |
3406 | 3682 | // Flush old entries from the `recentchanges` table; we do this on |
3407 | 3683 | // random requests so as to avoid an increase in writes for no good reason |
3408 | 3684 | global $wgRCMaxAge; |
| 3685 | + |
3409 | 3686 | $dbw = wfGetDB( DB_MASTER ); |
3410 | 3687 | $cutoff = $dbw->timestamp( time() - $wgRCMaxAge ); |
3411 | 3688 | $recentchanges = $dbw->tableName( 'recentchanges' ); |
3412 | 3689 | $sql = "DELETE FROM $recentchanges WHERE rc_timestamp < '{$cutoff}'"; |
| 3690 | + |
3413 | 3691 | $dbw->query( $sql ); |
3414 | 3692 | } |
3415 | 3693 | } |
— | — | @@ -3432,7 +3710,8 @@ |
3433 | 3711 | # load of user talk pages and piss people off, nor if it's a minor edit |
3434 | 3712 | # by a properly-flagged bot. |
3435 | 3713 | if ( $this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getTitleKey() && $changed |
3436 | | - && !( $minoredit && $wgUser->isAllowed( 'nominornewtalk' ) ) ) { |
| 3714 | + && !( $minoredit && $wgUser->isAllowed( 'nominornewtalk' ) ) |
| 3715 | + ) { |
3437 | 3716 | if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) { |
3438 | 3717 | $other = User::newFromName( $shortTitle, false ); |
3439 | 3718 | if ( !$other ) { |
— | — | @@ -3487,11 +3766,13 @@ |
3488 | 3767 | } |
3489 | 3768 | |
3490 | 3769 | $unhide = $wgRequest->getInt( 'unhide' ) == 1; |
| 3770 | + |
3491 | 3771 | # Cascade unhide param in links for easy deletion browsing |
3492 | 3772 | $extraParams = array(); |
3493 | 3773 | if ( $wgRequest->getVal( 'unhide' ) ) { |
3494 | 3774 | $extraParams['unhide'] = 1; |
3495 | 3775 | } |
| 3776 | + |
3496 | 3777 | $revision = Revision::newFromId( $oldid ); |
3497 | 3778 | |
3498 | 3779 | $current = ( $oldid == $this->mLatest ); |
— | — | @@ -3571,6 +3852,7 @@ |
3572 | 3853 | ); |
3573 | 3854 | |
3574 | 3855 | $cdel = ''; |
| 3856 | + |
3575 | 3857 | // User can delete revisions or view deleted revisions... |
3576 | 3858 | $canHide = $wgUser->isAllowed( 'deleterevision' ); |
3577 | 3859 | if ( $canHide || ( $revision->getVisibility() && $wgUser->isAllowed( 'deletedhistory' ) ) ) { |
— | — | @@ -3609,6 +3891,7 @@ |
3610 | 3892 | "</div>\n" . |
3611 | 3893 | "\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsgExt( 'revision-nav', array( 'escapenoentities', 'parsemag', 'replaceafter' ), |
3612 | 3894 | $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t"; |
| 3895 | + |
3613 | 3896 | $wgOut->setSubtitle( $r ); |
3614 | 3897 | } |
3615 | 3898 | |
— | — | @@ -3622,6 +3905,7 @@ |
3623 | 3906 | */ |
3624 | 3907 | public function preSaveTransform( $text ) { |
3625 | 3908 | global $wgParser, $wgUser; |
| 3909 | + |
3626 | 3910 | return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) ); |
3627 | 3911 | } |
3628 | 3912 | |
— | — | @@ -3636,10 +3920,12 @@ |
3637 | 3921 | */ |
3638 | 3922 | protected function tryFileCache() { |
3639 | 3923 | static $called = false; |
| 3924 | + |
3640 | 3925 | if ( $called ) { |
3641 | 3926 | wfDebug( "Article::tryFileCache(): called twice!?\n" ); |
3642 | 3927 | return false; |
3643 | 3928 | } |
| 3929 | + |
3644 | 3930 | $called = true; |
3645 | 3931 | if ( $this->isFileCacheable() ) { |
3646 | 3932 | $cache = new HTMLFileCache( $this->mTitle ); |
— | — | @@ -3654,6 +3940,7 @@ |
3655 | 3941 | } else { |
3656 | 3942 | wfDebug( "Article::tryFileCache(): not cacheable\n" ); |
3657 | 3943 | } |
| 3944 | + |
3658 | 3945 | return false; |
3659 | 3946 | } |
3660 | 3947 | |
— | — | @@ -3663,6 +3950,7 @@ |
3664 | 3951 | */ |
3665 | 3952 | public function isFileCacheable() { |
3666 | 3953 | $cacheable = false; |
| 3954 | + |
3667 | 3955 | if ( HTMLFileCache::useFileCache() ) { |
3668 | 3956 | $cacheable = $this->getID() && !$this->mRedirectedFrom; |
3669 | 3957 | // Extension may have reason to disable file caching on some pages. |
— | — | @@ -3670,6 +3958,7 @@ |
3671 | 3959 | $cacheable = wfRunHooks( 'IsFileCacheable', array( &$this ) ); |
3672 | 3960 | } |
3673 | 3961 | } |
| 3962 | + |
3674 | 3963 | return $cacheable; |
3675 | 3964 | } |
3676 | 3965 | |
— | — | @@ -3681,6 +3970,7 @@ |
3682 | 3971 | if ( !$this->mDataLoaded ) { |
3683 | 3972 | $this->loadPageData(); |
3684 | 3973 | } |
| 3974 | + |
3685 | 3975 | return !$this->mIsRedirect; |
3686 | 3976 | } |
3687 | 3977 | |
— | — | @@ -3693,6 +3983,7 @@ |
3694 | 3984 | if ( !$this->mDataLoaded ) { |
3695 | 3985 | $this->loadPageData(); |
3696 | 3986 | } |
| 3987 | + |
3697 | 3988 | return $this->mTouched; |
3698 | 3989 | } |
3699 | 3990 | |
— | — | @@ -3704,6 +3995,7 @@ |
3705 | 3996 | if ( !$this->mDataLoaded ) { |
3706 | 3997 | $this->loadPageData(); |
3707 | 3998 | } |
| 3999 | + |
3708 | 4000 | return (int)$this->mLatest; |
3709 | 4001 | } |
3710 | 4002 | |
— | — | @@ -3741,6 +4033,7 @@ |
3742 | 4034 | */ |
3743 | 4035 | public static function incViewCount( $id ) { |
3744 | 4036 | $id = intval( $id ); |
| 4037 | + |
3745 | 4038 | global $wgHitcounterUpdateFreq; |
3746 | 4039 | |
3747 | 4040 | $dbw = wfGetDB( DB_MASTER ); |
— | — | @@ -3750,6 +4043,7 @@ |
3751 | 4044 | |
3752 | 4045 | if ( $wgHitcounterUpdateFreq <= 1 ) { |
3753 | 4046 | $dbw->query( "UPDATE $pageTable SET page_counter = page_counter + 1 WHERE page_id = $id" ); |
| 4047 | + |
3754 | 4048 | return; |
3755 | 4049 | } |
3756 | 4050 | |
— | — | @@ -3762,12 +4056,14 @@ |
3763 | 4057 | if ( ( rand() % $checkfreq != 0 ) or ( $dbw->lastErrno() != 0 ) ) { |
3764 | 4058 | # Most of the time (or on SQL errors), skip row count check |
3765 | 4059 | $dbw->ignoreErrors( $oldignore ); |
| 4060 | + |
3766 | 4061 | return; |
3767 | 4062 | } |
3768 | 4063 | |
3769 | 4064 | $res = $dbw->query( "SELECT COUNT(*) as n FROM $hitcounterTable" ); |
3770 | 4065 | $row = $dbw->fetchObject( $res ); |
3771 | 4066 | $rown = intval( $row->n ); |
| 4067 | + |
3772 | 4068 | if ( $rown >= $wgHitcounterUpdateFreq ) { |
3773 | 4069 | wfProfileIn( 'Article::incViewCount-collect' ); |
3774 | 4070 | $old_user_abort = ignore_user_abort( true ); |
— | — | @@ -3780,11 +4076,11 @@ |
3781 | 4077 | 'GROUP BY hc_id', __METHOD__ ); |
3782 | 4078 | $dbw->delete( 'hitcounter', '*', __METHOD__ ); |
3783 | 4079 | $dbw->unlockTables( __METHOD__ ); |
| 4080 | + |
3784 | 4081 | if ( $dbType == 'mysql' ) { |
3785 | 4082 | $dbw->query( "UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n " . |
3786 | 4083 | 'WHERE page_id = hc_id', __METHOD__ ); |
3787 | | - } |
3788 | | - else { |
| 4084 | + } else { |
3789 | 4085 | $dbw->query( "UPDATE $pageTable SET page_counter=page_counter + hc_n " . |
3790 | 4086 | "FROM $acchitsTable WHERE page_id = hc_id", __METHOD__ ); |
3791 | 4087 | } |
— | — | @@ -3793,6 +4089,7 @@ |
3794 | 4090 | ignore_user_abort( $old_user_abort ); |
3795 | 4091 | wfProfileOut( 'Article::incViewCount-collect' ); |
3796 | 4092 | } |
| 4093 | + |
3797 | 4094 | $dbw->ignoreErrors( $oldignore ); |
3798 | 4095 | } |
3799 | 4096 | |
— | — | @@ -3814,6 +4111,7 @@ |
3815 | 4112 | } else { |
3816 | 4113 | $other = $title->getTalkPage(); |
3817 | 4114 | } |
| 4115 | + |
3818 | 4116 | $other->invalidateCache(); |
3819 | 4117 | $other->purgeSquid(); |
3820 | 4118 | |
— | — | @@ -3821,18 +4119,20 @@ |
3822 | 4120 | $title->purgeSquid(); |
3823 | 4121 | $title->deleteTitleProtection(); |
3824 | 4122 | } |
3825 | | - |
| 4123 | + |
3826 | 4124 | /** |
3827 | 4125 | * Clears caches when article is deleted |
3828 | 4126 | */ |
3829 | 4127 | public static function onArticleDelete( $title ) { |
3830 | 4128 | global $wgMessageCache; |
| 4129 | + |
3831 | 4130 | # Update existence markers on article/talk tabs... |
3832 | 4131 | if ( $title->isTalkPage() ) { |
3833 | 4132 | $other = $title->getSubjectPage(); |
3834 | 4133 | } else { |
3835 | 4134 | $other = $title->getTalkPage(); |
3836 | 4135 | } |
| 4136 | + |
3837 | 4137 | $other->invalidateCache(); |
3838 | 4138 | $other->purgeSquid(); |
3839 | 4139 | |
— | — | @@ -3846,16 +4146,19 @@ |
3847 | 4147 | if ( $title->getNamespace() == NS_MEDIAWIKI ) { |
3848 | 4148 | $wgMessageCache->replace( $title->getDBkey(), false ); |
3849 | 4149 | } |
| 4150 | + |
3850 | 4151 | # Images |
3851 | 4152 | if ( $title->getNamespace() == NS_FILE ) { |
3852 | 4153 | $update = new HTMLCacheUpdate( $title, 'imagelinks' ); |
3853 | 4154 | $update->doUpdate(); |
3854 | 4155 | } |
| 4156 | + |
3855 | 4157 | # User talk pages |
3856 | 4158 | if ( $title->getNamespace() == NS_USER_TALK ) { |
3857 | 4159 | $user = User::newFromName( $title->getText(), false ); |
3858 | 4160 | $user->setNewtalk( false ); |
3859 | 4161 | } |
| 4162 | + |
3860 | 4163 | # Image redirects |
3861 | 4164 | RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $title ); |
3862 | 4165 | } |
— | — | @@ -3890,6 +4193,7 @@ |
3891 | 4194 | */ |
3892 | 4195 | public function revert() { |
3893 | 4196 | global $wgOut; |
| 4197 | + |
3894 | 4198 | $wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' ); |
3895 | 4199 | } |
3896 | 4200 | |
— | — | @@ -3923,6 +4227,7 @@ |
3924 | 4228 | : 'noarticletextanon'; |
3925 | 4229 | $wgOut->addHTML( wfMsgExt( $msg, 'parse' ) ); |
3926 | 4230 | } |
| 4231 | + |
3927 | 4232 | $wgOut->addHTML( '</div>' ); |
3928 | 4233 | } else { |
3929 | 4234 | $dbr = wfGetDB( DB_SLAVE ); |
— | — | @@ -3941,13 +4246,17 @@ |
3942 | 4247 | |
3943 | 4248 | $wgOut->addHTML( "<ul><li>" . wfMsg( "numwatchers", $wgLang->formatNum( $numwatchers ) ) . '</li>' ); |
3944 | 4249 | $wgOut->addHTML( "<li>" . wfMsg( 'numedits', $wgLang->formatNum( $pageInfo['edits'] ) ) . '</li>' ); |
| 4250 | + |
3945 | 4251 | if ( $talkInfo ) { |
3946 | 4252 | $wgOut->addHTML( '<li>' . wfMsg( "numtalkedits", $wgLang->formatNum( $talkInfo['edits'] ) ) . '</li>' ); |
3947 | 4253 | } |
| 4254 | + |
3948 | 4255 | $wgOut->addHTML( '<li>' . wfMsg( "numauthors", $wgLang->formatNum( $pageInfo['authors'] ) ) . '</li>' ); |
| 4256 | + |
3949 | 4257 | if ( $talkInfo ) { |
3950 | 4258 | $wgOut->addHTML( '<li>' . wfMsg( 'numtalkauthors', $wgLang->formatNum( $talkInfo['authors'] ) ) . '</li>' ); |
3951 | 4259 | } |
| 4260 | + |
3952 | 4261 | $wgOut->addHTML( '</ul>' ); |
3953 | 4262 | } |
3954 | 4263 | } |
— | — | @@ -3961,9 +4270,11 @@ |
3962 | 4271 | */ |
3963 | 4272 | public function pageCountInfo( $title ) { |
3964 | 4273 | $id = $title->getArticleId(); |
| 4274 | + |
3965 | 4275 | if ( $id == 0 ) { |
3966 | 4276 | return false; |
3967 | 4277 | } |
| 4278 | + |
3968 | 4279 | $dbr = wfGetDB( DB_SLAVE ); |
3969 | 4280 | $rev_clause = array( 'rev_page' => $id ); |
3970 | 4281 | $edits = $dbr->selectField( |
— | — | @@ -3980,6 +4291,7 @@ |
3981 | 4292 | __METHOD__, |
3982 | 4293 | $this->getSelectOptions() |
3983 | 4294 | ); |
| 4295 | + |
3984 | 4296 | return array( 'edits' => $edits, 'authors' => $authors ); |
3985 | 4297 | } |
3986 | 4298 | |
— | — | @@ -3992,20 +4304,25 @@ |
3993 | 4305 | public function getUsedTemplates() { |
3994 | 4306 | $result = array(); |
3995 | 4307 | $id = $this->mTitle->getArticleID(); |
| 4308 | + |
3996 | 4309 | if ( $id == 0 ) { |
3997 | 4310 | return array(); |
3998 | 4311 | } |
| 4312 | + |
3999 | 4313 | $dbr = wfGetDB( DB_SLAVE ); |
4000 | 4314 | $res = $dbr->select( array( 'templatelinks' ), |
4001 | 4315 | array( 'tl_namespace', 'tl_title' ), |
4002 | 4316 | array( 'tl_from' => $id ), |
4003 | 4317 | __METHOD__ ); |
| 4318 | + |
4004 | 4319 | if ( $res !== false ) { |
4005 | 4320 | foreach ( $res as $row ) { |
4006 | 4321 | $result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title ); |
4007 | 4322 | } |
4008 | 4323 | } |
| 4324 | + |
4009 | 4325 | $dbr->freeResult( $res ); |
| 4326 | + |
4010 | 4327 | return $result; |
4011 | 4328 | } |
4012 | 4329 | |
— | — | @@ -4018,21 +4335,26 @@ |
4019 | 4336 | public function getHiddenCategories() { |
4020 | 4337 | $result = array(); |
4021 | 4338 | $id = $this->mTitle->getArticleID(); |
| 4339 | + |
4022 | 4340 | if ( $id == 0 ) { |
4023 | 4341 | return array(); |
4024 | 4342 | } |
| 4343 | + |
4025 | 4344 | $dbr = wfGetDB( DB_SLAVE ); |
4026 | 4345 | $res = $dbr->select( array( 'categorylinks', 'page_props', 'page' ), |
4027 | 4346 | array( 'cl_to' ), |
4028 | 4347 | array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat', |
4029 | 4348 | 'page_namespace' => NS_CATEGORY, 'page_title=cl_to' ), |
4030 | 4349 | __METHOD__ ); |
| 4350 | + |
4031 | 4351 | if ( $res !== false ) { |
4032 | 4352 | foreach ( $res as $row ) { |
4033 | 4353 | $result[] = Title::makeTitle( NS_CATEGORY, $row->cl_to ); |
4034 | 4354 | } |
4035 | 4355 | } |
| 4356 | + |
4036 | 4357 | $dbr->freeResult( $res ); |
| 4358 | + |
4037 | 4359 | return $result; |
4038 | 4360 | } |
4039 | 4361 | |
— | — | @@ -4049,6 +4371,7 @@ |
4050 | 4372 | # Redirect autosummaries |
4051 | 4373 | $ot = Title::newFromRedirect( $oldtext ); |
4052 | 4374 | $rt = Title::newFromRedirect( $newtext ); |
| 4375 | + |
4053 | 4376 | if ( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( $ot ) || $ot->getFragment() != $rt->getFragment() ) ) { |
4054 | 4377 | return wfMsgForContent( 'autoredircomment', $rt->getFullText() ); |
4055 | 4378 | } |
— | — | @@ -4057,9 +4380,11 @@ |
4058 | 4381 | if ( $flags & EDIT_NEW && strlen( $newtext ) ) { |
4059 | 4382 | # If they're making a new article, give its text, truncated, in the summary. |
4060 | 4383 | global $wgContLang; |
| 4384 | + |
4061 | 4385 | $truncatedtext = $wgContLang->truncate( |
4062 | 4386 | str_replace( "\n", ' ', $newtext ), |
4063 | 4387 | max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new' ) ) ) ); |
| 4388 | + |
4064 | 4389 | return wfMsgForContent( 'autosumm-new', $truncatedtext ); |
4065 | 4390 | } |
4066 | 4391 | |
— | — | @@ -4069,9 +4394,11 @@ |
4070 | 4395 | } elseif ( strlen( $oldtext ) > 10 * strlen( $newtext ) && strlen( $newtext ) < 500 ) { |
4071 | 4396 | # Removing more than 90% of the article |
4072 | 4397 | global $wgContLang; |
| 4398 | + |
4073 | 4399 | $truncatedtext = $wgContLang->truncate( |
4074 | 4400 | $newtext, |
4075 | 4401 | max( 0, 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) ) ); |
| 4402 | + |
4076 | 4403 | return wfMsgForContent( 'autosumm-replace', $truncatedtext ); |
4077 | 4404 | } |
4078 | 4405 | |
— | — | @@ -4128,13 +4455,16 @@ |
4129 | 4456 | $parserCache = ParserCache::singleton(); |
4130 | 4457 | $parserCache->save( $this->mParserOutput, $this, $parserOptions ); |
4131 | 4458 | } |
| 4459 | + |
4132 | 4460 | // Make sure file cache is not used on uncacheable content. |
4133 | 4461 | // Output that has magic words in it can still use the parser cache |
4134 | 4462 | // (if enabled), though it will generally expire sooner. |
4135 | 4463 | if ( $this->mParserOutput->getCacheTime() == -1 || $this->mParserOutput->containsOldMagic() ) { |
4136 | 4464 | $wgUseFileCache = false; |
4137 | 4465 | } |
| 4466 | + |
4138 | 4467 | $this->doCascadeProtectionUpdates( $this->mParserOutput ); |
| 4468 | + |
4139 | 4469 | return $this->mParserOutput; |
4140 | 4470 | } |
4141 | 4471 | |
— | — | @@ -4144,14 +4474,16 @@ |
4145 | 4475 | */ |
4146 | 4476 | public function getParserOptions() { |
4147 | 4477 | global $wgUser; |
| 4478 | + |
4148 | 4479 | if ( !$this->mParserOptions ) { |
4149 | 4480 | $this->mParserOptions = new ParserOptions( $wgUser ); |
4150 | 4481 | $this->mParserOptions->setTidy( true ); |
4151 | 4482 | $this->mParserOptions->enableLimitReport(); |
4152 | 4483 | } |
| 4484 | + |
4153 | 4485 | return $this->mParserOptions; |
4154 | 4486 | } |
4155 | | - |
| 4487 | + |
4156 | 4488 | /** |
4157 | 4489 | * Updates cascading protections |
4158 | 4490 | * |
— | — | @@ -4179,9 +4511,11 @@ |
4180 | 4512 | $res = $dbr->select( array( 'templatelinks' ), |
4181 | 4513 | array( 'tl_namespace', 'tl_title' ), |
4182 | 4514 | array( 'tl_from' => $id ), |
4183 | | - __METHOD__ ); |
| 4515 | + __METHOD__ |
| 4516 | + ); |
4184 | 4517 | |
4185 | 4518 | global $wgContLang; |
| 4519 | + |
4186 | 4520 | foreach ( $res as $row ) { |
4187 | 4521 | $tlTemplates["{$row->tl_namespace}:{$row->tl_title}"] = true; |
4188 | 4522 | } |
— | — | @@ -4227,7 +4561,9 @@ |
4228 | 4562 | # Okay, nothing to do |
4229 | 4563 | return; |
4230 | 4564 | } |
| 4565 | + |
4231 | 4566 | $insertRows = array(); |
| 4567 | + |
4232 | 4568 | foreach ( $insertCats as $cat ) { |
4233 | 4569 | $insertRows[] = array( |
4234 | 4570 | 'cat_id' => $dbw->nextSequenceValue( 'category_cat_id_seq' ), |
— | — | @@ -4238,6 +4574,7 @@ |
4239 | 4575 | |
4240 | 4576 | $addFields = array( 'cat_pages = cat_pages + 1' ); |
4241 | 4577 | $removeFields = array( 'cat_pages = cat_pages - 1' ); |
| 4578 | + |
4242 | 4579 | if ( $ns == NS_CATEGORY ) { |
4243 | 4580 | $addFields[] = 'cat_subcats = cat_subcats + 1'; |
4244 | 4581 | $removeFields[] = 'cat_subcats = cat_subcats - 1'; |
— | — | @@ -4254,6 +4591,7 @@ |
4255 | 4592 | __METHOD__ |
4256 | 4593 | ); |
4257 | 4594 | } |
| 4595 | + |
4258 | 4596 | if ( $deleted ) { |
4259 | 4597 | $dbw->update( |
4260 | 4598 | 'category', |
— | — | @@ -4276,11 +4614,12 @@ |
4277 | 4615 | |
4278 | 4616 | // Should the parser cache be used? |
4279 | 4617 | $useParserCache = $wgEnableParserCache && |
4280 | | - intval( $wgUser->getOption( 'stubthreshold' ) ) == 0 && |
4281 | | - $this->exists() && |
4282 | | - $oldid === null; |
| 4618 | + intval( $wgUser->getOption( 'stubthreshold' ) ) == 0 && |
| 4619 | + $this->exists() && |
| 4620 | + $oldid === null; |
4283 | 4621 | |
4284 | 4622 | wfDebug( __METHOD__ . ': using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" ); |
| 4623 | + |
4285 | 4624 | if ( $wgUser->getOption( 'stubthreshold' ) ) { |
4286 | 4625 | wfIncrStats( 'pcache_miss_stub' ); |
4287 | 4626 | } |
Index: trunk/phase3/includes/AjaxDispatcher.php |
— | — | @@ -42,31 +42,27 @@ |
43 | 43 | } |
44 | 44 | |
45 | 45 | switch( $this->mode ) { |
46 | | - |
47 | | - case 'get': |
48 | | - $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : ''; |
49 | | - if ( ! empty( $_GET["rsargs"] ) ) { |
50 | | - $this->args = $_GET["rsargs"]; |
51 | | - } else { |
52 | | - $this->args = array(); |
53 | | - } |
54 | | - break; |
55 | | - |
56 | | - case 'post': |
57 | | - $this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : ''; |
58 | | - if ( ! empty( $_POST["rsargs"] ) ) { |
59 | | - $this->args = $_POST["rsargs"]; |
60 | | - } else { |
61 | | - $this->args = array(); |
62 | | - } |
63 | | - break; |
64 | | - |
65 | | - default: |
66 | | - wfProfileOut( __METHOD__ ); |
67 | | - return; |
68 | | - # Or we could throw an exception: |
69 | | - # throw new MWException( __METHOD__ . ' called without any data (mode empty).' ); |
70 | | - |
| 46 | + case 'get': |
| 47 | + $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : ''; |
| 48 | + if ( ! empty( $_GET["rsargs"] ) ) { |
| 49 | + $this->args = $_GET["rsargs"]; |
| 50 | + } else { |
| 51 | + $this->args = array(); |
| 52 | + } |
| 53 | + break; |
| 54 | + case 'post': |
| 55 | + $this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : ''; |
| 56 | + if ( ! empty( $_POST["rsargs"] ) ) { |
| 57 | + $this->args = $_POST["rsargs"]; |
| 58 | + } else { |
| 59 | + $this->args = array(); |
| 60 | + } |
| 61 | + break; |
| 62 | + default: |
| 63 | + wfProfileOut( __METHOD__ ); |
| 64 | + return; |
| 65 | + # Or we could throw an exception: |
| 66 | + # throw new MWException( __METHOD__ . ' called without any data (mode empty).' ); |
71 | 67 | } |
72 | 68 | |
73 | 69 | wfProfileOut( __METHOD__ ); |
— | — | @@ -89,8 +85,11 @@ |
90 | 86 | if ( ! in_array( $this->func_name, $wgAjaxExportList ) ) { |
91 | 87 | wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" ); |
92 | 88 | |
93 | | - wfHttpError( 400, 'Bad Request', |
94 | | - "unknown function " . (string) $this->func_name ); |
| 89 | + wfHttpError( |
| 90 | + 400, |
| 91 | + 'Bad Request', |
| 92 | + "unknown function " . (string) $this->func_name |
| 93 | + ); |
95 | 94 | } else { |
96 | 95 | wfDebug( __METHOD__ . ' dispatching ' . $this->func_name . "\n" ); |
97 | 96 | |
— | — | @@ -99,6 +98,7 @@ |
100 | 99 | } else { |
101 | 100 | $func = $this->func_name; |
102 | 101 | } |
| 102 | + |
103 | 103 | try { |
104 | 104 | $result = call_user_func_array( $func, $this->args ); |
105 | 105 | |
— | — | @@ -109,8 +109,7 @@ |
110 | 110 | |
111 | 111 | wfHttpError( 500, 'Internal Error', |
112 | 112 | "{$this->func_name} returned no data" ); |
113 | | - } |
114 | | - else { |
| 113 | + } else { |
115 | 114 | if ( is_string( $result ) ) { |
116 | 115 | $result = new AjaxResponse( $result ); |
117 | 116 | } |
— | — | @@ -120,7 +119,6 @@ |
121 | 120 | |
122 | 121 | wfDebug( __METHOD__ . ' dispatch complete for ' . $this->func_name . "\n" ); |
123 | 122 | } |
124 | | - |
125 | 123 | } catch ( Exception $e ) { |
126 | 124 | wfDebug( __METHOD__ . ' ERROR while dispatching ' |
127 | 125 | . $this->func_name . "(" . var_export( $this->args, true ) . "): " |
Index: trunk/phase3/includes/AjaxFunctions.php |
— | — | @@ -28,6 +28,7 @@ |
29 | 29 | if ( $charAt == '%' ) { |
30 | 30 | $pos++; |
31 | 31 | $charAt = substr ( $source, $pos, 1 ); |
| 32 | + |
32 | 33 | if ( $charAt == 'u' ) { |
33 | 34 | // we got a unicode character |
34 | 35 | $pos++; |
— | — | @@ -62,14 +63,22 @@ |
63 | 64 | * @return utf8char |
64 | 65 | */ |
65 | 66 | function code2utf( $num ) { |
66 | | - if ( $num < 128 ) |
| 67 | + if ( $num < 128 ) { |
67 | 68 | return chr( $num ); |
68 | | - if ( $num < 2048 ) |
| 69 | + } |
| 70 | + |
| 71 | + if ( $num < 2048 ) { |
69 | 72 | return chr( ( $num >> 6 ) + 192 ) . chr( ( $num&63 ) + 128 ); |
70 | | - if ( $num < 65536 ) |
| 73 | + } |
| 74 | + |
| 75 | + if ( $num < 65536 ) { |
71 | 76 | return chr( ( $num >> 12 ) + 224 ) . chr( ( ( $num >> 6 )&63 ) + 128 ) . chr( ( $num&63 ) + 128 ); |
72 | | - if ( $num < 2097152 ) |
| 77 | + } |
| 78 | + |
| 79 | + if ( $num < 2097152 ) { |
73 | 80 | return chr( ( $num >> 18 ) + 240 ) . chr( ( ( $num >> 12 )&63 ) + 128 ) . chr( ( ( $num >> 6 )&63 ) + 128 ) . chr( ( $num&63 ) + 128 ); |
| 81 | + } |
| 82 | + |
74 | 83 | return ''; |
75 | 84 | } |
76 | 85 | |
— | — | @@ -80,8 +89,9 @@ |
81 | 90 | function wfAjaxGetThumbnailUrl( $file, $width, $height ) { |
82 | 91 | $file = wfFindFile( $file ); |
83 | 92 | |
84 | | - if ( !$file || !$file->exists() ) |
| 93 | + if ( !$file || !$file->exists() ) { |
85 | 94 | return null; |
| 95 | + } |
86 | 96 | |
87 | 97 | $url = $file->getThumbnail( $width, $height )->url; |
88 | 98 | |
— | — | @@ -95,8 +105,9 @@ |
96 | 106 | function wfAjaxGetFileUrl( $file ) { |
97 | 107 | $file = wfFindFile( $file ); |
98 | 108 | |
99 | | - if ( !$file || !$file->exists() ) |
| 109 | + if ( !$file || !$file->exists() ) { |
100 | 110 | return null; |
| 111 | + } |
101 | 112 | |
102 | 113 | $url = $file->getUrl(); |
103 | 114 | |
Index: trunk/phase3/includes/AjaxResponse.php |
— | — | @@ -15,7 +15,6 @@ |
16 | 16 | * @ingroup Ajax |
17 | 17 | */ |
18 | 18 | class AjaxResponse { |
19 | | - |
20 | 19 | /** Number of seconds to get the response cached by a proxy */ |
21 | 20 | private $mCacheDuration; |
22 | 21 | |
— | — | @@ -99,19 +98,16 @@ |
100 | 99 | |
101 | 100 | if ( $this->mLastModified ) { |
102 | 101 | header ( "Last-Modified: " . $this->mLastModified ); |
103 | | - } |
104 | | - else { |
| 102 | + } else { |
105 | 103 | header ( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" ); |
106 | 104 | } |
107 | 105 | |
108 | 106 | if ( $this->mCacheDuration ) { |
109 | | - |
110 | 107 | # If squid caches are configured, tell them to cache the response, |
111 | 108 | # and tell the client to always check with the squid. Otherwise, |
112 | 109 | # tell the client to use a cached copy, without a way to purge it. |
113 | 110 | |
114 | 111 | if ( $wgUseSquid ) { |
115 | | - |
116 | 112 | # Expect explicite purge of the proxy cache, but require end user agents |
117 | 113 | # to revalidate against the proxy on each visit. |
118 | 114 | # Surrogate-Control controls our Squid, Cache-Control downstream caches |
— | — | @@ -156,10 +152,12 @@ |
157 | 153 | wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n" ); |
158 | 154 | return; |
159 | 155 | } |
| 156 | + |
160 | 157 | if ( !$wgCachePages ) { |
161 | 158 | wfDebug( "$fname: CACHE DISABLED\n", false ); |
162 | 159 | return; |
163 | 160 | } |
| 161 | + |
164 | 162 | if ( $wgUser->getOption( 'nocache' ) ) { |
165 | 163 | wfDebug( "$fname: USER DISABLED CACHE\n", false ); |
166 | 164 | return; |
— | — | @@ -177,6 +175,7 @@ |
178 | 176 | $ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 ); |
179 | 177 | wfDebug( "$fname: -- client send If-Modified-Since: " . $modsince . "\n", false ); |
180 | 178 | wfDebug( "$fname: -- we might send Last-Modified : $lastmod\n", false ); |
| 179 | + |
181 | 180 | if ( ( $ismodsince >= $timestamp ) && $wgUser->validateCache( $ismodsince ) && $ismodsince >= $wgCacheEpoch ) { |
182 | 181 | ini_set( 'zlib.output_compression', 0 ); |
183 | 182 | $this->setResponseCode( "304 Not Modified" ); |
— | — | @@ -198,14 +197,18 @@ |
199 | 198 | |
200 | 199 | function loadFromMemcached( $mckey, $touched ) { |
201 | 200 | global $wgMemc; |
202 | | - if ( !$touched ) return false; |
203 | 201 | |
| 202 | + if ( !$touched ) { |
| 203 | + return false; |
| 204 | + } |
| 205 | + |
204 | 206 | $mcvalue = $wgMemc->get( $mckey ); |
205 | 207 | if ( $mcvalue ) { |
206 | 208 | # Check to see if the value has been invalidated |
207 | 209 | if ( $touched <= $mcvalue['timestamp'] ) { |
208 | 210 | wfDebug( "Got $mckey from cache\n" ); |
209 | 211 | $this->mText = $mcvalue['value']; |
| 212 | + |
210 | 213 | return true; |
211 | 214 | } else { |
212 | 215 | wfDebug( "$mckey has expired\n" ); |