123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- #!/usr/bin/env php
- <?php
- use splitbrain\phpcli\CLI;
- use splitbrain\phpcli\Options;
- if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
- define('NOSESSION', 1);
- require_once(DOKU_INC . 'inc/init.php');
- /**
- * Checkout and commit pages from the command line while maintaining the history
- */
- class PageCLI extends CLI {
- protected $force = false;
- protected $username = '';
- /**
- * Register options and arguments on the given $options object
- *
- * @param Options $options
- * @return void
- */
- protected function setup(Options $options) {
- /* global */
- $options->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();
|