#!/usr/bin/env php registerOption( 'force', 'force obtaining a lock for the page (generally bad idea)', 'f' ); $options->registerOption( 'user', 'work as this user. defaults to current CLI user', 'u', 'username' ); $options->setHelp( 'Utility to help command line Dokuwiki page editing, allow ' . 'pages to be checked out for editing then committed after changes' ); /* checkout command */ $options->registerCommand( 'checkout', 'Checks out a file from the repository, using the wiki id and obtaining ' . 'a lock for the page. ' . "\n" . 'If a working_file is specified, this is where the page is copied to. ' . 'Otherwise defaults to the same as the wiki page in the current ' . 'working directory.' ); $options->registerArgument( 'wikipage', 'The wiki page to checkout', true, 'checkout' ); $options->registerArgument( 'workingfile', 'How to name the local checkout', false, 'checkout' ); /* commit command */ $options->registerCommand( 'commit', 'Checks in the working_file into the repository using the specified ' . 'wiki id, archiving the previous version.' ); $options->registerArgument( 'workingfile', 'The local file to commit', true, 'commit' ); $options->registerArgument( 'wikipage', 'The wiki page to create or update', true, 'commit' ); $options->registerOption( 'message', 'Summary describing the change (required)', 'm', 'summary', 'commit' ); $options->registerOption( 'trivial', 'minor change', 't', false, 'commit' ); /* lock command */ $options->registerCommand( 'lock', 'Obtains or updates a lock for a wiki page' ); $options->registerArgument( 'wikipage', 'The wiki page to lock', true, 'lock' ); /* unlock command */ $options->registerCommand( 'unlock', 'Removes a lock for a wiki page.' ); $options->registerArgument( 'wikipage', 'The wiki page to unlock', true, 'unlock' ); /* gmeta command */ $options->registerCommand( 'getmeta', 'Prints metadata value for a page to stdout.' ); $options->registerArgument( 'wikipage', 'The wiki page to get the metadata for', true, 'getmeta' ); $options->registerArgument( 'key', 'The name of the metadata item to be retrieved.' . "\n" . 'If empty, an array of all the metadata items is returned.' ."\n" . 'For retrieving items that are stored in sub-arrays, separate the ' . 'keys of the different levels by spaces, in quotes, eg "date modified".', false, 'getmeta' ); } /** * Your main program * * Arguments and options have been parsed when this is run * * @param Options $options * @return void */ protected function main(Options $options) { $this->force = $options->getOpt('force', false); $this->username = $options->getOpt('user', $this->getUser()); $command = $options->getCmd(); $args = $options->getArgs(); switch($command) { case 'checkout': $wiki_id = array_shift($args); $localfile = array_shift($args); $this->commandCheckout($wiki_id, $localfile); break; case 'commit': $localfile = array_shift($args); $wiki_id = array_shift($args); $this->commandCommit( $localfile, $wiki_id, $options->getOpt('message', ''), $options->getOpt('trivial', false) ); break; case 'lock': $wiki_id = array_shift($args); $this->obtainLock($wiki_id); $this->success("$wiki_id locked"); break; case 'unlock': $wiki_id = array_shift($args); $this->clearLock($wiki_id); $this->success("$wiki_id unlocked"); break; case 'getmeta': $wiki_id = array_shift($args); $key = trim(array_shift($args)); $meta = p_get_metadata($wiki_id, $key, METADATA_RENDER_UNLIMITED); echo trim(json_encode($meta, JSON_PRETTY_PRINT)); echo "\n"; break; default: echo $options->help(); } } /** * Check out a file * * @param string $wiki_id * @param string $localfile */ protected function commandCheckout($wiki_id, $localfile) { global $conf; $wiki_id = cleanID($wiki_id); $wiki_fn = wikiFN($wiki_id); if(!file_exists($wiki_fn)) { $this->fatal("$wiki_id does not yet exist"); } if(empty($localfile)) { $localfile = getcwd() . '/' . \dokuwiki\Utf8\PhpString::basename($wiki_fn); } if(!file_exists(dirname($localfile))) { $this->fatal("Directory " . dirname($localfile) . " does not exist"); } if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) { $this->fatal("Attempt to check out file into data directory - not allowed"); } $this->obtainLock($wiki_id); if(!copy($wiki_fn, $localfile)) { $this->clearLock($wiki_id); $this->fatal("Unable to copy $wiki_fn to $localfile"); } $this->success("$wiki_id > $localfile"); } /** * Save a file as a new page revision * * @param string $localfile * @param string $wiki_id * @param string $message * @param bool $minor */ protected function commandCommit($localfile, $wiki_id, $message, $minor) { $wiki_id = cleanID($wiki_id); $message = trim($message); if(!file_exists($localfile)) { $this->fatal("$localfile does not exist"); } if(!is_readable($localfile)) { $this->fatal("Cannot read from $localfile"); } if(!$message) { $this->fatal("Summary message required"); } $this->obtainLock($wiki_id); saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor); $this->clearLock($wiki_id); $this->success("$localfile > $wiki_id"); } /** * Lock the given page or exit * * @param string $wiki_id */ protected function obtainLock($wiki_id) { if($this->force) $this->deleteLock($wiki_id); $_SERVER['REMOTE_USER'] = $this->username; if(checklock($wiki_id)) { $this->error("Page $wiki_id is already locked by another user"); exit(1); } lock($wiki_id); if(checklock($wiki_id)) { $this->error("Unable to obtain lock for $wiki_id "); var_dump(checklock($wiki_id)); exit(1); } } /** * Clear the lock on the given page * * @param string $wiki_id */ protected function clearLock($wiki_id) { if($this->force) $this->deleteLock($wiki_id); $_SERVER['REMOTE_USER'] = $this->username; if(checklock($wiki_id)) { $this->error("Page $wiki_id is locked by another user"); exit(1); } unlock($wiki_id); if(file_exists(wikiLockFN($wiki_id))) { $this->error("Unable to clear lock for $wiki_id"); exit(1); } } /** * Forcefully remove a lock on the page given * * @param string $wiki_id */ protected function deleteLock($wiki_id) { $wikiLockFN = wikiLockFN($wiki_id); if(file_exists($wikiLockFN)) { if(!unlink($wikiLockFN)) { $this->error("Unable to delete $wikiLockFN"); exit(1); } } } /** * Get the current user's username from the environment * * @return string */ protected function getUser() { $user = getenv('USER'); if(empty ($user)) { $user = getenv('USERNAME'); } else { return $user; } if(empty ($user)) { $user = 'admin'; } return $user; } } // Main $cli = new PageCLI(); $cli->run();