MediaWiki
REL1_22
|
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 00076 public function execute( $feed, $rows, $lastmod, $opts ) { 00077 global $wgLang, $wgRenderHashAppend; 00078 00079 if ( !FeedUtils::checkFeedOutput( $this->format ) ) { 00080 return null; 00081 } 00082 00083 $optionsHash = md5( serialize( $opts->getAllValues() ) ) . $wgRenderHashAppend; 00084 $timekey = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash, 'timestamp' ); 00085 $key = wfMemcKey( $this->type, $this->format, $wgLang->getCode(), $optionsHash ); 00086 00087 FeedUtils::checkPurge( $timekey, $key ); 00088 00094 $cachedFeed = $this->loadFromCache( $lastmod, $timekey, $key ); 00095 if ( is_string( $cachedFeed ) ) { 00096 wfDebug( "RC: Outputting cached feed\n" ); 00097 $feed->httpHeaders(); 00098 echo $cachedFeed; 00099 } else { 00100 wfDebug( "RC: rendering new feed and caching it\n" ); 00101 ob_start(); 00102 self::generateFeed( $rows, $feed ); 00103 $cachedFeed = ob_get_contents(); 00104 ob_end_flush(); 00105 $this->saveToCache( $cachedFeed, $timekey, $key ); 00106 } 00107 return true; 00108 } 00109 00117 public function saveToCache( $feed, $timekey, $key ) { 00118 global $messageMemc; 00119 $expire = 3600 * 24; # One day 00120 $messageMemc->set( $key, $feed, $expire ); 00121 $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire ); 00122 } 00123 00132 public function loadFromCache( $lastmod, $timekey, $key ) { 00133 global $wgFeedCacheTimeout, $wgOut, $messageMemc; 00134 00135 $feedLastmod = $messageMemc->get( $timekey ); 00136 00137 if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) { 00145 $feedAge = time() - wfTimestamp( TS_UNIX, $feedLastmod ); 00146 $feedLastmodUnix = wfTimestamp( TS_UNIX, $feedLastmod ); 00147 $lastmodUnix = wfTimestamp( TS_UNIX, $lastmod ); 00148 00149 if ( $feedAge < $wgFeedCacheTimeout || $feedLastmodUnix > $lastmodUnix ) { 00150 wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" ); 00151 if ( $feedLastmodUnix < $lastmodUnix ) { 00152 $wgOut->setLastModified( $feedLastmod ); // bug 21916 00153 } 00154 return $messageMemc->get( $key ); 00155 } else { 00156 wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" ); 00157 } 00158 } 00159 return false; 00160 } 00161 00167 public static function generateFeed( $rows, &$feed ) { 00168 wfProfileIn( __METHOD__ ); 00169 00170 $feed->outHeader(); 00171 00172 # Merge adjacent edits by one user 00173 $sorted = array(); 00174 $n = 0; 00175 foreach ( $rows as $obj ) { 00176 if ( $n > 0 && 00177 $obj->rc_type == RC_EDIT && 00178 $obj->rc_namespace >= 0 && 00179 $obj->rc_cur_id == $sorted[$n - 1]->rc_cur_id && 00180 $obj->rc_user_text == $sorted[$n - 1]->rc_user_text ) { 00181 $sorted[$n - 1]->rc_last_oldid = $obj->rc_last_oldid; 00182 } else { 00183 $sorted[$n] = $obj; 00184 $n++; 00185 } 00186 } 00187 00188 foreach ( $sorted as $obj ) { 00189 $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title ); 00190 $talkpage = MWNamespace::canTalk( $obj->rc_namespace ) ? $title->getTalkPage()->getFullURL() : ''; 00191 // Skip items with deleted content (avoids partially complete/inconsistent output) 00192 if ( $obj->rc_deleted ) { 00193 continue; 00194 } 00195 00196 if ( $obj->rc_this_oldid ) { 00197 $url = $title->getFullURL( array( 00198 'diff' => $obj->rc_this_oldid, 00199 'oldid' => $obj->rc_last_oldid, 00200 ) ); 00201 } else { 00202 // log entry or something like that. 00203 $url = $title->getFullURL(); 00204 } 00205 00206 $item = new FeedItem( 00207 $title->getPrefixedText(), 00208 FeedUtils::formatDiff( $obj ), 00209 $url, 00210 $obj->rc_timestamp, 00211 ( $obj->rc_deleted & Revision::DELETED_USER ) 00212 ? wfMessage( 'rev-deleted-user' )->escaped() : $obj->rc_user_text, 00213 $talkpage 00214 ); 00215 $feed->outItem( $item ); 00216 } 00217 $feed->outFooter(); 00218 wfProfileOut( __METHOD__ ); 00219 } 00220 00221 }