Index: trunk/extensions/RSS/RSS.php |
— | — | @@ -0,0 +1,287 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +<?php |
| 5 | +/** |
| 6 | + * RSS-Feed MediaWiki extension |
| 7 | + * |
| 8 | + * @file |
| 9 | + * @ingroup Extensions |
| 10 | + * @version 1.6 |
| 11 | + * @author mutante, Duesentrieb, Rdb, Mafs, Alxndr, Cmreigrut, K001 |
| 12 | + * @copyright © mutante, Duesentrieb, Rdb, Mafs, Alxndr, Cmreigrut, K001 |
| 13 | + * @link http://www.mediawiki.org/wiki/Extension:RSS Documentation |
| 14 | + * |
| 15 | + * Requires: |
| 16 | + * # magpie rss parser <http://magpierss.sourceforge.net/> |
| 17 | + * # iconv <http://www.gnu.org/software/libiconv/>, see also <http://www.php.net/iconv> |
| 18 | + * |
| 19 | + * 07.05.2008 compatible/checked with MediaWiki 1.12 |
| 20 | + */ |
| 21 | + |
| 22 | +if( !defined( 'MEDIAWIKI' ) ) { |
| 23 | + die( "This is not a valid entry point.\n" ); |
| 24 | +} |
| 25 | + |
| 26 | +$wgExtensionCredits['parserhook'][] = array( |
| 27 | + 'name' => 'RSS feed', |
| 28 | + 'author' => array('mutante', 'Duesentrieb', 'Rdb', 'Mafs', 'Alxndr', 'Wikinaut', 'Cmreigrut', 'K001'), |
| 29 | + 'version' => '1.6', |
| 30 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:RSS', |
| 31 | + 'description' => 'Displays an RSS feed on a wiki page' |
| 32 | +); |
| 33 | + |
| 34 | +define('MAGPIE_OUTPUT_ENCODING', 'UTF-8'); |
| 35 | + |
| 36 | +#change this according to your magpie installation! |
| 37 | +require_once('extensions/magpierss/rss_fetch.inc'); |
| 38 | + |
| 39 | +// Avoid unstubbing $wgParser too early on modern (1.12+) MW versions, as per r35980 |
| 40 | +if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { |
| 41 | + $wgHooks['ParserFirstCallInit'][] = 'wfRssExtension'; |
| 42 | +} else { |
| 43 | + $wgExtensionFunctions[] = 'wfRssExtension'; |
| 44 | +} |
| 45 | + |
| 46 | +#Extension hook callback function |
| 47 | +function wfRssExtension() { |
| 48 | + global $wgParser; |
| 49 | + |
| 50 | + #Install parser hook for <rss> tags |
| 51 | + $wgParser->setHook( 'rss', 'renderRss' ); |
| 52 | + return true; |
| 53 | +} |
| 54 | + |
| 55 | +#Parser hook callback function |
| 56 | +function renderRss( $input ) { |
| 57 | + global $wgOutputEncoding, $wgParser; |
| 58 | + |
| 59 | + // Kill parser cache |
| 60 | + $wgParser->disableCache(); |
| 61 | + |
| 62 | + if ( !$input ) return ''; #if <rss>-section is empty, return nothing |
| 63 | + |
| 64 | + #Parse fields in rss-section |
| 65 | + $fields = explode( "|", $input ); |
| 66 | + $url = @$fields[0]; |
| 67 | + |
| 68 | + $args = array(); |
| 69 | + for ( $i = 1; $i < sizeof( $fields ); $i++ ) { |
| 70 | + $f = $fields[$i]; |
| 71 | + |
| 72 | + if ( strpos( $f, "=" ) === false ) $args[strtolower(trim($f))] = false; |
| 73 | + else { |
| 74 | + list( $k, $v ) = explode( "=", $f, 2 ); |
| 75 | + if ( trim( $v ) == false ) $args[strtolower(trim($k))] = false; |
| 76 | + else $args[strtolower(trim($k))] = trim($v); |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + #Get charset from argument-array |
| 81 | + $charset = @$args['charset']; |
| 82 | + if( !$charset ) $charset = $wgOutputEncoding; |
| 83 | + #Get max number of headlines from argument-array |
| 84 | + $maxheads = @$args['max']; |
| 85 | + $headcnt = 0; |
| 86 | + |
| 87 | + #Get short-flag from argument-array |
| 88 | + #If short is set, no description text is printed |
| 89 | + if( isset( $args['short'] ) ) $short = true; else $short = false; |
| 90 | + #Get reverse-flag from argument-array |
| 91 | + if( isset( $args['reverse'] ) ) $reverse = true; else $reverse = false; |
| 92 | + |
| 93 | + # Get date format from argument-array |
| 94 | + if (isset($args["date"])) { |
| 95 | + $date = @$args["date"]; |
| 96 | + if ($date == '') |
| 97 | + $date = 'd M Y H:i'; |
| 98 | + } |
| 99 | + else |
| 100 | + $date = false; |
| 101 | + |
| 102 | + #Get highlight terms from argument array |
| 103 | + $rssHighlight = @$args['highlight']; |
| 104 | + $rssHighlight = str_replace( ' ', ' ', $rssHighlight ); |
| 105 | + $rssHighlight = explode( ' ', trim( $rssHighlight ) ); |
| 106 | + |
| 107 | + #Get filter terms from argument-array |
| 108 | + $rssFilter = @$args['filter']; |
| 109 | + $rssFilter = str_replace( ' ', ' ', $rssFilter ); |
| 110 | + $rssFilter = explode( ' ', trim( $rssFilter ) ); |
| 111 | + |
| 112 | + #Filterout terms |
| 113 | + $rssFilterout = @$args['filterout']; |
| 114 | + $rssFilterout = str_replace( ' ', ' ', $rssFilterout ); |
| 115 | + $rssFilterout = explode( ' ', trim( $rssFilterout ) ); |
| 116 | + |
| 117 | + #Fetch RSS. May be cached locally. |
| 118 | + #Refer to the documentation of magpie for details. |
| 119 | + $rss = @fetch_rss( $url ); |
| 120 | + |
| 121 | + #Check for errors. |
| 122 | + if ( $rss->ERROR ) { |
| 123 | + return "<div>Failed to load RSS feed from $url: ".$rss->ERROR."</div>"; #localize… |
| 124 | + } |
| 125 | + |
| 126 | + if ( !is_array( $rss->items ) ) { |
| 127 | + return "<div>Failed to load RSS feed from $url!</div>"; #localize… |
| 128 | + } |
| 129 | + |
| 130 | + #Build title line |
| 131 | + #$title = iconv($charset, $wgOutputEncoding, $rss->channel['title']); |
| 132 | + #if( $rss->channel['link'] ) $title = "<a href='".$rss->channel['link']."'>$title</a>"; |
| 133 | + |
| 134 | + $output = ''; |
| 135 | + if( $reverse ) $rss->items = array_reverse( $rss->items ); |
| 136 | + $description = false; |
| 137 | + foreach ( $rss->items as $item ) { |
| 138 | + if ( $item['description'] ) { |
| 139 | + $description = true; |
| 140 | + break; |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + #Build items |
| 145 | + if ( !$short and $description ) { #full item list |
| 146 | + $output.= '<dl>'; |
| 147 | + |
| 148 | + foreach ( $rss->items as $item ) { |
| 149 | + $d_text = true; |
| 150 | + $d_title = true; |
| 151 | + |
| 152 | + $href = htmlspecialchars( trim( iconv( $charset, $wgOutputEncoding, $item['link'] ) ) ); |
| 153 | + $title = htmlspecialchars( trim( iconv( $charset, $wgOutputEncoding, $item['title'] ) ) ); |
| 154 | + |
| 155 | + if ($date) { |
| 156 | + $pubdate = trim( iconv( $charset, $wgOutputEncoding, $item['pubdate'] ) ); |
| 157 | + $pubdate = date( $date, strtotime( $pubdate ) ); |
| 158 | + } |
| 159 | + |
| 160 | + $d_title = wfRssFilter( $title, $rssFilter ); |
| 161 | + $d_title = wfRssFilterout( $title, $rssFilterout ); |
| 162 | + $title = wfRssHighlight( $title, $rssHighlight ); |
| 163 | + |
| 164 | + #Build description text if desired |
| 165 | + if ( $item['description'] ) { |
| 166 | + $text = trim( iconv( $charset, $wgOutputEncoding, $item['description'] ) ); |
| 167 | + #Avoid pre-tags |
| 168 | + $text = str_replace( "\r", ' ', $text ); |
| 169 | + $text = str_replace( "\n", ' ', $text ); |
| 170 | + $text = str_replace( "\t", ' ', $text ); |
| 171 | + $text = str_replace( '<br>', '', $text ); |
| 172 | + |
| 173 | + $d_text = wfRssFilter( $text, $rssFilter ); |
| 174 | + $d_text = wfRssFilterout( $text, $rssFilterout ); |
| 175 | + $text = wfRssHighlight( $text, $rssHighlight ); |
| 176 | + $display = $d_text or $d_title; |
| 177 | + } else { |
| 178 | + $text = ''; |
| 179 | + $display = $d_title; |
| 180 | + } |
| 181 | + if ( $display ) { |
| 182 | + $output.= "<dt><a href='$href'><b>$title</b></a></dt>"; |
| 183 | + if ( $date ) $output.= " ($pubdate)"; |
| 184 | + if ( $text ) $output.= "<dd>$text <b>[<a href='$href'>?</a>]</b></dd>"; |
| 185 | + } |
| 186 | + #Cut off output when maxheads is reached: |
| 187 | + if ( ++$headcnt == $maxheads ) break; |
| 188 | + } |
| 189 | + |
| 190 | + $output.= '</dl>'; |
| 191 | + } else { #short item list |
| 192 | + ## HACKY HACKY HACKY |
| 193 | + $output.= '<ul>'; |
| 194 | + $displayed = array(); |
| 195 | + foreach ( $rss->items as $item ) { |
| 196 | + $href = htmlspecialchars( trim( iconv( $charset, $wgOutputEncoding, $item['link'] ) ) ); |
| 197 | + $title = htmlspecialchars( trim( iconv( $charset, $wgOutputEncoding, $item['title'] ) ) ); |
| 198 | + $d_title = wfRssFilter( $title, $rssFilter ) && wfRssFilterout( $title, $rssFilterout ); |
| 199 | + $title = wfRssHighlight( $title, $rssHighlight ); |
| 200 | + if ($date) { |
| 201 | + $pubdate = trim( iconv( $charset, $wgOutputEncoding, $item['pubdate'] ) ); |
| 202 | + if ( $pubdate == '' ) { |
| 203 | + $pubdate = trim( iconv( $charset, $wgOutputEncoding, $item['dc']['date'] ) ); |
| 204 | + } |
| 205 | + $pubdate = date( $date, strtotime( $pubdate ) ); |
| 206 | + } |
| 207 | + if ( $d_title && !in_array( $title, $displayed ) ) { |
| 208 | + // Add date to ouput if specified |
| 209 | + $output.= '<li><a href="'.$href.'" title="'.$title.'">'.$title.'</a>'; |
| 210 | + if( $date ) { |
| 211 | + $output.= " ($pubdate)"; |
| 212 | + } |
| 213 | + $output.= '</li>'; |
| 214 | + |
| 215 | + $displayed[] = $title; |
| 216 | + #Cut off output when maxheads is reached: |
| 217 | + if ( ++$headcnt == $maxheads ) break; |
| 218 | + } |
| 219 | + } |
| 220 | + $output.= '</ul>'; |
| 221 | + } |
| 222 | + |
| 223 | + return $output; |
| 224 | +} |
| 225 | + |
| 226 | +function wfRssFilter( $text, $rssFilter ) { |
| 227 | + $display = true; |
| 228 | + if ( is_array( $rssFilter ) ) { |
| 229 | + foreach( $rssFilter as $term ) { |
| 230 | + if ( $term ) { |
| 231 | + $display = false; |
| 232 | + if ( preg_match( "|$term|i", $text, $a ) ) { |
| 233 | + $display = true; |
| 234 | + return $display; |
| 235 | + } |
| 236 | + } |
| 237 | + if ( $display ) break; |
| 238 | + } |
| 239 | + } |
| 240 | + return $display; |
| 241 | +} |
| 242 | + |
| 243 | +function wfRssFilterout( $text, $rssFilterout ) { |
| 244 | + $display = true; |
| 245 | + if ( is_array( $rssFilterout ) ) { |
| 246 | + foreach ( $rssFilterout as $term ) { |
| 247 | + if ( $term ) { |
| 248 | + if ( preg_match( "|$term|i", $text, $a ) ) { |
| 249 | + $display = false; |
| 250 | + return $display; |
| 251 | + } |
| 252 | + } |
| 253 | + } |
| 254 | + } |
| 255 | + return $display; |
| 256 | +} |
| 257 | + |
| 258 | +function wfRssHighlight( $text, $rssHighlight ) { |
| 259 | + $i = 0; |
| 260 | + $starttag = 'v8x5u3t3u8h'; |
| 261 | + $endtag = 'q8n4f6n4n4x'; |
| 262 | + |
| 263 | + $color[] = 'coral'; |
| 264 | + $color[] = 'greenyellow'; |
| 265 | + $color[] = 'lightskyblue'; |
| 266 | + $color[] = 'gold'; |
| 267 | + $color[] = 'violet'; |
| 268 | + $count_color = count( $color ); |
| 269 | + |
| 270 | + if ( is_array( $rssHighlight ) ) { |
| 271 | + foreach( $rssHighlight as $term ) { |
| 272 | + if ( $term ) { |
| 273 | + $text = preg_replace("|\b(\w*?".$term."\w*?)\b|i", "$starttag"."_".$i."\\1$endtag", $text); |
| 274 | + $i++; |
| 275 | + if ( $i == $count_color ) $i = 0; |
| 276 | + } |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + #To avoid trouble should someone wants to highlight the terms "span", "style", … |
| 281 | + for ( $i = 0; $i < 5; $i++ ) { |
| 282 | + $text = preg_replace( "|$starttag"."_".$i."|", "<span style=\"background-color:".$color[$i]."; font-weight: bold;\">", $text ); |
| 283 | + $text = preg_replace( "|$endtag|", '</span>', $text ); |
| 284 | + } |
| 285 | + |
| 286 | + return $text; |
| 287 | +} |
| 288 | +#PHP closing tag intentionally left blank |
\ No newline at end of file |