[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/extension/ -> cli.php (source)

   1  <?php
   2  
   3  use dokuwiki\Extension\CLIPlugin;
   4  use splitbrain\phpcli\Options;
   5  use splitbrain\phpcli\TableFormatter;
   6  use splitbrain\phpcli\Colors;
   7  
   8  /**
   9   * Class cli_plugin_extension
  10   *
  11   * Command Line component for the extension manager
  12   *
  13   * @license GPL2
  14   * @author Andreas Gohr <andi@splitbrain.org>
  15   */
  16  class cli_plugin_extension extends CLIPlugin
  17  {
  18      /** @inheritdoc */
  19      protected function setup(Options $options)
  20      {
  21          // general setup
  22          $options->setHelp(
  23              "Manage plugins and templates for this DokuWiki instance\n\n" .
  24              "Status codes:\n" .
  25              "   i - installed\n" .
  26              "   b - bundled with DokuWiki\n" .
  27              "   g - installed via git\n" .
  28              "   d - disabled\n" .
  29              "   u - update available\n"
  30          );
  31  
  32          // search
  33          $options->registerCommand('search', 'Search for an extension');
  34          $options->registerOption('max', 'Maximum number of results (default 10)', 'm', 'number', 'search');
  35          $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'search');
  36          $options->registerArgument('query', 'The keyword(s) to search for', true, 'search');
  37  
  38          // list
  39          $options->registerCommand('list', 'List installed extensions');
  40          $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'list');
  41          $options->registerOption('filter', 'Filter by this status', 'f', 'status', 'list');
  42  
  43          // upgrade
  44          $options->registerCommand('upgrade', 'Update all installed extensions to their latest versions');
  45  
  46          // install
  47          $options->registerCommand('install', 'Install or upgrade extensions');
  48          $options->registerArgument(
  49              'extensions...',
  50              'One or more extensions to install. Either by name or download URL',
  51              true,
  52              'install'
  53          );
  54  
  55          // uninstall
  56          $options->registerCommand('uninstall', 'Uninstall a new extension');
  57          $options->registerArgument('extensions...', 'One or more extensions to install', true, 'uninstall');
  58  
  59          // enable
  60          $options->registerCommand('enable', 'Enable installed extensions');
  61          $options->registerArgument('extensions...', 'One or more extensions to enable', true, 'enable');
  62  
  63          // disable
  64          $options->registerCommand('disable', 'Disable installed extensions');
  65          $options->registerArgument('extensions...', 'One or more extensions to disable', true, 'disable');
  66      }
  67  
  68      /** @inheritdoc */
  69      protected function main(Options $options)
  70      {
  71          /** @var helper_plugin_extension_repository $repo */
  72          $repo = plugin_load('helper', 'extension_repository');
  73          if (!$repo->hasAccess(false)) {
  74              $this->warning('Extension Repository API is not accessible, no remote info available!');
  75          }
  76  
  77          switch ($options->getCmd()) {
  78              case 'list':
  79                  $ret = $this->cmdList($options->getOpt('verbose'), $options->getOpt('filter', ''));
  80                  break;
  81              case 'search':
  82                  $ret = $this->cmdSearch(
  83                      implode(' ', $options->getArgs()),
  84                      $options->getOpt('verbose'),
  85                      (int)$options->getOpt('max', 10)
  86                  );
  87                  break;
  88              case 'install':
  89                  $ret = $this->cmdInstall($options->getArgs());
  90                  break;
  91              case 'uninstall':
  92                  $ret = $this->cmdUnInstall($options->getArgs());
  93                  break;
  94              case 'enable':
  95                  $ret = $this->cmdEnable(true, $options->getArgs());
  96                  break;
  97              case 'disable':
  98                  $ret = $this->cmdEnable(false, $options->getArgs());
  99                  break;
 100              case 'upgrade':
 101                  $ret = $this->cmdUpgrade();
 102                  break;
 103              default:
 104                  echo $options->help();
 105                  $ret = 0;
 106          }
 107  
 108          exit($ret);
 109      }
 110  
 111      /**
 112       * Upgrade all extensions
 113       *
 114       * @return int
 115       */
 116      protected function cmdUpgrade()
 117      {
 118          /* @var helper_plugin_extension_extension $ext */
 119          $ext = $this->loadHelper('extension_extension');
 120          $list = $this->getInstalledExtensions();
 121  
 122          $ok = 0;
 123          foreach ($list as $extname) {
 124              $ext->setExtension($extname);
 125              $date = $ext->getInstalledVersion();
 126              $avail = $ext->getLastUpdate();
 127              if ($avail && $avail > $date && !$ext->isBundled()) {
 128                  $ok += $this->cmdInstall([$extname]);
 129              }
 130          }
 131  
 132          return $ok;
 133      }
 134  
 135      /**
 136       * Enable or disable one or more extensions
 137       *
 138       * @param bool $set
 139       * @param string[] $extensions
 140       * @return int
 141       */
 142      protected function cmdEnable($set, $extensions)
 143      {
 144          /* @var helper_plugin_extension_extension $ext */
 145          $ext = $this->loadHelper('extension_extension');
 146  
 147          $ok = 0;
 148          foreach ($extensions as $extname) {
 149              $ext->setExtension($extname);
 150              if (!$ext->isInstalled()) {
 151                  $this->error(sprintf('Extension %s is not installed', $ext->getID()));
 152                  ++$ok;
 153                  continue;
 154              }
 155  
 156              if ($set) {
 157                  $status = $ext->enable();
 158                  $msg = 'msg_enabled';
 159              } else {
 160                  $status = $ext->disable();
 161                  $msg = 'msg_disabled';
 162              }
 163  
 164              if ($status !== true) {
 165                  $this->error($status);
 166                  ++$ok;
 167                  continue;
 168              } else {
 169                  $this->success(sprintf($this->getLang($msg), $ext->getID()));
 170              }
 171          }
 172  
 173          return $ok;
 174      }
 175  
 176      /**
 177       * Uninstall one or more extensions
 178       *
 179       * @param string[] $extensions
 180       * @return int
 181       */
 182      protected function cmdUnInstall($extensions)
 183      {
 184          /* @var helper_plugin_extension_extension $ext */
 185          $ext = $this->loadHelper('extension_extension');
 186  
 187          $ok = 0;
 188          foreach ($extensions as $extname) {
 189              $ext->setExtension($extname);
 190              if (!$ext->isInstalled()) {
 191                  $this->error(sprintf('Extension %s is not installed', $ext->getID()));
 192                  ++$ok;
 193                  continue;
 194              }
 195  
 196              $status = $ext->uninstall();
 197              if ($status) {
 198                  $this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID()));
 199              } else {
 200                  $this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID())));
 201                  $ok = 1;
 202              }
 203          }
 204  
 205          return $ok;
 206      }
 207  
 208      /**
 209       * Install one or more extensions
 210       *
 211       * @param string[] $extensions
 212       * @return int
 213       */
 214      protected function cmdInstall($extensions)
 215      {
 216          /* @var helper_plugin_extension_extension $ext */
 217          $ext = $this->loadHelper('extension_extension');
 218  
 219          $ok = 0;
 220          foreach ($extensions as $extname) {
 221              $installed = [];
 222  
 223              if (preg_match("/^https?:\/\//i", $extname)) {
 224                  try {
 225                      $installed = $ext->installFromURL($extname, true);
 226                  } catch (Exception $e) {
 227                      $this->error($e->getMessage());
 228                      ++$ok;
 229                  }
 230              } else {
 231                  $ext->setExtension($extname);
 232  
 233                  if (!$ext->getDownloadURL()) {
 234                      ++$ok;
 235                      $this->error(
 236                          sprintf('Could not find download for %s', $ext->getID())
 237                      );
 238                      continue;
 239                  }
 240  
 241                  try {
 242                      $installed = $ext->installOrUpdate();
 243                  } catch (Exception $e) {
 244                      $this->error($e->getMessage());
 245                      ++$ok;
 246                  }
 247              }
 248  
 249              foreach ($installed as $info) {
 250                  $this->success(
 251                      sprintf(
 252                          $this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'),
 253                          $info['base']
 254                      )
 255                  );
 256              }
 257          }
 258          return $ok;
 259      }
 260  
 261      /**
 262       * Search for an extension
 263       *
 264       * @param string $query
 265       * @param bool $showdetails
 266       * @param int $max
 267       * @return int
 268       * @throws \splitbrain\phpcli\Exception
 269       */
 270      protected function cmdSearch($query, $showdetails, $max)
 271      {
 272          /** @var helper_plugin_extension_repository $repository */
 273          $repository = $this->loadHelper('extension_repository');
 274          $result = $repository->search($query);
 275          if ($max) {
 276              $result = array_slice($result, 0, $max);
 277          }
 278  
 279          $this->listExtensions($result, $showdetails);
 280          return 0;
 281      }
 282  
 283      /**
 284       * @param bool $showdetails
 285       * @param string $filter
 286       * @return int
 287       * @throws \splitbrain\phpcli\Exception
 288       */
 289      protected function cmdList($showdetails, $filter)
 290      {
 291          $list = $this->getInstalledExtensions();
 292          $this->listExtensions($list, $showdetails, $filter);
 293  
 294          return 0;
 295      }
 296  
 297      /**
 298       * Get all installed extensions
 299       *
 300       * @return array
 301       */
 302      protected function getInstalledExtensions()
 303      {
 304          /** @var Doku_Plugin_Controller $plugin_controller */
 305          global $plugin_controller;
 306          $pluginlist = $plugin_controller->getList('', true);
 307          $tpllist = glob(DOKU_INC . 'lib/tpl/*', GLOB_ONLYDIR);
 308          $tpllist = array_map(static fn($path) => 'template:' . basename($path), $tpllist);
 309  
 310          $list = array_merge($pluginlist, $tpllist);
 311          sort($list);
 312          return $list;
 313      }
 314  
 315      /**
 316       * List the given extensions
 317       *
 318       * @param string[] $list
 319       * @param bool $details display details
 320       * @param string $filter filter for this status
 321       * @throws \splitbrain\phpcli\Exception
 322       */
 323      protected function listExtensions($list, $details, $filter = '')
 324      {
 325          /** @var helper_plugin_extension_extension $ext */
 326          $ext = $this->loadHelper('extension_extension');
 327          $tr = new TableFormatter($this->colors);
 328  
 329  
 330          foreach ($list as $name) {
 331              $ext->setExtension($name);
 332  
 333              $status = '';
 334              if ($ext->isInstalled()) {
 335                  $date = $ext->getInstalledVersion();
 336                  $avail = $ext->getLastUpdate();
 337                  $status = 'i';
 338                  if ($avail && $avail > $date) {
 339                      $vcolor = Colors::C_RED;
 340                      $status .= 'u';
 341                  } else {
 342                      $vcolor = Colors::C_GREEN;
 343                  }
 344                  if ($ext->isGitControlled()) $status = 'g';
 345                  if ($ext->isBundled()) $status = 'b';
 346                  if ($ext->isEnabled()) {
 347                      $ecolor = Colors::C_BROWN;
 348                  } else {
 349                      $ecolor = Colors::C_DARKGRAY;
 350                      $status .= 'd';
 351                  }
 352              } else {
 353                  $ecolor = null;
 354                  $date = $ext->getLastUpdate();
 355                  $vcolor = null;
 356              }
 357  
 358              if ($filter && strpos($status, $filter) === false) {
 359                  continue;
 360              }
 361  
 362              echo $tr->format(
 363                  [20, 3, 12, '*'],
 364                  [
 365                      $ext->getID(),
 366                      $status,
 367                      $date,
 368                      strip_tags(sprintf(
 369                          $this->getLang('extensionby'),
 370                          $ext->getDisplayName(),
 371                          $this->colors->wrap($ext->getAuthor(), Colors::C_PURPLE)
 372                      ))
 373                  ],
 374                  [
 375                      $ecolor,
 376                      Colors::C_YELLOW,
 377                      $vcolor,
 378                      null,
 379                  ]
 380              );
 381  
 382              if (!$details) continue;
 383  
 384              echo $tr->format(
 385                  [5, '*'],
 386                  ['', $ext->getDescription()],
 387                  [null, Colors::C_CYAN]
 388              );
 389          }
 390      }
 391  }