]> git.mxchange.org Git - friendica.git/commitdiff
Implement uninstallAddon
authorArt4 <art4@wlabs.de>
Wed, 14 May 2025 14:54:14 +0000 (14:54 +0000)
committerArt4 <art4@wlabs.de>
Wed, 14 May 2025 14:54:14 +0000 (14:54 +0000)
src/Core/Addon/AddonManagerHelper.php
tests/Unit/Core/Addon/AddonManagerHelperTest.php

index 6bf12285ac09a76fed22875d016af4970a37760b..d8ff19af93577199713c1f5ea3c513fc5b3df561 100644 (file)
@@ -9,7 +9,9 @@ declare(strict_types=1);
 
 namespace Friendica\Core\Addon;
 
+use Friendica\Core\Cache\Capability\ICanCache;
 use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Database\Database;
 use Friendica\Util\Profiler;
 use Friendica\Util\Strings;
 use Psr\Log\LoggerInterface;
@@ -23,8 +25,12 @@ final class AddonManagerHelper implements AddonHelper
 {
        private string $addonPath;
 
+       private Database $database;
+
        private IManageConfigValues $config;
 
+       private ICanCache $cache;
+
        private LoggerInterface $logger;
 
        private Profiler $profiler;
@@ -37,12 +43,16 @@ final class AddonManagerHelper implements AddonHelper
 
        public function __construct(
                string $addonPath,
+               Database $database,
                IManageConfigValues $config,
+               ICanCache $cache,
                LoggerInterface $logger,
                Profiler $profiler
        ) {
                $this->addonPath = $addonPath;
+               $this->database  = $database;
                $this->config    = $config;
+               $this->cache     = $cache;
                $this->logger    = $logger;
                $this->profiler  = $profiler;
 
@@ -153,7 +163,31 @@ final class AddonManagerHelper implements AddonHelper
         */
        public function uninstallAddon(string $addonId): void
        {
-               $this->proxy->uninstallAddon($addonId);
+               $addonId = Strings::sanitizeFilePathItem($addonId);
+
+               $this->logger->debug("Addon {addon}: {action}", ['action' => 'uninstall', 'addon' => $addonId]);
+               $this->config->delete('addons', $addonId);
+
+               $addon_file_path = $this->getAddonPath() . '/' . $addonId . '/' . $addonId . '.php';
+
+               @include_once($addon_file_path);
+
+               if (function_exists($addonId . '_uninstall')) {
+                       $func = $addonId . '_uninstall';
+                       $func();
+               }
+
+               // Remove registered hooks for the addon
+               // Handles both relative and absolute file paths
+               $condition = ['`file` LIKE ?', "%/$addonId/$addonId.php"];
+
+               $result = $this->database->delete('hook', $condition);
+
+               if ($result) {
+                       $this->cache->delete('routerDispatchData');
+               }
+
+               unset($this->addons[array_search($addonId, $this->addons)]);
        }
 
        /**
index f7b4960fda5ce117766fee200916c76eba0f377d..951f9655ac9fe00b7cbe3e5b86cedad4ea1b72c8 100644 (file)
@@ -12,7 +12,9 @@ namespace Friendica\Test\Unit\Core\Addon;
 use Exception;
 use Friendica\Core\Addon\AddonInfo;
 use Friendica\Core\Addon\AddonManagerHelper;
+use Friendica\Core\Cache\Capability\ICanCache;
 use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Database\Database;
 use Friendica\Util\Profiler;
 use org\bovigo\vfs\vfsStream;
 use PHPUnit\Framework\TestCase;
@@ -24,7 +26,9 @@ class AddonManagerHelperTest extends TestCase
        {
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
+                       $this->createStub(Database::class),
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -48,7 +52,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
+                       $this->createStub(Database::class),
                        $config,
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -74,7 +80,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
+                       $this->createStub(Database::class),
                        $config,
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -98,7 +106,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
+                       $this->createStub(Database::class),
                        $config,
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -110,7 +120,9 @@ class AddonManagerHelperTest extends TestCase
        {
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
+                       $this->createStub(Database::class),
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -128,7 +140,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        $root->url(),
+                       $this->createStub(Database::class),
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -159,7 +173,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        $root->url(),
+                       $this->createStub(Database::class),
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -189,7 +205,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        $root->url(),
+                       $this->createStub(Database::class),
                        $config,
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -207,7 +225,9 @@ class AddonManagerHelperTest extends TestCase
 
                $addonManagerHelper = new AddonManagerHelper(
                        $root->url(),
+                       $this->createStub(Database::class),
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
                        $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
@@ -218,4 +238,121 @@ class AddonManagerHelperTest extends TestCase
 
                $this->assertSame(['helloaddon'], $addonManagerHelper->getEnabledAddons());
        }
+       public function testUninstallAddonIncludesAddonFile(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php throw new \Exception("Addon file loaded");',
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(Database::class),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->expectException(Exception::class);
+               $this->expectExceptionMessage('Addon file loaded');
+
+               $addonManagerHelper->uninstallAddon('helloaddon');
+       }
+
+       public function testUninstallAddonCallsUninstallFunction(): void
+       {
+               // We need a unique name for the addon to avoid conflicts
+               // with other tests that may define the same install function.
+               $addonName = __FUNCTION__;
+
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       $addonName => [
+                               $addonName . '.php' => <<<PHP
+                                                                       <?php
+                                                                       function {$addonName}_uninstall()
+                                                                       {
+                                                                               throw new \Exception("Addon uninstalled");
+                                                                       }
+                                                                       PHP,
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(Database::class),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->expectException(Exception::class);
+               $this->expectExceptionMessage('Addon uninstalled');
+
+               $addonManagerHelper->uninstallAddon($addonName);
+       }
+
+       public function testUninstallAddonRemovesHooksFromDatabase(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php',
+                       ]
+               ]);
+
+               $database = $this->createMock(Database::class);
+               $database->expects($this->once())
+                       ->method('delete')
+                       ->with(
+                               'hook',
+                               ['`file` LIKE ?', '%/helloaddon/helloaddon.php']
+                       );
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $database,
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(ICanCache::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $addonManagerHelper->uninstallAddon('helloaddon');
+       }
+
+       public function testUninstallAddonDisablesAddon(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php',
+                       ]
+               ]);
+
+               $config = $this->createStub(IManageConfigValues::class);
+               $config->method('get')->willReturn([
+                       'helloaddon' => [
+                               'last_update' => 1234567890,
+                               'admin' => false,
+                       ],
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(Database::class),
+                       $config,
+                       $this->createStub(ICanCache::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $addonManagerHelper->loadAddons();
+
+               $this->assertSame(['helloaddon'], $addonManagerHelper->getEnabledAddons());
+
+               $addonManagerHelper->uninstallAddon('helloaddon');
+
+               $this->assertSame([], $addonManagerHelper->getEnabledAddons());
+       }
 }