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

index d8873869b9691d2424c8377bfeb23f27b018bf91..6bf12285ac09a76fed22875d016af4970a37760b 100644 (file)
@@ -11,6 +11,8 @@ namespace Friendica\Core\Addon;
 
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Util\Profiler;
+use Friendica\Util\Strings;
+use Psr\Log\LoggerInterface;
 
 /**
  * helper functions to handle addons
@@ -23,6 +25,8 @@ final class AddonManagerHelper implements AddonHelper
 
        private IManageConfigValues $config;
 
+       private LoggerInterface $logger;
+
        private Profiler $profiler;
 
        /** @var string[] */
@@ -34,10 +38,12 @@ final class AddonManagerHelper implements AddonHelper
        public function __construct(
                string $addonPath,
                IManageConfigValues $config,
+               LoggerInterface $logger,
                Profiler $profiler
        ) {
                $this->addonPath = $addonPath;
                $this->config    = $config;
+               $this->logger    = $logger;
                $this->profiler  = $profiler;
 
                $this->proxy = new AddonProxy($addonPath);
@@ -108,7 +114,36 @@ final class AddonManagerHelper implements AddonHelper
         */
        public function installAddon(string $addonId): bool
        {
-               return $this->proxy->installAddon($addonId);
+               $addonId = Strings::sanitizeFilePathItem($addonId);
+
+               $addon_file_path = $this->getAddonPath() . '/' . $addonId . '/' . $addonId . '.php';
+
+               // silently fail if addon was removed or if $addonId is funky
+               if (!file_exists($addon_file_path)) {
+                       return false;
+               }
+
+               $this->logger->debug("Addon {addon}: {action}", ['action' => 'install', 'addon' => $addonId]);
+
+               $timestamp = @filemtime($addon_file_path);
+
+               @include_once($addon_file_path);
+
+               if (function_exists($addonId . '_install')) {
+                       $func = $addonId . '_install';
+                       $func();
+               }
+
+               $this->config->set('addons', $addonId, [
+                       'last_update' => $timestamp,
+                       'admin'       => function_exists($addonId . '_addon_admin'),
+               ]);
+
+               if (!$this->isAddonEnabled($addonId)) {
+                       $this->addons[] = $addonId;
+               }
+
+               return true;
        }
 
        /**
index 1ad73524ad071deb9eb8fbc781648631a5677a91..f7b4960fda5ce117766fee200916c76eba0f377d 100644 (file)
@@ -9,11 +9,14 @@ declare(strict_types=1);
 
 namespace Friendica\Test\Unit\Core\Addon;
 
+use Exception;
 use Friendica\Core\Addon\AddonInfo;
 use Friendica\Core\Addon\AddonManagerHelper;
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Util\Profiler;
+use org\bovigo\vfs\vfsStream;
 use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
 
 class AddonManagerHelperTest extends TestCase
 {
@@ -22,6 +25,7 @@ class AddonManagerHelperTest extends TestCase
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
 
@@ -45,6 +49,7 @@ class AddonManagerHelperTest extends TestCase
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
                        $config,
+                       $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
 
@@ -70,6 +75,7 @@ class AddonManagerHelperTest extends TestCase
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
                        $config,
+                       $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
 
@@ -93,6 +99,7 @@ class AddonManagerHelperTest extends TestCase
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
                        $config,
+                       $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
 
@@ -104,9 +111,111 @@ class AddonManagerHelperTest extends TestCase
                $addonManagerHelper = new AddonManagerHelper(
                        __DIR__ . '/../../../Util/addons',
                        $this->createStub(IManageConfigValues::class),
+                       $this->createStub(LoggerInterface::class),
                        $this->createStub(Profiler::class)
                );
 
                $this->assertSame(['helloaddon'], $addonManagerHelper->getAvailableAddons());
        }
+
+       public function testInstallAddonIncludesAddonFile(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php throw new \Exception("Addon file loaded");',
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->expectException(Exception::class);
+               $this->expectExceptionMessage('Addon file loaded');
+
+               $addonManagerHelper->installAddon('helloaddon');
+       }
+
+       public function testInstallAddonCallsInstallFunction(): 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}_install()
+                                                                       {
+                                                                               throw new \Exception("Addon installed");
+                                                                       }
+                                                                       PHP,
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->expectException(Exception::class);
+               $this->expectExceptionMessage('Addon installed');
+
+               $addonManagerHelper->installAddon($addonName);
+       }
+
+       public function testInstallAddonUpdatesConfig(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php',
+                       ]
+               ]);
+
+               $root->getChild('helloaddon/helloaddon.php')->lastModified(1234567890);
+
+               $config = $this->createMock(IManageConfigValues::class);
+               $config->expects($this->once())->method('set')->with(
+                       'addons',
+                       'helloaddon',
+                       ['last_update' => 1234567890, 'admin' => false]
+               );
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $config,
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $addonManagerHelper->installAddon('helloaddon');
+       }
+
+       public function testInstallAddonEnablesAddon(): void
+       {
+               $root = vfsStream::setup(__FUNCTION__ . '_addons', 0777, [
+                       'helloaddon' => [
+                               'helloaddon.php' => '<?php',
+                       ]
+               ]);
+
+               $addonManagerHelper = new AddonManagerHelper(
+                       $root->url(),
+                       $this->createStub(IManageConfigValues::class),
+                       $this->createStub(LoggerInterface::class),
+                       $this->createStub(Profiler::class)
+               );
+
+               $this->assertSame([], $addonManagerHelper->getEnabledAddons());
+
+               $this->assertTrue($addonManagerHelper->installAddon('helloaddon'));
+
+               $this->assertSame(['helloaddon'], $addonManagerHelper->getEnabledAddons());
+       }
 }