From e185e2b9b36babb3db1036e84f2dd2d2bccda304 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 10 Feb 2010 04:13:43 +0000 Subject: [PATCH] * Fix for r60163: in RC/RCL, hash together all the options, not just namespace, in order to form the cache key. * 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 | 1 - includes/ChangesFeed.php | 12 ++--- includes/specials/SpecialRecentchanges.php | 48 ++++++++++++++----- .../specials/SpecialRecentchangeslinked.php | 36 ++++++++++---- 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/CREDITS b/CREDITS index e24bab9d4c..4a6b4ea026 100644 --- 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 diff --git a/includes/ChangesFeed.php b/includes/ChangesFeed.php index 69a285e91e..bc50fe0214 100644 --- a/includes/ChangesFeed.php +++ b/includes/ChangesFeed.php @@ -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 +} diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index dca658c8c2..283eeaf425 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -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 * diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php index 49cef5b53a..3b549843fe 100644 --- a/includes/specials/SpecialRecentchangeslinked.php +++ b/includes/specials/SpecialRecentchangeslinked.php @@ -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( "
\n$1

", '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' ); } -- 2.20.1