EventDispatcher proof of concept

This commit is contained in:
Art4 2025-01-24 14:36:05 +00:00 committed by Hypolite Petovan
parent 827541ed86
commit 9e6f77c4b1
17 changed files with 887 additions and 27 deletions

View file

@ -71,9 +71,11 @@
"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"

296
composer.lock generated
View file

@ -4,7 +4,7 @@
"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",
@ -3234,6 +3234,56 @@
],
"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",
@ -3709,6 +3759,170 @@
],
"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",
@ -3774,6 +3988,86 @@
],
"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",

View file

@ -23,10 +23,6 @@ use Friendica\Core\Container;
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;
@ -35,9 +31,15 @@ use Friendica\Core\Logger\Handler\ErrorHandler;
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;
@ -45,6 +47,7 @@ use Friendica\Util\DateTimeFormat;
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;
@ -153,6 +156,8 @@ class App
$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);
@ -178,6 +183,7 @@ class App
$this->registerTemplateEngine();
$this->runFrontend(
$this->container->create(EventDispatcherInterface::class),
$this->container->create(IManagePersonalConfigValues::class),
$this->container->create(Page::class),
$this->container->create(Nav::class),
@ -202,6 +208,8 @@ class App
$this->registerErrorHandler();
$this->registerEventDispatcher();
$this->load(
$serverParams,
$this->container->create(DbaDefinition::class),
@ -230,6 +238,8 @@ class App
$this->registerErrorHandler();
$this->registerEventDispatcher();
$this->load(
$serverParams,
$this->container->create(DbaDefinition::class),
@ -301,6 +311,16 @@ class App
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');
@ -385,6 +405,7 @@ class App
* @throws \ImagickException
*/
private function runFrontend(
EventDispatcherInterface $eventDispatcher,
IManagePersonalConfigValues $pconfig,
Page $page,
Nav $nav,
@ -424,7 +445,8 @@ class App
$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);

View file

@ -14,7 +14,6 @@ use Friendica\App;
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;
@ -22,12 +21,14 @@ use Friendica\Core\Session\Model\UserSession;
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;
/**
@ -70,6 +71,8 @@ class Page implements ArrayAccess
*/
private $basePath;
private EventDispatcherInterface $eventDispatcher;
private $timestamp = 0;
private $method = '';
private $module = '';
@ -78,10 +81,11 @@ class Page implements ArrayAccess
/**
* @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->eventDispatcher = $eventDispatcher;
}
public function setLogging(string $method, string $module, string $command)
@ -229,7 +233,10 @@ class Page implements ArrayAccess
$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']
@ -351,7 +358,10 @@ class Page implements ArrayAccess
]);
}
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, [
@ -376,7 +386,10 @@ class Page implements ArrayAccess
{
// 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();
@ -474,7 +487,10 @@ class Page implements ArrayAccess
$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

33
src/Event/Event.php Normal file
View file

@ -0,0 +1,33 @@
<?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;
}
}

View file

@ -0,0 +1,35 @@
<?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);
}
}

View file

@ -0,0 +1,49 @@
<?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;
}
}

18
src/Event/NamedEvent.php Normal file
View file

@ -0,0 +1,18 @@
<?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;
}

View file

@ -0,0 +1,90 @@
<?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;
}
}

View file

@ -0,0 +1,32 @@
<?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;
}

View file

@ -182,6 +182,9 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo
['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' => [

View file

@ -0,0 +1,37 @@
<?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'));
}
}

View file

@ -0,0 +1,46 @@
<?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());
}
}

View file

@ -0,0 +1,69 @@
<?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());
}
}

View file

@ -0,0 +1,114 @@
<?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);
}
}

View file

@ -5,7 +5,7 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types = 1);
declare(strict_types=1);
namespace Friendica\Test\Unit\Util;

View file

@ -5,7 +5,7 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
declare(strict_types = 1);
declare(strict_types=1);
namespace Friendica\Test\Unit\Util;