"pragmarx/recovery": "^0.2",
"psr/clock": "^1.0",
"psr/container": "^2.0",
+ "psr/event-dispatcher": "^1.0",
"psr/log": "^1.1",
"seld/cli-prompt": "^1.0",
"smarty/smarty": "^4",
+ "symfony/event-dispatcher": "^5.4",
"textalk/websocket": "^1.6",
"ua-parser/uap-php": "^3.9",
"xemlock/htmlpurifier-html5": "^0.1.11"
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "64436f375561718bb857e3e1b0e503c9",
+ "content-hash": "8ee8f9186d271b65b83c2ddbd12c5c03",
"packages": [
{
"name": "asika/simple-console",
],
"time": "2021-11-05T16:47:00+00:00"
},
+ {
+ "name": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
{
"name": "psr/http-client",
"version": "1.0.3",
],
"time": "2022-01-02T09:53:40+00:00"
},
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v5.4.45",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9",
+ "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/event-dispatcher-contracts": "^2|^3",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<4.4"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^4.4|^5.0|^6.0",
+ "symfony/dependency-injection": "^4.4|^5.0|^6.0",
+ "symfony/error-handler": "^4.4|^5.0|^6.0",
+ "symfony/expression-language": "^4.4|^5.0|^6.0",
+ "symfony/http-foundation": "^4.4|^5.0|^6.0",
+ "symfony/service-contracts": "^1.1|^2|^3",
+ "symfony/stopwatch": "^4.4|^5.0|^6.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.45"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-25T14:11:13+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f",
+ "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "psr/event-dispatcher": "^1"
+ },
+ "suggest": {
+ "symfony/event-dispatcher-implementation": ""
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-25T14:11:13+00:00"
+ },
{
"name": "symfony/polyfill-php56",
"version": "v1.20.0",
],
"time": "2020-10-23T14:02:19+00:00"
},
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
{
"name": "textalk/websocket",
"version": "1.6.3",
use Friendica\Core\Logger\LoggerManager;
use Friendica\Core\Renderer;
use Friendica\Core\Session\Capability\IHandleUserSessions;
-use Friendica\Database\Definition\DbaDefinition;
-use Friendica\Database\Definition\ViewDefinition;
-use Friendica\Module\Maintenance;
-use Friendica\Security\Authentication;
use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\DiceContainer;
use Friendica\Core\L10n;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\System;
use Friendica\Core\Update;
+use Friendica\Database\Definition\DbaDefinition;
+use Friendica\Database\Definition\ViewDefinition;
+use Friendica\Event\Event;
+use Friendica\EventSubscriber\HookEventBridge;
+use Friendica\Module\Maintenance;
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
use Friendica\Network\HTTPException;
use Friendica\Protocol\ATProtocol\DID;
+use Friendica\Security\Authentication;
use Friendica\Security\ExAuth;
use Friendica\Security\OpenWebAuth;
use Friendica\Util\BasePath;
use Friendica\Util\HTTPInputData;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Profiler;
+use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
$this->registerErrorHandler();
+ $this->registerEventDispatcher();
+
$this->requestId = $this->container->create(Request::class)->getRequestId();
$this->auth = $this->container->create(Authentication::class);
$this->config = $this->container->create(IManageConfigValues::class);
$this->registerTemplateEngine();
$this->runFrontend(
+ $this->container->create(EventDispatcherInterface::class),
$this->container->create(IManagePersonalConfigValues::class),
$this->container->create(Page::class),
$this->container->create(Nav::class),
$this->registerErrorHandler();
+ $this->registerEventDispatcher();
+
$this->load(
$serverParams,
$this->container->create(DbaDefinition::class),
$this->registerErrorHandler();
+ $this->registerEventDispatcher();
+
$this->load(
$serverParams,
$this->container->create(DbaDefinition::class),
ErrorHandler::register($this->container->create(LoggerInterface::class));
}
+ private function registerEventDispatcher(): void
+ {
+ /** @var \Friendica\Event\EventDispatcher */
+ $eventDispatcher = $this->container->create(EventDispatcherInterface::class);
+
+ foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) {
+ $eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]);
+ }
+ }
+
private function registerTemplateEngine(): void
{
Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine');
* @throws \ImagickException
*/
private function runFrontend(
+ EventDispatcherInterface $eventDispatcher,
IManagePersonalConfigValues $pconfig,
Page $page,
Nav $nav,
$serverVars['REQUEST_METHOD'] === 'GET') {
System::externalRedirect($this->baseURL . '/' . $this->args->getQueryString());
}
- Core\Hook::callAll('init_1');
+
+ $eventDispatcher->dispatch(new Event(Event::INIT));
}
DID::routeRequest($this->args->getCommand(), $serverVars);
use Friendica\AppHelper;
use Friendica\Content\Nav;
use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Theme;
use Friendica\DI;
+use Friendica\Event\HtmlFilterEvent;
use Friendica\Network\HTTPException;
use Friendica\Util\Images;
use Friendica\Util\Network;
use Friendica\Util\Profiler;
use Friendica\Util\Strings;
use GuzzleHttp\Psr7\Utils;
+use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
/**
*/
private $basePath;
+ private EventDispatcherInterface $eventDispatcher;
+
private $timestamp = 0;
private $method = '';
private $module = '';
/**
* @param string $basepath The Page basepath
*/
- public function __construct(string $basepath)
+ public function __construct(string $basepath, EventDispatcherInterface $eventDispatcher)
{
- $this->timestamp = microtime(true);
- $this->basePath = $basepath;
+ $this->timestamp = microtime(true);
+ $this->basePath = $basepath;
+ $this->eventDispatcher = $eventDispatcher;
}
public function setLogging(string $method, string $module, string $command)
$touch_icon = 'images/friendica-192.png';
}
- Hook::callAll('head', $this->page['htmlhead']);
+ $this->page['htmlhead'] = $this->eventDispatcher->dispatch(new HtmlFilterEvent(
+ HtmlFilterEvent::HEAD,
+ $this->page['htmlhead']
+ ))->getHtml();
$tpl = Renderer::getMarkupTemplate('head.tpl');
/* put the head template at the beginning of page['htmlhead']
]);
}
- Hook::callAll('footer', $this->page['footer']);
+ $this->page['footer'] = $this->eventDispatcher->dispatch(new HtmlFilterEvent(
+ HtmlFilterEvent::FOOTER,
+ $this->page['footer']
+ ))->getHtml();
$tpl = Renderer::getMarkupTemplate('footer.tpl');
$this->page['footer'] = Renderer::replaceMacros($tpl, [
{
// initialise content region
if ($mode->isNormal()) {
- Hook::callAll('page_content_top', $this->page['content']);
+ $this->page['content'] = $this->eventDispatcher->dispatch(new HtmlFilterEvent(
+ HtmlFilterEvent::PAGE_CONTENT_TOP,
+ $this->page['content']
+ ))->getHtml();
}
$this->page['content'] .= (string)$response->getBody();
$profiler->set(microtime(true) - $timestamp, 'aftermath');
if (!$mode->isAjax()) {
- Hook::callAll('page_end', $this->page['content']);
+ $this->page['content'] = $this->eventDispatcher->dispatch(new HtmlFilterEvent(
+ HtmlFilterEvent::PAGE_END,
+ $this->page['content']
+ ))->getHtml();
}
// Add the navigation (menu) template
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Event;
+
+/**
+ * One-way Event to inform listener about something happend.
+ */
+final class Event implements NamedEvent
+{
+ /**
+ * Friendica is initialized.
+ */
+ public const INIT = 'friendica.init';
+
+ private string $name;
+
+ public function __construct(string $name)
+ {
+ $this->name = $name;
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Event;
+
+use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyEventDispatcher;
+
+/**
+ * Modified Event Dispatcher.
+ */
+final class EventDispatcher extends SymfonyEventDispatcher
+{
+ /**
+ * Add support for named events.
+ *
+ * @template T of object
+ * @param T $event
+ *
+ * @return T The passed $event MUST be returned
+ */
+ public function dispatch(object $event, ?string $eventName = null): object
+ {
+ if ($eventName === null && $event instanceof NamedEvent) {
+ $eventName = $event->getName();
+ }
+
+ return parent::dispatch($event, $eventName);
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Event;
+
+/**
+ * Allow Event listener to modify HTML.
+ */
+final class HtmlFilterEvent implements NamedEvent
+{
+ public const HEAD = 'friendica.html.head';
+
+ public const FOOTER = 'friendica.html.footer';
+
+ public const PAGE_CONTENT_TOP = 'friendica.html.page_content_top';
+
+ public const PAGE_END = 'friendica.html.page_end';
+
+ private string $name;
+
+ private string $html;
+
+ public function __construct(string $name, string $html)
+ {
+ $this->name = $name;
+ $this->html = $html;
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ public function getHtml(): string
+ {
+ return $this->html;
+ }
+
+ public function setHtml(string $html): void
+ {
+ $this->html = $html;
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Event;
+
+/**
+ * Interface for named events.
+ */
+interface NamedEvent
+{
+ public function getName(): string;
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\EventSubscriber;
+
+use Friendica\Core\Hook;
+use Friendica\Event\Event;
+use Friendica\Event\HtmlFilterEvent;
+use Friendica\Event\NamedEvent;
+
+/**
+ * Bridge between the EventDispatcher and the Hook class.
+ */
+final class HookEventBridge implements StaticEventSubscriber
+{
+ /**
+ * This allows us to mock the Hook call in tests.
+ *
+ * @var \Closure|null
+ */
+ private static $mockedCallHook = null;
+
+ /**
+ * This maps the new event names to the legacy Hook names.
+ */
+ private static array $eventMapper = [
+ Event::INIT => 'init_1',
+ HtmlFilterEvent::HEAD => 'head',
+ HtmlFilterEvent::FOOTER => 'footer',
+ HtmlFilterEvent::PAGE_CONTENT_TOP => 'page_content_top',
+ HtmlFilterEvent::PAGE_END => 'page_end',
+ ];
+
+ /**
+ * @return array<string, string>
+ */
+ public static function getStaticSubscribedEvents(): array
+ {
+ return [
+ Event::INIT => 'onNamedEvent',
+ HtmlFilterEvent::HEAD => 'onHtmlFilterEvent',
+ HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent',
+ HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent',
+ HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent',
+ ];
+ }
+
+ public static function onNamedEvent(NamedEvent $event): void
+ {
+ $name = $event->getName();
+
+ $name = static::$eventMapper[$name] ?? $name;
+
+ static::callHook($name, '');
+ }
+
+ public static function onHtmlFilterEvent(HtmlFilterEvent $event): void
+ {
+ $name = $event->getName();
+
+ $name = static::$eventMapper[$name] ?? $name;
+
+ $event->setHtml(
+ static::callHook($name, $event->getHtml())
+ );
+ }
+
+ /**
+ * @param string|array $data
+ *
+ * @return string|array
+ */
+ private static function callHook(string $name, $data)
+ {
+ // Little hack to allow mocking the Hook call in tests.
+ if (static::$mockedCallHook instanceof \Closure) {
+ return (static::$mockedCallHook)->__invoke($name, $data);
+ }
+
+ Hook::callAll($name, $data);
+
+ return $data;
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\EventSubscriber;
+
+/**
+ * Define events that should be reacted to.
+ */
+interface StaticEventSubscriber
+{
+ /**
+ * Return an array of events to subscribe to.
+ * The key must the event class name.
+ * The value must the method of the implementing class to call.
+ * The method will be called statically with the event class as first parameter.
+ *
+ * Example:
+ *
+ * ```php
+ * return [Event::class => 'onEvent'];
+ * ```
+ *
+ * @return array<class-string, string>
+ */
+ public static function getStaticSubscribedEvents(): array;
+}
['create', [], Dice::CHAIN_CALL],
],
],
+ \Psr\EventDispatcher\EventDispatcherInterface::class => [
+ 'instanceOf' => \Friendica\Event\EventDispatcher::class,
+ ],
\Friendica\Core\Logger\Capability\IHaveCallIntrospections::class => [
'instanceOf' => \Friendica\Core\Logger\Util\Introspection::class,
'constructParams' => [
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Test\Unit\Event;
+
+use Friendica\Event\Event;
+use Friendica\Event\EventDispatcher;
+use Friendica\Event\NamedEvent;
+use PHPUnit\Framework\TestCase;
+use Psr\EventDispatcher\EventDispatcherInterface;
+
+class EventDispatcherTest extends TestCase
+{
+ public function testImplementationOfInstances(): void
+ {
+ $eventDispatcher = new EventDispatcher();
+
+ $this->assertInstanceOf(EventDispatcherInterface::class, $eventDispatcher);
+ }
+
+ public function testDispatchANamedEventUsesNameAsEventName(): void
+ {
+ $eventDispatcher = new EventDispatcher();
+
+ $eventDispatcher->addListener('test', function (NamedEvent $event) {
+ $this->assertSame('test', $event->getName());
+ });
+
+ $eventDispatcher->dispatch(new Event('test'));
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Test\Unit\Event;
+
+use Friendica\Event\Event;
+use Friendica\Event\NamedEvent;
+use PHPUnit\Framework\TestCase;
+
+class EventTest extends TestCase
+{
+ public function testImplementationOfInstances(): void
+ {
+ $event = new Event('test');
+
+ $this->assertInstanceOf(NamedEvent::class, $event);
+ }
+
+ public static function getPublicConstants(): array
+ {
+ return [
+ [Event::INIT, 'friendica.init'],
+ ];
+ }
+
+ /**
+ * @dataProvider getPublicConstants
+ */
+ public function testPublicConstantsAreAvailable($value, $expected): void
+ {
+ $this->assertSame($expected, $value);
+ }
+
+ public function testGetNameReturnsName(): void
+ {
+ $event = new Event('test');
+
+ $this->assertSame('test', $event->getName());
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Test\Unit\Event;
+
+use Friendica\Event\HtmlFilterEvent;
+use Friendica\Event\NamedEvent;
+use PHPUnit\Framework\TestCase;
+
+class HtmlFilterEventTest extends TestCase
+{
+ public function testImplementationOfInstances(): void
+ {
+ $event = new HtmlFilterEvent('test', 'original');
+
+ $this->assertInstanceOf(NamedEvent::class, $event);
+ }
+
+ public static function getPublicConstants(): array
+ {
+ return [
+ [HtmlFilterEvent::HEAD, 'friendica.html.head'],
+ [HtmlFilterEvent::FOOTER, 'friendica.html.footer'],
+ [HtmlFilterEvent::PAGE_CONTENT_TOP, 'friendica.html.page_content_top'],
+ [HtmlFilterEvent::PAGE_END, 'friendica.html.page_end'],
+ ];
+ }
+
+ /**
+ * @dataProvider getPublicConstants
+ */
+ public function testPublicConstantsAreAvailable($value, $expected): void
+ {
+ $this->assertSame($expected, $value);
+ }
+
+ public function testGetNameReturnsName(): void
+ {
+ $event = new HtmlFilterEvent('test', '');
+
+ $this->assertSame('test', $event->getName());
+ }
+
+ public function testGetHtmlReturnsCorrectString(): void
+ {
+ $data = 'original';
+
+ $event = new HtmlFilterEvent('test', $data);
+
+ $this->assertSame($data, $event->getHtml());
+ }
+
+ public function testSetHtmlUpdatesHtml(): void
+ {
+ $event = new HtmlFilterEvent('test', 'original');
+
+ $expected = 'updated';
+
+ $event->setHtml($expected);
+
+ $this->assertSame($expected, $event->getHtml());
+ }
+}
--- /dev/null
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+declare(strict_types=1);
+
+namespace Friendica\Test\Unit\EventSubscriber;
+
+use Friendica\Event\Event;
+use Friendica\Event\HtmlFilterEvent;
+use Friendica\EventSubscriber\HookEventBridge;
+use Friendica\EventSubscriber\StaticEventSubscriber;
+use PHPUnit\Framework\TestCase;
+
+class HookEventBridgeTest extends TestCase
+{
+ public function testCorrectImplementation(): void
+ {
+ $this->assertTrue(
+ is_subclass_of(HookEventBridge::class, StaticEventSubscriber::class, true),
+ HookEventBridge::class . ' does not implement ' . StaticEventSubscriber::class
+ );
+ }
+
+ public function testGetStaticSubscribedEventsReturnsStaticMethods(): void
+ {
+ $expected = [
+ Event::INIT => 'onNamedEvent',
+ HtmlFilterEvent::HEAD => 'onHtmlFilterEvent',
+ HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent',
+ HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent',
+ HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent',
+ ];
+
+ $this->assertSame(
+ $expected,
+ HookEventBridge::getStaticSubscribedEvents()
+ );
+
+ foreach ($expected as $methodName) {
+ $this->assertTrue(
+ method_exists(HookEventBridge::class, $methodName),
+ $methodName . '() is not defined'
+ );
+
+ $this->assertTrue(
+ (new \ReflectionMethod(HookEventBridge::class, $methodName))->isStatic(),
+ $methodName . '() is not static'
+ );
+ }
+ }
+
+ public static function getNamedEventData(): array
+ {
+ return [
+ ['test', 'test'],
+ [Event::INIT, 'init_1'],
+ ];
+ }
+
+ /**
+ * @dataProvider getNamedEventData
+ */
+ public function testOnNamedEventCallsHook($name, $expected): void
+ {
+ $event = new Event($name);
+
+ $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
+ $reflectionProperty->setAccessible(true);
+
+ $reflectionProperty->setValue(null, function (string $name, $data) use ($expected) {
+ $this->assertSame($expected, $name);
+ $this->assertSame('', $data);
+
+ return $data;
+ });
+
+ HookEventBridge::onNamedEvent($event);
+ }
+
+ public static function getHtmlFilterEventData(): array
+ {
+ return [
+ ['test', 'test'],
+ [HtmlFilterEvent::HEAD, 'head'],
+ [HtmlFilterEvent::FOOTER, 'footer'],
+ [HtmlFilterEvent::PAGE_CONTENT_TOP, 'page_content_top'],
+ [HtmlFilterEvent::PAGE_END, 'page_end'],
+ ];
+ }
+
+ /**
+ * @dataProvider getHtmlFilterEventData
+ */
+ public function testOnHtmlFilterEventCallsHookWithCorrectValue($name, $expected): void
+ {
+ $event = new HtmlFilterEvent($name, 'original');
+
+ $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
+ $reflectionProperty->setAccessible(true);
+
+ $reflectionProperty->setValue(null, function (string $name, $data) use ($expected) {
+ $this->assertSame($expected, $name);
+ $this->assertSame('original', $data);
+
+ return $data;
+ });
+
+ HookEventBridge::onHtmlFilterEvent($event);
+ }
+}
//
// SPDX-License-Identifier: AGPL-3.0-or-later
-declare(strict_types = 1);
+declare(strict_types=1);
namespace Friendica\Test\Unit\Util;
{
public static function getDataPaths(): array
{
- $basePath = dirname(__DIR__, 3);
+ $basePath = dirname(__DIR__, 3);
$configPath = $basePath . DIRECTORY_SEPARATOR . 'config';
return [
'fullPath' => [
- 'server' => [],
- 'baseDir' => $configPath,
+ 'server' => [],
+ 'baseDir' => $configPath,
'expected' => $configPath,
],
'relative' => [
- 'server' => [],
- 'baseDir' => 'config',
+ 'server' => [],
+ 'baseDir' => 'config',
'expected' => $configPath,
],
'document_root' => [
'server' => [
'DOCUMENT_ROOT' => $configPath,
],
- 'baseDir' => '/noooop',
+ 'baseDir' => '/noooop',
'expected' => $configPath,
],
'pwd' => [
'server' => [
'PWD' => $configPath,
],
- 'baseDir' => '/noooop',
+ 'baseDir' => '/noooop',
'expected' => $configPath,
],
'no_overwrite' => [
'server' => [
'DOCUMENT_ROOT' => $basePath,
- 'PWD' => $basePath,
+ 'PWD' => $basePath,
],
- 'baseDir' => 'config',
+ 'baseDir' => 'config',
'expected' => $configPath,
],
'no_overwrite_if_invalid' => [
'server' => [
'DOCUMENT_ROOT' => '/nopopop',
- 'PWD' => $configPath,
+ 'PWD' => $configPath,
],
- 'baseDir' => '/noatgawe22fafa',
+ 'baseDir' => '/noatgawe22fafa',
'expected' => $configPath,
]
];
//
// SPDX-License-Identifier: AGPL-3.0-or-later
-declare(strict_types = 1);
+declare(strict_types=1);
namespace Friendica\Test\Unit\Util;