MediaWiki
REL1_24
|
00001 <?php 00028 class ChangesFeed { 00029 public $format, $type, $titleMsg, $descMsg; 00030 00037 public function __construct( $format, $type ) { 00038 $this->format = $format; 00039 $this->type = $type; 00040 } 00041 00050 public function getFeedObject( $title, $description, $url ) { 00051 global $wgSitename, $wgLanguageCode, $wgFeedClasses; 00052 00053 if ( !isset( $wgFeedClasses[$this->format] ) ) { 00054 return false; 00055 } 00056 00057 if ( !array_key_exists( $this->format, $wgFeedClasses ) ) { 00058 // falling back to atom 00059 $this->format = 'atom'; 00060 } 00061 00062 $feedTitle = "$wgSitename - {$title} [$wgLanguageCode]"; 00063 return new $wgFeedClasses[$this->format]( 00064 $feedTitle, htmlspecialchars( $description ), $url ); 00065 } 00066 00078 public function execute( $feed, $rows, $lastmod, $opts ) { 00079 global $wgLang, $wgRenderHashAppend; 00080 00081 if ( !FeedUtils::checkFeedOutput( $this->format ) ) { 00082 return null; 00083 } 00084 00085 $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend; 00086 $timekey = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' ); 00087 $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash ); 00088 00089 FeedUtils::checkPurge( $timekey, $key ); 00090 00096 $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key ); 00097 if ( is_string( $cachedFeed ) ) { 00098 wfDebug( "RC: Outputting cached feed\n" ); 00099 $feed->httpHeaders(); 00100 echo $cachedFeed; 00101 } else { 00102 wfDebug( "RC: rendering new feed and caching it\n" ); 00103 ob_start(); 00104 self::generateFeed( $rows, $feed ); 00105 $cachedFeed = ob_get_contents(); 00106 ob_end_flush(); 00107 $this->saveToCache( $cachedFeed, $timekey, $key ); 00108 } 00109 return true; 00110 } 00111 00119 public function saveToCache( $feed, $timekey, $key ) { 00120 global $messageMemc; 00121 $expire = 3600 * 24; # One day 00122 $messageMemc->set( $key, $feed, $expire ); 00123 $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire ); 00124 } 00125 00134 public function loadFromCache( $lastmod, $timekey, $key ) { 00135 global $wgFeedCacheTimeout, $wgOut, $messageMemc; 00136 00137 $feedLastmod = $messageMemc->get( $timekey ); 00138 00139 if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) { 00147 $feedAge = time() - wfTimestamp( TS_UNIX, $feedLastmod ); 00148 $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod ); 00149 $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod ); 00150 00151 if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) { 00152 wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" ); 00153 if ( $feedLastmodUnix < $lastmodUnix ) { 00154 $wgOut->setLastModified( $feedLastmod ); // bug 21916 00155 } 00156 return $messageMemc->get( $key ); 00157 } else { 00158 wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" ); 00159 } 00160 } 00161 return false; 00162 } 00163 00169 public static function generateFeed( $rows, &$feed ) { 00170 wfProfileIn( __METHOD__ ); 00171 $items = self::buildItems( $rows ); 00172 $feed->outHeader(); 00173 foreach ( $items as $item ) { 00174 $feed->outItem( $item ); 00175 } 00176 $feed->outFooter(); 00177 wfProfileOut( __METHOD__ ); 00178 } 00179 00185 public static function buildItems( $rows ) { 00186 wfProfileIn( __METHOD__ ); 00187 $items = array(); 00188 00189 # Merge adjacent edits by one user 00190 $sorted = array(); 00191 $n = 0; 00192 foreach ( $rows as $obj ) { 00193 if ( $n > 0 && 00194 $obj->rc_type == RC_EDIT && 00195 $obj->rc_namespace >= 0 && 00196 $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id && 00197 $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) { 00198 $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid; 00199 } else { 00200 $sorted[$n] = $obj; 00201 $n++; 00202 } 00203 } 00204 00205 foreach ( $sorted as $obj ) { 00206 $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title ); 00207 $talkpage = MWNamespace::canTalk( $obj->rc_namespace ) 00208 ? $title->getTalkPage()->getFullURL() 00209 : ''; 00210 00211 // Skip items with deleted content (avoids partially complete/inconsistent output) 00212 if ( $obj->rc_deleted ) { 00213 continue; 00214 } 00215 00216 if ( $obj->rc_this_oldid ) { 00217 $url = $title->getFullURL( array( 00218 'diff' => $obj->rc_this_oldid, 00219 'oldid' => $obj->rc_last_oldid, 00220 ) ); 00221 } else { 00222 // log entry or something like that. 00223 $url = $title->getFullURL(); 00224 } 00225 00226 $items[] = new FeedItem( 00227 $title->getPrefixedText(), 00228 FeedUtils::formatDiff( $obj ), 00229 $url, 00230 $obj->rc_timestamp, 00231 ( $obj->rc_deleted & Revision::DELETED_USER ) 00232 ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text, 00233 $talkpage 00234 ); 00235 } 00236 00237 wfProfileOut( __METHOD__ ); 00238 return $items; 00239 } 00240 }