r49425 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49424‎ | r49425 | r49426 >
Date:14:57, 12 April 2009
Author:ialex
Status:deferred (Comments)
Tags:
Comment:
* Converted spaces to tabs for identation
* Removed trailing spaces
Modified paths:
  • /trunk/extensions/WikiArticleFeeds/WikiArticleFeeds.php (modified) (history)

Diff [purge]

Index: trunk/extensions/WikiArticleFeeds/WikiArticleFeeds.php
@@ -1,4 +1,4 @@
2 -<?php
 2+<?php
33 /*
44 * WikiArticleFeeds.php - A MediaWiki extension for converting regular pages into feeds.
55 * @author Jim R. Wilson
@@ -93,24 +93,24 @@
9494 * OTHER DEALINGS IN THE SOFTWARE.
9595 * -----------------------------------------------------------------------
9696 */
97 -
98 - # Confirm MW environment
99 -if (!defined('MEDIAWIKI')) die();
10097
101 -define('WIKIARTICLEFEEDS_VERSION','0.6.4');
 98+# Confirm MW environment
 99+if ( !defined( 'MEDIAWIKI' ) ) die();
102100
 101+define( 'WIKIARTICLEFEEDS_VERSION', '0.6.4' );
 102+
103103 # Bring in supporting classes
104 -require_once("$IP/includes/Feed.php");
105 -require_once("$IP/includes/Sanitizer.php");
 104+require_once( "$IP/includes/Feed.php" );
 105+require_once( "$IP/includes/Sanitizer.php" );
106106
107107 # Credits
108108 $wgExtensionCredits['specialpage'][] = array(
109 - 'name'=>'WikiArticleFeeds',
110 - 'author'=>'Jim Wilson (wilson.jim.r&lt;at&gt;gmail.com)',
111 - 'url'=>'http://jimbojw.com/wiki/index.php?title=WikiArticleFeeds',
112 - 'description'=>'Produces feeds generated from MediaWiki articles.',
 109+ 'name' => 'WikiArticleFeeds',
 110+ 'author' => 'Jim Wilson (wilson.jim.r&lt;at&gt;gmail.com)',
 111+ 'url' => 'http://jimbojw.com/wiki/index.php?title=WikiArticleFeeds',
 112+ 'description' => 'Produces feeds generated from MediaWiki articles.',
113113 'descriptionmsg' => 'wikiarticlefeeds-desc',
114 - 'version'=>WIKIARTICLEFEEDS_VERSION
 114+ 'version' => WIKIARTICLEFEEDS_VERSION
115115 );
116116
117117 $dir = dirname( __FILE__ ) . '/';
@@ -122,62 +122,62 @@
123123 */
124124 class WikiArticleFeedsParser {
125125
126 - function feedStart( $text, $params = array() ) {
127 - return '<!-- FEED_START -->';
128 - }
129 -
130 - function feedEnd( $text, $params = array() ) {
131 - return '<!-- FEED_END -->';
132 - }
133 -
134 - function burnFeed( $text, $params = array() ) {
135 - return ($params['name']?'<!-- BURN_FEED '.base64_encode(serialize($params['name'])).' -->':'');
136 - }
137 -
138 - function itemTagsTag( $text, $params = array() ) {
139 - return ($text?'<!-- ITEM_TAGS '.base64_encode(serialize($text)).' -->':'');
140 - }
141 -
142 - function itemTagsFunction( $parser ) {
143 - $tags = func_get_args();
144 - array_shift( $tags );
145 - return (!empty($tags)?'<pre>@ITEMTAGS@'.base64_encode(serialize(implode(',',$tags))).'@ITEMTAGS@</pre>':'');
146 - }
147 -
148 - function itemTagsMagic( &$magicWords, $langCode=null ) {
149 - $magicWords['itemtags'] = array( 0, 'itemtags' );
150 - return true;
151 - }
152 -
153 - function itemTagsPlaceholderCorrections( $parser, &$text ) {
154 - $text = preg_replace(
155 - '|<pre>@ITEMTAGS@([0-9a-zA-Z\\+\\/]+=*)@ITEMTAGS@</pre>|',
156 - '<!-- ITEM_TAGS $1 -->',
157 - $text
158 - );
159 - return true;
160 - }
 126+ function feedStart( $text, $params = array() ) {
 127+ return '<!-- FEED_START -->';
 128+ }
 129+
 130+ function feedEnd( $text, $params = array() ) {
 131+ return '<!-- FEED_END -->';
 132+ }
 133+
 134+ function burnFeed( $text, $params = array() ) {
 135+ return ( $params['name'] ? '<!-- BURN_FEED ' . base64_encode( serialize( $params['name'] ) ) . ' -->':'' );
 136+ }
 137+
 138+ function itemTagsTag( $text, $params = array() ) {
 139+ return ( $text ? '<!-- ITEM_TAGS ' . base64_encode( serialize( $text ) ) . ' -->':'' );
 140+ }
 141+
 142+ function itemTagsFunction( $parser ) {
 143+ $tags = func_get_args();
 144+ array_shift( $tags );
 145+ return ( !empty( $tags ) ? '<pre>@ITEMTAGS@' . base64_encode( serialize( implode( ',', $tags ) ) ) . '@ITEMTAGS@</pre>':'' );
 146+ }
 147+
 148+ function itemTagsMagic( &$magicWords, $langCode = null ) {
 149+ $magicWords['itemtags'] = array( 0, 'itemtags' );
 150+ return true;
 151+ }
 152+
 153+ function itemTagsPlaceholderCorrections( $parser, &$text ) {
 154+ $text = preg_replace(
 155+ '|<pre>@ITEMTAGS@([0-9a-zA-Z\\+\\/]+=*)@ITEMTAGS@</pre>|',
 156+ '<!-- ITEM_TAGS $1 -->',
 157+ $text
 158+ );
 159+ return true;
 160+ }
161161 }
162162
163163 # Create global instance
164164 $wgWikiArticleFeedsParser = new WikiArticleFeedsParser();
165 -if (version_compare($wgVersion, '1.7', '<')) {
166 - # Hack solution to resolve 1.6 array parameter nullification for hook args
167 - function wfWAFParserItemTagsMagic( &$magicWords ) {
168 - global $wgWikiArticleFeedsParser;
169 - $wgWikiArticleFeedsParser->itemTagsMagic( $magicWords );
170 - return true;
171 - }
172 - function wfWAFParserPlaceholderCorrections( $parser, &$text ) {
173 - global $wgWikiArticleFeedsParser;
174 - $wgWikiArticleFeedsParser->itemTagsPlaceholderCorrections( $parser, $text );
175 - return true;
176 - }
177 - $wgHooks['LanguageGetMagic'][] = 'wfWAFParserItemTagsMagic';
178 - $wgHooks['ParserBeforeTidy'][] = 'wfWAFParserPlaceholderCorrections';
 165+if ( version_compare( $wgVersion, '1.7', '<' ) ) {
 166+ # Hack solution to resolve 1.6 array parameter nullification for hook args
 167+ function wfWAFParserItemTagsMagic( &$magicWords ) {
 168+ global $wgWikiArticleFeedsParser;
 169+ $wgWikiArticleFeedsParser->itemTagsMagic( $magicWords );
 170+ return true;
 171+ }
 172+ function wfWAFParserPlaceholderCorrections( $parser, &$text ) {
 173+ global $wgWikiArticleFeedsParser;
 174+ $wgWikiArticleFeedsParser->itemTagsPlaceholderCorrections( $parser, $text );
 175+ return true;
 176+ }
 177+ $wgHooks['LanguageGetMagic'][] = 'wfWAFParserItemTagsMagic';
 178+ $wgHooks['ParserBeforeTidy'][] = 'wfWAFParserPlaceholderCorrections';
179179 } else {
180 - $wgHooks['LanguageGetMagic'][] = array($wgWikiArticleFeedsParser, 'itemTagsMagic');
181 - $wgHooks['ParserBeforeTidy'][] = array($wgWikiArticleFeedsParser, 'itemTagsPlaceholderCorrections');
 180+ $wgHooks['LanguageGetMagic'][] = array( $wgWikiArticleFeedsParser, 'itemTagsMagic' );
 181+ $wgHooks['ParserBeforeTidy'][] = array( $wgWikiArticleFeedsParser, 'itemTagsPlaceholderCorrections' );
182182 }
183183
184184 # Add Extension Functions
@@ -185,14 +185,14 @@
186186
187187 # Sets up the WikiArticleFeeds Parser hooks
188188 function wfWikiArticleFeedsParserSetup() {
189 - global $wgParser, $wgWikiArticleFeedsParser;
190 -
191 - $wgParser->setHook( 'startFeed', array($wgWikiArticleFeedsParser, 'feedStart') );
192 - $wgParser->setHook( 'endFeed', array($wgWikiArticleFeedsParser, 'feedEnd') );
193 - $wgParser->setHook( 'feedBurner', array($wgWikiArticleFeedsParser, 'burnFeed') );
194 - $wgParser->setHook( 'itemTags', array($wgWikiArticleFeedsParser, 'itemTagsTag') );
195 -
196 - $wgParser->setFunctionHook( 'itemtags', array($wgWikiArticleFeedsParser, 'itemTagsFunction') );
 189+ global $wgParser, $wgWikiArticleFeedsParser;
 190+
 191+ $wgParser->setHook( 'startFeed', array( $wgWikiArticleFeedsParser, 'feedStart' ) );
 192+ $wgParser->setHook( 'endFeed', array( $wgWikiArticleFeedsParser, 'feedEnd' ) );
 193+ $wgParser->setHook( 'feedBurner', array( $wgWikiArticleFeedsParser, 'burnFeed' ) );
 194+ $wgParser->setHook( 'itemTags', array( $wgWikiArticleFeedsParser, 'itemTagsTag' ) );
 195+
 196+ $wgParser->setFunctionHook( 'itemtags', array( $wgWikiArticleFeedsParser, 'itemTagsFunction' ) );
197197 }
198198
199199 # Attach Hooks
@@ -207,49 +207,49 @@
208208 * @param $out Handle to an OutputPage object (presumably $wgOut).
209209 * @param $text Article/Output text.
210210 */
211 -function wfAddWikiFeedHeaders($out, $text) {
 211+function wfAddWikiFeedHeaders( $out, $text ) {
212212
213 - # Short-circuit if this article contains no feeds
214 - if (!preg_match('/<!-- FEED_START -->/m', $text)) return true;
215 -
216 - $rssArr = array(
217 - 'rel' => 'alternate',
218 - 'type' => 'application/rss+xml',
219 - 'title' => 'RSS 2.0',
220 - );
221 - $atomArr = array(
222 - 'rel' => 'alternate',
223 - 'type' => 'application/atom+xml',
224 - 'title' => 'Atom 0.3',
225 - );
 213+ # Short-circuit if this article contains no feeds
 214+ if ( !preg_match( '/<!-- FEED_START -->/m', $text ) ) return true;
226215
227 - # Test for feedBurner presence
228 - if (preg_match('/<!-- BURN_FEED ([0-9a-zA-Z\\+\\/]+=*) -->/m', $text, $matches)) {
229 - $name = @unserialize(@base64_decode($matches[1]));
230 - if ($name) {
231 - $rssArr['href'] = 'http://feeds.feedburner.com/'.urlencode($name).'?format=xml';
232 - $atomArr['href'] = 'http://feeds.feedburner.com/'.urlencode($name).'?format=xml';
233 - }
234 - }
235 -
236 - # If its not being fed by feedBurner, do it ourselves!
237 - if (!array_key_exists('href', $rssArr) || !$rssArr['href']) {
 216+ $rssArr = array(
 217+ 'rel' => 'alternate',
 218+ 'type' => 'application/rss+xml',
 219+ 'title' => 'RSS 2.0',
 220+ );
 221+ $atomArr = array(
 222+ 'rel' => 'alternate',
 223+ 'type' => 'application/atom+xml',
 224+ 'title' => 'Atom 0.3',
 225+ );
238226
239 - global $wgServer, $wgScript, $wgTitle;
240 -
241 - $baseUrl = $wgServer.$wgScript.'?title='.$wgTitle->getDBkey().'&action=feed&feed=';
242 - $rssArr['href'] = $baseUrl.'rss';
243 - $atomArr['href'] = $baseUrl.'atom';
244 - }
 227+ # Test for feedBurner presence
 228+ if ( preg_match( '/<!-- BURN_FEED ([0-9a-zA-Z\\+\\/]+=*) -->/m', $text, $matches ) ) {
 229+ $name = @unserialize( @base64_decode( $matches[1] ) );
 230+ if ( $name ) {
 231+ $rssArr['href'] = 'http://feeds.feedburner.com/' . urlencode( $name ) . '?format=xml';
 232+ $atomArr['href'] = 'http://feeds.feedburner.com/' . urlencode( $name ) . '?format=xml';
 233+ }
 234+ }
245235
246 - $out->addLink($rssArr);
247 - $out->addLink($atomArr);
 236+ # If its not being fed by feedBurner, do it ourselves!
 237+ if ( !array_key_exists( 'href', $rssArr ) || !$rssArr['href'] ) {
248238
249 - global $wgWikiFeedPresent;
250 - $wgWikiFeedPresent = true;
251 -
252 - # True to indicate that other action handlers should continue to process this page
253 - return true;
 239+ global $wgServer, $wgScript, $wgTitle;
 240+
 241+ $baseUrl = $wgServer . $wgScript . '?title=' . $wgTitle->getDBkey() . '&action=feed&feed=';
 242+ $rssArr['href'] = $baseUrl . 'rss';
 243+ $atomArr['href'] = $baseUrl . 'atom';
 244+ }
 245+
 246+ $out->addLink( $rssArr );
 247+ $out->addLink( $atomArr );
 248+
 249+ global $wgWikiFeedPresent;
 250+ $wgWikiFeedPresent = true;
 251+
 252+ # True to indicate that other action handlers should continue to process this page
 253+ return true;
254254 }
255255
256256 /**
@@ -257,53 +257,52 @@
258258 * Usage: $wgHooks['MonoBookTemplateToolboxEnd'][] = 'wfWikiArticleFeedsToolboxLinks';
259259 * @param QuickTemplate $template Instance of MonoBookTemplate or other QuickTemplate
260260 */
261 -function wfWikiArticleFeedsToolboxLinks($template) {
262 -
263 - global $wgOut, $wgServer, $wgScript, $wgArticle, $wgWikiFeedPresent;
264 -
265 - # Short-circuit if wgArticle has not been set or there are no Feeds present
266 - if (!$wgArticle || !$wgWikiFeedPresent) return true;
267 -
268 - $result = '<li id="feedlinks">';
 261+function wfWikiArticleFeedsToolboxLinks( $template ) {
 262+ global $wgOut, $wgServer, $wgScript, $wgArticle, $wgWikiFeedPresent;
269263
270 - # Test for feedBurner presence
271 - $burned = false;
272 - ob_start();
273 - $template->html('bodytext');
274 - $text = ob_get_contents();
275 - ob_end_clean();
276 - if (preg_match('/<!-- BURN_FEED ([0-9a-zA-Z\\+\\/]+=*) -->/m', $text, $matches)) {
277 - $feedBurnerName = @unserialize(@base64_decode($matches[1]));
278 - if ($feedBurnerName) {
279 - $feeds = array( 'rss'=>'RSS', 'atom'=>'Atom' );
280 - foreach($feeds as $feed=>$name) {
281 - $result .=
282 - '<span id="feed-'.htmlspecialchars($feed).'">'.
283 - '<a href="http://feeds.feedburner.com/'.urlencode($feedBurnerName).'?format=xml">'.
284 - htmlspecialchars($name).'</a>&nbsp;</span>';
285 - }
286 - $burned = true;
287 - }
288 - }
 264+ # Short-circuit if wgArticle has not been set or there are no Feeds present
 265+ if ( !$wgArticle || !$wgWikiFeedPresent ) return true;
289266
290 - # Generate regular RSS and Atom feeds if not fed by feedBurner
291 - if (!$burned) {
292 - $title = $wgArticle->getTitle();
293 - $dbKey = $title->getPrefixedDBkey();
294 - $baseUrl = $wgServer.$wgScript.'?title='.$dbKey.'&action=feed&feed=';
295 - $feeds = array( 'rss'=>'RSS', 'atom'=>'Atom' );
296 - foreach($feeds as $feed=>$name) {
297 - $result .=
298 - '<span id="feed-'.htmlspecialchars($feed).'">'.
299 - '<a href="'.htmlspecialchars($baseUrl.$feed).'">'.
300 - htmlspecialchars($name).'</a>&nbsp;</span>';
301 - }
302 - }
 267+ $result = '<li id="feedlinks">';
303268
304 - echo ($result.'</li>');
305 -
306 - # True to indicate that other action handlers should continue to process this page
307 - return true;
 269+ # Test for feedBurner presence
 270+ $burned = false;
 271+ ob_start();
 272+ $template->html( 'bodytext' );
 273+ $text = ob_get_contents();
 274+ ob_end_clean();
 275+ if ( preg_match( '/<!-- BURN_FEED ([0-9a-zA-Z\\+\\/]+=*) -->/m', $text, $matches ) ) {
 276+ $feedBurnerName = @unserialize( @base64_decode( $matches[1] ) );
 277+ if ( $feedBurnerName ) {
 278+ $feeds = array( 'rss' => 'RSS', 'atom' => 'Atom' );
 279+ foreach ( $feeds as $feed => $name ) {
 280+ $result .=
 281+ '<span id="feed-' . htmlspecialchars( $feed ) . '">' .
 282+ '<a href="http://feeds.feedburner.com/' . urlencode( $feedBurnerName ) . '?format=xml">' .
 283+ htmlspecialchars( $name ) . '</a>&nbsp;</span>';
 284+ }
 285+ $burned = true;
 286+ }
 287+ }
 288+
 289+ # Generate regular RSS and Atom feeds if not fed by feedBurner
 290+ if ( !$burned ) {
 291+ $title = $wgArticle->getTitle();
 292+ $dbKey = $title->getPrefixedDBkey();
 293+ $baseUrl = $wgServer . $wgScript . '?title=' . $dbKey . '&action=feed&feed=';
 294+ $feeds = array( 'rss' => 'RSS', 'atom' => 'Atom' );
 295+ foreach ( $feeds as $feed => $name ) {
 296+ $result .=
 297+ '<span id="feed-' . htmlspecialchars( $feed ) . '">' .
 298+ '<a href="' . htmlspecialchars( $baseUrl . $feed ) . '">' .
 299+ htmlspecialchars( $name ) . '</a>&nbsp;</span>';
 300+ }
 301+ }
 302+
 303+ echo ( $result . '</li>' );
 304+
 305+ # True to indicate that other action handlers should continue to process this page
 306+ return true;
308307 }
309308
310309 /**
@@ -312,82 +311,82 @@
313312 * @param $action Handle to an action string (presumably same as global $action).
314313 * @param $article Article to be converted to rss or atom feed (presumably same as $wgArticle).
315314 */
316 -function wfWikiArticleFeedsAction($action, $article) {
 315+function wfWikiArticleFeedsAction( $action, $article ) {
 316+
 317+ # If some other action is in the works, cut and run!
 318+ if ( $action != 'feed' ) return true;
317319
318 - # If some other action is in the works, cut and run!
319 - if ($action!='feed') return true;
320 -
321 - global $wgOut, $wgRequest, $wgFeedClasses, $wgFeedCacheTimeout, $wgDBname, $messageMemc, $wgSitename;
 320+ global $wgOut, $wgRequest, $wgFeedClasses, $wgFeedCacheTimeout, $wgDBname, $messageMemc, $wgSitename;
322321
323 - # Get query parameters
324 - $feedFormat = $wgRequest->getVal( 'feed', 'atom');
325 - $filterTags = $wgRequest->getVal('tags', null);
326 -
327 - # Process requested tags for use in keys
328 - if ($filterTags) {
329 - $filterTags = explode(',',$filterTags);
330 - array_walk($filterTags, 'trim');
331 - sort($filterTags);
332 - }
 322+ # Get query parameters
 323+ $feedFormat = $wgRequest->getVal( 'feed', 'atom' );
 324+ $filterTags = $wgRequest->getVal( 'tags', null );
333325
334 - if( !isset( $wgFeedClasses[$feedFormat] ) ) {
335 - wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
336 - return false;
337 - }
338 -
339 - # Setup cache-checking vars
340 - $title = $article->getTitle();
341 - $titleDBkey = $title->getPrefixedDBkey();
342 - $tags = (is_array($filterTags)?':'.implode(',',$filterTags):'');
343 - $key = "{$wgDBname}:wikiarticlefeedsextension:{$titleDBkey}:{$feedFormat}{$tags}";
344 - $timekey = $key.":timestamp";
345 - $cachedFeed = false;
346 - $feedLastmod = $messageMemc->get($timekey);
 326+ # Process requested tags for use in keys
 327+ if ( $filterTags ) {
 328+ $filterTags = explode( ',', $filterTags );
 329+ array_walk( $filterTags, 'trim' );
 330+ sort( $filterTags );
 331+ }
347332
348 - # Dermine last modification time for either the article itself or an included template
349 - $lastmod = $article->getTimestamp();
350 - $templates = $article->getUsedTemplates();
351 - foreach ($templates as $tTitle) {
352 - $tArticle = new Article($tTitle);
353 - $tmod = $tArticle->getTimestamp();
354 - $lastmod = ($lastmod>$tmod?$lastmod:$tmod);
355 - }
 333+ if ( !isset( $wgFeedClasses[$feedFormat] ) ) {
 334+ wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
 335+ return false;
 336+ }
356337
357 - # Check for availability of existing cached version
358 - if( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
359 - $feedLastmodTS = wfTimestamp( TS_UNIX, $feedLastmod );
360 - if(
361 - time() - $feedLastmodTS < $wgFeedCacheTimeout ||
362 - $feedLastmodTS > wfTimestamp( TS_UNIX, $lastmod )
363 - ) {
364 - wfDebug( "WikiArticleFeedsExtension: Loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
365 - $cachedFeed = $messageMemc->get( $key );
366 - } else {
367 - wfDebug( "WikiArticleFeedsExtension: Cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
368 - }
369 - }
370 -
371 - # Display cachedFeed, or generate one from scratch
372 - global $wgWikiArticleFeedsSkipCache;
373 - if(!$wgWikiArticleFeedsSkipCache && is_string( $cachedFeed ) ) {
374 - wfDebug( "WikiArticleFeedsExtension: Outputting cached feed\n" );
375 - $feed = new $wgFeedClasses[$feedFormat]($wgSitename.' - '.$title->getText(),'', $title->getFullURL());
376 - $feed->httpHeaders();
377 - echo $cachedFeed;
378 - } else {
379 - wfDebug( "WikiArticleFeedsExtension: Rendering new feed and caching it\n" );
380 - ob_start();
381 - wfGenerateWikiFeed( $article, $feedFormat, $filterTags );
382 - $cachedFeed = ob_get_contents();
383 - ob_end_flush();
 338+ # Setup cache-checking vars
 339+ $title = $article->getTitle();
 340+ $titleDBkey = $title->getPrefixedDBkey();
 341+ $tags = ( is_array( $filterTags ) ? ':' . implode( ',', $filterTags ):'' );
 342+ $key = "{$wgDBname}:wikiarticlefeedsextension:{$titleDBkey}:{$feedFormat}{$tags}";
 343+ $timekey = $key . ":timestamp";
 344+ $cachedFeed = false;
 345+ $feedLastmod = $messageMemc->get( $timekey );
384346
385 - $expire = 3600 * 24; # One day
386 - $messageMemc->set( $key, $cachedFeed );
387 - $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
388 - }
389 -
390 - # False to indicate that other action handlers should not process this page
391 - return false;
 347+ # Dermine last modification time for either the article itself or an included template
 348+ $lastmod = $article->getTimestamp();
 349+ $templates = $article->getUsedTemplates();
 350+ foreach ( $templates as $tTitle ) {
 351+ $tArticle = new Article( $tTitle );
 352+ $tmod = $tArticle->getTimestamp();
 353+ $lastmod = ( $lastmod > $tmod ? $lastmod:$tmod );
 354+ }
 355+
 356+ # Check for availability of existing cached version
 357+ if ( ( $wgFeedCacheTimeout > 0 ) && $feedLastmod ) {
 358+ $feedLastmodTS = wfTimestamp( TS_UNIX, $feedLastmod );
 359+ if (
 360+ time() - $feedLastmodTS < $wgFeedCacheTimeout ||
 361+ $feedLastmodTS > wfTimestamp( TS_UNIX, $lastmod )
 362+ ) {
 363+ wfDebug( "WikiArticleFeedsExtension: Loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
 364+ $cachedFeed = $messageMemc->get( $key );
 365+ } else {
 366+ wfDebug( "WikiArticleFeedsExtension: Cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
 367+ }
 368+ }
 369+
 370+ # Display cachedFeed, or generate one from scratch
 371+ global $wgWikiArticleFeedsSkipCache;
 372+ if ( !$wgWikiArticleFeedsSkipCache && is_string( $cachedFeed ) ) {
 373+ wfDebug( "WikiArticleFeedsExtension: Outputting cached feed\n" );
 374+ $feed = new $wgFeedClasses[$feedFormat]( $wgSitename . ' - ' . $title->getText(), '', $title->getFullURL() );
 375+ $feed->httpHeaders();
 376+ echo $cachedFeed;
 377+ } else {
 378+ wfDebug( "WikiArticleFeedsExtension: Rendering new feed and caching it\n" );
 379+ ob_start();
 380+ wfGenerateWikiFeed( $article, $feedFormat, $filterTags );
 381+ $cachedFeed = ob_get_contents();
 382+ ob_end_flush();
 383+
 384+ $expire = 3600 * 24; # One day
 385+ $messageMemc->set( $key, $cachedFeed );
 386+ $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
 387+ }
 388+
 389+ # False to indicate that other action handlers should not process this page
 390+ return false;
392391 }
393392
394393 /**
@@ -396,15 +395,15 @@
397396 * @param Article $article The Article which is being purged.
398397 * @return boolean Always true to permit additional hook processing.
399398 */
400 -function wfPurgeFeedsOnArticlePurge($article) {
401 - global $messageMemc,$wgDBname;
402 - $titleDBKey = $article->mTitle->getPrefixedDBkey();
403 - $keyPrefix = "{$wgDBname}:wikiarticlefeedsextension:{$titleDBKey}";
404 - $messageMemc->delete("{$keyPrefix}:atom:timestamp");
405 - $messageMemc->delete("{$keyPrefix}:atom");
406 - $messageMemc->delete("{$keyPrefix}:rss");
407 - $messageMemc->delete("{$keyPrefix}:rss:timestamp");
408 - return true;
 399+function wfPurgeFeedsOnArticlePurge( $article ) {
 400+ global $messageMemc, $wgDBname;
 401+ $titleDBKey = $article->mTitle->getPrefixedDBkey();
 402+ $keyPrefix = "{$wgDBname}:wikiarticlefeedsextension:{$titleDBKey}";
 403+ $messageMemc->delete( "{$keyPrefix}:atom:timestamp" );
 404+ $messageMemc->delete( "{$keyPrefix}:atom" );
 405+ $messageMemc->delete( "{$keyPrefix}:rss" );
 406+ $messageMemc->delete( "{$keyPrefix}:rss:timestamp" );
 407+ return true;
409408 }
410409
411410 /**
@@ -413,180 +412,179 @@
414413 * @param String $feedFormat A format type - must be either 'rss' or 'atom'
415414 * @param Array $filterTags Tags to use in filtering out items.
416415 */
417 -function wfGenerateWikiFeed($article, $feedFormat = 'atom', $filterTags = null) {
 416+function wfGenerateWikiFeed( $article, $feedFormat = 'atom', $filterTags = null ) {
 417+ global $wgOut, $wgScript, $wgServer, $wgFeedClasses, $wgVersion, $wgSitename;
418418
419 - global $wgOut, $wgScript, $wgServer, $wgFeedClasses, $wgVersion, $wgSitename;
 419+ # Setup, handle redirects
 420+ if ( $article->isRedirect() ) {
 421+ $rtitle = Title::newFromRedirect( $article->getContent() );
 422+ if ( $rtitle ) {
 423+ $article = new Article( $rtitle );
 424+ }
 425+ }
 426+ $title = $article->getTitle();
 427+ $feedUrl = $title->getFullUrl();
420428
421 - # Setup, handle redirects
422 - if ($article->isRedirect()) {
423 - $rtitle = Title::newFromRedirect($article->getContent());
424 - if ($rtitle) {
425 - $article = new Article($rtitle);
426 - }
427 - }
428 - $title = $article->getTitle();
429 - $feedUrl = $title->getFullUrl();
 429+ # Parse page into feed items.
 430+ $content = $wgOut->parse( $article->getContent() . "\n__NOEDITSECTION__ __NOTOC__" );
 431+ preg_match_all(
 432+ '/<!--\\s*FEED_START\\s*-->(.*?)<!--\\s*FEED_END\\s*-->/s',
 433+ $content,
 434+ $matches
 435+ );
 436+ $feedContentSections = $matches[1];
430437
431 - # Parse page into feed items.
432 - $content = $wgOut->parse($article->getContent()."\n__NOEDITSECTION__ __NOTOC__");
433 - preg_match_all(
434 - '/<!--\\s*FEED_START\\s*-->(.*?)<!--\\s*FEED_END\\s*-->/s',
435 - $content,
436 - $matches
437 - );
438 - $feedContentSections = $matches[1];
 438+ # Parse and process all feeds, collecting feed items
 439+ $items = array();
 440+ $feedDescription = '';
 441+ foreach ( $feedContentSections as $feedKey => $feedContent ) {
439442
440 - # Parse and process all feeds, collecting feed items
441 - $items = array();
442 - $feedDescription = '';
443 - foreach ($feedContentSections as $feedKey=>$feedContent) {
444 -
445 - # Determine Feed item depth (what header level defines a feed)
446 - preg_match_all( '/<h(\\d)>/m', $feedContent, $matches);
447 - if (empty($matches[1])) next;
448 - $lvl = $matches[1][0];
449 - foreach ($matches[1] as $match) {
450 - if ($match < $lvl) $lvl = $match;
451 - }
452 -
453 - # Determine the item titles and default item links
454 - preg_match_all(
455 - '/<a[^>]*\\s+name=([\'"])(.*?)\\1[^>]*><\\/a><h'.$lvl.'>\\s*(.*?)\\s*<\\/h'.$lvl.'>/m',
456 - $feedContent,
457 - $matches
458 - );
459 - $itemLinks = $matches[2];
460 - $itemTitles = $matches[3];
461 -
462 - # Split content into segments
463 - $segments = preg_split( '/<a name=([\'"]).*?\\1\\s*><\\/a><h'.$lvl.'>.*?<\\/h'.$lvl.'>/m', $feedContent);
464 - $segDesc = trim(strip_tags(array_shift($segments)));
465 - if ($segDesc) {
466 - if (!$feedDescription) {
467 - $feedDescription = $segDesc;
468 - } else {
 443+ # Determine Feed item depth (what header level defines a feed)
 444+ preg_match_all( '/<h(\\d)>/m', $feedContent, $matches );
 445+ if ( empty( $matches[1] ) ) next;
 446+ $lvl = $matches[1][0];
 447+ foreach ( $matches[1] as $match ) {
 448+ if ( $match < $lvl ) $lvl = $match;
 449+ }
 450+
 451+ # Determine the item titles and default item links
 452+ preg_match_all(
 453+ '/<a[^>]*\\s+name=([\'"])(.*?)\\1[^>]*><\\/a><h' . $lvl . '>\\s*(.*?)\\s*<\\/h' . $lvl . '>/m',
 454+ $feedContent,
 455+ $matches
 456+ );
 457+ $itemLinks = $matches[2];
 458+ $itemTitles = $matches[3];
 459+
 460+ # Split content into segments
 461+ $segments = preg_split( '/<a name=([\'"]).*?\\1\\s*><\\/a><h' . $lvl . '>.*?<\\/h' . $lvl . '>/m', $feedContent );
 462+ $segDesc = trim( strip_tags( array_shift( $segments ) ) );
 463+ if ( $segDesc ) {
 464+ if ( !$feedDescription ) {
 465+ $feedDescription = $segDesc;
 466+ } else {
469467 wfLoadExtensionMessages( 'WikiArticleFeeds' );
470 - $feedDescription = wfMsg('wikiarticlefeeds_combined_description');
471 - }
472 - }
473 -
474 - # Loop over parsed segments and add all items to item array
475 - foreach ($segments as $key=>$seg) {
476 -
477 - # Filter by tag (if any are present)
478 - $skip = false;
479 - $tags = null;
480 - if (is_array($filterTags) && !empty($filterTags)) {
481 - if (preg_match_all('/<!-- ITEM_TAGS ([0-9a-zA-Z\\+\\/]+=*) -->/m', $seg, $matches)) {
482 - $tags = array();
483 - foreach ($matches[1] as $encodedString) {
484 - $t = @unserialize(@base64_decode($encodedString));
485 - if ($t) {
486 - $t = explode(',',$t);
487 - array_walk($t, 'trim');
488 - sort($t);
489 - $tags = array_merge($tags, $t);
490 - }
491 - }
492 - $tags = array_unique($tags);
493 - if (!count(array_intersect($tags, $filterTags))) $skip = true;
494 - $seg = preg_replace('/<!-- ITEM_TAGS ([0-9a-zA-Z\\+\\/]+=*) -->/m', '', $seg);
495 - } else {
496 - $skip = true;
497 - }
498 - }
499 - if ($skip) continue;
500 -
501 - # Determine the item author and date
502 - $author = null;
503 - $date = null;
 468+ $feedDescription = wfMsg( 'wikiarticlefeeds_combined_description' );
 469+ }
 470+ }
504471
505 - # Look for a regular ~~~~ sig
506 - $isAttributable = preg_match(
507 - '%<a [^>]*href=([\'"])'.preg_quote($wgScript).'(/|\\?title=)User:.*?\\1[^>]*>(.*?)</a> (\\d\\d):(\\d\\d), (\\d+) ([A-z][a-z]+) (\\d{4}) \\([A-Z]+\\)%m',
508 - $seg,
509 - $matches
510 - );
 472+ # Loop over parsed segments and add all items to item array
 473+ foreach ( $segments as $key => $seg ) {
511474
512 - # As a fallback - look for a --~~~~ like sig with a user page outside the User NS
513 - if (!$isAttributable) {
514 - $isAttributable = preg_match(
515 - '%--<a [^>]*href=([\'"])'.preg_quote($wgScript).'(/|\\?title=).*?\\1[^>]*>(.*?)</a> (\\d\\d):(\\d\\d), (\\d+) ([A-z][a-z]+) (\\d{4}) \\([A-Z]+\\)%m',
516 - $seg,
517 - $matches
518 - );
519 - }
520 -
521 - # Parse it out - if we can
522 - if ($isAttributable) {
523 - list($author, $hour, $min, $day, $monthName, $year) = array_slice($matches, 3);
524 - $months = array(
525 - 'January' => '01', 'February' => '02', 'March' => '03', 'April' => '04',
526 - 'May' => '05', 'June' => '06', 'July' => '07', 'August' => '08',
527 - 'September' => '09', 'October' => '10', 'November' => '11', 'December' => '12'
528 - );
529 - $month = $months[$monthName];
530 - $day = str_pad($day,2,'0',STR_PAD_LEFT);
531 - $date = $year.$month.$day.$hour.$min.'00';
532 - }
 475+ # Filter by tag (if any are present)
 476+ $skip = false;
 477+ $tags = null;
 478+ if ( is_array( $filterTags ) && !empty( $filterTags ) ) {
 479+ if ( preg_match_all( '/<!-- ITEM_TAGS ([0-9a-zA-Z\\+\\/]+=*) -->/m', $seg, $matches ) ) {
 480+ $tags = array();
 481+ foreach ( $matches[1] as $encodedString ) {
 482+ $t = @unserialize( @base64_decode( $encodedString ) );
 483+ if ( $t ) {
 484+ $t = explode( ',', $t );
 485+ array_walk( $t, 'trim' );
 486+ sort( $t );
 487+ $tags = array_merge( $tags, $t );
 488+ }
 489+ }
 490+ $tags = array_unique( $tags );
 491+ if ( !count( array_intersect( $tags, $filterTags ) ) ) $skip = true;
 492+ $seg = preg_replace( '/<!-- ITEM_TAGS ([0-9a-zA-Z\\+\\/]+=*) -->/m', '', $seg );
 493+ } else {
 494+ $skip = true;
 495+ }
 496+ }
 497+ if ( $skip ) continue;
533498
534 - # Set default 'article section' feed-link
535 - $url = $feedUrl.'#'.$itemLinks[$key];
536 -
537 - # Look for an alternative to the default link (unless default 'section linking' has been forced)
538 - global $wgForceArticleFeedSectionLinks;
539 - if (!$wgForceArticleFeedSectionLinks) {
540 - $strippedSeg = preg_replace(
541 - array(
542 - '%<a [^>]*href=([\'"])'.preg_quote($wgScript).'(/|\\?title=)User:.*?\\1[^>]*>(.*?)</a> (\\d\\d:\\d\\d, \\d+ [A-z][a-z]+ \\d{4} \\([A-Z]+\\))%m',
543 - '%--<a [^>]*href=([\'"])'.preg_quote($wgScript).'(/|\\?title=).*?\\1[^>]*>(.*?)</a> (\\d\\d:\\d\\d, \\d+ [A-z][a-z]+ \\d{4} \\([A-Z]+\\))%m'
544 - ),
545 - '',
546 - $seg
547 - );
548 - preg_match(
549 - '%<a [^>]*href=([\'"])(.*?)\\1[^>]*>(.*?)</a>%m',
550 - $strippedSeg,
551 - $matches
552 - );
553 - if ($matches[2]) {
554 - $url = $matches[2];
555 - if (preg_match('%^/%', $url)) {
556 - $url = $wgServer.$url;
557 - }
558 - }
559 - }
 499+ # Determine the item author and date
 500+ $author = null;
 501+ $date = null;
560502
561 - # Create 'absolutified' segment - where all URLs are fully qualified
562 - $seg = preg_replace('/ (href|src)=([\'"])\\//',' $1=$2'.$wgServer.'/',$seg);
 503+ # Look for a regular ~~~~ sig
 504+ $isAttributable = preg_match(
 505+ '%<a [^>]*href=([\'"])' . preg_quote( $wgScript ) . '(/|\\?title=)User:.*?\\1[^>]*>(.*?)</a> (\\d\\d):(\\d\\d), (\\d+) ([A-z][a-z]+) (\\d{4}) \\([A-Z]+\\)%m',
 506+ $seg,
 507+ $matches
 508+ );
563509
564 - # Create item and push onto item list
565 - $items[$date][] = new FeedItem(strip_tags($itemTitles[$key]), $seg, $url, $date, $author);
566 - }
567 - }
568 -
569 - # Programmatically determine the feed title and id.
570 - $feedTitle = $wgSitename.' - '.$title->getPrefixedText();
571 - $feedId = $title->getFullUrl();
 510+ # As a fallback - look for a --~~~~ like sig with a user page outside the User NS
 511+ if ( !$isAttributable ) {
 512+ $isAttributable = preg_match(
 513+ '%--<a [^>]*href=([\'"])' . preg_quote( $wgScript ) . '(/|\\?title=).*?\\1[^>]*>(.*?)</a> (\\d\\d):(\\d\\d), (\\d+) ([A-z][a-z]+) (\\d{4}) \\([A-Z]+\\)%m',
 514+ $seg,
 515+ $matches
 516+ );
 517+ }
572518
573 - # Create feed
574 - $feed = new $wgFeedClasses[$feedFormat]($feedTitle, $feedDescription, $feedId);
575 -
576 - # Push feed header
577 - $tempWgVersion = $wgVersion;
578 - $wgVersion .= ' via WikiArticleFeeds '.WIKIARTICLEFEEDS_VERSION;
579 - $feed->outHeader();
580 - $wgVersion = $tempWgVersion;
581 -
582 - # Sort all items by date and push onto feed
583 - krsort($items);
584 - foreach ($items as $itemGroup) {
585 - foreach ($itemGroup as $item) {
586 - $feed->outItem($item);
587 - }
588 - }
 519+ # Parse it out - if we can
 520+ if ( $isAttributable ) {
 521+ list( $author, $hour, $min, $day, $monthName, $year ) = array_slice( $matches, 3 );
 522+ $months = array(
 523+ 'January' => '01', 'February' => '02', 'March' => '03', 'April' => '04',
 524+ 'May' => '05', 'June' => '06', 'July' => '07', 'August' => '08',
 525+ 'September' => '09', 'October' => '10', 'November' => '11', 'December' => '12'
 526+ );
 527+ $month = $months[$monthName];
 528+ $day = str_pad( $day, 2, '0', STR_PAD_LEFT );
 529+ $date = $year . $month . $day . $hour . $min . '00';
 530+ }
589531
590 - # Feed footer
591 - $feed->outFooter();
 532+ # Set default 'article section' feed-link
 533+ $url = $feedUrl . '#' . $itemLinks[$key];
 534+
 535+ # Look for an alternative to the default link (unless default 'section linking' has been forced)
 536+ global $wgForceArticleFeedSectionLinks;
 537+ if ( !$wgForceArticleFeedSectionLinks ) {
 538+ $strippedSeg = preg_replace(
 539+ array(
 540+ '%<a [^>]*href=([\'"])' . preg_quote( $wgScript ) . '(/|\\?title=)User:.*?\\1[^>]*>(.*?)</a> (\\d\\d:\\d\\d, \\d+ [A-z][a-z]+ \\d{4} \\([A-Z]+\\))%m',
 541+ '%--<a [^>]*href=([\'"])' . preg_quote( $wgScript ) . '(/|\\?title=).*?\\1[^>]*>(.*?)</a> (\\d\\d:\\d\\d, \\d+ [A-z][a-z]+ \\d{4} \\([A-Z]+\\))%m'
 542+ ),
 543+ '',
 544+ $seg
 545+ );
 546+ preg_match(
 547+ '%<a [^>]*href=([\'"])(.*?)\\1[^>]*>(.*?)</a>%m',
 548+ $strippedSeg,
 549+ $matches
 550+ );
 551+ if ( $matches[2] ) {
 552+ $url = $matches[2];
 553+ if ( preg_match( '%^/%', $url ) ) {
 554+ $url = $wgServer . $url;
 555+ }
 556+ }
 557+ }
 558+
 559+ # Create 'absolutified' segment - where all URLs are fully qualified
 560+ $seg = preg_replace( '/ (href|src)=([\'"])\\//', ' $1=$2' . $wgServer . '/', $seg );
 561+
 562+ # Create item and push onto item list
 563+ $items[$date][] = new FeedItem( strip_tags( $itemTitles[$key] ), $seg, $url, $date, $author );
 564+ }
 565+ }
 566+
 567+ # Programmatically determine the feed title and id.
 568+ $feedTitle = $wgSitename . ' - ' . $title->getPrefixedText();
 569+ $feedId = $title->getFullUrl();
 570+
 571+ # Create feed
 572+ $feed = new $wgFeedClasses[$feedFormat]( $feedTitle, $feedDescription, $feedId );
 573+
 574+ # Push feed header
 575+ $tempWgVersion = $wgVersion;
 576+ $wgVersion .= ' via WikiArticleFeeds ' . WIKIARTICLEFEEDS_VERSION;
 577+ $feed->outHeader();
 578+ $wgVersion = $tempWgVersion;
 579+
 580+ # Sort all items by date and push onto feed
 581+ krsort( $items );
 582+ foreach ( $items as $itemGroup ) {
 583+ foreach ( $itemGroup as $item ) {
 584+ $feed->outItem( $item );
 585+ }
 586+ }
 587+
 588+ # Feed footer
 589+ $feed->outFooter();
592590 }
593591

Comments

#Comment by IAlex (talk | contribs)   14:58, 12 April 2009

And forgot to say that I ran stylize.php.

Status & tagging log