summaryrefslogtreecommitdiff
path: root/platform/www/bin/dwpage.php
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/bin/dwpage.php')
-rwxr-xr-xplatform/www/bin/dwpage.php322
1 files changed, 322 insertions, 0 deletions
diff --git a/platform/www/bin/dwpage.php b/platform/www/bin/dwpage.php
new file mode 100755
index 0000000..dee8039
--- /dev/null
+++ b/platform/www/bin/dwpage.php
@@ -0,0 +1,322 @@
+#!/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'
+ );
+ }
+
+ /**
+ * 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;
+ 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();