Index: trunk/phase3/includes/ParserOutput.php |
— | — | @@ -14,7 +14,9 @@ |
15 | 15 | $mTitleText, # title text of the chosen language variant |
16 | 16 | $mLinks, # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken. |
17 | 17 | $mTemplates, # 2-D map of NS/DBK to ID for the template references. ID=zero for broken. |
| 18 | + $mTemplateIds, # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken. |
18 | 19 | $mImages, # DB keys of the images used, in the array key only |
| 20 | + $mImageTimestamps, # Map of DBK to rev ID for the template references. ID=zero for broken. |
19 | 21 | $mExternalLinks, # External link URLs, in the key only |
20 | 22 | $mHTMLtitle, # Display HTML title |
21 | 23 | $mSubtitle, # Additional subtitle |
— | — | @@ -41,10 +43,12 @@ |
42 | 44 | $this->mNewSection = false; |
43 | 45 | $this->mNoGallery = false; |
44 | 46 | $this->mHeadItems = array(); |
| 47 | + $this->mTemplateIds = array(); |
| 48 | + $this->mImageTimestamps = array(); |
45 | 49 | } |
46 | 50 | |
47 | 51 | function getText() { return $this->mText; } |
48 | | - function &getLanguageLinks() { return $this->mLanguageLinks; } |
| 52 | + function &getLanguageLinks() { return $this->mLanguageLinks; } |
49 | 53 | function getCategoryLinks() { return array_keys( $this->mCategories ); } |
50 | 54 | function &getCategories() { return $this->mCategories; } |
51 | 55 | function getCacheTime() { return $this->mCacheTime; } |
— | — | @@ -66,7 +70,6 @@ |
67 | 71 | function setSubtitle( $st ) { return wfSetVar( $this->mSubtitle, $st ); } |
68 | 72 | |
69 | 73 | function addCategory( $c, $sort ) { $this->mCategories[$c] = $sort; } |
70 | | - function addImage( $name ) { $this->mImages[$name] = 1; } |
71 | 74 | function addLanguageLink( $t ) { $this->mLanguageLinks[] = $t; } |
72 | 75 | function addExternalLink( $url ) { $this->mExternalLinks[$url] = 1; } |
73 | 76 | |
— | — | @@ -88,14 +91,33 @@ |
89 | 92 | } |
90 | 93 | $this->mLinks[$ns][$dbk] = $id; |
91 | 94 | } |
| 95 | + |
| 96 | + function addImage( $name, $timestamp=NULL ) { |
| 97 | + if( isset($this->mImages[$name]) ) |
| 98 | + return; // No repeated pointless DB calls! |
| 99 | + $this->mImages[$name] = 1; |
| 100 | + if( is_null($timestamp) ) { |
| 101 | + wfProfileIn( __METHOD__ ); |
| 102 | + $dbr = wfGetDB(DB_SLAVE); |
| 103 | + $timestamp = $dbr->selectField('image', 'img_timestamp', |
| 104 | + array('img_name' => $name), |
| 105 | + __METHOD__ ); |
| 106 | + } |
| 107 | + $timestamp = $timestamp ? $timestamp : 0; |
| 108 | + $this->mImageTimestamps[$name] = $timestamp; // For versioning |
| 109 | + } |
92 | 110 | |
93 | | - function addTemplate( $title, $id ) { |
| 111 | + function addTemplate( $title, $page_id, $rev_id ) { |
94 | 112 | $ns = $title->getNamespace(); |
95 | 113 | $dbk = $title->getDBkey(); |
96 | 114 | if ( !isset( $this->mTemplates[$ns] ) ) { |
97 | 115 | $this->mTemplates[$ns] = array(); |
98 | 116 | } |
99 | | - $this->mTemplates[$ns][$dbk] = $id; |
| 117 | + $this->mTemplates[$ns][$dbk] = $page_id; |
| 118 | + if ( !isset( $this->mTemplateIds[$ns] ) ) { |
| 119 | + $this->mTemplateIds[$ns] = array(); |
| 120 | + } |
| 121 | + $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning |
100 | 122 | } |
101 | 123 | |
102 | 124 | /** |
Index: trunk/phase3/includes/Parser.php |
— | — | @@ -400,12 +400,15 @@ |
401 | 401 | * Expand templates and variables in the text, producing valid, static wikitext. |
402 | 402 | * Also removes comments. |
403 | 403 | */ |
404 | | - function preprocess( $text, $title, $options ) { |
| 404 | + function preprocess( $text, $title, $options, $revid = null ) { |
405 | 405 | wfProfileIn( __METHOD__ ); |
406 | 406 | $this->clearState(); |
407 | 407 | $this->setOutputType( OT_PREPROCESS ); |
408 | 408 | $this->mOptions = $options; |
409 | 409 | $this->mTitle = $title; |
| 410 | + if( $revid !== null ) { |
| 411 | + $this->mRevisionId = $revid; |
| 412 | + } |
410 | 413 | wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) ); |
411 | 414 | $text = $this->strip( $text, $this->mStripState ); |
412 | 415 | wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) ); |
— | — | @@ -3264,13 +3267,25 @@ |
3265 | 3268 | * Fetch the unparsed text of a template and register a reference to it. |
3266 | 3269 | */ |
3267 | 3270 | function fetchTemplateAndtitle( $title ) { |
3268 | | - $text = false; |
| 3271 | + $text = $skip = false; |
3269 | 3272 | $finalTitle = $title; |
3270 | 3273 | // Loop to fetch the article, with up to 1 redirect |
3271 | 3274 | for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) { |
3272 | | - $rev = Revision::newFromTitle( $title ); |
3273 | | - $this->mOutput->addTemplate( $title, $title->getArticleID() ); |
3274 | | - if ( $rev ) { |
| 3275 | + # Give extensions a chance to select the revision instead |
| 3276 | + $id = false; // Assume current |
| 3277 | + wfRunHooks( 'BeforeParserFetchTemplateAndtitle', array( &$this, &$title, &$skip, &$id ) ); |
| 3278 | + |
| 3279 | + if( $skip ) { |
| 3280 | + $text = false; |
| 3281 | + $this->mOutput->addTemplate( $title, $title->getArticleID(), 0 ); |
| 3282 | + break; |
| 3283 | + } |
| 3284 | + $rev = $id ? Revision::newFromId( $id ) : Revision::newFromTitle( $title ); |
| 3285 | + $rev_id = $rev ? $rev->getId() : 0; |
| 3286 | + |
| 3287 | + $this->mOutput->addTemplate( $title, $title->getArticleID(), $rev_id ); |
| 3288 | + |
| 3289 | + if( $rev ) { |
3275 | 3290 | $text = $rev->getText(); |
3276 | 3291 | } elseif( $title->getNamespace() == NS_MEDIAWIKI ) { |
3277 | 3292 | global $wgLang; |
— | — | @@ -4124,7 +4139,7 @@ |
4125 | 4140 | } |
4126 | 4141 | |
4127 | 4142 | // process categories, check if a category exists in some variant |
4128 | | - foreach( $categories as $category){ |
| 4143 | + foreach( $categories as $category ){ |
4129 | 4144 | $variants = $wgContLang->convertLinkToAllVariants($category); |
4130 | 4145 | foreach($variants as $variant){ |
4131 | 4146 | if($variant != $category){ |
— | — | @@ -4346,6 +4361,7 @@ |
4347 | 4362 | $ig->setShowFilename( false ); |
4348 | 4363 | $ig->setParsing(); |
4349 | 4364 | $ig->useSkin( $this->mOptions->getSkin() ); |
| 4365 | + $ig->mRevisionId = $this->mRevisionId; |
4350 | 4366 | |
4351 | 4367 | if( isset( $params['caption'] ) ) { |
4352 | 4368 | $caption = $params['caption']; |
— | — | @@ -4362,6 +4378,8 @@ |
4363 | 4379 | if( isset( $params['heights'] ) ) { |
4364 | 4380 | $ig->setHeights( $params['heights'] ); |
4365 | 4381 | } |
| 4382 | + |
| 4383 | + wfRunHooks( 'BeforeParserrenderImageGallery', array( &$this, &$ig ) ); |
4366 | 4384 | |
4367 | 4385 | $lines = explode( "\n", $text ); |
4368 | 4386 | foreach ( $lines as $line ) { |
— | — | @@ -4510,8 +4528,18 @@ |
4511 | 4529 | $alt = $this->mStripState->unstripBoth( $alt ); |
4512 | 4530 | $alt = Sanitizer::stripAllTags( $alt ); |
4513 | 4531 | |
| 4532 | + # Give extensions a chance to select the file revision for us |
| 4533 | + $skip = $time = false; |
| 4534 | + wfRunHooks( 'BeforeParserMakeImageLinkObj', array( &$this, &$nt, &$skip, &$time ) ); |
| 4535 | + |
4514 | 4536 | # Linker does the rest |
4515 | | - return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, $valign ); |
| 4537 | + if( $skip ) { |
| 4538 | + $link = $sk->makeLinkObj( $nt ); |
| 4539 | + } else { |
| 4540 | + $link = $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $params, $framed, $thumb, $manual_thumb, $valign, $time ); |
| 4541 | + } |
| 4542 | + |
| 4543 | + return $link; |
4516 | 4544 | } |
4517 | 4545 | |
4518 | 4546 | /** |
Index: trunk/phase3/includes/OutputPage.php |
— | — | @@ -54,6 +54,8 @@ |
55 | 55 | $this->mETag = false; |
56 | 56 | $this->mRevisionId = null; |
57 | 57 | $this->mNewSectionLink = false; |
| 58 | + $this->mTemplateIds = array(); |
| 59 | + $this->mImageTimestamps = array(); |
58 | 60 | } |
59 | 61 | |
60 | 62 | public function redirect( $url, $responsecode = '302' ) { |
— | — | @@ -384,6 +386,10 @@ |
385 | 387 | } |
386 | 388 | $this->mNoGallery = $parserOutput->getNoGallery(); |
387 | 389 | $this->mHeadItems = array_merge( $this->mHeadItems, (array)$parserOutput->mHeadItems ); |
| 390 | + // Versioning... |
| 391 | + $this->mTemplateIds += (array)$parserOutput->mTemplateIds; |
| 392 | + $this->mImageTimestamps += (array)$parserOutput->mImageTimestamps; |
| 393 | + |
388 | 394 | wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) ); |
389 | 395 | } |
390 | 396 | |
Index: trunk/phase3/includes/LinksUpdate.php |
— | — | @@ -76,6 +76,7 @@ |
77 | 77 | } else { |
78 | 78 | $this->doIncrementalUpdate(); |
79 | 79 | } |
| 80 | + wfRunHooks( 'TitleLinkUpdatesAfterCompletion', array( &$this->mTitle ) ); |
80 | 81 | } |
81 | 82 | |
82 | 83 | function doIncrementalUpdate() { |
Index: trunk/phase3/includes/ImageGallery.php |
— | — | @@ -17,6 +17,7 @@ |
18 | 18 | var $mImages, $mShowBytes, $mShowFilename; |
19 | 19 | var $mCaption = false; |
20 | 20 | var $mSkin = false; |
| 21 | + var $mRevisionId = 0; |
21 | 22 | |
22 | 23 | /** |
23 | 24 | * Is the gallery on a wiki page (i.e. not a special page) |
— | — | @@ -201,8 +202,12 @@ |
202 | 203 | foreach ( $this->mImages as $pair ) { |
203 | 204 | $nt = $pair[0]; |
204 | 205 | $text = $pair[1]; |
| 206 | + |
| 207 | + # Give extensions a chance to select the file revision for us |
| 208 | + $time = false; |
| 209 | + wfRunHooks( 'BeforeGalleryFindFile', array( &$this, &$nt, &$time ) ); |
205 | 210 | |
206 | | - $img = wfFindFile( $nt ); |
| 211 | + $img = wfFindFile( $nt, $time ); |
207 | 212 | |
208 | 213 | if( $nt->getNamespace() != NS_IMAGE || !$img ) { |
209 | 214 | # We're dealing with a non-image, spit out the name and be done with it. |