Implement register subscribed events from addons

This commit is contained in:
Art4 2025-01-03 14:04:15 +00:00
parent a85343dbed
commit 57ddf69d1c
6 changed files with 77 additions and 7 deletions

View file

@ -39,6 +39,7 @@ use Friendica\Network\HTTPException;
use Friendica\Protocol\ATProtocol\DID; use Friendica\Protocol\ATProtocol\DID;
use Friendica\Security\ExAuth; use Friendica\Security\ExAuth;
use Friendica\Security\OpenWebAuth; use Friendica\Security\OpenWebAuth;
use Friendica\Service\Addon\AddonManager;
use Friendica\Util\BasePath; use Friendica\Util\BasePath;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\HTTPInputData; use Friendica\Util\HTTPInputData;
@ -125,6 +126,8 @@ class App
*/ */
private $appHelper; private $appHelper;
private AddonManager $addonManager;
private function __construct(Dice $container) private function __construct(Dice $container)
{ {
$this->container = $container; $this->container = $container;
@ -270,18 +273,22 @@ class App
$processRepository->delete($process); $processRepository->delete($process);
} }
private function setupContainerForAddons(): void private function setupAddonManager(): void
{ {
$config = $this->container->create(IManageConfigValues::class); $config = $this->container->create(IManageConfigValues::class);
/** @var \Friendica\Service\Addon\AddonManager $addonManager */ $this->addonManager = $this->container->create(\Friendica\Service\Addon\AddonManager::class);
$addonManager = $this->container->create(\Friendica\Service\Addon\AddonManager::class);
$addonManager->bootstrapAddons($config->get('addons') ?? []); $this->addonManager->bootstrapAddons($config->get('addons') ?? []);
}
private function setupContainerForAddons(): void
{
$this->setupAddonManager();
// At this place we should be careful because addons can change the container // At this place we should be careful because addons can change the container
// Maybe we should create a new container especially for the addons // Maybe we should create a new container especially for the addons
$this->container = $this->container->addRules($addonManager->getProvidedDependencyRules()); $this->container = $this->container->addRules($this->addonManager->getProvidedDependencyRules());
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */ /** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
$addonLoader = $this->container->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class); $addonLoader = $this->container->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
@ -290,11 +297,11 @@ class App
$dependencies = []; $dependencies = [];
foreach ($addonManager->getAllRequiredDependencies() as $dependency) { foreach ($this->addonManager->getAllRequiredDependencies() as $dependency) {
$dependencies[$dependency] = $this->container->create($dependency); $dependencies[$dependency] = $this->container->create($dependency);
} }
$addonManager->initAddons($dependencies); $this->addonManager->initAddons($dependencies);
} }
private function setupContainerForLogger(string $logChannel): void private function setupContainerForLogger(string $logChannel): void
@ -312,6 +319,10 @@ class App
foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) { foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) {
$eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]); $eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]);
} }
foreach ($this->addonManager->getAllSubscribedEvents() as $listener) {
$eventDispatcher->addListener($listener[0], $listener[1]);
}
} }
private function setupLegacyServiceLocator(): void private function setupLegacyServiceLocator(): void

View file

@ -16,6 +16,8 @@ interface Addon
{ {
public function getRequiredDependencies(): array; public function getRequiredDependencies(): array;
public function getSubscribedEvents(): array;
public function getProvidedDependencyRules(): array; public function getProvidedDependencyRules(): array;
public function initAddon(array $dependencies): void; public function initAddon(array $dependencies): void;

View file

@ -65,6 +65,17 @@ final class AddonManager
return $dependencyRules; return $dependencyRules;
} }
public function getAllSubscribedEvents(): array
{
$events = [];
foreach ($this->addons as $addon) {
$events = array_merge($events, $addon->getSubscribedEvents());
}
return $events;
}
private function bootstrapAddon(string $addonName): void private function bootstrapAddon(string $addonName): void
{ {
$bootstrapFile = sprintf('%s/%s/bootstrap.php', $this->addonPath, $addonName); $bootstrapFile = sprintf('%s/%s/bootstrap.php', $this->addonPath, $addonName);

View file

@ -32,6 +32,17 @@ final class AddonProxy implements Addon
return $this->bootstrap->getRequiredDependencies(); return $this->bootstrap->getRequiredDependencies();
} }
public function getSubscribedEvents(): array
{
$events = [];
foreach ($this->bootstrap->getSubscribedEvents() as $eventName => $methodName) {
$events[] = [$eventName, [$this->bootstrap, $methodName]];
}
return $events;
}
public function getProvidedDependencyRules(): array public function getProvidedDependencyRules(): array
{ {
if ($this->bootstrap instanceof DependencyProvider) { if ($this->bootstrap instanceof DependencyProvider) {

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace Friendica\Test\Unit\Service\Addon; namespace Friendica\Test\Unit\Service\Addon;
use Friendica\Event\HtmlFilterEvent;
use Friendica\Service\Addon\AddonManager; use Friendica\Service\Addon\AddonManager;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -27,4 +28,22 @@ class AddonManagerTest extends TestCase
$manager->bootstrapAddons(['helloaddon' => []]); $manager->bootstrapAddons(['helloaddon' => []]);
} }
public function testGetAllSubscribedEventsReturnsEvents(): void
{
$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->once())->method('info')->with('Addon "helloaddon" loaded.');
$manager = new AddonManager(
dirname(__DIR__, 3) . '/Util',
$logger
);
$manager->bootstrapAddons(['helloaddon' => []]);
$this->assertSame(
[[HtmlFilterEvent::PAGE_END, ['', 'onPageEnd']]],
$manager->getAllSubscribedEvents()
);
}
} }

View file

@ -55,6 +55,22 @@ class AddonProxyTest extends TestCase
$addon->getProvidedDependencyRules(); $addon->getProvidedDependencyRules();
} }
public function testGetSubscribedEventsCallsBootstrap(): void
{
$bootstrap = $this->createMock(AddonBootstrap::class);
$bootstrap->expects($this->once())->method('getSubscribedEvents')->willReturn(['foo' => 'bar']);
$addon = new AddonProxy($bootstrap);
$this->assertSame(
[
['foo', [$bootstrap, 'bar']],
],
$addon->getSubscribedEvents()
);
}
public function testInitAddonCallsBootstrap(): void public function testInitAddonCallsBootstrap(): void
{ {
$bootstrap = $this->createMock(AddonBootstrap::class); $bootstrap = $this->createMock(AddonBootstrap::class);