Index: trunk/phase3/includes/Article.php |
— | — | @@ -186,7 +186,7 @@ |
187 | 187 | |
188 | 188 | return $text; |
189 | 189 | } else { |
190 | | - $this->loadContent(); |
| 190 | + $this->fetchContent(); |
191 | 191 | wfProfileOut( __METHOD__ ); |
192 | 192 | |
193 | 193 | return $this->mContent; |
— | — | @@ -215,27 +215,37 @@ |
216 | 216 | |
217 | 217 | $this->mRedirectUrl = false; |
218 | 218 | |
219 | | - $oldid = $wgRequest->getVal( 'oldid' ); |
| 219 | + $oldid = $wgRequest->getIntOrNull( 'oldid' ); |
220 | 220 | |
221 | | - if ( isset( $oldid ) ) { |
222 | | - $oldid = intval( $oldid ); |
223 | | - if ( $wgRequest->getVal( 'direction' ) == 'next' ) { |
224 | | - $nextid = $this->getTitle()->getNextRevisionID( $oldid ); |
225 | | - if ( $nextid ) { |
226 | | - $oldid = $nextid; |
227 | | - } else { |
228 | | - $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' ); |
| 221 | + if ( $oldid === null ) { |
| 222 | + return 0; |
| 223 | + } |
| 224 | + |
| 225 | + if ( $oldid !== 0 ) { |
| 226 | + # Load the given revision and check whether the page is another one. |
| 227 | + # In that case, update this instance to reflect the change. |
| 228 | + $this->mRevision = Revision::newFromId( $oldid ); |
| 229 | + if ( $this->mRevision !== null ) { |
| 230 | + // Revision title doesn't match the page title given? |
| 231 | + if ( $this->mPage->getID() != $this->mRevision->getPage() ) { |
| 232 | + $function = array( get_class( $this->mPage ), 'newFromID' ); |
| 233 | + $this->mPage = call_user_func( $function, $revision->getPage() ); |
229 | 234 | } |
230 | | - } elseif ( $wgRequest->getVal( 'direction' ) == 'prev' ) { |
231 | | - $previd = $this->getTitle()->getPreviousRevisionID( $oldid ); |
232 | | - if ( $previd ) { |
233 | | - $oldid = $previd; |
234 | | - } |
235 | 235 | } |
236 | 236 | } |
237 | 237 | |
238 | | - if ( !$oldid ) { |
239 | | - $oldid = 0; |
| 238 | + if ( $wgRequest->getVal( 'direction' ) == 'next' ) { |
| 239 | + $nextid = $this->getTitle()->getNextRevisionID( $oldid ); |
| 240 | + if ( $nextid ) { |
| 241 | + $oldid = $nextid; |
| 242 | + } else { |
| 243 | + $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' ); |
| 244 | + } |
| 245 | + } elseif ( $wgRequest->getVal( 'direction' ) == 'prev' ) { |
| 246 | + $previd = $this->getTitle()->getPreviousRevisionID( $oldid ); |
| 247 | + if ( $previd ) { |
| 248 | + $oldid = $previd; |
| 249 | + } |
240 | 250 | } |
241 | 251 | |
242 | 252 | return $oldid; |
— | — | @@ -243,31 +253,30 @@ |
244 | 254 | |
245 | 255 | /** |
246 | 256 | * Load the revision (including text) into this object |
| 257 | + * |
| 258 | + * @deprecated in 1.19; use fetchContent() |
247 | 259 | */ |
248 | 260 | function loadContent() { |
249 | | - if ( $this->mContentLoaded ) { |
250 | | - return; |
251 | | - } |
252 | | - |
253 | | - wfProfileIn( __METHOD__ ); |
254 | | - |
255 | | - $this->fetchContent( $this->getOldID() ); |
256 | | - |
257 | | - wfProfileOut( __METHOD__ ); |
| 261 | + $this->fetchContent(); |
258 | 262 | } |
259 | 263 | |
260 | 264 | /** |
261 | 265 | * Get text of an article from database |
262 | 266 | * Does *NOT* follow redirects. |
263 | 267 | * |
264 | | - * @param $oldid Int: 0 for whatever the latest revision is |
265 | 268 | * @return mixed string containing article contents, or false if null |
266 | 269 | */ |
267 | | - function fetchContent( $oldid = 0 ) { |
| 270 | + function fetchContent() { |
268 | 271 | if ( $this->mContentLoaded ) { |
269 | 272 | return $this->mContent; |
270 | 273 | } |
271 | 274 | |
| 275 | + wfProfileIn( __METHOD__ ); |
| 276 | + |
| 277 | + $this->mContentLoaded = true; |
| 278 | + |
| 279 | + $oldid = $this->getOldID(); |
| 280 | + |
272 | 281 | # Pre-fill content with error message so that if something |
273 | 282 | # fails we'll have something telling us what we intended. |
274 | 283 | $t = $this->getTitle()->getPrefixedText(); |
— | — | @@ -275,17 +284,11 @@ |
276 | 285 | $this->mContent = wfMsgNoTrans( 'missing-article', $t, $d ) ; |
277 | 286 | |
278 | 287 | if ( $oldid ) { |
279 | | - $revision = Revision::newFromId( $oldid ); |
280 | | - if ( !$revision ) { |
281 | | - wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" ); |
282 | | - return false; |
283 | | - } |
284 | | - // Revision title doesn't match the page title given? |
285 | | - if ( $this->mPage->getID() != $revision->getPage() ) { |
286 | | - $function = array( get_class( $this->mPage ), 'newFromID' ); |
287 | | - $this->mPage = call_user_func( $function, $revision->getPage() ); |
288 | | - if ( !$this->mPage->getId() ) { |
289 | | - wfDebug( __METHOD__ . " failed to get page data linked to revision id $oldid\n" ); |
| 288 | + # $this->mRevision might already be fetched by getOldIDFromRequest() |
| 289 | + if ( !$this->mRevision ) { |
| 290 | + $this->mRevision = Revision::newFromId( $oldid ); |
| 291 | + if ( !$this->mRevision ) { |
| 292 | + wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" ); |
290 | 293 | return false; |
291 | 294 | } |
292 | 295 | } |
— | — | @@ -295,8 +298,8 @@ |
296 | 299 | return false; |
297 | 300 | } |
298 | 301 | |
299 | | - $revision = $this->mPage->getRevision(); |
300 | | - if ( !$revision ) { |
| 302 | + $this->mRevision = $this->mPage->getRevision(); |
| 303 | + if ( !$this->mRevision ) { |
301 | 304 | wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" ); |
302 | 305 | return false; |
303 | 306 | } |
— | — | @@ -304,14 +307,13 @@ |
305 | 308 | |
306 | 309 | // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks. |
307 | 310 | // We should instead work with the Revision object when we need it... |
308 | | - $this->mContent = $revision->getText( Revision::FOR_THIS_USER ); // Loads if user is allowed |
| 311 | + $this->mContent = $this->mRevision->getText( Revision::FOR_THIS_USER ); // Loads if user is allowed |
| 312 | + $this->mRevIdFetched = $this->mRevision->getId(); |
309 | 313 | |
310 | | - $this->mRevIdFetched = $revision->getId(); |
311 | | - $this->mContentLoaded = true; |
312 | | - $this->mRevision =& $revision; |
313 | | - |
314 | 314 | wfRunHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) ); |
315 | 315 | |
| 316 | + wfProfileOut( __METHOD__ ); |
| 317 | + |
316 | 318 | return $this->mContent; |
317 | 319 | } |
318 | 320 | |
— | — | @@ -361,9 +363,20 @@ |
362 | 364 | wfProfileIn( __METHOD__ ); |
363 | 365 | |
364 | 366 | # Get variables from query string |
| 367 | + # As side effect this will load the revision and update the title |
| 368 | + # in a revision ID is passed in the request, so this should remain |
| 369 | + # the first call of this method even if $oldid is used way below. |
365 | 370 | $oldid = $this->getOldID(); |
366 | 371 | |
367 | | - # getOldID may want us to redirect somewhere else |
| 372 | + # Another whitelist check in case getOldID() is altering the title |
| 373 | + $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $wgUser ); |
| 374 | + if ( count( $permErrors ) ) { |
| 375 | + wfDebug( __METHOD__ . ": denied on secondary read check\n" ); |
| 376 | + wfProfileOut( __METHOD__ ); |
| 377 | + throw new PermissionsError( 'read', $permErrors ); |
| 378 | + } |
| 379 | + |
| 380 | + # getOldID() may as well want us to redirect somewhere else |
368 | 381 | if ( $this->mRedirectUrl ) { |
369 | 382 | $wgOut->redirect( $this->mRedirectUrl ); |
370 | 383 | wfDebug( __METHOD__ . ": redirecting due to oldid\n" ); |
— | — | @@ -372,9 +385,6 @@ |
373 | 386 | return; |
374 | 387 | } |
375 | 388 | |
376 | | - # Set page title (may be overridden by DISPLAYTITLE) |
377 | | - $wgOut->setPageTitle( $this->getTitle()->getPrefixedText() ); |
378 | | - |
379 | 389 | # If we got diff in the query, we want to see a diff page instead of the article. |
380 | 390 | if ( $wgRequest->getCheck( 'diff' ) ) { |
381 | 391 | wfDebug( __METHOD__ . ": showing diff page\n" ); |
— | — | @@ -384,6 +394,9 @@ |
385 | 395 | return; |
386 | 396 | } |
387 | 397 | |
| 398 | + # Set page title (may be overridden by DISPLAYTITLE) |
| 399 | + $wgOut->setPageTitle( $this->getTitle()->getPrefixedText() ); |
| 400 | + |
388 | 401 | $wgOut->setArticleFlag( true ); |
389 | 402 | # Allow frames by default |
390 | 403 | $wgOut->allowClickjacking(); |
— | — | @@ -395,7 +408,7 @@ |
396 | 409 | if ( $wgOut->isPrintable() ) { |
397 | 410 | $parserOptions->setIsPrintable( true ); |
398 | 411 | $parserOptions->setEditSection( false ); |
399 | | - } elseif ( $wgUseETag && !$this->getTitle()->quickUserCan( 'edit' ) ) { |
| 412 | + } elseif ( !$this->getTitle()->quickUserCan( 'edit' ) ) { |
400 | 413 | $parserOptions->setEditSection( false ); |
401 | 414 | } |
402 | 415 | |
— | — | @@ -423,12 +436,8 @@ |
424 | 437 | } |
425 | 438 | } |
426 | 439 | |
427 | | - if ( !$wgUseETag && !$this->getTitle()->quickUserCan( 'edit' ) ) { |
428 | | - $parserOptions->setEditSection( false ); |
429 | | - } |
430 | | - |
431 | 440 | # Should the parser cache be used? |
432 | | - $useParserCache = $this->useParserCache( $oldid ); |
| 441 | + $useParserCache = $this->mPage->isParserCacheUsed( $wgUser, $oldid ); |
433 | 442 | wfDebug( 'Article::view using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" ); |
434 | 443 | if ( $wgUser->getStubThreshold() ) { |
435 | 444 | wfIncrStats( 'pcache_miss_stub' ); |
— | — | @@ -449,12 +458,25 @@ |
450 | 459 | wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) ); |
451 | 460 | break; |
452 | 461 | case 2: |
| 462 | + # Early abort if the page doesn't exist |
| 463 | + if ( !$this->mPage->exists() ) { |
| 464 | + wfDebug( __METHOD__ . ": showing missing article\n" ); |
| 465 | + $this->showMissingArticle(); |
| 466 | + wfProfileOut( __METHOD__ ); |
| 467 | + return; |
| 468 | + } |
| 469 | + |
453 | 470 | # Try the parser cache |
454 | 471 | if ( $useParserCache ) { |
455 | 472 | $this->mParserOutput = $parserCache->get( $this, $parserOptions ); |
456 | 473 | |
457 | 474 | if ( $this->mParserOutput !== false ) { |
458 | | - wfDebug( __METHOD__ . ": showing parser cache contents\n" ); |
| 475 | + if ( $oldid ) { |
| 476 | + wfDebug( __METHOD__ . ": showing parser cache contents for current rev permalink\n" ); |
| 477 | + $this->setOldSubtitle( $oldid ); |
| 478 | + } else { |
| 479 | + wfDebug( __METHOD__ . ": showing parser cache contents\n" ); |
| 480 | + } |
459 | 481 | $wgOut->addParserOutput( $this->mParserOutput ); |
460 | 482 | # Ensure that UI elements requiring revision ID have |
461 | 483 | # the correct version information. |
— | — | @@ -468,24 +490,11 @@ |
469 | 491 | } |
470 | 492 | break; |
471 | 493 | case 3: |
472 | | - $text = $this->getContent(); |
473 | | - if ( $text === false || $this->mPage->getID() == 0 ) { |
474 | | - wfDebug( __METHOD__ . ": showing missing article\n" ); |
475 | | - $this->showMissingArticle(); |
476 | | - wfProfileOut( __METHOD__ ); |
477 | | - return; |
478 | | - } |
| 494 | + # This will set $this->mRevision if needed |
| 495 | + $this->fetchContent(); |
479 | 496 | |
480 | | - # Another whitelist check in case oldid is altering the title |
481 | | - $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $wgUser ); |
482 | | - if ( count( $permErrors ) ) { |
483 | | - wfDebug( __METHOD__ . ": denied on secondary read check\n" ); |
484 | | - wfProfileOut( __METHOD__ ); |
485 | | - throw new PermissionsError( 'read', $permErrors ); |
486 | | - } |
487 | | - |
488 | 497 | # Are we looking at an old revision |
489 | | - if ( $oldid && !is_null( $this->mRevision ) ) { |
| 498 | + if ( $oldid && $this->mRevision ) { |
490 | 499 | $this->setOldSubtitle( $oldid ); |
491 | 500 | |
492 | 501 | if ( !$this->showDeletedRevisionHeader() ) { |
— | — | @@ -493,18 +502,6 @@ |
494 | 503 | wfProfileOut( __METHOD__ ); |
495 | 504 | return; |
496 | 505 | } |
497 | | - |
498 | | - # If this "old" version is the current, then try the parser cache... |
499 | | - if ( $oldid === $this->mPage->getLatest() && $this->useParserCache( false ) ) { |
500 | | - $this->mParserOutput = $parserCache->get( $this, $parserOptions ); |
501 | | - if ( $this->mParserOutput ) { |
502 | | - wfDebug( __METHOD__ . ": showing parser cache for current rev permalink\n" ); |
503 | | - $wgOut->addParserOutput( $this->mParserOutput ); |
504 | | - $wgOut->setRevisionId( $this->mPage->getLatest() ); |
505 | | - $outputDone = true; |
506 | | - break; |
507 | | - } |
508 | | - } |
509 | 506 | } |
510 | 507 | |
511 | 508 | # Ensure that UI elements requiring revision ID have |
— | — | @@ -520,6 +517,7 @@ |
521 | 518 | # Allow extensions do their own custom view for certain pages |
522 | 519 | $outputDone = true; |
523 | 520 | } else { |
| 521 | + $text = $this->getContent(); |
524 | 522 | $rt = Title::newFromRedirectArray( $text ); |
525 | 523 | if ( $rt ) { |
526 | 524 | wfDebug( __METHOD__ . ": showing redirect=no page\n" ); |
Index: trunk/phase3/includes/WikiPage.php |
— | — | @@ -718,7 +718,7 @@ |
719 | 719 | return $wgEnableParserCache |
720 | 720 | && $user->getStubThreshold() == 0 |
721 | 721 | && $this->exists() |
722 | | - && empty( $oldid ) |
| 722 | + && ( $oldid === null || $oldid === 0 || $oldid === $this->getLatest() ) |
723 | 723 | && $this->mTitle->isWikitextPage(); |
724 | 724 | } |
725 | 725 | |