[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 #!/usr/bin/env php 2 <?php 3 4 use splitbrain\phpcli\CLI; 5 use splitbrain\phpcli\Options; 6 7 if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/'); 8 define('NOSESSION', 1); 9 require_once (DOKU_INC . 'inc/init.php'); 10 11 /** 12 * Checkout and commit pages from the command line while maintaining the history 13 */ 14 class PageCLI extends CLI { 15 16 protected $force = false; 17 protected $username = ''; 18 19 /** 20 * Register options and arguments on the given $options object 21 * 22 * @param Options $options 23 * @return void 24 */ 25 protected function setup(Options $options) { 26 /* global */ 27 $options->registerOption( 28 'force', 29 'force obtaining a lock for the page (generally bad idea)', 30 'f' 31 ); 32 $options->registerOption( 33 'user', 34 'work as this user. defaults to current CLI user', 35 'u', 36 'username' 37 ); 38 $options->setHelp( 39 'Utility to help command line Dokuwiki page editing, allow ' . 40 'pages to be checked out for editing then committed after changes' 41 ); 42 43 /* checkout command */ 44 $options->registerCommand( 45 'checkout', 46 'Checks out a file from the repository, using the wiki id and obtaining ' . 47 'a lock for the page. ' . "\n" . 48 'If a working_file is specified, this is where the page is copied to. ' . 49 'Otherwise defaults to the same as the wiki page in the current ' . 50 'working directory.' 51 ); 52 $options->registerArgument( 53 'wikipage', 54 'The wiki page to checkout', 55 true, 56 'checkout' 57 ); 58 $options->registerArgument( 59 'workingfile', 60 'How to name the local checkout', 61 false, 62 'checkout' 63 ); 64 65 /* commit command */ 66 $options->registerCommand( 67 'commit', 68 'Checks in the working_file into the repository using the specified ' . 69 'wiki id, archiving the previous version.' 70 ); 71 $options->registerArgument( 72 'workingfile', 73 'The local file to commit', 74 true, 75 'commit' 76 ); 77 $options->registerArgument( 78 'wikipage', 79 'The wiki page to create or update', 80 true, 81 'commit' 82 ); 83 $options->registerOption( 84 'message', 85 'Summary describing the change (required)', 86 'm', 87 'summary', 88 'commit' 89 ); 90 $options->registerOption( 91 'trivial', 92 'minor change', 93 't', 94 false, 95 'commit' 96 ); 97 98 /* lock command */ 99 $options->registerCommand( 100 'lock', 101 'Obtains or updates a lock for a wiki page' 102 ); 103 $options->registerArgument( 104 'wikipage', 105 'The wiki page to lock', 106 true, 107 'lock' 108 ); 109 110 /* unlock command */ 111 $options->registerCommand( 112 'unlock', 113 'Removes a lock for a wiki page.' 114 ); 115 $options->registerArgument( 116 'wikipage', 117 'The wiki page to unlock', 118 true, 119 'unlock' 120 ); 121 122 /* gmeta command */ 123 $options->registerCommand( 124 'getmeta', 125 'Prints metadata value for a page to stdout.' 126 ); 127 $options->registerArgument( 128 'wikipage', 129 'The wiki page to get the metadata for', 130 true, 131 'getmeta' 132 ); 133 $options->registerArgument( 134 'key', 135 'The name of the metadata item to be retrieved.' . "\n" . 136 'If empty, an array of all the metadata items is returned.' ."\n" . 137 'For retrieving items that are stored in sub-arrays, separate the ' . 138 'keys of the different levels by spaces, in quotes, eg "date modified".', 139 false, 140 'getmeta' 141 ); 142 } 143 144 /** 145 * Your main program 146 * 147 * Arguments and options have been parsed when this is run 148 * 149 * @param Options $options 150 * @return void 151 */ 152 protected function main(Options $options) { 153 $this->force = $options->getOpt('force', false); 154 $this->username = $options->getOpt('user', $this->getUser()); 155 156 $command = $options->getCmd(); 157 $args = $options->getArgs(); 158 switch($command) { 159 case 'checkout': 160 $wiki_id = array_shift($args); 161 $localfile = array_shift($args); 162 $this->commandCheckout($wiki_id, $localfile); 163 break; 164 case 'commit': 165 $localfile = array_shift($args); 166 $wiki_id = array_shift($args); 167 $this->commandCommit( 168 $localfile, 169 $wiki_id, 170 $options->getOpt('message', ''), 171 $options->getOpt('trivial', false) 172 ); 173 break; 174 case 'lock': 175 $wiki_id = array_shift($args); 176 $this->obtainLock($wiki_id); 177 $this->success("$wiki_id locked"); 178 break; 179 case 'unlock': 180 $wiki_id = array_shift($args); 181 $this->clearLock($wiki_id); 182 $this->success("$wiki_id unlocked"); 183 break; 184 case 'getmeta': 185 $wiki_id = array_shift($args); 186 $key = trim(array_shift($args)); 187 $meta = p_get_metadata($wiki_id, $key, METADATA_RENDER_UNLIMITED); 188 echo trim(json_encode($meta, JSON_PRETTY_PRINT)); 189 echo "\n"; 190 break; 191 default: 192 echo $options->help(); 193 } 194 } 195 196 /** 197 * Check out a file 198 * 199 * @param string $wiki_id 200 * @param string $localfile 201 */ 202 protected function commandCheckout($wiki_id, $localfile) { 203 global $conf; 204 205 $wiki_id = cleanID($wiki_id); 206 $wiki_fn = wikiFN($wiki_id); 207 208 if(!file_exists($wiki_fn)) { 209 $this->fatal("$wiki_id does not yet exist"); 210 } 211 212 if(empty($localfile)) { 213 $localfile = getcwd() . '/' . \dokuwiki\Utf8\PhpString::basename($wiki_fn); 214 } 215 216 if(!file_exists(dirname($localfile))) { 217 $this->fatal("Directory " . dirname($localfile) . " does not exist"); 218 } 219 220 if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) { 221 $this->fatal("Attempt to check out file into data directory - not allowed"); 222 } 223 224 $this->obtainLock($wiki_id); 225 226 if(!copy($wiki_fn, $localfile)) { 227 $this->clearLock($wiki_id); 228 $this->fatal("Unable to copy $wiki_fn to $localfile"); 229 } 230 231 $this->success("$wiki_id > $localfile"); 232 } 233 234 /** 235 * Save a file as a new page revision 236 * 237 * @param string $localfile 238 * @param string $wiki_id 239 * @param string $message 240 * @param bool $minor 241 */ 242 protected function commandCommit($localfile, $wiki_id, $message, $minor) { 243 $wiki_id = cleanID($wiki_id); 244 $message = trim($message); 245 246 if(!file_exists($localfile)) { 247 $this->fatal("$localfile does not exist"); 248 } 249 250 if(!is_readable($localfile)) { 251 $this->fatal("Cannot read from $localfile"); 252 } 253 254 if(!$message) { 255 $this->fatal("Summary message required"); 256 } 257 258 $this->obtainLock($wiki_id); 259 260 saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor); 261 262 $this->clearLock($wiki_id); 263 264 $this->success("$localfile > $wiki_id"); 265 } 266 267 /** 268 * Lock the given page or exit 269 * 270 * @param string $wiki_id 271 */ 272 protected function obtainLock($wiki_id) { 273 if($this->force) $this->deleteLock($wiki_id); 274 275 $_SERVER['REMOTE_USER'] = $this->username; 276 277 if(checklock($wiki_id)) { 278 $this->error("Page $wiki_id is already locked by another user"); 279 exit(1); 280 } 281 282 lock($wiki_id); 283 284 if(checklock($wiki_id)) { 285 $this->error("Unable to obtain lock for $wiki_id "); 286 var_dump(checklock($wiki_id)); 287 exit(1); 288 } 289 } 290 291 /** 292 * Clear the lock on the given page 293 * 294 * @param string $wiki_id 295 */ 296 protected function clearLock($wiki_id) { 297 if($this->force) $this->deleteLock($wiki_id); 298 299 $_SERVER['REMOTE_USER'] = $this->username; 300 if(checklock($wiki_id)) { 301 $this->error("Page $wiki_id is locked by another user"); 302 exit(1); 303 } 304 305 unlock($wiki_id); 306 307 if(file_exists(wikiLockFN($wiki_id))) { 308 $this->error("Unable to clear lock for $wiki_id"); 309 exit(1); 310 } 311 } 312 313 /** 314 * Forcefully remove a lock on the page given 315 * 316 * @param string $wiki_id 317 */ 318 protected function deleteLock($wiki_id) { 319 $wikiLockFN = wikiLockFN($wiki_id); 320 321 if(file_exists($wikiLockFN)) { 322 if(!unlink($wikiLockFN)) { 323 $this->error("Unable to delete $wikiLockFN"); 324 exit(1); 325 } 326 } 327 } 328 329 /** 330 * Get the current user's username from the environment 331 * 332 * @return string 333 */ 334 protected function getUser() { 335 $user = getenv('USER'); 336 if(empty ($user)) { 337 $user = getenv('USERNAME'); 338 } else { 339 return $user; 340 } 341 if(empty ($user)) { 342 $user = 'admin'; 343 } 344 return $user; 345 } 346 } 347 348 // Main 349 $cli = new PageCLI(); 350 $cli->run();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body