[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/bin/ -> dwpage.php (source)

   1  #!/usr/bin/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  
 123      /**
 124       * Your main program
 125       *
 126       * Arguments and options have been parsed when this is run
 127       *
 128       * @param Options $options
 129       * @return void
 130       */
 131      protected function main(Options $options) {
 132          $this->force = $options->getOpt('force', false);
 133          $this->username = $options->getOpt('user', $this->getUser());
 134  
 135          $command = $options->getCmd();
 136          $args = $options->getArgs();
 137          switch($command) {
 138              case 'checkout':
 139                  $wiki_id = array_shift($args);
 140                  $localfile = array_shift($args);
 141                  $this->commandCheckout($wiki_id, $localfile);
 142                  break;
 143              case 'commit':
 144                  $localfile = array_shift($args);
 145                  $wiki_id = array_shift($args);
 146                  $this->commandCommit(
 147                      $localfile,
 148                      $wiki_id,
 149                      $options->getOpt('message', ''),
 150                      $options->getOpt('trivial', false)
 151                  );
 152                  break;
 153              case 'lock':
 154                  $wiki_id = array_shift($args);
 155                  $this->obtainLock($wiki_id);
 156                  $this->success("$wiki_id locked");
 157                  break;
 158              case 'unlock':
 159                  $wiki_id = array_shift($args);
 160                  $this->clearLock($wiki_id);
 161                  $this->success("$wiki_id unlocked");
 162                  break;
 163              default:
 164                  echo $options->help();
 165          }
 166      }
 167  
 168      /**
 169       * Check out a file
 170       *
 171       * @param string $wiki_id
 172       * @param string $localfile
 173       */
 174      protected function commandCheckout($wiki_id, $localfile) {
 175          global $conf;
 176  
 177          $wiki_id = cleanID($wiki_id);
 178          $wiki_fn = wikiFN($wiki_id);
 179  
 180          if(!file_exists($wiki_fn)) {
 181              $this->fatal("$wiki_id does not yet exist");
 182          }
 183  
 184          if(empty($localfile)) {
 185              $localfile = getcwd() . '/' . utf8_basename($wiki_fn);
 186          }
 187  
 188          if(!file_exists(dirname($localfile))) {
 189              $this->fatal("Directory " . dirname($localfile) . " does not exist");
 190          }
 191  
 192          if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) {
 193              $this->fatal("Attempt to check out file into data directory - not allowed");
 194          }
 195  
 196          $this->obtainLock($wiki_id);
 197  
 198          if(!copy($wiki_fn, $localfile)) {
 199              $this->clearLock($wiki_id);
 200              $this->fatal("Unable to copy $wiki_fn to $localfile");
 201          }
 202  
 203          $this->success("$wiki_id > $localfile");
 204      }
 205  
 206      /**
 207       * Save a file as a new page revision
 208       *
 209       * @param string $localfile
 210       * @param string $wiki_id
 211       * @param string $message
 212       * @param bool $minor
 213       */
 214      protected function commandCommit($localfile, $wiki_id, $message, $minor) {
 215          $wiki_id = cleanID($wiki_id);
 216          $message = trim($message);
 217  
 218          if(!file_exists($localfile)) {
 219              $this->fatal("$localfile does not exist");
 220          }
 221  
 222          if(!is_readable($localfile)) {
 223              $this->fatal("Cannot read from $localfile");
 224          }
 225  
 226          if(!$message) {
 227              $this->fatal("Summary message required");
 228          }
 229  
 230          $this->obtainLock($wiki_id);
 231  
 232          saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor);
 233  
 234          $this->clearLock($wiki_id);
 235  
 236          $this->success("$localfile > $wiki_id");
 237      }
 238  
 239      /**
 240       * Lock the given page or exit
 241       *
 242       * @param string $wiki_id
 243       */
 244      protected function obtainLock($wiki_id) {
 245          if($this->force) $this->deleteLock($wiki_id);
 246  
 247          $_SERVER['REMOTE_USER'] = $this->username;
 248  
 249          if(checklock($wiki_id)) {
 250              $this->error("Page $wiki_id is already locked by another user");
 251              exit(1);
 252          }
 253  
 254          lock($wiki_id);
 255  
 256          if(checklock($wiki_id)) {
 257              $this->error("Unable to obtain lock for $wiki_id ");
 258              var_dump(checklock($wiki_id));
 259              exit(1);
 260          }
 261      }
 262  
 263      /**
 264       * Clear the lock on the given page
 265       *
 266       * @param string $wiki_id
 267       */
 268      protected function clearLock($wiki_id) {
 269          if($this->force) $this->deleteLock($wiki_id);
 270  
 271          $_SERVER['REMOTE_USER'] = $this->username;
 272          if(checklock($wiki_id)) {
 273              $this->error("Page $wiki_id is locked by another user");
 274              exit(1);
 275          }
 276  
 277          unlock($wiki_id);
 278  
 279          if(file_exists(wikiLockFN($wiki_id))) {
 280              $this->error("Unable to clear lock for $wiki_id");
 281              exit(1);
 282          }
 283      }
 284  
 285      /**
 286       * Forcefully remove a lock on the page given
 287       *
 288       * @param string $wiki_id
 289       */
 290      protected function deleteLock($wiki_id) {
 291          $wikiLockFN = wikiLockFN($wiki_id);
 292  
 293          if(file_exists($wikiLockFN)) {
 294              if(!unlink($wikiLockFN)) {
 295                  $this->error("Unable to delete $wikiLockFN");
 296                  exit(1);
 297              }
 298          }
 299      }
 300  
 301      /**
 302       * Get the current user's username from the environment
 303       *
 304       * @return string
 305       */
 306      protected function getUser() {
 307          $user = getenv('USER');
 308          if(empty ($user)) {
 309              $user = getenv('USERNAME');
 310          } else {
 311              return $user;
 312          }
 313          if(empty ($user)) {
 314              $user = 'admin';
 315          }
 316          return $user;
 317      }
 318  }
 319  
 320  // Main
 321  $cli = new PageCLI();
 322  $cli->run();