1<?php 2/** 3 * Move Plugin Page Rename Functionality 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <gohr@cosmocode.de> 7 */ 8// must be run within Dokuwiki 9if(!defined('DOKU_INC')) die(); 10 11/** 12 * Class action_plugin_move_rename 13 */ 14class action_plugin_move_rename extends DokuWiki_Action_Plugin { 15 16 /** 17 * Register event handlers. 18 * 19 * @param Doku_Event_Handler $controller The plugin controller 20 */ 21 public function register(Doku_Event_Handler $controller) { 22 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handle_init'); 23 24 // TODO: DEPRECATED JAN 2018 25 $controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, 'handle_pagetools'); 26 27 $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addsvgbutton', array()); 28 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax'); 29 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxMediaManager'); 30 } 31 32 /** 33 * set JavaScript info if renaming of current page is possible 34 */ 35 public function handle_init() { 36 global $JSINFO; 37 global $INFO; 38 global $INPUT; 39 global $USERINFO; 40 41 $JSINFO['move_renameokay'] = $this->renameOkay($INFO['id']); 42 $JSINFO['move_allowrename'] = auth_isMember( 43 $this->getConf('allowrename'), 44 $INPUT->server->str('REMOTE_USER'), 45 $USERINFO['grps'] ?? [] 46 ); 47 } 48 49 /** 50 * Adds a button to the default template 51 * 52 * TODO: DEPRECATED JAN 2018 53 * 54 * @param Doku_Event $event 55 */ 56 public function handle_pagetools(Doku_Event $event) { 57 if($event->data['view'] != 'main') return; 58 if (!$this->getConf('pagetools_integration')) { 59 return; 60 } 61 62 $newitem = '<li class="plugin_move_page"><a href=""><span>' . $this->getLang('renamepage') . '</span></a></li>'; 63 $offset = count($event->data['items']) - 1; 64 $event->data['items'] = 65 array_slice($event->data['items'], 0, $offset, true) + 66 array('plugin_move' => $newitem) + 67 array_slice($event->data['items'], $offset, null, true); 68 } 69 70 /** 71 * Add 'rename' button to page tools, new SVG based mechanism 72 * 73 * @param Doku_Event $event 74 */ 75 public function addsvgbutton(Doku_Event $event) { 76 global $INFO, $JSINFO; 77 if( 78 $event->data['view'] !== 'page' || 79 !$this->getConf('pagetools_integration') || 80 !$JSINFO['move_renameokay'] 81 ) { 82 return; 83 } 84 if(!$INFO['exists']) { 85 return; 86 } 87 array_splice($event->data['items'], -1, 0, array(new \dokuwiki\plugin\move\MenuItem())); 88 } 89 90 /** 91 * Rename a single page 92 */ 93 public function handle_ajax(Doku_Event $event) { 94 if($event->data != 'plugin_move_rename') return; 95 $event->preventDefault(); 96 $event->stopPropagation(); 97 98 global $MSG; 99 global $INPUT; 100 101 $src = cleanID($INPUT->str('id')); 102 $dst = cleanID($INPUT->str('newid')); 103 104 /** @var helper_plugin_move_op $MoveOperator */ 105 $MoveOperator = plugin_load('helper', 'move_op'); 106 107 $JSON = new JSON(); 108 109 header('Content-Type: application/json'); 110 111 if($this->renameOkay($src) && $MoveOperator->movePage($src, $dst)) { 112 // all went well, redirect 113 echo $JSON->encode(array('redirect_url' => wl($dst, '', true, '&'))); 114 } else { 115 if(isset($MSG[0])) { 116 $error = $MSG[0]; // first error 117 } else { 118 $error = $this->getLang('cantrename'); 119 } 120 echo $JSON->encode(array('error' => $error)); 121 } 122 } 123 124 /** 125 * Handle media renames in media manager 126 * 127 * @param Doku_Event $event 128 * @return void 129 */ 130 public function handleAjaxMediaManager(Doku_Event $event) 131 { 132 if ($event->data !== 'plugin_move_rename_mediamanager') return; 133 134 if (!checkSecurityToken()) { 135 throw new \Exception('Security token did not match'); 136 } 137 138 $event->preventDefault(); 139 $event->stopPropagation(); 140 141 global $INPUT; 142 global $MSG; 143 global $USERINFO; 144 145 $src = cleanID($INPUT->str('src')); 146 $dst = cleanID($INPUT->str('dst')); 147 148 /** @var helper_plugin_move_op $moveOperator */ 149 $moveOperator = plugin_load('helper', 'move_op'); 150 151 if ($src && $dst) { 152 header('Content-Type: application/json'); 153 154 $response = []; 155 156 // check user/group restrictions 157 if ( 158 !auth_isMember($this->getConf('allowrename'), $INPUT->server->str('REMOTE_USER'), (array) $USERINFO['grps']) 159 ) { 160 $response['error'] = $this->getLang('notallowed'); 161 echo json_encode($response); 162 return; 163 } 164 165 $response['success'] = $moveOperator->moveMedia($src, $dst); 166 167 if ($response['success']) { 168 $ns = getNS($dst); 169 $response['redirect_url'] = wl($dst, ['do' => 'media', 'ns' => $ns], true, '&'); 170 } else { 171 $response['error'] = sprintf($this->getLang('mediamoveerror'), $src); 172 if (isset($MSG)) { 173 foreach ($MSG as $msg) { 174 $response['error'] .= ' ' . $msg['msg']; 175 } 176 } 177 } 178 179 echo json_encode($response); 180 } 181 } 182 183 /** 184 * Determines if it would be okay to show a rename page button for the given page and current user 185 * 186 * @param $id 187 * @return bool 188 */ 189 public function renameOkay($id) { 190 global $conf; 191 global $ACT; 192 global $USERINFO; 193 if(!($ACT == 'show' || empty($ACT))) return false; 194 if(!page_exists($id)) return false; 195 if(auth_quickaclcheck($id) < AUTH_EDIT) return false; 196 if(checklock($id) !== false || @file_exists(wikiLockFN($id))) return false; 197 if(!$conf['useacl']) return true; 198 if(!isset($_SERVER['REMOTE_USER'])) return false; 199 if(!auth_isMember($this->getConf('allowrename'), $_SERVER['REMOTE_USER'], (array) $USERINFO['grps'])) return false; 200 201 return true; 202 } 203 204 /** 205 * Use this in your template to add a simple "move this page" link 206 * 207 * Alternatively give anything the class "plugin_move_page" - it will automatically be hidden and shown and 208 * trigger the page move dialog. 209 */ 210 public function tpl() { 211 echo '<a href="" class="plugin_move_page">'; 212 echo $this->getLang('renamepage'); 213 echo '</a>'; 214 } 215 216} 217