1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Gina Haeussge <osd@foosel.net> 5 */ 6 7/** 8 * Class action_plugin_blogtng_feed 9 */ 10class action_plugin_blogtng_feed extends DokuWiki_Action_Plugin{ 11 12 /** @var helper_plugin_blogtng_entry */ 13 private $entryhelper = null; 14 /** @var helper_plugin_blogtng_tools */ 15 private $tools = null; 16 17 private $defaultConf = array( 18 'sortby' => 'created', 19 'sortorder' => 'DESC', 20 ); 21 22 public function __construct() { 23 $this->entryhelper = plugin_load('helper', 'blogtng_entry'); 24 $this->tools = plugin_load('helper', 'blogtng_tools'); 25 } 26 27 /** 28 * Registers a callback function for a given event 29 * 30 * @param Doku_Event_Handler $controller 31 */ 32 public function register(Doku_Event_Handler $controller) { 33 $controller->register_hook('FEED_OPTS_POSTPROCESS', 'AFTER', $this, 'handleBlogFeedParameters', array()); 34 $controller->register_hook('FEED_MODE_UNKNOWN', 'BEFORE', $this, 'handleBlogFeed', array ()); 35 $controller->register_hook('FEED_ITEM_ADD', 'BEFORE', $this, 'handleBlogpostAddedToFeed', array()); 36 } 37 38 /** 39 * Parses blogtng specific feed parameters if the feed mode is 'blogtng'. 40 * 41 * @param Doku_Event $event event object by reference 42 * @param array $param empty array as passed to register_hook() 43 * @return void 44 */ 45 public function handleBlogFeedParameters(Doku_Event $event, $param) { 46 $opt =& $event->data['opt']; 47 if ($opt['feed_mode'] != 'blogtng') return; 48 49 global $INPUT; 50 51 $opt['blog'] = $INPUT->str('blog'); 52 $opt['tags'] = $INPUT->str('tags'); 53 $opt['sortby'] = $INPUT->str('sortby'); 54 $opt['sortorder'] = $INPUT->str('sortorder'); 55 } 56 57 /** 58 * Handles the 'blogtng' feed mode and prevents the default action (recents). 59 * Retrieves all blog posts as defined by blog and tags parameters, orders 60 * and limits them as requested and returns them inside the event. 61 * 62 * @param Doku_Event $event the event as triggered in feed.php 63 * @param array $param empty 64 * @return void 65 */ 66 public function handleBlogFeed(Doku_Event $event, $param) { 67 $opt = $event->data['opt']; 68 if ($opt['feed_mode'] != 'blogtng') return; 69 70 $event->preventDefault(); 71 $event->data['data'] = []; 72 $conf = [ 73 'blog' => explode(',', $opt['blog']), 74 'tags' => ($opt['tags'] ? explode(',', $opt['tags']) : null), 75 'sortby' => $opt['sortby'], 76 'sortorder' => $opt['sortorder'], 77 'limit' => $opt['items'], 78 'offset' => 0, 79 ]; 80 $this->tools->cleanConf($conf); 81 $conf = array_merge($conf, $this->defaultConf); 82 $posts = $this->entryhelper->get_posts($conf); 83 foreach ($posts as $row) { 84 $event->data['data'][] = array( 85 'id' => $row['page'], 86 'date' => $row['created'], 87 'user' => $row['author'], 88 'entry' => $row, 89 ); 90 } 91 } 92 93 /** 94 * Preprocesses a blog post as its added to the feed. Makes sure to 95 * remove the first header from the text (otherwise it would be doubled) 96 * and takes care of presentation as configured via template. 97 * 98 * @param Doku_Event $event the event as triggered in feed.php 99 * @param array $param empty 100 * @return void 101 */ 102 public function handleBlogpostAddedToFeed(Doku_Event $event, $param) { 103 $opt = $event->data['opt']; 104 $ditem = $event->data['ditem']; 105 if ($opt['feed_mode'] !== 'blogtng') return; 106 if ($opt['item_content'] !== 'html') return; 107 if ($opt['link_to'] !== 'current') return; 108 109 // don't add drafts to the feed 110 if(p_get_metadata($ditem['id'], 'type') == 'draft') { 111 $event->preventDefault(); 112 return; 113 } 114 115 // retrieve first heading from page instructions 116 $ins = p_cached_instructions(wikiFN($ditem['id'])); 117 $headers = array_filter($ins, array($this, 'filterHeaders')); 118 $headingIns = array_shift($headers); 119 $firstheading = $headingIns[1][0]; 120 121 $this->entryhelper->load_by_row($ditem['entry']); 122 123 ob_start(); 124 $this->entryhelper->tpl_content($ditem['entry']['blog'], 'feed'); 125 $output = ob_get_contents(); 126 ob_end_clean(); 127 // make URLs work when canonical is not set, regexp instead of rerendering! 128 global $conf; 129 if(!$conf['canonical']){ 130 $base = preg_quote(DOKU_REL,'/'); 131 $output = preg_replace('/(<a href|<img src)="('.$base.')/s','$1="'.DOKU_URL,$output); 132 } 133 134 // strip first heading and replace item title 135 $event->data['item']->description = preg_replace('#[^\n]*?>\s*?' . preg_quote(hsc($firstheading), '#') . '\s*?<.*\n#', '', $output, 1); 136 $event->data['item']->title = $ditem['entry']['title']; 137 138 //only supported by RSS 0.91 and RSS 2.0 139 if($ditem['entry']['commentstatus'] !== 'disabled') { 140 $event->data['item']->comments = $event->data['item']->link.'#the__comments'; 141 } 142 } 143 144 /** 145 * Returns true if $entry is a valid header instruction, false otherwise. 146 * 147 * @author Gina Häußge <osd@foosel.net> 148 * 149 * @param $entry 150 * @return bool 151 */ 152 private function filterHeaders($entry) { 153 // normal headers 154 if (is_array($entry) && $entry[0] == 'header' && count($entry) == 3 && is_array($entry[1]) && count($entry[1]) == 3) 155 return true; 156 157 // no known header 158 return false; 159 } 160} 161