* Fix for r60163: in RC/RCL, hash together all the options, not just namespace, in...
authorTim Starling <tstarling@users.mediawiki.org>
Wed, 10 Feb 2010 04:13:43 +0000 (04:13 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Wed, 10 Feb 2010 04:13:43 +0000 (04:13 +0000)
* Removed Crb from the credits since none of his code remains.
* Fixed two bugs which both broke feed links on RCL: $this->mTargetTitle not initialised when setTopText() is called, and $out->setFeedAppendQuery() in setBottomText() overridden by a subsequent call to setSyndicated(). Fixed both by rearranging data flow, using memoized accessors instead of setup functions to eliminate bugs due to execution order.
* Renamed a few variables which were unclear ($feed and $feedObj).

CREDITS
includes/ChangesFeed.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRecentchangeslinked.php

diff --git a/CREDITS b/CREDITS
index e24bab9..4a6b4ea 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -74,7 +74,6 @@ following names for their contribution to the product.
 * Brianna Laugher
 * Carlin
 * Conrad Irwin
-* Crb
 * Dan Nessett
 * Daniel Arnold
 * Denny Vrandecic
index 69a285e..bc50fe0 100644 (file)
@@ -40,14 +40,11 @@ class ChangesFeed {
         *
         * @param $feed ChannelFeed subclass object (generally the one returned by getFeedObject())
         * @param $rows ResultWrapper object with rows in recentchanges table
-        * @param $limit Integer: number of rows in $rows (only used for the cache key)
-        * @param $hideminor Boolean: whether to hide minor edits (only used for the cache key)
         * @param $lastmod Integer: timestamp of the last item in the recentchanges table (only used for the cache key)
-        * @param $target String: target's name; for Special:RecentChangesLinked (only used for the cache key)
-        * @param $namespace Integer: namespace id (only used for the cache key)
+        * @param $opts FormOptions as in SpecialRecentChanges::getDefaultOptions()
         * @return null or true
         */
-       public function execute( $feed, $rows, $limit=0, $hideminor=false, $lastmod=false, $target='', $namespace='' ) {
+       public function execute( $feed, $rows, $lastmod, $opts ) {
                global $messageMemc, $wgFeedCacheTimeout;
                global $wgSitename, $wgLang;
 
@@ -56,7 +53,8 @@ class ChangesFeed {
                }
 
                $timekey = wfMemcKey( $this->type, $this->format, 'timestamp' );
-               $key = wfMemcKey( $this->type, $this->format, $limit, $hideminor, $target, $wgLang->getCode(), $namespace );
+               $optionsHash = md5( serialize( $opts->getAllValues() ) );
+               $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash );
 
                FeedUtils::checkPurge($timekey, $key);
 
@@ -173,4 +171,4 @@ class ChangesFeed {
                wfProfileOut( __METHOD__ );
        }
 
-}
\ No newline at end of file
+}
index dca658c..283eeaf 100644 (file)
@@ -5,6 +5,8 @@
  * @ingroup SpecialPage
  */
 class SpecialRecentChanges extends SpecialPage {
+       var $rcOptions, $rcSubpage;
+
        public function __construct() {
                parent::__construct( 'Recentchanges' );
                $this->includable( true );
@@ -40,7 +42,7 @@ class SpecialRecentChanges extends SpecialPage {
        }
 
        /**
-        * Get a FormOptions object with options as specified by the user
+        * Create a FormOptions object with options as specified by the user
         *
         * @return FormOptions
         */
@@ -60,7 +62,7 @@ class SpecialRecentChanges extends SpecialPage {
        }
 
        /**
-        * Get a FormOptions object sepcific for feed requests
+        * Create a FormOptions object specific for feed requests and return it
         *
         * @return FormOptions
         */
@@ -73,13 +75,27 @@ class SpecialRecentChanges extends SpecialPage {
                return $opts;
        }
 
+       /**
+        * Get the current FormOptions for this request
+        */
+       public function getOptions() {
+               if ( $this->rcOptions === null ) {
+                       global $wgRequest;
+                       $feedFormat = $wgRequest->getVal( 'feed' );
+                       $this->rcOptions = $feedFormat ? $this->feedSetup() : $this->setup( $this->rcSubpage );
+               }
+               return $this->rcOptions;
+       }
+
+
        /**
         * Main execution point
         *
-        * @param $parameters string
+        * @param $subpage string
         */
-       public function execute( $parameters ) {
+       public function execute( $subpage ) {
                global $wgRequest, $wgOut;
+               $this->rcSubpage = $subpage;
                $feedFormat = $wgRequest->getVal( 'feed' );
 
                # 10 seconds server-side caching max
@@ -90,12 +106,11 @@ class SpecialRecentChanges extends SpecialPage {
                        return;
                }
 
-               $opts = $feedFormat ? $this->feedSetup() : $this->setup( $parameters );
+               $opts = $this->getOptions();
                $this->setHeaders();
                $this->outputHeader();
 
                // Fetch results, prepare a batch link existence check query
-               $rows = array();
                $conds = $this->buildMainQueryConds( $opts );
                $rows = $this->doMainQuery( $conds, $opts );
                if( $rows === false ){
@@ -114,10 +129,9 @@ class SpecialRecentChanges extends SpecialPage {
                        }
                        $batch->execute();
                }
-               $target = isset($opts['target']) ? $opts['target'] : ''; // RCL has targets
                if( $feedFormat ) {
-                       list( $feed, $feedObj ) = $this->getFeedObject( $feedFormat );
-                       $feed->execute( $feedObj, $rows, $opts['limit'], $opts['hideminor'], $lastmod, $target, $opts['namespace'] );
+                       list( $changesFeed, $formatter ) = $this->getFeedObject( $feedFormat );
+                       $changesFeed->execute( $formatter, $rows, $lastmod, $opts );
                } else {
                        $this->webOutput( $rows, $opts );
                }
@@ -131,12 +145,12 @@ class SpecialRecentChanges extends SpecialPage {
         * @return array
         */
        public function getFeedObject( $feedFormat ){
-               $feed = new ChangesFeed( $feedFormat, 'rcfeed' );
-               $feedObj = $feed->getFeedObject(
+               $changesFeed = new ChangesFeed( $feedFormat, 'rcfeed' );
+               $formatter = $changesFeed->getFeedObject(
                        wfMsgForContent( 'recentchanges' ),
                        wfMsgForContent( 'recentchanges-feed-description' )
                );
-               return array( $feed, $feedObj );
+               return array( $changesFeed, $formatter );
        }
 
        /**
@@ -355,7 +369,7 @@ class SpecialRecentChanges extends SpecialPage {
                }
 
                // And now for the content
-               $wgOut->setSyndicated( true );
+               $wgOut->setFeedAppendQuery( $this->getFeedQuery() );
 
                if( $wgAllowCategorizedRecentChanges ) {
                        $this->filterByCategories( $rows, $opts );
@@ -402,6 +416,14 @@ class SpecialRecentChanges extends SpecialPage {
                $wgOut->addHTML( $s );
        }
 
+       /**
+        * Get the query string to append to feed link URLs.
+        * This is overridden by RCL to add the target parameter
+        */
+       public function getFeedQuery() {
+               return false;
+       }
+
        /**
         * Return the text to be displayed above the changes
         *
index 49cef5b..3b54984 100644 (file)
@@ -5,6 +5,7 @@
  * @ingroup SpecialPage
  */
 class SpecialRecentchangeslinked extends SpecialRecentchanges {
+       var $rclTargetTitle;
 
        function __construct(){
                SpecialPage::SpecialPage( 'Recentchangeslinked' );
@@ -26,7 +27,6 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
        public function feedSetup() {
                global $wgRequest;
                $opts = parent::feedSetup();
-               # Feed is cached on limit,hideminor,target; other params would randomly not work
                $opts['target'] = $wgRequest->getVal( 'target' );
                return $opts;
        }
@@ -34,7 +34,7 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
        public function getFeedObject( $feedFormat ){
                $feed = new ChangesFeed( $feedFormat, false );
                $feedObj = $feed->getFeedObject(
-                       wfMsgForContent( 'recentchangeslinked-title', $this->mTargetTitle->getPrefixedText() ),
+                       wfMsgForContent( 'recentchangeslinked-title', $this->getTargetTitle()->getPrefixedText() ),
                        wfMsgForContent( 'recentchangeslinked-feed' )
                );
                return array( $feed, $feedObj );
@@ -55,7 +55,6 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
                        $wgOut->wrapWikiMsg( "<div class=\"errorbox\">\n$1</div><br style=\"clear: both\" />", 'allpagesbadtitle' );
                        return false;
                }
-               $this->mTargetTitle = $title;
 
                $wgOut->setPageTitle( wfMsg( 'recentchangeslinked-title', $title->getPrefixedText() ) );
 
@@ -197,18 +196,37 @@ class SpecialRecentchangeslinked extends SpecialRecentchanges {
                return $extraOpts;
        }
 
+       function getTargetTitle() {
+               if ( $this->rclTargetTitle === null ) {
+                       $opts = $this->getOptions();
+                       if ( isset( $opts['target'] ) && $opts['target'] !== '' ) {
+                               $this->rclTargetTitle = Title::newFromText( $opts['target'] );
+                       } else {
+                               $this->rclTargetTitle = false;
+                       }
+               }
+               return $this->rclTargetTitle;
+       }
+
        function setTopText( OutputPage $out, FormOptions $opts ) {
                global $wgUser;
                $skin = $wgUser->getSkin();
-               if( isset( $this->mTargetTitle ) && is_object( $this->mTargetTitle ) )
-                       $out->setSubtitle( wfMsg( 'recentchangeslinked-backlink', $skin->link( $this->mTargetTitle,
-                               $this->mTargetTitle->getPrefixedText(), array(), array( 'redirect' => 'no'  ) ) ) );
+               $target = $this->getTargetTitle();
+               if( $target )
+                       $out->setSubtitle( wfMsg( 'recentchangeslinked-backlink', $skin->link( $target,
+                               $target->getPrefixedText(), array(), array( 'redirect' => 'no'  ) ) ) );
        }
 
-       function setBottomText( OutputPage $out, FormOptions $opts ){
-               if( isset( $this->mTargetTitle ) && is_object( $this->mTargetTitle ) ){
-                       $out->setFeedAppendQuery( "target=" . urlencode( $this->mTargetTitle->getPrefixedDBkey() ) );
+       public function getFeedQuery() {
+               $target = $this->getTargetTitle();
+               if( $target ) {
+                       return "target=" . urlencode( $target->getPrefixedDBkey() );
+               } else {
+                       return false;
                }
+       }
+
+       function setBottomText( OutputPage $out, FormOptions $opts ) {
                if( isset( $this->mResultEmpty ) && $this->mResultEmpty ){
                        $out->addWikiMsg( 'recentchangeslinked-noresult' );     
                }