1<?php 2/** 3 * @license GPL 3 (http://www.gnu.org/licenses/gpl.html) 4 * @author Szymon Olewniczak <(my first name) [at] imz [dot] re> 5 * @author Cejka Rudolf <cejkar@fit.vutbr.cz> 6 */ 7 8// must be run within DokuWiki 9if(!defined('DOKU_INC')) die(); 10 11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 12require_once DOKU_PLUGIN.'syntax.php'; 13 14/** 15 * All DokuWiki plugins to extend the parser/rendering mechanism 16 * need to inherit from this class 17 */ 18class syntax_plugin_filterrss extends DokuWiki_Syntax_Plugin { 19 20 function getPType(){ 21 return 'block'; 22 } 23 24 function getType() { return 'substition'; } 25 function getSort() { return 32; } 26 27 28 function connectTo($mode) { 29 $this->Lexer->addSpecialPattern('\[filterrss.*?\]',$mode,'plugin_filterrss'); 30 } 31 32 function handle($match, $state, $pos, Doku_Handler $handler) { 33 34 //Remove ] from the end 35 $match = substr($match, 0, -1); 36 //Remove [filterrss 37 $match = substr($match, 10); 38 39 $known_fileds = array('pubDate', 'title', 'description', 'link'); 40 $opposite_signs = array('>' => '<', '<' => '>', '>=' => '<=', '<=' => '>='); 41 42 $query = preg_split('/order by/i', $match); 43 44 $args = trim($query[0]); 45 46 if( isset( $query[1] ) ) 47 { 48 $sort = trim($query[1]); 49 //ASC ist't isteresting 50 $sort = str_ireplace('asc', '', $sort); 51 52 $desc = false; 53 if(stripos($sort, 'desc') !== false) 54 { 55 $sort = str_ireplace('desc', '', $sort); 56 $desc = true; 57 } 58 59 //check if we define limit 60 //I believe this's enough 61 $limit = 99999999; 62 $limit_reg = '/limit\s*([0-9]*)/i'; 63 if(preg_match($limit_reg, $sort, $matches) ) 64 { 65 $limit = (int)$matches[1]; 66 $sort = preg_replace($limit_reg, '', $sort); 67 } 68 69 $order_by = trim($sort); 70 } else 71 { 72 //check if we define limit 73 //I believe this's enough 74 $limit = 99999999; 75 $limit_reg = '/limit\s*([0-9]*)\s*$/i'; 76 if(preg_match($limit_reg, $args, $matches) ) 77 { 78 $limit = (int)$matches[1]; 79 $query = preg_replace($limit_reg, '', $query); 80 } 81 82 } 83 84 $exploded = explode(' ', $args); 85 $url = $exploded[0]; 86 87 //we have no arguments 88 if(count($exploded) < 3) 89 { 90 return array('url' => $url, 'conditions' => array(), 'order_by' => $order_by, 'desc' => $desc, 'limit' => $limit); 91 } 92 array_shift($exploded); 93 array_shift($exploded); 94 95 96 $conditions = implode('', $exploded); 97 98 //Remove ] from the end 99 $conditions = substr($conditions, 0, -1); 100 101 $cond_array = explode('&&', $conditions); 102 103 $cond_output = array(); 104 105 foreach($cond_array as $cond) 106 { 107 preg_match('/(.*?)(>|<|=|>=|<=)+(.*)/', $cond, $res); 108 if(in_array($res[1], $known_fileds)) 109 { 110 $name = $res[1]; 111 $value = $res[3]; 112 $sign = $res[2]; 113 } elseif(in_array($res[3], $known_fileds)) 114 { 115 $name = $res[3]; 116 $value = $res[1]; 117 $sign = $opposite_signs[$res[2]]; 118 } else 119 { 120 continue; 121 } 122 123 //remove "" and '' 124 $value = str_replace(array('"', "'"), '', $value); 125 126 if(!isset($cond_output[$name])) 127 $cond_output[$name] = array(); 128 129 array_push($cond_output[$name], array($sign, $value)); 130 } 131 return array('url' => $url, 'conditions' => $cond_output, 'order_by' => $order_by, 'desc' => $desc, 'limit' => $limit); 132 } 133 134 function render($mode, Doku_Renderer $renderer, $data) { 135 if($mode == 'xhtml') { 136 137 $filterrss =& plugin_load('helper', 'filterrss'); 138 139 $rss = simplexml_load_file($data['url']); 140 $rss_array = array(); 141 142 if($rss) 143 { 144 $items = $rss->channel->item; 145 $items_count = 0; 146 foreach($items as $item) 147 { 148 if( $items_count >= $data['limit']) 149 break; 150 $items_count++; 151 $jump_this_entry = false; 152 foreach($data['conditions'] as $entry => $conditions) 153 { 154 switch($entry) 155 { 156 case 'pubDate': 157 foreach($conditions as $comparison) 158 { 159 $left = strtotime($item->$entry); 160 $right = strtotime($comparison[1]); 161 switch($comparison[0]) 162 { 163 case '>': 164 if(!($left > $right)) 165 { 166 $jump_this_entry = true; 167 break; 168 } 169 break; 170 case '<': 171 if(!($left < $right)) 172 { 173 $jump_this_entry = true; 174 break; 175 } 176 break; 177 case '>=': 178 if(!($left >= $right)) 179 { 180 $jump_this_entry = true; 181 break; 182 } 183 break; 184 case '<=': 185 if(!($left <= $right)) 186 { 187 $jump_this_entry = true; 188 break; 189 } 190 break; 191 case '=': 192 if(!($left == $right)) 193 { 194 $jump_this_entry = true; 195 break; 196 } 197 break; 198 } 199 } 200 break; 201 case 'title': 202 case 'description': 203 case 'link': 204 foreach($conditions as $comparison) 205 { 206 $subject = $item->$entry; 207 208 //simple regexp option 209 $pattern ='/'. str_replace('%', '.*', preg_quote($comparison[1])).'/'; 210 211 switch($comparison[0]) 212 { 213 case '=': 214 if(!preg_match($pattern, $subject)) 215 { 216 $jump_this_entry = true; 217 break; 218 } 219 break; 220 } 221 } 222 break; 223 } 224 225 if($jump_this_entry == true) 226 break; 227 } 228 if($jump_this_entry == false) 229 { 230 $entry = array(); 231 $entry['title'] = $item->title; 232 $entry['link'] = $item->link; 233 $entry['pubDate'] = strtotime($item->pubDate); 234 $entry['description'] = $item->description; 235 236 array_push($rss_array, $entry); 237 238 } 239 } 240 if(!empty($data['order_by'])) 241 { 242 switch($data['order_by']) 243 { 244 case 'pubDate': 245 $rss_array = $filterrss->int_sort($rss_array, $data['order_by']); 246 break; 247 case 'title': 248 case 'description': 249 case 'link': 250 $rss_array = $filterrss->nat_sort($rss_array, $data['order_by']); 251 break; 252 } 253 if($data['desc']) 254 { 255 $rss_array = array_reverse($rss_array); 256 } 257 } 258 foreach($rss_array as $entry) 259 { 260 $renderer->doc .= '<div class="filterrss_plugin">'; 261 $renderer->doc .= '<a href="'.$entry['link'].'">'.$entry['title'].'</a><br>'; 262 $renderer->doc .= '<span>'.date('d.m.Y',$entry['pubDate']).'</span>'; 263 if($this->getConf('bbcode') == true) 264 { 265 $renderer->doc .= '<p>'.$filterrss->bbcode_parse($entry['description']).'</p>'; 266 } else 267 { 268 $renderer->doc .= '<p>'.$entry['description'].'</p>'; 269 } 270 $renderer->doc .= '</div>'; 271 } 272 } else 273 { 274 $renderer->doc .= 'Cannot load rss feed.'; 275 } 276 return true; 277 } elseif ($mode == "metadata") { 278 $renderer->meta['plugin_filterrss']['purge'] = true; 279 } 280 return false; 281 } 282} 283