mirror of
https://github.com/friendica/friendica
synced 2025-03-13 10:28:26 +00:00
Merge pull request #14640 from Art4/introduce-eventdispatcher
[EventDispatcher] Proof of concept
This commit is contained in:
commit
a378a85c04
23 changed files with 1229 additions and 73 deletions
|
@ -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
296
composer.lock
generated
|
@ -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",
|
||||
|
|
40
src/App.php
40
src/App.php
|
@ -20,13 +20,10 @@ use Friendica\Content\Nav;
|
|||
use Friendica\Core\Addon\Capability\ICanLoadAddons;
|
||||
use Friendica\Core\Config\Factory\Config;
|
||||
use Friendica\Core\Container;
|
||||
use Friendica\Core\Hooks\HookEventBridge;
|
||||
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 +32,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\ConfigLoadedEvent;
|
||||
use Friendica\Event\Event;
|
||||
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 +48,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 +157,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);
|
||||
|
@ -172,12 +178,14 @@ class App
|
|||
$this->mode,
|
||||
$this->config,
|
||||
$this->profiler,
|
||||
$this->container->create(EventDispatcherInterface::class),
|
||||
$this->appHelper,
|
||||
);
|
||||
|
||||
$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 +210,8 @@ class App
|
|||
|
||||
$this->registerErrorHandler();
|
||||
|
||||
$this->registerEventDispatcher();
|
||||
|
||||
$this->load(
|
||||
$serverParams,
|
||||
$this->container->create(DbaDefinition::class),
|
||||
|
@ -209,6 +219,7 @@ class App
|
|||
$this->container->create(Mode::class),
|
||||
$this->container->create(IManageConfigValues::class),
|
||||
$this->container->create(Profiler::class),
|
||||
$this->container->create(EventDispatcherInterface::class),
|
||||
$this->container->create(AppHelper::class),
|
||||
);
|
||||
|
||||
|
@ -230,6 +241,8 @@ class App
|
|||
|
||||
$this->registerErrorHandler();
|
||||
|
||||
$this->registerEventDispatcher();
|
||||
|
||||
$this->load(
|
||||
$serverParams,
|
||||
$this->container->create(DbaDefinition::class),
|
||||
|
@ -237,6 +250,7 @@ class App
|
|||
$this->container->create(Mode::class),
|
||||
$this->container->create(IManageConfigValues::class),
|
||||
$this->container->create(Profiler::class),
|
||||
$this->container->create(EventDispatcherInterface::class),
|
||||
$this->container->create(AppHelper::class),
|
||||
);
|
||||
|
||||
|
@ -301,6 +315,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');
|
||||
|
@ -316,6 +340,7 @@ class App
|
|||
Mode $mode,
|
||||
IManageConfigValues $config,
|
||||
Profiler $profiler,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
AppHelper $appHelper
|
||||
): void {
|
||||
if ($config->get('system', 'ini_max_execution_time') !== false) {
|
||||
|
@ -339,7 +364,8 @@ class App
|
|||
if ($mode->has(Mode::DBAVAILABLE)) {
|
||||
Core\Hook::loadHooks();
|
||||
$loader = (new Config())->createConfigFileManager($appHelper->getBasePath(), $serverParams);
|
||||
Core\Hook::callAll('load_config', $loader);
|
||||
|
||||
$eventDispatcher->dispatch(new ConfigLoadedEvent(ConfigLoadedEvent::CONFIG_LOADED, $loader));
|
||||
|
||||
// Hooks are now working, reload the whole definitions with hook enabled
|
||||
$dbaDefinition->load(true);
|
||||
|
@ -385,6 +411,7 @@ class App
|
|||
* @throws \ImagickException
|
||||
*/
|
||||
private function runFrontend(
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
IManagePersonalConfigValues $pconfig,
|
||||
Page $page,
|
||||
Nav $nav,
|
||||
|
@ -424,7 +451,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);
|
||||
|
|
|
@ -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->timestamp = microtime(true);
|
||||
$this->basePath = $basepath;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
public function setLogging(string $method, string $module, string $command)
|
||||
|
@ -229,7 +233,9 @@ 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 +357,9 @@ 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 +384,9 @@ 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 +484,9 @@ 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
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
namespace Friendica\Content;
|
||||
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\DI;
|
||||
use Friendica\Event\ArrayFilterEvent;
|
||||
|
||||
class Feature
|
||||
{
|
||||
|
@ -41,15 +41,23 @@ class Feature
|
|||
*/
|
||||
public static function isEnabled(int $uid, $feature): bool
|
||||
{
|
||||
if (!DI::config()->get('feature_lock', $feature, false)) {
|
||||
$enabled = DI::config()->get('feature', $feature) ?? self::getDefault($feature);
|
||||
$enabled = DI::pConfig()->get($uid, 'feature', $feature) ?? $enabled;
|
||||
$config = DI::config();
|
||||
$pConfig = DI::pConfig();
|
||||
$eventDispatcher = DI::eventDispatcher();
|
||||
|
||||
if (!$config->get('feature_lock', $feature, false)) {
|
||||
$enabled = $config->get('feature', $feature) ?? self::getDefault($feature);
|
||||
$enabled = $pConfig->get($uid, 'feature', $feature) ?? $enabled;
|
||||
} else {
|
||||
$enabled = true;
|
||||
}
|
||||
|
||||
$arr = ['uid' => $uid, 'feature' => $feature, 'enabled' => $enabled];
|
||||
Hook::callAll('isEnabled', $arr);
|
||||
|
||||
$arr = $eventDispatcher->dispatch(
|
||||
new ArrayFilterEvent(ArrayFilterEvent::FEATURE_ENABLED, $arr)
|
||||
)->getArray();
|
||||
|
||||
return (bool)$arr['enabled'];
|
||||
}
|
||||
|
||||
|
@ -86,55 +94,58 @@ class Feature
|
|||
*/
|
||||
public static function get($filtered = true)
|
||||
{
|
||||
$arr = [
|
||||
$l10n = DI::l10n();
|
||||
$config = DI::config();
|
||||
$eventDispatcher = DI::eventDispatcher();
|
||||
|
||||
$arr = [
|
||||
// General
|
||||
'general' => [
|
||||
DI::l10n()->t('General Features'),
|
||||
//array('expire', DI::l10n()->t('Content Expiration'), DI::l10n()->t('Remove old posts/comments after a period of time')),
|
||||
[self::PHOTO_LOCATION, DI::l10n()->t('Photo Location'), DI::l10n()->t("Photo metadata is normally stripped. This extracts the location \x28if present\x29 prior to stripping metadata and links it to a map."), false, DI::config()->get('feature_lock', self::PHOTO_LOCATION, false)],
|
||||
[self::COMMUNITY, DI::l10n()->t('Display the community in the navigation'), DI::l10n()->t('If enabled, the community can be accessed via the navigation menu. Independent from this setting, the community timelines can always be accessed via the channels.'), true, DI::config()->get('feature_lock', self::COMMUNITY, false)],
|
||||
$l10n->t('General Features'),
|
||||
//array('expire', $l10n->t('Content Expiration'), $l10n->t('Remove old posts/comments after a period of time')),
|
||||
[self::PHOTO_LOCATION, $l10n->t('Photo Location'), $l10n->t("Photo metadata is normally stripped. This extracts the location \x28if present\x29 prior to stripping metadata and links it to a map."), false, $config->get('feature_lock', self::PHOTO_LOCATION, false)],
|
||||
[self::COMMUNITY, $l10n->t('Display the community in the navigation'), $l10n->t('If enabled, the community can be accessed via the navigation menu. Independent from this setting, the community timelines can always be accessed via the channels.'), true, $config->get('feature_lock', self::COMMUNITY, false)],
|
||||
],
|
||||
|
||||
// Post composition
|
||||
'composition' => [
|
||||
DI::l10n()->t('Post Composition Features'),
|
||||
[self::EXPLICIT_MENTIONS, DI::l10n()->t('Explicit Mentions'), DI::l10n()->t('Add explicit mentions to comment box for manual control over who gets mentioned in replies.'), false, DI::config()->get('feature_lock', Feature::EXPLICIT_MENTIONS, false)],
|
||||
[self::ADD_ABSTRACT, DI::l10n()->t('Add an abstract from ActivityPub content warnings'), DI::l10n()->t('Add an abstract when commenting on ActivityPub posts with a content warning. Abstracts are displayed as content warning on systems like Mastodon or Pleroma.'), false, DI::config()->get('feature_lock', self::ADD_ABSTRACT, false)],
|
||||
$l10n->t('Post Composition Features'),
|
||||
[self::EXPLICIT_MENTIONS, $l10n->t('Explicit Mentions'), $l10n->t('Add explicit mentions to comment box for manual control over who gets mentioned in replies.'), false, $config->get('feature_lock', Feature::EXPLICIT_MENTIONS, false)],
|
||||
[self::ADD_ABSTRACT, $l10n->t('Add an abstract from ActivityPub content warnings'), $l10n->t('Add an abstract when commenting on ActivityPub posts with a content warning. Abstracts are displayed as content warning on systems like Mastodon or Pleroma.'), false, $config->get('feature_lock', self::ADD_ABSTRACT, false)],
|
||||
],
|
||||
|
||||
// Item tools
|
||||
'tools' => [
|
||||
DI::l10n()->t('Post/Comment Tools'),
|
||||
[self::CATEGORIES, DI::l10n()->t('Post Categories'), DI::l10n()->t('Add categories to your posts'), false, DI::config()->get('feature_lock', self::CATEGORIES, false)],
|
||||
$l10n->t('Post/Comment Tools'),
|
||||
[self::CATEGORIES, $l10n->t('Post Categories'), $l10n->t('Add categories to your posts'), false, $config->get('feature_lock', self::CATEGORIES, false)],
|
||||
],
|
||||
|
||||
// Widget visibility on the network stream
|
||||
'network' => [
|
||||
DI::l10n()->t('Network Widgets'),
|
||||
[self::CIRCLES, DI::l10n()->t('Circles'), DI::l10n()->t('Display posts that have been created by accounts of the selected circle.'), true, DI::config()->get('feature_lock', self::CIRCLES, false)],
|
||||
[self::GROUPS, DI::l10n()->t('Groups'), DI::l10n()->t('Display posts that have been distributed by the selected group.'), true, DI::config()->get('feature_lock', self::GROUPS, false)],
|
||||
[self::ARCHIVE, DI::l10n()->t('Archives'), DI::l10n()->t('Display an archive where posts can be selected by month and year.'), true, DI::config()->get('feature_lock', self::ARCHIVE, false)],
|
||||
[self::NETWORKS, DI::l10n()->t('Protocols'), DI::l10n()->t('Display posts with the selected protocols.'), true, DI::config()->get('feature_lock', self::NETWORKS, false)],
|
||||
[self::ACCOUNTS, DI::l10n()->t('Account Types'), DI::l10n()->t('Display posts done by accounts with the selected account type.'), true, DI::config()->get('feature_lock', self::ACCOUNTS, false)],
|
||||
[self::CHANNELS, DI::l10n()->t('Channels'), DI::l10n()->t('Display posts in the system channels and user defined channels.'), true, DI::config()->get('feature_lock', self::CHANNELS, false)],
|
||||
[self::SEARCHES, DI::l10n()->t('Saved Searches'), DI::l10n()->t('Display posts that contain subscribed hashtags.'), true, DI::config()->get('feature_lock', self::SEARCHES, false)],
|
||||
[self::FOLDERS, DI::l10n()->t('Saved Folders'), DI::l10n()->t('Display a list of folders in which posts are stored.'), true, DI::config()->get('feature_lock', self::FOLDERS, false)],
|
||||
[self::NOSHARER, DI::l10n()->t('Own Contacts'), DI::l10n()->t('Include or exclude posts from subscribed accounts. This widget is not visible on all channels.'), true, DI::config()->get('feature_lock', self::NOSHARER, false)],
|
||||
[self::TRENDING_TAGS, DI::l10n()->t('Trending Tags'), DI::l10n()->t('Display a list of the most popular tags in recent public posts.'), false, DI::config()->get('feature_lock', self::TRENDING_TAGS, false)],
|
||||
$l10n->t('Network Widgets'),
|
||||
[self::CIRCLES, $l10n->t('Circles'), $l10n->t('Display posts that have been created by accounts of the selected circle.'), true, $config->get('feature_lock', self::CIRCLES, false)],
|
||||
[self::GROUPS, $l10n->t('Groups'), $l10n->t('Display posts that have been distributed by the selected group.'), true, $config->get('feature_lock', self::GROUPS, false)],
|
||||
[self::ARCHIVE, $l10n->t('Archives'), $l10n->t('Display an archive where posts can be selected by month and year.'), true, $config->get('feature_lock', self::ARCHIVE, false)],
|
||||
[self::NETWORKS, $l10n->t('Protocols'), $l10n->t('Display posts with the selected protocols.'), true, $config->get('feature_lock', self::NETWORKS, false)],
|
||||
[self::ACCOUNTS, $l10n->t('Account Types'), $l10n->t('Display posts done by accounts with the selected account type.'), true, $config->get('feature_lock', self::ACCOUNTS, false)],
|
||||
[self::CHANNELS, $l10n->t('Channels'), $l10n->t('Display posts in the system channels and user defined channels.'), true, $config->get('feature_lock', self::CHANNELS, false)],
|
||||
[self::SEARCHES, $l10n->t('Saved Searches'), $l10n->t('Display posts that contain subscribed hashtags.'), true, $config->get('feature_lock', self::SEARCHES, false)],
|
||||
[self::FOLDERS, $l10n->t('Saved Folders'), $l10n->t('Display a list of folders in which posts are stored.'), true, $config->get('feature_lock', self::FOLDERS, false)],
|
||||
[self::NOSHARER, $l10n->t('Own Contacts'), $l10n->t('Include or exclude posts from subscribed accounts. This widget is not visible on all channels.'), true, $config->get('feature_lock', self::NOSHARER, false)],
|
||||
[self::TRENDING_TAGS, $l10n->t('Trending Tags'), $l10n->t('Display a list of the most popular tags in recent public posts.'), false, $config->get('feature_lock', self::TRENDING_TAGS, false)],
|
||||
],
|
||||
|
||||
// Advanced Profile Settings
|
||||
'advanced_profile' => [
|
||||
DI::l10n()->t('Advanced Profile Settings'),
|
||||
[self::TAGCLOUD, DI::l10n()->t('Tag Cloud'), DI::l10n()->t('Provide a personal tag cloud on your profile page'), false, DI::config()->get('feature_lock', self::TAGCLOUD, false)],
|
||||
[self::MEMBER_SINCE, DI::l10n()->t('Display Membership Date'), DI::l10n()->t('Display membership date in profile'), false, DI::config()->get('feature_lock', self::MEMBER_SINCE, false)],
|
||||
$l10n->t('Advanced Profile Settings'),
|
||||
[self::TAGCLOUD, $l10n->t('Tag Cloud'), $l10n->t('Provide a personal tag cloud on your profile page'), false, $config->get('feature_lock', self::TAGCLOUD, false)],
|
||||
[self::MEMBER_SINCE, $l10n->t('Display Membership Date'), $l10n->t('Display membership date in profile'), false, $config->get('feature_lock', self::MEMBER_SINCE, false)],
|
||||
],
|
||||
|
||||
//Advanced Calendar Settings
|
||||
'advanced_calendar' => [
|
||||
DI::l10n()->t('Advanced Calendar Settings'),
|
||||
[self::PUBLIC_CALENDAR, DI::l10n()->t('Allow anonymous access to your calendar'), DI::l10n()->t('Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you.'), false, DI::config()->get('feature_lock', self::PUBLIC_CALENDAR, false)],
|
||||
$l10n->t('Advanced Calendar Settings'),
|
||||
[self::PUBLIC_CALENDAR, $l10n->t('Allow anonymous access to your calendar'), $l10n->t('Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you.'), false, $config->get('feature_lock', self::PUBLIC_CALENDAR, false)],
|
||||
]
|
||||
];
|
||||
|
||||
|
@ -144,7 +155,7 @@ class Feature
|
|||
foreach ($arr as $k => $x) {
|
||||
$has_items = false;
|
||||
$kquantity = count($arr[$k]);
|
||||
for ($y = 0; $y < $kquantity; $y ++) {
|
||||
for ($y = 0; $y < $kquantity; $y++) {
|
||||
if (is_array($arr[$k][$y])) {
|
||||
if ($arr[$k][$y][4] === false) {
|
||||
$has_items = true;
|
||||
|
@ -159,7 +170,10 @@ class Feature
|
|||
}
|
||||
}
|
||||
|
||||
Hook::callAll('get', $arr);
|
||||
$arr = $eventDispatcher->dispatch(
|
||||
new ArrayFilterEvent(ArrayFilterEvent::FEATURE_GET, $arr)
|
||||
)->getArray();
|
||||
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,12 @@ namespace Friendica\Content;
|
|||
use Friendica\App\BaseURL;
|
||||
use Friendica\App\Router;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Database\Database;
|
||||
use Friendica\Event\ArrayFilterEvent;
|
||||
use Friendica\Event\HtmlFilterEvent;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Conversation\Community;
|
||||
|
@ -22,6 +23,7 @@ use Friendica\Module\Home;
|
|||
use Friendica\Module\Security\Login;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Security\OpenWebAuth;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class Nav
|
||||
{
|
||||
|
@ -63,14 +65,17 @@ class Nav
|
|||
/** @var Router */
|
||||
private $router;
|
||||
|
||||
public function __construct(BaseURL $baseUrl, L10n $l10n, IHandleUserSessions $session, Database $database, IManageConfigValues $config, Router $router)
|
||||
private EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
public function __construct(BaseURL $baseUrl, L10n $l10n, IHandleUserSessions $session, Database $database, IManageConfigValues $config, Router $router, EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->baseUrl = $baseUrl;
|
||||
$this->l10n = $l10n;
|
||||
$this->session = $session;
|
||||
$this->database = $database;
|
||||
$this->config = $config;
|
||||
$this->router = $router;
|
||||
$this->baseUrl = $baseUrl;
|
||||
$this->l10n = $l10n;
|
||||
$this->session = $session;
|
||||
$this->database = $database;
|
||||
$this->config = $config;
|
||||
$this->router = $router;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,7 +119,9 @@ class Nav
|
|||
'$search_hint' => $this->l10n->t('@name, !group, #tags, content')
|
||||
]);
|
||||
|
||||
Hook::callAll('page_header', $nav);
|
||||
$nav = $this->eventDispatcher->dispatch(
|
||||
new HtmlFilterEvent(HtmlFilterEvent::PAGE_HEADER, $nav)
|
||||
)->getHtml();
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
@ -151,9 +158,11 @@ class Nav
|
|||
) {
|
||||
$arr = ['app_menu' => $appMenu];
|
||||
|
||||
Hook::callAll('app_menu', $arr);
|
||||
$arr = $this->eventDispatcher->dispatch(
|
||||
new ArrayFilterEvent(ArrayFilterEvent::APP_MENU, $arr)
|
||||
)->getArray();
|
||||
|
||||
$appMenu = $arr['app_menu'];
|
||||
$appMenu = $arr['app_menu'] ?? [];
|
||||
}
|
||||
|
||||
return $appMenu;
|
||||
|
@ -337,7 +346,9 @@ class Nav
|
|||
'userinfo' => $userinfo,
|
||||
];
|
||||
|
||||
Hook::callAll('nav_info', $nav_info);
|
||||
$nav_info = $this->eventDispatcher->dispatch(
|
||||
new ArrayFilterEvent(ArrayFilterEvent::NAV_INFO, $nav_info)
|
||||
)->getArray();
|
||||
|
||||
return $nav_info;
|
||||
}
|
||||
|
|
113
src/Core/Hooks/HookEventBridge.php
Normal file
113
src/Core/Hooks/HookEventBridge.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?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\Core\Hooks;
|
||||
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Event\ArrayFilterEvent;
|
||||
use Friendica\Event\ConfigLoadedEvent;
|
||||
use Friendica\Event\Event;
|
||||
use Friendica\Event\HtmlFilterEvent;
|
||||
use Friendica\Event\NamedEvent;
|
||||
|
||||
/**
|
||||
* Bridge between the EventDispatcher and the Hook class.
|
||||
*
|
||||
* @internal Provides BC
|
||||
*/
|
||||
final class HookEventBridge
|
||||
{
|
||||
/**
|
||||
* @internal 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',
|
||||
ConfigLoadedEvent::CONFIG_LOADED => 'load_config',
|
||||
ArrayFilterEvent::APP_MENU => 'app_menu',
|
||||
ArrayFilterEvent::NAV_INFO => 'nav_info',
|
||||
ArrayFilterEvent::FEATURE_ENABLED => 'isEnabled',
|
||||
ArrayFilterEvent::FEATURE_GET => 'get',
|
||||
HtmlFilterEvent::HEAD => 'head',
|
||||
HtmlFilterEvent::FOOTER => 'footer',
|
||||
HtmlFilterEvent::PAGE_HEADER => 'page_header',
|
||||
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',
|
||||
ConfigLoadedEvent::CONFIG_LOADED => 'onConfigLoadedEvent',
|
||||
ArrayFilterEvent::APP_MENU => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent',
|
||||
HtmlFilterEvent::HEAD => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent',
|
||||
];
|
||||
}
|
||||
|
||||
public static function onNamedEvent(NamedEvent $event): void
|
||||
{
|
||||
static::callHook($event->getName(), '');
|
||||
}
|
||||
|
||||
public static function onConfigLoadedEvent(ConfigLoadedEvent $event): void
|
||||
{
|
||||
static::callHook($event->getName(), $event->getConfig());
|
||||
}
|
||||
|
||||
public static function onArrayFilterEvent(ArrayFilterEvent $event): void
|
||||
{
|
||||
$event->setArray(
|
||||
static::callHook($event->getName(), $event->getArray())
|
||||
);
|
||||
}
|
||||
|
||||
public static function onHtmlFilterEvent(HtmlFilterEvent $event): void
|
||||
{
|
||||
$event->setHtml(
|
||||
static::callHook($event->getName(), $event->getHtml())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|object $data
|
||||
*
|
||||
* @return string|array|object
|
||||
*/
|
||||
private static function callHook(string $name, $data)
|
||||
{
|
||||
// If possible, map the event name to the legacy Hook name
|
||||
$name = static::$eventMapper[$name] ?? $name;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
|
@ -789,4 +789,13 @@ abstract class DI
|
|||
{
|
||||
return self::$dice->create(Content\Post\Repository\PostMedia::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal The EventDispatcher should never called outside of the core, like in addons or themes
|
||||
* @deprecated 2025.02 Use constructor injection instead
|
||||
*/
|
||||
public static function eventDispatcher(): \Psr\EventDispatcher\EventDispatcherInterface
|
||||
{
|
||||
return self::$dice->create(\Psr\EventDispatcher\EventDispatcherInterface::class);
|
||||
}
|
||||
}
|
||||
|
|
45
src/Event/ArrayFilterEvent.php
Normal file
45
src/Event/ArrayFilterEvent.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?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 an array.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class ArrayFilterEvent extends Event
|
||||
{
|
||||
public const APP_MENU = 'friendica.data.app_menu';
|
||||
|
||||
public const NAV_INFO = 'friendica.data.nav_info';
|
||||
|
||||
public const FEATURE_ENABLED = 'friendica.data.feature_enabled';
|
||||
|
||||
public const FEATURE_GET = 'friendica.data.feature_get';
|
||||
|
||||
private array $array;
|
||||
|
||||
public function __construct(string $name, array $array)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->array = $array;
|
||||
}
|
||||
|
||||
public function getArray(): array
|
||||
{
|
||||
return $this->array;
|
||||
}
|
||||
|
||||
public function setArray(array $array): void
|
||||
{
|
||||
$this->array = $array;
|
||||
}
|
||||
}
|
36
src/Event/ConfigLoadedEvent.php
Normal file
36
src/Event/ConfigLoadedEvent.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?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 Friendica\Core\Config\Util\ConfigFileManager;
|
||||
|
||||
/**
|
||||
* Notify that the config was loaded
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class ConfigLoadedEvent extends Event
|
||||
{
|
||||
public const CONFIG_LOADED = 'friendica.config_loaded';
|
||||
|
||||
private ConfigFileManager $config;
|
||||
|
||||
public function __construct(string $name, ConfigFileManager $config)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function getConfig(): ConfigFileManager
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
}
|
35
src/Event/Event.php
Normal file
35
src/Event/Event.php
Normal 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;
|
||||
|
||||
/**
|
||||
* One-way Event to inform listener about something happend.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
37
src/Event/EventDispatcher.php
Normal file
37
src/Event/EventDispatcher.php
Normal 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\Event;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher as SymfonyEventDispatcher;
|
||||
|
||||
/**
|
||||
* Modified Event Dispatcher.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
47
src/Event/HtmlFilterEvent.php
Normal file
47
src/Event/HtmlFilterEvent.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?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.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class HtmlFilterEvent extends Event
|
||||
{
|
||||
public const HEAD = 'friendica.html.head';
|
||||
|
||||
public const FOOTER = 'friendica.html.footer';
|
||||
|
||||
public const PAGE_HEADER = 'friendica.html.page_header';
|
||||
|
||||
public const PAGE_CONTENT_TOP = 'friendica.html.page_content_top';
|
||||
|
||||
public const PAGE_END = 'friendica.html.page_end';
|
||||
|
||||
private string $html;
|
||||
|
||||
public function __construct(string $name, string $html)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->html = $html;
|
||||
}
|
||||
|
||||
public function getHtml(): string
|
||||
{
|
||||
return $this->html;
|
||||
}
|
||||
|
||||
public function setHtml(string $html): void
|
||||
{
|
||||
$this->html = $html;
|
||||
}
|
||||
}
|
20
src/Event/NamedEvent.php
Normal file
20
src/Event/NamedEvent.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?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.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface NamedEvent
|
||||
{
|
||||
public function getName(): string;
|
||||
}
|
|
@ -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' => [
|
||||
|
|
176
tests/Unit/Core/Hooks/HookEventBridgeTest.php
Normal file
176
tests/Unit/Core/Hooks/HookEventBridgeTest.php
Normal file
|
@ -0,0 +1,176 @@
|
|||
<?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\Core\Hooks;
|
||||
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Core\Hooks\HookEventBridge;
|
||||
use Friendica\Event\ArrayFilterEvent;
|
||||
use Friendica\Event\ConfigLoadedEvent;
|
||||
use Friendica\Event\Event;
|
||||
use Friendica\Event\HtmlFilterEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class HookEventBridgeTest extends TestCase
|
||||
{
|
||||
public function testGetStaticSubscribedEventsReturnsStaticMethods(): void
|
||||
{
|
||||
$expected = [
|
||||
Event::INIT => 'onNamedEvent',
|
||||
ConfigLoadedEvent::CONFIG_LOADED => 'onConfigLoadedEvent',
|
||||
ArrayFilterEvent::APP_MENU => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent',
|
||||
ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent',
|
||||
HtmlFilterEvent::HEAD => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent',
|
||||
HtmlFilterEvent::PAGE_HEADER => '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 getConfigLoadedEventData(): array
|
||||
{
|
||||
return [
|
||||
['test', 'test'],
|
||||
[ConfigLoadedEvent::CONFIG_LOADED, 'load_config'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getConfigLoadedEventData
|
||||
*/
|
||||
public function testOnConfigLoadedEventCallsHookWithCorrectValue($name, $expected): void
|
||||
{
|
||||
$config = $this->createStub(ConfigFileManager::class);
|
||||
|
||||
$event = new ConfigLoadedEvent($name, $config);
|
||||
|
||||
$reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
|
||||
$reflectionProperty->setValue(null, function (string $name, $data) use ($expected, $config) {
|
||||
$this->assertSame($expected, $name);
|
||||
$this->assertSame($config, $data);
|
||||
|
||||
return $data;
|
||||
});
|
||||
|
||||
HookEventBridge::onConfigLoadedEvent($event);
|
||||
}
|
||||
|
||||
public static function getArrayFilterEventData(): array
|
||||
{
|
||||
return [
|
||||
['test', 'test'],
|
||||
[ArrayFilterEvent::APP_MENU, 'app_menu'],
|
||||
[ArrayFilterEvent::NAV_INFO, 'nav_info'],
|
||||
[ArrayFilterEvent::FEATURE_ENABLED, 'isEnabled'],
|
||||
[ArrayFilterEvent::FEATURE_GET, 'get'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getArrayFilterEventData
|
||||
*/
|
||||
public function testOnArrayFilterEventCallsHookWithCorrectValue($name, $expected): void
|
||||
{
|
||||
$event = new ArrayFilterEvent($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::onArrayFilterEvent($event);
|
||||
}
|
||||
|
||||
public static function getHtmlFilterEventData(): array
|
||||
{
|
||||
return [
|
||||
['test', 'test'],
|
||||
[HtmlFilterEvent::HEAD, 'head'],
|
||||
[HtmlFilterEvent::FOOTER, 'footer'],
|
||||
[HtmlFilterEvent::PAGE_HEADER, 'page_header'],
|
||||
[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);
|
||||
}
|
||||
}
|
66
tests/Unit/Event/ArrayFilterEventTest.php
Normal file
66
tests/Unit/Event/ArrayFilterEventTest.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?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\ArrayFilterEvent;
|
||||
use Friendica\Event\NamedEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ArrayFilterEventTest extends TestCase
|
||||
{
|
||||
public function testImplementationOfInstances(): void
|
||||
{
|
||||
$event = new ArrayFilterEvent('test', []);
|
||||
|
||||
$this->assertInstanceOf(NamedEvent::class, $event);
|
||||
}
|
||||
|
||||
public static function getPublicConstants(): array
|
||||
{
|
||||
return [
|
||||
[ArrayFilterEvent::APP_MENU, 'friendica.data.app_menu'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getPublicConstants
|
||||
*/
|
||||
public function testPublicConstantsAreAvailable($value, $expected): void
|
||||
{
|
||||
$this->assertSame($expected, $value);
|
||||
}
|
||||
|
||||
public function testGetNameReturnsName(): void
|
||||
{
|
||||
$event = new ArrayFilterEvent('test', []);
|
||||
|
||||
$this->assertSame('test', $event->getName());
|
||||
}
|
||||
|
||||
public function testGetArrayReturnsCorrectString(): void
|
||||
{
|
||||
$data = ['original'];
|
||||
|
||||
$event = new ArrayFilterEvent('test', $data);
|
||||
|
||||
$this->assertSame($data, $event->getArray());
|
||||
}
|
||||
|
||||
public function testSetArrayUpdatesHtml(): void
|
||||
{
|
||||
$event = new ArrayFilterEvent('test', ['original']);
|
||||
|
||||
$expected = ['updated'];
|
||||
|
||||
$event->setArray($expected);
|
||||
|
||||
$this->assertSame($expected, $event->getArray());
|
||||
}
|
||||
}
|
56
tests/Unit/Event/ConfigLoadedEventTest.php
Normal file
56
tests/Unit/Event/ConfigLoadedEventTest.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?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\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Event\ConfigLoadedEvent;
|
||||
use Friendica\Event\NamedEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ConfigLoadedEventTest extends TestCase
|
||||
{
|
||||
public function testImplementationOfInstances(): void
|
||||
{
|
||||
$event = new ConfigLoadedEvent('test', $this->createStub(ConfigFileManager::class));
|
||||
|
||||
$this->assertInstanceOf(NamedEvent::class, $event);
|
||||
}
|
||||
|
||||
public static function getPublicConstants(): array
|
||||
{
|
||||
return [
|
||||
[ConfigLoadedEvent::CONFIG_LOADED, 'friendica.config_loaded'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getPublicConstants
|
||||
*/
|
||||
public function testPublicConstantsAreAvailable($value, $expected): void
|
||||
{
|
||||
$this->assertSame($expected, $value);
|
||||
}
|
||||
|
||||
public function testGetNameReturnsName(): void
|
||||
{
|
||||
$event = new ConfigLoadedEvent('test', $this->createStub(ConfigFileManager::class));
|
||||
|
||||
$this->assertSame('test', $event->getName());
|
||||
}
|
||||
|
||||
public function testGetConfigReturnsCorrectString(): void
|
||||
{
|
||||
$config = $this->createStub(ConfigFileManager::class);
|
||||
|
||||
$event = new ConfigLoadedEvent('test', $config);
|
||||
|
||||
$this->assertSame($config, $event->getConfig());
|
||||
}
|
||||
}
|
37
tests/Unit/Event/EventDispatcherTest.php
Normal file
37
tests/Unit/Event/EventDispatcherTest.php
Normal 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'));
|
||||
}
|
||||
}
|
46
tests/Unit/Event/EventTest.php
Normal file
46
tests/Unit/Event/EventTest.php
Normal 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());
|
||||
}
|
||||
}
|
69
tests/Unit/Event/HtmlFilterEventTest.php
Normal file
69
tests/Unit/Event/HtmlFilterEventTest.php
Normal 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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
@ -16,48 +16,48 @@ class BasePathTest extends TestCase
|
|||
{
|
||||
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,
|
||||
]
|
||||
];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue