1<?php 2if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/'); 3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 4require_once(DOKU_PLUGIN.'action.php'); 5 6/** 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 * @author Myron Turner <turnermm02@shaw.ca> 9 */ 10 11class action_plugin_openas extends DokuWiki_Action_Plugin { 12 13 private $ext = '.txt'; 14 private $locks_set=false; 15 private $locked_fn; 16 /** 17 * Constructor 18 */ 19 function __construct() { 20 21 $this->locked_fn = $this->metaFilePath('locks','ser',false); 22 } 23 24 function register(Doku_Event_Handler $controller) { 25 $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'openas_preprocess'); 26 $controller->register_hook('DOKUWIKI_DONE', 'BEFORE', $this, 'update_locked_pages'); 27 } 28 29 30 /** 31 $_REQUEST['saveas_orig']: id of the original page which will be moved or copied to a new name 32 $_REQUEST['id'] or $INFO['id']: name of the new page 33 */ 34 function openas_preprocess(Doku_Event $event){ 35 global $INFO; 36 if(!$this->check_url()) return; 37 38 if(isset($_REQUEST['openas'])) { 39 $new_file = wikiFN($INFO['id']); 40 if(file_exists($new_file) && isset($_REQUEST['saveas_orig'])) { 41 // handle relative links for both save and move 42 $this->update_relative_links($_REQUEST['id'],$_REQUEST['saveas_orig']) ; 43 if($_REQUEST['openas'] == 'delete') { 44 $this->get_backs($_REQUEST['id'],$_REQUEST['saveas_orig']) ; 45 $file = wikiFN($_REQUEST['saveas_orig']); 46 if(file_exists($file)&&!$this->locks_set) @unlink($file); 47 } 48 } 49 } 50 51 52 } 53 54 function get_backs($id,$orig) { 55 $backlinks = ft_backlinks($orig); 56 57 foreach($backlinks as $backlink) { 58 if(!checklock($backlink)) { 59 lock($backlink); 60 } 61 } 62 63 $locked_array=$this->get_locked_array() ; 64 $locks_found = false; 65 foreach($backlinks as $link) { 66 if(checklock($link)) { 67 $this->locks_set = true; 68 $locked_array[$link] = array($id,$orig); 69 continue; 70 } 71 $this->resolve_ids($id,$orig,$link); 72 unlock($link); 73 } 74 if($this->locks_set) { 75 io_saveFile($this->locked_fn,serialize($locked_array)); 76 } 77 } 78 79 /** 80 Determines the absolute link for any relative links in the original page 81 Then replaces relative links in moved page with the absolute links 82 $c_link in the create_function will hold the absolute link for an id based on the 83 resolved link from the original page 84 85 @params 86 $new_id: page to which original is being moved 87 $orig_id: page which is being moved and deleted 88 */ 89 function update_relative_links($new_id, $orig_id) { 90 global $orig_namespace, $openas_debug; 91 $orig_namespace = rtrim(getNS($orig_id),':') . ':'; 92 $openas_debug = $this; 93 $current_wikifn=wikiFN($new_id); 94 $data = io_readFile($current_wikifn); 95 $metafn=$this->metaFilePath($orig_id,'orig'); 96 97 io_saveFile($metafn,$data); 98 99 $data = preg_replace_callback('/\[\[(.*?)\]\]/', 100 create_function( 101 '$matches', 102 'global $openas_debug,$orig_namespace; 103 $link_array = explode("|",$matches[1]); 104 $c_link = $link_array[0]; 105 $link_text = isset($link_array[1]) ? $link_array[1] : ""; 106 resolve_pageid($orig_namespace,$c_link,$c_exists); 107 if($c_exists) { 108 return "[[:$c_link|$link_text]]"; 109 } 110 return $matches[0];' 111 ) , 112 $data 113 ); 114 115 $dir = dirname($current_wikifn); 116 $fname = basename($current_wikifn, '.txt'); 117 $path = "$dir/$fname" . $this->ext; 118 io_saveFile($path,$data); 119 120 } 121 /** 122 This function updates all links in the backlink page which reference the 123 page being deleted. The updated links will now refer to the new page. 124 The updated links will be absolute links. 125 @params: 126 $orig_id: deleted page 127 $new_id: page to which $orig_id is being moved 128 $curid: the page which is being currently being updated as determined 129 from the backlinks array 130 */ 131 function resolve_ids($new_id, $orig_id, $curid) { 132 $current_wikifn=wikiFN($curid); 133 if(!$current_wikifn) return; 134 135 global $current_ns; 136 global $openas_debug; 137 global $old_id; 138 global $new_page_id; 139 $old_id = $orig_id; 140 ltrim($new_id,':'); 141 $new_page_id = ':' . $new_id; 142 143 $current_ns = rtrim(getNS($curid),':') . ':'; 144 145 if(!function_exists("openas_check_pageid")) { 146 147 function openas_check_pageid($matches) { 148 global $openas_debug,$old_id,$current_ns,$new_page_id; 149 $link_array = explode('|',$matches[1]); 150 $c_link = $link_array[0]; 151 152 resolve_pageid($current_ns,$c_link,$c_exists); 153 154 if($c_exists) { // found a link in the namespace of current page that relates to namespace of page being deleted (original page) 155 if(preg_match("/$old_id/",$c_link)) { //is this link id found in the current page 156 list($name,$hash) = explode('#',$link_array[0]); 157 if(isset($hash)) { 158 $new_link = $new_page_id . "#" .$hash; 159 } 160 else $new_link = $new_page_id ; 161 162 return '[[' . $new_link . ']]'; 163 } 164 165 } 166 167 return '[[' . $matches[1] . ']]'; 168 } 169 170 } 171 $data = io_readFile($current_wikifn); 172 $metafn = $this->metaFilePath($curid); 173 174 io_saveFile($metafn,$data); 175 176 $data = preg_replace_callback('/\[\[(.*?)\]\]/', "openas_check_pageid",$data); 177 178 $dir = dirname($current_wikifn); 179 $fname = basename($current_wikifn, '.txt'); 180 $path = "$dir/$fname" . $this->ext; 181 io_saveFile($path,$data); 182 } 183 184 function metaFilePath($current_id, $ext='mvd', $numbered=true) { 185 $namespace = 'openas:' . $current_id; 186 187 if($numbered) { 188 for($i=1; ; $i++) { 189 $metafnn = metaFN($namespace, '.' . "$i.$ext"); 190 if(!@file_exists($metafnn)) { 191 return $metafnn; 192 } 193 } 194 } 195 196 $metafn = metaFN($namespace, '.' . $ext); 197 return $metafn; 198 } 199 200 /** 201 $orig_id: deleted page 202 $new_id: page to which $orig_id is being moved 203 $curid: the page which is being currently being updated as determined 204 from the backlinks array 205 206 */ 207 function save_locked($new_id,$orig_id,$back_link) { 208 $this->locked_array[$back_link] = array($new_id,$orig_id); 209 } 210 211 function get_locked_array() { 212 if(@file_exists($this->locked_fn)) { 213 return unserialize(io_readFile($this->locked_fn,false)); 214 } 215 216 return array(); 217 } 218 219 function update_locked_pages(Doku_Event $event) { 220 global $ID; 221 $locked_array=$this->get_locked_array() ; 222 223 if(isset($locked_array[$ID])) { 224 // $this->ext = '.locked2.txt'; 225 $new_id = $locked_array[$ID][0]; 226 $orig_id = $locked_array[$ID][1]; 227 $this->resolve_ids($new_id, $orig_id, $ID); 228 } 229 unset($locked_array[$ID]); 230 io_saveFile($this->locked_fn,serialize($locked_array)); 231 if(empty($locked_array)) { 232 $file = wikiFN($orig_id); 233 if(file_exists($file)) @unlink($file); 234 } 235 236 } 237 238 function check_url() { 239 global $INPUT,$USERINFO; 240 241 if(empty($USERINFO)) { 242 $action = $INPUT->get->str('openas'); 243 if($action) { 244 $db = DOKU_BASE; 245 $default = "${db}lib/plugins/openas/images/404.jpg"; 246 $fourOhfour = $this->getConf("404"); 247 if(!$fourOhfour) $fourOhfour = $default; 248 header("Location: $fourOhfour"); /* Redirect browser */ 249 return false; 250 } 251 } 252 //id=tower2&saveas_orig=tower&openas=delete 253 $newid = $INPUT->get->str('id'); 254 $saveas_orig = $INPUT->get->str('saveas_orig'); 255 $action = $INPUT->get->str('openas'); 256 if(!$action) return false; 257 258 resolve_pageid(getNS($newid), $newid, $exists); 259 $newid = cleanID($newid); 260 $auth_newid = auth_quickaclcheck($newid); 261 262 resolve_pageid(getNS($saveas_orig), $saveas_orig, $exists); 263 cleanID($saveas_orig); 264 $auth_origid = auth_quickaclcheck($saveas_orig); 265 266 // msg("$action original page: $saveas_orig // " . $auth_origid); 267 // msg("new page: $newid //". $auth_newid ); 268 269 switch($action) 270 { 271 case 'delete': 272 if($auth_origid < AUTH_EDIT) { 273 $nodel = $this->getLang('nodelete'); 274 msg("1. $nodel $saveas_orig"); 275 return false; 276 } 277 if($auth_newid < AUTH_CREATE) { 278 $nocreate = $this->getLang('nocreate'); 279 msg("2. $nocreate $id"); 280 return false; 281 } 282 return true; 283 284 case 'save': 285 if($auth_newid < AUTH_CREATE) { 286 $nocreate = $this->getLang('nocreate'); 287 msg("3. $nocreate $newid"); 288 return false; 289 } 290 if($auth_origid < AUTH_EDIT) { 291 $nocopy = $this->getLang('nocopy'); 292 msg("4. $nocopy $saveas_orig"); 293 return false; 294 } 295 return true; 296 297 default: 298 return false; 299 } 300 301 return false; 302 } 303 304 function write_debug($what,$pre=false) { 305 if(is_array($what)) $what = print_r($what,true); 306 if($pre) { 307 msg('<pre>' . $what . '</pre>'); 308 return; 309 } 310 $handle = fopen("openas.txt", "a"); 311 fwrite($handle,"$what\n"); 312 fclose($handle); 313 } 314 315} //end of action class 316?> 317