From a39850871eca4dd0fa0a41f8402e60a935101125 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 14 May 2025 11:37:47 +0000 Subject: [PATCH] Implement installAddon --- src/Core/Addon/AddonManagerHelper.php | 37 +++++- .../Core/Addon/AddonManagerHelperTest.php | 109 ++++++++++++++++++ 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/src/Core/Addon/AddonManagerHelper.php b/src/Core/Addon/AddonManagerHelper.php index d8873869b9..6bf12285ac 100644 --- a/src/Core/Addon/AddonManagerHelper.php +++ b/src/Core/Addon/AddonManagerHelper.php @@ -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; } /** diff --git a/tests/Unit/Core/Addon/AddonManagerHelperTest.php b/tests/Unit/Core/Addon/AddonManagerHelperTest.php index 1ad73524ad..f7b4960fda 100644 --- a/tests/Unit/Core/Addon/AddonManagerHelperTest.php +++ b/tests/Unit/Core/Addon/AddonManagerHelperTest.php @@ -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' => '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' => <<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' => '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' => '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()); + } }