MediaWiki
REL1_24
|
00001 <?php 00034 class ApiFeedWatchlist extends ApiBase { 00035 00036 private $watchlistModule = null; 00037 private $linkToSections = false; 00038 00044 public function getCustomPrinter() { 00045 return new ApiFormatFeedWrapper( $this->getMain() ); 00046 } 00047 00052 public function execute() { 00053 $config = $this->getConfig(); 00054 $feedClasses = $config->get( 'FeedClasses' ); 00055 try { 00056 $params = $this->extractRequestParams(); 00057 00058 if ( !$config->get( 'Feed' ) ) { 00059 $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' ); 00060 } 00061 00062 if ( !isset( $feedClasses[$params['feedformat']] ) ) { 00063 $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' ); 00064 } 00065 00066 // limit to the number of hours going from now back 00067 $endTime = wfTimestamp( TS_MW, time() - intval( $params['hours'] * 60 * 60 ) ); 00068 00069 // Prepare parameters for nested request 00070 $fauxReqArr = array( 00071 'action' => 'query', 00072 'meta' => 'siteinfo', 00073 'siprop' => 'general', 00074 'list' => 'watchlist', 00075 'wlprop' => 'title|user|comment|timestamp|ids', 00076 'wldir' => 'older', // reverse order - from newest to oldest 00077 'wlend' => $endTime, // stop at this time 00078 'wllimit' => min( 50, $this->getConfig()->get( 'FeedLimit' ) ) 00079 ); 00080 00081 if ( $params['wlowner'] !== null ) { 00082 $fauxReqArr['wlowner'] = $params['wlowner']; 00083 } 00084 if ( $params['wltoken'] !== null ) { 00085 $fauxReqArr['wltoken'] = $params['wltoken']; 00086 } 00087 if ( $params['wlexcludeuser'] !== null ) { 00088 $fauxReqArr['wlexcludeuser'] = $params['wlexcludeuser']; 00089 } 00090 if ( $params['wlshow'] !== null ) { 00091 $fauxReqArr['wlshow'] = $params['wlshow']; 00092 } 00093 if ( $params['wltype'] !== null ) { 00094 $fauxReqArr['wltype'] = $params['wltype']; 00095 } 00096 00097 // Support linking directly to sections when possible 00098 // (possible only if section name is present in comment) 00099 if ( $params['linktosections'] ) { 00100 $this->linkToSections = true; 00101 } 00102 00103 // Check for 'allrev' parameter, and if found, show all revisions to each page on wl. 00104 if ( $params['allrev'] ) { 00105 $fauxReqArr['wlallrev'] = ''; 00106 } 00107 00108 // Create the request 00109 $fauxReq = new FauxRequest( $fauxReqArr ); 00110 00111 // Execute 00112 $module = new ApiMain( $fauxReq ); 00113 $module->execute(); 00114 00115 // Get data array 00116 $data = $module->getResultData(); 00117 00118 $feedItems = array(); 00119 foreach ( (array)$data['query']['watchlist'] as $info ) { 00120 $feedItems[] = $this->createFeedItem( $info ); 00121 } 00122 00123 $msg = wfMessage( 'watchlist' )->inContentLanguage()->text(); 00124 00125 $feedTitle = $this->getConfig()->get( 'Sitename' ) . ' - ' . $msg . ' [' . $this->getConfig()->get( 'LanguageCode' ) . ']'; 00126 $feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullURL(); 00127 00128 $feed = new $feedClasses[$params['feedformat']] ( 00129 $feedTitle, 00130 htmlspecialchars( $msg ), 00131 $feedUrl 00132 ); 00133 00134 ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); 00135 } catch ( Exception $e ) { 00136 // Error results should not be cached 00137 $this->getMain()->setCacheMaxAge( 0 ); 00138 00139 // @todo FIXME: Localise brackets 00140 $feedTitle = $this->getConfig()->get( 'Sitename' ) . ' - Error - ' . 00141 wfMessage( 'watchlist' )->inContentLanguage()->text() . 00142 ' [' . $this->getConfig()->get( 'LanguageCode' ) . ']'; 00143 $feedUrl = SpecialPage::getTitleFor( 'Watchlist' )->getFullURL(); 00144 00145 $feedFormat = isset( $params['feedformat'] ) ? $params['feedformat'] : 'rss'; 00146 $msg = wfMessage( 'watchlist' )->inContentLanguage()->escaped(); 00147 $feed = new $feedClasses[$feedFormat] ( $feedTitle, $msg, $feedUrl ); 00148 00149 if ( $e instanceof UsageException ) { 00150 $errorCode = $e->getCodeString(); 00151 } else { 00152 // Something is seriously wrong 00153 $errorCode = 'internal_api_error'; 00154 } 00155 00156 $errorText = $e->getMessage(); 00157 $feedItems[] = new FeedItem( "Error ($errorCode)", $errorText, '', '', '' ); 00158 ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); 00159 } 00160 } 00161 00166 private function createFeedItem( $info ) { 00167 $titleStr = $info['title']; 00168 $title = Title::newFromText( $titleStr ); 00169 if ( isset( $info['revid'] ) ) { 00170 $titleUrl = $title->getFullURL( array( 'diff' => $info['revid'] ) ); 00171 } else { 00172 $titleUrl = $title->getFullURL(); 00173 } 00174 $comment = isset( $info['comment'] ) ? $info['comment'] : null; 00175 00176 // Create an anchor to section. 00177 // The anchor won't work for sections that have dupes on page 00178 // as there's no way to strip that info from ApiWatchlist (apparently?). 00179 // RegExp in the line below is equal to Linker::formatAutocomments(). 00180 if ( $this->linkToSections && $comment !== null && 00181 preg_match( '!(.*)/\*\s*(.*?)\s*\*/(.*)!', $comment, $matches ) 00182 ) { 00183 global $wgParser; 00184 00185 $sectionTitle = $wgParser->stripSectionName( $matches[2] ); 00186 $sectionTitle = Sanitizer::normalizeSectionNameWhitespace( $sectionTitle ); 00187 $titleUrl .= Title::newFromText( '#' . $sectionTitle )->getFragmentForURL(); 00188 } 00189 00190 $timestamp = $info['timestamp']; 00191 $user = $info['user']; 00192 00193 $completeText = "$comment ($user)"; 00194 00195 return new FeedItem( $titleStr, $completeText, $titleUrl, $timestamp, $user ); 00196 } 00197 00198 private function getWatchlistModule() { 00199 if ( $this->watchlistModule === null ) { 00200 $this->watchlistModule = $this->getMain()->getModuleManager()->getModule( 'query' ) 00201 ->getModuleManager()->getModule( 'watchlist' ); 00202 } 00203 00204 return $this->watchlistModule; 00205 } 00206 00207 public function getAllowedParams( $flags = 0 ) { 00208 $feedFormatNames = array_keys( $this->getConfig()->get( 'FeedClasses' ) ); 00209 $ret = array( 00210 'feedformat' => array( 00211 ApiBase::PARAM_DFLT => 'rss', 00212 ApiBase::PARAM_TYPE => $feedFormatNames 00213 ), 00214 'hours' => array( 00215 ApiBase::PARAM_DFLT => 24, 00216 ApiBase::PARAM_TYPE => 'integer', 00217 ApiBase::PARAM_MIN => 1, 00218 ApiBase::PARAM_MAX => 72, 00219 ), 00220 'linktosections' => false, 00221 ); 00222 if ( $flags ) { 00223 $wlparams = $this->getWatchlistModule()->getAllowedParams( $flags ); 00224 $ret['allrev'] = $wlparams['allrev']; 00225 $ret['wlowner'] = $wlparams['owner']; 00226 $ret['wltoken'] = $wlparams['token']; 00227 $ret['wlshow'] = $wlparams['show']; 00228 $ret['wltype'] = $wlparams['type']; 00229 $ret['wlexcludeuser'] = $wlparams['excludeuser']; 00230 } else { 00231 $ret['allrev'] = null; 00232 $ret['wlowner'] = null; 00233 $ret['wltoken'] = null; 00234 $ret['wlshow'] = null; 00235 $ret['wltype'] = null; 00236 $ret['wlexcludeuser'] = null; 00237 } 00238 00239 return $ret; 00240 } 00241 00242 public function getParamDescription() { 00243 $wldescr = $this->getWatchlistModule()->getParamDescription(); 00244 00245 return array( 00246 'feedformat' => 'The format of the feed', 00247 'hours' => 'List pages modified within this many hours from now', 00248 'linktosections' => 'Link directly to changed sections if possible', 00249 'allrev' => $wldescr['allrev'], 00250 'wlowner' => $wldescr['owner'], 00251 'wltoken' => $wldescr['token'], 00252 'wlshow' => $wldescr['show'], 00253 'wltype' => $wldescr['type'], 00254 'wlexcludeuser' => $wldescr['excludeuser'], 00255 ); 00256 } 00257 00258 public function getDescription() { 00259 return 'Returns a watchlist feed.'; 00260 } 00261 00262 public function getExamples() { 00263 return array( 00264 'api.php?action=feedwatchlist', 00265 'api.php?action=feedwatchlist&allrev=&hours=6' 00266 ); 00267 } 00268 00269 public function getHelpUrls() { 00270 return 'https://www.mediawiki.org/wiki/API:Watchlist_feed'; 00271 } 00272 }