dokuwiki/lib/plugins/extension/cli.php

373 lines
11 KiB
PHP

<?php
use splitbrain\phpcli\Colors;
/**
* Class cli_plugin_extension
*
* Command Line component for the extension manager
*
* @license GPL2
* @author Andreas Gohr <andi@splitbrain.org>
*/
class cli_plugin_extension extends DokuWiki_CLI_Plugin
{
/** @inheritdoc */
protected function setup(\splitbrain\phpcli\Options $options)
{
// general setup
$options->setHelp(
"Manage plugins and templates for this DokuWiki instance\n\n" .
"Status codes:\n" .
" i - installed\n" .
" b - bundled with DokuWiki\n" .
" g - installed via git\n" .
" d - disabled\n" .
" u - update available\n"
);
// search
$options->registerCommand('search', 'Search for an extension');
$options->registerOption('max', 'Maximum number of results (default 10)', 'm', 'number', 'search');
$options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'search');
$options->registerArgument('query', 'The keyword(s) to search for', true, 'search');
// list
$options->registerCommand('list', 'List installed extensions');
$options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'list');
$options->registerOption('filter', 'Filter by this status', 'f', 'status', 'list');
// upgrade
$options->registerCommand('upgrade', 'Update all installed extensions to their latest versions');
// install
$options->registerCommand('install', 'Install or upgrade extensions');
$options->registerArgument('extensions...', 'One or more extensions to install', true, 'install');
// uninstall
$options->registerCommand('uninstall', 'Uninstall a new extension');
$options->registerArgument('extensions...', 'One or more extensions to install', true, 'uninstall');
// enable
$options->registerCommand('enable', 'Enable installed extensions');
$options->registerArgument('extensions...', 'One or more extensions to enable', true, 'enable');
// disable
$options->registerCommand('disable', 'Disable installed extensions');
$options->registerArgument('extensions...', 'One or more extensions to disable', true, 'disable');
}
/** @inheritdoc */
protected function main(\splitbrain\phpcli\Options $options)
{
/** @var helper_plugin_extension_repository $repo */
$repo = plugin_load('helper', 'extension_repository');
if (!$repo->hasAccess(false)) {
$this->warning('Extension Repository API is not accessible, no remote info available!');
}
switch ($options->getCmd()) {
case 'list':
$ret = $this->cmdList($options->getOpt('verbose'), $options->getOpt('filter', ''));
break;
case 'search':
$ret = $this->cmdSearch(
implode(' ', $options->getArgs()),
$options->getOpt('verbose'),
(int)$options->getOpt('max', 10)
);
break;
case 'install':
$ret = $this->cmdInstall($options->getArgs());
break;
case 'uninstall':
$ret = $this->cmdUnInstall($options->getArgs());
break;
case 'enable':
$ret = $this->cmdEnable(true, $options->getArgs());
break;
case 'disable':
$ret = $this->cmdEnable(false, $options->getArgs());
break;
case 'upgrade':
$ret = $this->cmdUpgrade();
break;
default:
echo $options->help();
$ret = 0;
}
exit($ret);
}
/**
* Upgrade all extensions
*
* @return int
*/
protected function cmdUpgrade()
{
/* @var helper_plugin_extension_extension $ext */
$ext = $this->loadHelper('extension_extension');
$list = $this->getInstalledExtensions();
$ok = 0;
foreach ($list as $extname) {
$ext->setExtension($extname);
$date = $ext->getInstalledVersion();
$avail = $ext->getLastUpdate();
if ($avail && $avail > $date) {
$ok += $this->cmdInstall([$extname]);
}
}
return $ok;
}
/**
* Enable or disable one or more extensions
*
* @param bool $set
* @param string[] $extensions
* @return int
*/
protected function cmdEnable($set, $extensions)
{
/* @var helper_plugin_extension_extension $ext */
$ext = $this->loadHelper('extension_extension');
$ok = 0;
foreach ($extensions as $extname) {
$ext->setExtension($extname);
if (!$ext->isInstalled()) {
$this->error(sprintf('Extension %s is not installed', $ext->getID()));
$ok += 1;
continue;
}
if ($set) {
$status = $ext->enable();
$msg = 'msg_enabled';
} else {
$status = $ext->disable();
$msg = 'msg_disabled';
}
if ($status !== true) {
$this->error($status);
$ok += 1;
continue;
} else {
$this->success(sprintf($this->getLang($msg), $ext->getID()));
}
}
return $ok;
}
/**
* Uninstall one or more extensions
*
* @param string[] $extensions
* @return int
*/
protected function cmdUnInstall($extensions)
{
/* @var helper_plugin_extension_extension $ext */
$ext = $this->loadHelper('extension_extension');
$ok = 0;
foreach ($extensions as $extname) {
$ext->setExtension($extname);
if (!$ext->isInstalled()) {
$this->error(sprintf('Extension %s is not installed', $ext->getID()));
$ok += 1;
continue;
}
$status = $ext->uninstall();
if ($status) {
$this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID()));
} else {
$this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID())));
$ok = 1;
}
}
return $ok;
}
/**
* Install one or more extensions
*
* @param string[] $extensions
* @return int
*/
protected function cmdInstall($extensions)
{
/* @var helper_plugin_extension_extension $ext */
$ext = $this->loadHelper('extension_extension');
$ok = 0;
foreach ($extensions as $extname) {
$ext->setExtension($extname);
if (!$ext->getDownloadURL()) {
$ok += 1;
$this->error(
sprintf('Could not find download for %s', $ext->getID())
);
continue;
}
try {
$installed = $ext->installOrUpdate();
foreach ($installed as $name => $info) {
$this->success(sprintf(
$this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'),
$info['base'])
);
}
} catch (Exception $e) {
$this->error($e->getMessage());
$ok += 1;
}
}
return $ok;
}
/**
* Search for an extension
*
* @param string $query
* @param bool $showdetails
* @param int $max
* @return int
* @throws \splitbrain\phpcli\Exception
*/
protected function cmdSearch($query, $showdetails, $max)
{
/** @var helper_plugin_extension_repository $repository */
$repository = $this->loadHelper('extension_repository');
$result = $repository->search($query);
if ($max) {
$result = array_slice($result, 0, $max);
}
$this->listExtensions($result, $showdetails);
return 0;
}
/**
* @param bool $showdetails
* @param string $filter
* @return int
* @throws \splitbrain\phpcli\Exception
*/
protected function cmdList($showdetails, $filter)
{
$list = $this->getInstalledExtensions();
$this->listExtensions($list, $showdetails, $filter);
return 0;
}
/**
* Get all installed extensions
*
* @return array
*/
protected function getInstalledExtensions()
{
/** @var Doku_Plugin_Controller $plugin_controller */
global $plugin_controller;
$pluginlist = $plugin_controller->getList('', true);
$tpllist = glob(DOKU_INC . 'lib/tpl/*', GLOB_ONLYDIR);
$tpllist = array_map(function ($path) {
return 'template:' . basename($path);
}, $tpllist);
$list = array_merge($pluginlist, $tpllist);
sort($list);
return $list;
}
/**
* List the given extensions
*
* @param string[] $list
* @param bool $details display details
* @param string $filter filter for this status
* @throws \splitbrain\phpcli\Exception
*/
protected function listExtensions($list, $details, $filter = '')
{
/** @var helper_plugin_extension_extension $ext */
$ext = $this->loadHelper('extension_extension');
$tr = new \splitbrain\phpcli\TableFormatter($this->colors);
foreach ($list as $name) {
$ext->setExtension($name);
$status = '';
if ($ext->isInstalled()) {
$date = $ext->getInstalledVersion();
$avail = $ext->getLastUpdate();
$status = 'i';
if ($avail && $avail > $date) {
$vcolor = Colors::C_RED;
$status .= 'u';
} else {
$vcolor = Colors::C_GREEN;
}
if ($ext->isGitControlled()) $status = 'g';
if ($ext->isBundled()) $status = 'b';
if ($ext->isEnabled()) {
$ecolor = Colors::C_BROWN;
} else {
$ecolor = Colors::C_DARKGRAY;
$status .= 'd';
}
} else {
$ecolor = null;
$date = $ext->getLastUpdate();
$vcolor = null;
}
if ($filter && strpos($status, $filter) === false) {
continue;
}
echo $tr->format(
[20, 3, 12, '*'],
[
$ext->getID(),
$status,
$date,
strip_tags(sprintf(
$this->getLang('extensionby'),
$ext->getDisplayName(),
$this->colors->wrap($ext->getAuthor(), Colors::C_PURPLE))
)
],
[
$ecolor,
Colors::C_YELLOW,
$vcolor,
null,
]
);
if (!$details) continue;
echo $tr->format(
[5, '*'],
['', $ext->getDescription()],
[null, Colors::C_CYAN]
);
}
}
}