* 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).
* Brianna Laugher
* Carlin
* Conrad Irwin
-* Crb
* Dan Nessett
* Daniel Arnold
* Denny Vrandecic
*
* @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;
}
$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);
wfProfileOut( __METHOD__ );
}
-}
\ No newline at end of file
+}
* @ingroup SpecialPage
*/
class SpecialRecentChanges extends SpecialPage {
+ var $rcOptions, $rcSubpage;
+
public function __construct() {
parent::__construct( 'Recentchanges' );
$this->includable( true );
}
/**
- * Get a FormOptions object with options as specified by the user
+ * Create a FormOptions object with options as specified by the user
*
* @return FormOptions
*/
}
/**
- * Get a FormOptions object sepcific for feed requests
+ * Create a FormOptions object specific for feed requests and return it
*
* @return FormOptions
*/
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
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 ){
}
$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 );
}
* @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 );
}
/**
}
// And now for the content
- $wgOut->setSyndicated( true );
+ $wgOut->setFeedAppendQuery( $this->getFeedQuery() );
if( $wgAllowCategorizedRecentChanges ) {
$this->filterByCategories( $rows, $opts );
$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
*
* @ingroup SpecialPage
*/
class SpecialRecentchangeslinked extends SpecialRecentchanges {
+ var $rclTargetTitle;
function __construct(){
SpecialPage::SpecialPage( 'Recentchangeslinked' );
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;
}
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 );
$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() ) );
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' );
}