1<?php 2/** 3 * DokuWiki Plugin tumblr (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Lee Kwangyoung <ipari@leaflette.com> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12class syntax_plugin_tumblr extends DokuWiki_Syntax_Plugin { 13 function getInfo() { 14 return array( 15 'author' => 'Lee, Kwangyoung', 16 'email' => 'ipari@leaflette.com', 17 'date' => '2011-04-04', 18 'name' => 'Tumblr Plugin', 19 'desc' => 'Embed tumblr into DokuWiki', 20 'url' => 'http://www.dokuwiki.org/plugin:tumblr' 21 ); 22 } 23 24 /** 25 * @return string Syntax mode type 26 */ 27 function getType() { 28 return 'substition'; 29 } 30 /** 31 * @return string Paragraph type 32 */ 33 function getPType() { 34 return 'normal'; 35 } 36 /** 37 * https://www.dokuwiki.org/devel:parser:getsort_list 38 * 39 * @return int Sort order - Low numbers go before high numbers 40 */ 41 function getSort() { 42 return 315; 43 } 44 45 /** 46 * Connect lookup pattern to lexer. 47 * 48 * @param string $mode Parser mode 49 */ 50 function connectTo($mode) { 51 $this->Lexer->addSpecialPattern('\{\{tumblr>[^}]*\}\}',$mode,'plugin_tumblr'); 52 } 53 54// function postConnect() { 55// $this->Lexer->addExitPattern('</FIXME>','plugin_tumblr'); 56// } 57 58 /** 59 * Handle matches of the tumblr syntax 60 * 61 * @param string $match The match of the syntax 62 * @param int $state The state of the handler 63 * @param int $pos The position in the document 64 * @param Doku_Handler $handler The handler 65 * @return array Data for the renderer 66 */ 67 function handle($match, $state, $pos, Doku_Handler &$handler){ 68 $match = substr($match,9,-2); //strip '{{tumblr>' and '}}' 69 $params = explode('&',$match); 70 71 $data = array(); 72 foreach($params as $param) { 73 $param = explode('=',$param); 74 $data[$param[0]] = $param[1]; 75 } 76 return $data; 77 } 78 79 /** 80 * Render xhtml output or metadata 81 * 82 * @param string $mode Renderer mode (supported modes: xhtml) 83 * @param Doku_Renderer $renderer The renderer 84 * @param array $data The data from the handler() function 85 * @return bool If rendering was successful. 86 */ 87 function render($mode, Doku_Renderer &$renderer, $data) { 88 if($mode != 'xhtml') return false; 89 // prevent caching to show lastest posts 90 $renderer->info['cache'] = false; 91 $renderer->doc .= $this->tumblr($data); 92 return true; 93 } 94 95 public $tumblr_url = false; 96 97 function load_rss($url) { 98 global $conf; 99 require_once(DOKU_INC.'inc/FeedParser.php'); 100 101 $feed = new FeedParser(); 102 $feed->set_feed_url($url); 103 $rc = $feed->init(); 104 if (!$rc) { 105 return false; 106 } 107 108 $posts = array(); 109 foreach($feed->get_items() as $item) { 110 $posts[] = array( 111 'title' => $item->get_title(), 112 'date' => $item->get_local_date($conf['dformat']), 113 'permalink' => $item->get_permalink(), 114 'description' => $item->get_description(), 115 'tags' => $this->tags($item->get_categories()) 116 ); 117 } 118 return $posts; 119 } 120 121 function page_exists($url) { 122 require_once(DOKU_INC.'inc/FeedParser.php'); 123 $feed = new FeedParser(); 124 $feed->set_feed_url($url); 125 $feed->init(); 126 return $feed->get_item_quantity(); 127 } 128 129 function get_url_parameters() { 130 $parameters = array( 131 'page' => $_REQUEST['page'] ? $_REQUEST['page'] : 0, 132 'post' => $_REQUEST['post'], 133 'search' => $_REQUEST['search'], 134 'tagged' => $_REQUEST['tagged'] 135 ); 136 return $parameters; 137 } 138 139 function get_url($page=false) { 140 $url = $this->tumblr_url; 141 $params = $this->get_url_parameters(); 142 if ($page !== false) { 143 $params['page'] = $page; 144 } 145 // return rss url by URL parameter 146 if ($params['search']) { 147 $new_url = $url.'/search/'.$params['search'].'/page/'.$params['page'].'/rss'; 148 } elseif ($params['tagged']) { 149 $new_url = $url.'/tagged/'.$params['tagged'].'/page/'.$params['page'].'/rss'; 150 } elseif ($params['post']) { 151 $new_url = $url.'/'.$params['post'].'/rss'; 152 } else { 153 $new_url = $url.'/page/'.$params['page'].'/rss'; 154 } 155 return $new_url; 156 } 157 158 function tags($tags) { 159 // SimplePie Object to Array 160 if(!$tags) { 161 return false; 162 } 163 $new_tags = array(); 164 foreach($tags as $tag) { 165 $new_tags[] = $tag->term; 166 } 167 return $new_tags; 168 } 169 170 function make_link($url, $ID, $inner=false) { 171 // tumblr post url format is http://oo.tumblr.com/post/123456789012 172 $post_id = end(explode('/',$url)); 173 $html .= '<a href="'.wl($ID, 'post='.$post_id).'">'; 174 $html .= $inner ? $inner : $url; 175 $html .= '</a>'; 176 return $html; 177 } 178 179 function print_tags($tags, $ID) { 180 if(!$tags) { 181 return false; 182 } 183 $html .= '<ul>'; 184 foreach($tags as $tag) { 185 $html .= '<li>'; 186 $html .= '<a href="'.wl($ID, 'tagged='.str_replace(" ", "-", $tag)).'">'.$tag.'</a>'; 187 $html .= '</li>'; 188 } 189 $html .= '</ul>'; 190 return $html; 191 } 192 193 function get_nav_query($next) { 194 $params = $this->get_url_parameters(); 195 // page 1 is not exists on tumblr 196 if ($next) { 197 $params['page'] = ($params['page'] == 0) ? 2 : $params['page'] + 1; 198 } else { 199 $params['page'] = ($params['page'] == 2) ? 0 : $params['page'] - 1; 200 } 201 202 // check url exists 203 $url = $this->get_url($params['page']); 204 if ($params['page'] >= 0 && $this->page_exists($url)) { 205 return http_build_query($params, '', '&'); 206 } else { 207 return false; 208 } 209 } 210 211 function tumblr($options) { 212 global $lang; 213 global $ID; 214 $this->tumblr_url = $options['url']; 215 216 $html = ''; 217 $url = $this->get_url(); 218 $pID = $options['target'] ? $options['target'] : $ID; 219 $posts = $this->load_rss($url); 220 if (!$posts) { 221 $html .= '<div class="tumblr-post">'; 222 $html .= '<h2>'.$this->getLang('page_not_exists').'</h2>'; 223 $html .= '<p>'; 224 $html .= '<a href="javascript:history.go(-1)">'.$this->getLang('back_to_list').'</a><br />'; 225 $html .= $this->getLang('err_shown_when'); 226 $html .= '</p>'; 227 $html .= '<ul>'; 228 $html .= '<li>'.$this->getLang('err_no_result').'</li>'; 229 $html .= '<li>'.$this->getLang('err_not_accessible').'</li>'; 230 $html .= '<li>'.$this->getLang('err_wrong_url').'</li>'; 231 $html .= '</ul>'; 232 $html .= '</div>'; 233 return $html; 234 } 235 // render page 236 $html .= '<div class="tumblr-container">'; 237 if ($options['type'] != 'list') { 238 foreach($posts as $post) { 239 $html .= '<div class="tumblr-post">'; 240 $html .= '<h2>'.$this->make_link($post['permalink'], $pID, $post['title']).'</h2>'; 241 $html .= '<div>'.$post['description'].'</div>'; 242 243 // post meta 244 $html .= '<div class="tumblr-meta">'; 245 $html .= '<dl>'; 246 $html .= '<dt>DATE</dt>'; 247 $html .= '<dd>'.$post['date'].'</dd>'; 248 $html .= '<dt>PERMALINK</dt>'; 249 $html .= '<dd>'.$this->make_link($post['permalink'], $pID).'</dd>'; 250 $html .= '</dl>'; 251 252 // tags 253 if ($post['tags']) { 254 $html .= '<div class="tumblr-tags">'; 255 $html .= $this->print_tags($post['tags'], $pID); 256 $html .= '</div>'; 257 } 258 $html .= '</div>'; 259 $html .= '</div>'; // end of tumblr-post 260 } 261 } else { 262 $html .= '<div class="tumblr-list">'; 263 $html .= '<table>'; 264 foreach($posts as $post) { 265 $html .= '<tr>'; 266 $html .= '<td class="post-date"><time>'.$post['date'].'</time></td>'; 267 $html .= '<td class="post-title">'; 268 $html .= $this->make_link($post['permalink'], $pID, $post['title']); 269 $html .= '</td>'; 270 $html .= '</tr>'; 271 } 272 $html .= '</table>'; 273 $html .= '</div>'; 274 } 275 276 // page navigation 277 $html .= '<div class="tumblr-nav">'; 278 if ($_REQUEST['post']) { 279 $html .= '<div class="tumblr-btn-left" style="visibility:hidden">a</div>'; 280 // go back to list 281 $html .= '<div class="tumblr-btn-right">'; 282 $html .= '<a href="javascript:history.go(-1)">'.$this->getLang('back_to_list').'</a>'; 283 $html .= '</div>'; 284 } else { 285 $prev_query = $this->get_nav_query(false); 286 $next_query = $this->get_nav_query(true); 287 // left button 288 $html .= '<div class="tumblr-btn-left"'; 289 if (!$prev_query) { $html .= ' style="visibility:hidden"'; } 290 $html .= '>'; 291 $html .= '<a href="'.wl($ID, $prev_query).'">'.$this->getLang('newer_posts').'</a>'; 292 $html .= '</div>'; 293 // right button 294 $html .= '<div class="tumblr-btn-right"'; 295 if (!$next_query) { $html .= ' style="visibility:hidden"'; } 296 $html .= '>'; 297 $html .= '<a href="'.wl($ID, $next_query).'">'.$this->getLang('older_posts').'</a>'; 298 $html .= '</div>'; 299 } 300 // search form 301 if (!$options['search']) { 302 $html .= '<div class="tumblr-search">'; 303 $html .= '<form method="get">'; 304 $html .= '<input type="text" name="search">'; 305 $html .= '<button type="submit">'.$lang['btn_search'].'</button>'; 306 $html .= '</form>'; 307 $html .= '</div>'; // end of tumblr-search 308 } 309 $html .= '<div class="tumblr-clear"></div>'; 310 $html .= '</div>'; // end of tumblr-nav 311 $html .= '</div>'; // end of tumblr-container 312 return $html; 313 } 314} 315 316// vim:ts=4:sw=4:et: 317