aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/lib/plugins/extension
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2024-04-17 14:49:08 +0200
committerAndreas Gohr <andi@splitbrain.org>2024-12-04 10:51:13 +0100
commit160d3688fe2b70ebe88d464cba3417440127a155 (patch)
tree90b51f13067f59958474dd6e22cfde4bf478b3f0 /lib/plugins/extension
parent25d28a0105a16bf32f2784e80b3cf268074c8c8a (diff)
downloaddokuwiki-160d3688fe2b70ebe88d464cba3417440127a155.tar.gz
dokuwiki-160d3688fe2b70ebe88d464cba3417440127a155.zip
Extension Manager: CLI now should completely use new classes
Diffstat (limited to 'lib/plugins/extension')
-rw-r--r--lib/plugins/extension/Extension.php40
-rw-r--r--lib/plugins/extension/Installer.php35
-rw-r--r--lib/plugins/extension/Manager.php18
-rw-r--r--lib/plugins/extension/cli.php136
-rw-r--r--lib/plugins/extension/lang/en/lang.php7
5 files changed, 138 insertions, 98 deletions
diff --git a/lib/plugins/extension/Extension.php b/lib/plugins/extension/Extension.php
index baecce194..b2dd9abbd 100644
--- a/lib/plugins/extension/Extension.php
+++ b/lib/plugins/extension/Extension.php
@@ -406,6 +406,31 @@ class Extension
return $plugin_controller->isEnabled($this->base);
}
+ /**
+ * Has the download URL changed since the last download?
+ *
+ * @return bool
+ */
+ public function hasChangedURL()
+ {
+ $last = $this->getManager()->getDownloadUrl();
+ if(!$last) return false;
+ return $last !== $this->getDownloadURL();
+ }
+
+ /**
+ * Is an update available for this extension?
+ *
+ * @return bool
+ */
+ public function updateAvailable()
+ {
+ if($this->isBundled()) return false; // bundled extensions are never updated
+ $self = $this->getInstalledVersion();
+ $remote = $this->getLastUpdate();
+ return $self < $remote;
+ }
+
// endregion
// region Remote Info
@@ -544,10 +569,7 @@ class Extension
public function installOrUpdate()
{
$installer = new Installer(true);
- $installer->installFromUrl(
- $this->getURL(),
- $this->getBase(),
- );
+ $installer->installExtension($this);
}
/**
@@ -568,8 +590,8 @@ class Extension
public function enable()
{
if ($this->isTemplate()) throw new Exception('notimplemented');
- if (!$this->isInstalled()) throw new Exception('notinstalled');
- if ($this->isEnabled()) throw new Exception('alreadyenabled');
+ if (!$this->isInstalled()) throw new Exception('error_notinstalled', [$this->getId()]);
+ if ($this->isEnabled()) throw new Exception('error_alreadyenabled', [$this->getId()]);
/* @var PluginController $plugin_controller */
global $plugin_controller;
@@ -587,9 +609,9 @@ class Extension
public function disable()
{
if ($this->isTemplate()) throw new Exception('notimplemented');
- if (!$this->isInstalled()) throw new Exception('notinstalled');
- if (!$this->isEnabled()) throw new Exception('alreadydisabled');
- if ($this->isProtected()) throw new Exception('error_disable_protected');
+ if (!$this->isInstalled()) throw new Exception('error_notinstalled', [$this->getId()]);
+ if (!$this->isEnabled()) throw new Exception('error_alreadydisabled', [$this->getId()]);
+ if ($this->isProtected()) throw new Exception('error_disable_protected', [$this->getId()]);
/* @var PluginController $plugin_controller */
global $plugin_controller;
diff --git a/lib/plugins/extension/Installer.php b/lib/plugins/extension/Installer.php
index 214f53bf0..75e836367 100644
--- a/lib/plugins/extension/Installer.php
+++ b/lib/plugins/extension/Installer.php
@@ -36,7 +36,6 @@ class Installer
public const STATUS_SKIPPED = 'skipped';
public const STATUS_UPDATED = 'updated';
public const STATUS_INSTALLED = 'installed';
- public const STATUS_DELETED = 'deleted';
/**
@@ -63,9 +62,9 @@ class Installer
}
/**
- * Install an extension
+ * Install an extension by ID
*
- * This will simply call installFromUrl() with the URL from the extension
+ * This will simply call installExtension after constructing an extension from the ID
*
* The $skipInstalled parameter should only be used when installing dependencies
*
@@ -73,11 +72,25 @@ class Installer
* @param bool $skipInstalled Ignore the overwrite setting and skip installed extensions
* @throws Exception
*/
- public function installFromId($id, $skipInstalled = false) {
+ public function installFromId($id, $skipInstalled = false)
+ {
$extension = Extension::createFromId($id);
- if($skipInstalled && $extension->isInstalled()) return;
+ if ($skipInstalled && $extension->isInstalled()) return;
+ $this->installExtension($extension);
+ }
+
+ /**
+ * Install an extension
+ *
+ * This will simply call installFromUrl() with the URL from the extension
+ *
+ * @param Extension $extension
+ * @throws Exception
+ */
+ public function installExtension(Extension $extension)
+ {
$url = $extension->getDownloadURL();
- if(!$url) {
+ if (!$url) {
throw new Exception('error_nourl', [$extension->getId()]);
}
$this->installFromUrl($url);
@@ -142,7 +155,7 @@ class Installer
foreach ($extensions as $extension) {
// check installation status
if ($extension->isInstalled()) {
- if(!$this->overwrite) {
+ if (!$this->overwrite) {
$this->processed[$extension->getId()] = self::STATUS_SKIPPED;
continue;
}
@@ -184,7 +197,11 @@ class Installer
{
// FIXME check if dependencies are still needed
- if($extension->isProtected()) {
+ if (!$extension->isInstalled()) {
+ throw new Exception('error_notinstalled', [$extension->getId()]);
+ }
+
+ if ($extension->isProtected()) {
throw new Exception('error_uninstall_protected', [$extension->getId()]);
}
@@ -284,7 +301,7 @@ class Installer
}
/**
- * Get the list of processed extensions and the processing status
+ * Get the list of processed extensions and their status during an installation run
*
* @return array id => status
*/
diff --git a/lib/plugins/extension/Manager.php b/lib/plugins/extension/Manager.php
index b99b082b4..a4e31905a 100644
--- a/lib/plugins/extension/Manager.php
+++ b/lib/plugins/extension/Manager.php
@@ -3,7 +3,7 @@
namespace dokuwiki\plugin\extension;
/**
- * Manages info about installation/deinstallation of extensions
+ * Manages info about installation of extensions
*/
class Manager
{
@@ -54,7 +54,6 @@ class Manager
}
-
/**
* Reads the manager.dat file and fills the managerInfo array
*/
@@ -75,4 +74,19 @@ class Manager
return $data;
}
+
+ public function getLastUpdate()
+ {
+ return $this->data['updated'] ?? $this->data['installed'] ?? '';
+ }
+
+ public function getDownloadUrl()
+ {
+ return $this->data['downloadurl'] ?? '';
+ }
+
+ public function getInstallDate()
+ {
+ return $this->data['installed'] ?? '';
+ }
}
diff --git a/lib/plugins/extension/cli.php b/lib/plugins/extension/cli.php
index f2d44b553..01bc3b1c8 100644
--- a/lib/plugins/extension/cli.php
+++ b/lib/plugins/extension/cli.php
@@ -29,14 +29,11 @@ class cli_plugin_extension extends CLIPlugin
$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" .
- " ☠ - security issue\n" .
- " ⚠ - security warning\n" .
- " ▽ - update message\n"
+ " i - installed ☠ - security issue\n" .
+ " b - bundled with DokuWiki ⚠ - security warning\n" .
+ " g - installed via git ↯ - update message\n" .
+ " d - disabled ⮎ - URL changed\n" .
+ " u - update available\n"
);
// search
@@ -126,21 +123,12 @@ class cli_plugin_extension extends CLIPlugin
*/
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 && !$ext->isBundled()) {
- $ok += $this->cmdInstall([$extname]);
- }
+ $local = new Local();
+ $extensions = [];
+ foreach ($local->getExtensions() as $ext) {
+ if($ext->updateAvailable()) $extensions[] = $ext->getID();
}
-
- return $ok;
+ return $this->cmdInstall($extensions);
}
/**
@@ -152,32 +140,23 @@ class cli_plugin_extension extends CLIPlugin
*/
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;
- continue;
- }
-
- if ($set) {
- $status = $ext->enable();
- $msg = 'msg_enabled';
- } else {
- $status = $ext->disable();
- $msg = 'msg_disabled';
- }
+ $ext = Extension::createFromId($extname);
- if ($status !== true) {
- $this->error($status);
+ try {
+ if ($set) {
+ $ext->enable();
+ $msg = 'msg_enabled';
+ } else {
+ $ext->disable();
+ $msg = 'msg_disabled';
+ }
+ $this->success(sprintf($this->getLang($msg), $ext->getID()));
+ } catch (ExtensionException $e) {
+ $this->error($e->getMessage());
++$ok;
continue;
- } else {
- $this->success(sprintf($this->getLang($msg), $ext->getID()));
}
}
@@ -192,27 +171,21 @@ class cli_plugin_extension extends CLIPlugin
*/
protected function cmdUnInstall($extensions)
{
- /* @var helper_plugin_extension_extension $ext */
- $ext = $this->loadHelper('extension_extension');
+ $installer = new Installer();
$ok = 0;
foreach ($extensions as $extname) {
- $ext->setExtension($extname);
- if (!$ext->isInstalled()) {
- $this->error(sprintf('Extension %s is not installed', $ext->getID()));
- ++$ok;
- continue;
- }
+ $ext = Extension::createFromId($extname);
- $status = $ext->uninstall();
- if ($status) {
+ try {
+ $installer->uninstall($ext);
$this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID()));
- } else {
- $this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID())));
- $ok = 1;
+ } catch (ExtensionException $e) {
+ $this->debug($e->getTraceAsString());
+ $this->error($e->getMessage());
+ $ok++; // error code is number of failed uninstalls
}
}
-
return $ok;
}
@@ -224,11 +197,10 @@ class cli_plugin_extension extends CLIPlugin
*/
protected function cmdInstall($extensions)
{
-
- $installer = new Installer(true);
-
$ok = 0;
foreach ($extensions as $extname) {
+ $installer = new Installer(true);
+
try {
if (preg_match("/^https?:\/\//i", $extname)) {
$installer->installFromURL($extname, true);
@@ -240,18 +212,17 @@ class cli_plugin_extension extends CLIPlugin
$this->error($e->getMessage());
$ok++; // error code is number of failed installs
}
- }
- $processed = $installer->getProcessed();
- foreach($processed as $id => $status){
- if($status == Installer::STATUS_INSTALLED) {
- $this->success(sprintf($this->getLang('msg_install_success'), $id));
- } else if($status == Installer::STATUS_UPDATED) {
- $this->success(sprintf($this->getLang('msg_update_success'), $id));
+ $processed = $installer->getProcessed();
+ foreach($processed as $id => $status){
+ if($status == Installer::STATUS_INSTALLED) {
+ $this->success(sprintf($this->getLang('msg_install_success'), $id));
+ } else if($status == Installer::STATUS_UPDATED) {
+ $this->success(sprintf($this->getLang('msg_update_success'), $id));
+ }
}
}
-
return $ok;
}
@@ -295,6 +266,7 @@ class cli_plugin_extension extends CLIPlugin
* @param bool $details display details
* @param string $filter filter for this status
* @throws Exception
+ * @todo break into smaller methods
*/
protected function listExtensions($list, $details, $filter = '')
{
@@ -337,10 +309,11 @@ class cli_plugin_extension extends CLIPlugin
if ($ext->getSecurityIssue()) $status .= '☠';
if ($ext->getSecurityWarning()) $status .= '⚠';
- if ($ext->getUpdateMessage()) $status .= '▽';
+ if ($ext->getUpdateMessage()) $status .= '↯';
+ if ($ext->hasChangedURL()) $status .= '⮎';
echo $tr->format(
- [20, 3, 12, '*'],
+ [20, 5, 12, '*'],
[
$ext->getID(),
$status,
@@ -363,31 +336,44 @@ class cli_plugin_extension extends CLIPlugin
if (!$details) continue;
echo $tr->format(
- [5, '*'],
+ [7, '*'],
['', $ext->getDescription()],
[null, Colors::C_CYAN]
);
if ($ext->getSecurityWarning()) {
echo $tr->format(
- [5, '*'],
+ [7, '*'],
['', '⚠ ' . $ext->getSecurityWarning()],
[null, Colors::C_YELLOW]
);
}
if ($ext->getSecurityIssue()) {
echo $tr->format(
- [5, '*'],
+ [7, '*'],
['', '☠ ' . $ext->getSecurityIssue()],
[null, Colors::C_LIGHTRED]
);
}
if ($ext->getUpdateMessage()) {
echo $tr->format(
- [5, '*'],
- ['', '▽ ' . $ext->getUpdateMessage()],
+ [7, '*'],
+ ['', '↯ ' . $ext->getUpdateMessage()],
[null, Colors::C_LIGHTBLUE]
);
}
+ if ($ext->hasChangedURL()) {
+ $msg = $this->getLang('url_change');
+ $msg = str_replace('<br>',"\n", $msg);
+ $msg = str_replace('<br/>',"\n", $msg);
+ $msg = str_replace('<br />',"\n", $msg);
+ $msg = strip_tags($msg);
+
+ echo $tr->format(
+ [7, '*'],
+ ['', '⮎ ' . sprintf($msg, $ext->getDownloadURL(), $ext->getManager()->getDownloadUrl())],
+ [null, Colors::C_BLUE]
+ );
+ }
}
}
}
diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php
index 46af03d43..75e391e22 100644
--- a/lib/plugins/extension/lang/en/lang.php
+++ b/lib/plugins/extension/lang/en/lang.php
@@ -14,9 +14,6 @@ $lang['tab_search'] = 'Search and Install';
$lang['tab_install'] = 'Manual Install';
$lang['notimplemented'] = 'This feature hasn\'t been implemented yet';
-$lang['notinstalled'] = 'This extension is not installed';
-$lang['alreadyenabled'] = 'This extension has already been enabled';
-$lang['alreadydisabled'] = 'This extension has already been disabled';
$lang['pluginlistsaveerror'] = 'There was an error saving the plugin list';
$lang['unknownauthor'] = 'Unknown author';
$lang['unknownversion'] = 'Unknown version';
@@ -98,6 +95,10 @@ $lang['error_archive_extract'] = 'Could not extract archive %s: %s';
$lang['error_uninstall_protected'] = 'Extension %s is protected and cannot be uninstalled';
$lang['error_disable_protected'] = 'Extension %s is protected and cannot be disabled';
$lang['error_nourl'] = 'No download URL could be found for extension %s';
+$lang['error_notinstalled'] = 'Extension %s is not installed';
+$lang['error_alreadyenabled'] = 'Extension %s has already been enabled';
+$lang['error_alreadydisabled'] = 'Extension %s has already been disabled';
+
$lang['noperms'] = 'Extension directory is not writable';
$lang['notplperms'] = 'Template directory is not writable';