1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Esther Brunner <wikidesign@gmail.com> 5 */ 6 7class action_plugin_blog extends DokuWiki_Action_Plugin { 8 9 /** 10 * register the eventhandlers 11 * @param Doku_Event_Handler $contr 12 */ 13 function register(Doku_Event_Handler $contr) { 14 $contr->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_act_preprocess', array()); 15 $contr->register_hook('FEED_ITEM_ADD', 'BEFORE', $this, 'handle_feed_item'); 16 $contr->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache'); 17 } 18 19 /** 20 * Checks if 'newentry' was given as action, if so we 21 * do handle the event our self and no further checking takes place 22 * @param Doku_Event $event 23 * @param $param 24 */ 25 function handle_act_preprocess(Doku_Event $event, $param) { 26 if ($event->data != 'newentry') return; // nothing to do for us 27 28 $event->data = $this->_handle_newEntry($event); 29 } 30 31 /** 32 * Removes draft entries from feeds 33 * 34 * @param Doku_Event $event 35 * @param $param 36 * 37 * @author Michael Klier <chi@chimeric.de> 38 */ 39 function handle_feed_item(Doku_Event $event, $param) { 40 global $conf; 41 42 $url = parse_url($event->data['item']->link); 43 $base_url = getBaseURL(); 44 45 // determine page id by rewrite mode 46 switch($conf['userewrite']) { 47 case 0: 48 preg_match('#id=([^&]*)#', $url['query'], $match); 49 if($base_url != '/') { 50 $id = cleanID(str_replace($base_url, '', $match[1])); 51 } else { 52 $id = cleanID($match[1]); 53 } 54 break; 55 56 case 1: 57 if($base_url != '/') { 58 $id = cleanID(str_replace('/',':',str_replace($base_url, '', $url['path']))); 59 } else { 60 $id = cleanID(str_replace('/',':', $url['path'])); 61 } 62 break; 63 64 case 2: 65 preg_match('#doku.php/([^&]*)#', $url['path'], $match); 66 if($base_url != '/') { 67 $id = cleanID(str_replace($base_url, '', $match[1])); 68 } else { 69 $id = cleanID($match[1]); 70 } 71 break; 72 } 73 74 // don't add drafts to the feed 75 if(p_get_metadata($id, 'type') == 'draft') { 76 $event->preventDefault(); 77 return; 78 } 79 } 80 81 /** 82 * Creates a new entry page 83 * 84 * @param Doku_Event $event 85 * @return string 86 */ 87 function _handle_newEntry(Doku_Event $event) { 88 global $ID, $INFO; 89 90 $ns = cleanID($_REQUEST['ns']); 91 $ID = $this->_newEntryID($ns, $_REQUEST['title']); 92 $INFO = pageinfo(); 93 94 // check if we are allowed to create this file 95 if ($INFO['perm'] >= AUTH_CREATE) { 96 97 // prepare the new thread file with default stuff 98 if (!@file_exists($INFO['filepath'])) { 99 100 //check if locked by anyone - if not lock for my self 101 if ($INFO['locked']) return 'locked'; 102 else lock($ID); 103 104 global $TEXT; 105 106 $TEXT = pageTemplate($ID); 107 if (!$TEXT) { 108 // if there is no page template, load our custom one 109 $TEXT = io_readFile(DOKU_PLUGIN.'blog/_template.txt'); 110 } 111 112 $data = array('id' => $ID, 'ns' => $ns, 'title' => $_REQUEST['title']); 113 // Apply replacements regardless if they have already been applied by DokuWiki in order to 114 // make custom replacements like @TITLE@ available in standard page templates. 115 $TEXT = $this->_pageTemplate($TEXT, $data); 116 117 return 'preview'; 118 } else { 119 return 'edit'; 120 } 121 } else { 122 return 'show'; 123 } 124 } 125 126 /** 127 * Adapted version of pageTemplate() function 128 * 129 * @param $text 130 * @param $data 131 * @return string|string[] 132 */ 133 function _pageTemplate($text, $data) { 134 global $conf, $INFO; 135 136 $id = $data['id']; 137 $user = $_SERVER['REMOTE_USER']; 138 139 // standard replacements 140 $replace = array( 141 '@ID@' => $id, 142 '@NS@' => $data['ns'], 143 '@PAGE@' => strtr(noNS($id),'_',' '), 144 '@USER@' => $user, 145 '@NAME@' => $INFO['userinfo']['name'], 146 '@MAIL@' => $INFO['userinfo']['mail'], 147 '@DATE@' => strftime($conf['dformat']), 148 ); 149 150 // additional replacements 151 $replace['@TITLE@'] = $data['title']; 152 153 // tag if tag plugin is available 154 if ((@file_exists(DOKU_PLUGIN.'tag/syntax/tag.php')) 155 && (!plugin_isdisabled('tag'))) { 156 $replace['@TAG@'] = "\n\n{{tag>}}"; 157 } else { 158 $replace['@TAG@'] = ''; 159 } 160 161 // discussion if discussion plugin is available 162 if ((@file_exists(DOKU_PLUGIN.'discussion/syntax/comments.php')) 163 && (!plugin_isdisabled('discussion'))) { 164 $replace['@DISCUSSION@'] = "~~DISCUSSION~~"; 165 } else { 166 $replace['@DISCUSSION@'] = ''; 167 } 168 169 // linkbacks if linkback plugin is available 170 if ((@file_exists(DOKU_PLUGIN.'linkback/syntax.php')) 171 && (!plugin_isdisabled('linkback'))) { 172 $replace['@LINKBACK@'] = "~~LINKBACK~~"; 173 } else { 174 $replace['@LINKBACK@'] = ''; 175 } 176 177 // do the replace 178 return str_replace(array_keys($replace), array_values($replace), $text); 179 } 180 181 /** 182 * Returns the ID of a new entry based on its namespace, title and the date prefix 183 * 184 * @param $ns 185 * @param $title 186 * @return mixed|string|string[]|null 187 * 188 * @author Michael Arlt <michael.arlt@sk-chwanstetten.de> 189 * @author Esther Brunner <wikidesign@gmail.com> 190 */ 191 function _newEntryID($ns, $title) { 192 $dateprefix = $this->getConf('dateprefix'); 193 if (substr($dateprefix, 0, 1) == '<') { 194 // <9?%y1-%y2:%d.%m._ -> 05-06:31.08._ | 06-07:01.09._ 195 list($newmonth, $dateprefix) = explode('?', substr($dateprefix, 1)); 196 if (intval(strftime("%m")) < intval($newmonth)) { 197 $longyear2 = strftime("%Y"); 198 $longyear1 = $longyear2 - 1; 199 } else { 200 $longyear1 = strftime("%Y"); 201 $longyear2 = $longyear1 + 1; 202 } 203 $shortyear1 = substr($longyear1, 2); 204 $shortyear2 = substr($longyear2, 2); 205 $dateprefix = str_replace( 206 array('%Y1', '%Y2', '%y1', '%y2'), 207 array($longyear1, $longyear2, $shortyear1, $shortyear2), 208 $dateprefix 209 ); 210 } 211 $pre = strftime($dateprefix); 212 $title = str_replace([':', ';', '#', '&', '%', '/', '\\', '?'], '', $title); 213 return cleanID(($ns ? $ns.':' : '').$pre.$title); 214 } 215 216 /** 217 * Expire the renderer cache of archive pages whenever a page is updated or a comment or linkback is added 218 * 219 * @param Doku_Event $event 220 * @param $params 221 * 222 * @author Michael Hamann <michael@content-space.de> 223 */ 224 function handle_cache(Doku_Event $event, $params) { 225 global $conf; 226 /** @var cache_parser $cache */ 227 $cache = $event->data; 228 if (!in_array($cache->mode, array('xhtml', 'metadata'))) return; 229 $page = $cache->page; 230 231 // try to extract the page id from the file if possible 232 if (empty($page)) { 233 if (strpos($cache->file, $conf['datadir']) === 0) { 234 $page = pathID(substr($cache->file, strlen($conf['datadir'])+1)); 235 } else { 236 return; 237 } 238 } 239 240 $meta = p_get_metadata($page, 'plugin_blog'); 241 if ($meta === null) return; 242 243 if (isset($meta['purgefile_cache'])) { 244 $cache->depends['files'][] = $conf['cachedir'].'/purgefile'; 245 $cache->depends['files'][] = $conf['metadir'].'/_comments.changes'; 246 $cache->depends['files'][] = $conf['metadir'].'/_linkbacks.changes'; 247 } 248 249 // purge the cache when a page is listed that the current user can't access 250 if (isset($meta['archive_pages'])) { 251 foreach ($meta['archive_pages'] as $page) { 252 if (auth_quickaclcheck($page) < AUTH_READ) { 253 $cache->depends['purge'] = true; 254 return; 255 } 256 } 257 } 258 } 259} 260