diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 68ee53a8b0..bc976e61a4 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -44,15 +44,12 @@ if (php_sapi_name() !== 'cli') { exit(); } -use Dice\Dice; +chdir(dirname(__DIR__)); -chdir(dirname(__FILE__, 2)); +require dirname(__DIR__) . '/vendor/autoload.php'; -require dirname(__FILE__, 2) . '/vendor/autoload.php'; +$container = \Friendica\Core\DiceContainer::fromBasePath(dirname(__DIR__)); -$dice = (new Dice())->addRules(require(dirname(__FILE__, 2) . '/static/dependencies.config.php')); - -$container = \Friendica\Core\Container::fromDice($dice); -$app = \Friendica\App::fromContainer($container); +$app = \Friendica\App::fromContainer($container); $app->processEjabberd(); diff --git a/bin/console.php b/bin/console.php index 63412887d5..ad612f4363 100755 --- a/bin/console.php +++ b/bin/console.php @@ -13,11 +13,10 @@ if (php_sapi_name() !== 'cli') { exit(); } -use Dice\Dice; - require dirname(__DIR__) . '/vendor/autoload.php'; -$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php')); +$container = \Friendica\Core\DiceContainer::fromBasePath(dirname(__DIR__)); -$container = \Friendica\Core\Container::fromDice($dice); -\Friendica\Core\Console::create($container, $_SERVER['argv'] ?? [])->execute(); +$app = \Friendica\App::fromContainer($container); + +$app->processConsole($_SERVER['argv'] ?? []); diff --git a/bin/daemon.php b/bin/daemon.php index 18af315bc3..546f207e08 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -19,17 +19,16 @@ if (php_sapi_name() !== 'cli') { exit(); } -use Dice\Dice; - // Ensure that daemon.php is executed from the base path of the installation chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php')); - $argv = $_SERVER['argv'] ?? []; array_splice($argv, 1, 0, "daemon"); -$container = \Friendica\Core\Container::fromDice($dice); -\Friendica\Core\Console::create($container, $argv)->execute(); +$container = \Friendica\Core\DiceContainer::fromBasePath(dirname(__DIR__)); + +$app = \Friendica\App::fromContainer($container); + +$app->processConsole($argv); diff --git a/bin/jetstream.php b/bin/jetstream.php index e3df667d3f..156f961856 100755 --- a/bin/jetstream.php +++ b/bin/jetstream.php @@ -9,8 +9,6 @@ * @deprecated 2025.02 use bin/console.php jetstream instead */ -use Dice\Dice; - if (php_sapi_name() !== 'cli') { header($_SERVER["SERVER_PROTOCOL"] . ' 403 Forbidden'); exit(); @@ -21,10 +19,11 @@ chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php')); - $argv = $_SERVER['argv'] ?? []; array_splice($argv, 1, 0, "jetstream"); -$container = \Friendica\Core\Container::fromDice($dice); -\Friendica\Core\Console::create($container, $argv)->execute(); +$container = \Friendica\Core\DiceContainer::fromBasePath(dirname(__DIR__)); + +$app = \Friendica\App::fromContainer($container); + +$app->processConsole($argv); diff --git a/bin/worker.php b/bin/worker.php index a58d657a0f..a79d8836a7 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -16,17 +16,16 @@ if (php_sapi_name() !== 'cli') { exit(); } -use Dice\Dice; - // Ensure that worker.php is executed from the base path of the installation chdir(dirname(__DIR__)); require dirname(__DIR__) . '/vendor/autoload.php'; -$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php')); - $argv = $_SERVER['argv'] ?? []; array_splice($argv, 1, 0, "worker"); -$container = \Friendica\Core\Container::fromDice($dice); -\Friendica\Core\Console::create($container, $argv)->execute(); +$container = \Friendica\Core\DiceContainer::fromBasePath(dirname(__DIR__)); + +$app = \Friendica\App::fromContainer($container); + +$app->processConsole($argv); diff --git a/index.php b/index.php index 6654dcb515..850d9cd1c0 100644 --- a/index.php +++ b/index.php @@ -5,8 +5,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use Dice\Dice; - $start_time = microtime(true); if (!file_exists(__DIR__ . '/vendor/autoload.php')) { @@ -17,9 +15,8 @@ require __DIR__ . '/vendor/autoload.php'; $request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals(); -$dice = (new Dice())->addRules(require(__DIR__ . '/static/dependencies.config.php')); +$container = \Friendica\Core\DiceContainer::fromBasePath(__DIR__); -$container = \Friendica\Core\Container::fromDice($dice); -$app = \Friendica\App::fromContainer($container); +$app = \Friendica\App::fromContainer($container); $app->processRequest($request, $start_time); diff --git a/src/App.php b/src/App.php index 487707f9fd..73f2913b1a 100644 --- a/src/App.php +++ b/src/App.php @@ -17,8 +17,10 @@ use Friendica\App\Router; use Friendica\Capabilities\ICanCreateResponses; use Friendica\Capabilities\ICanHandleRequests; use Friendica\Content\Nav; +use Friendica\Core\Addon\Capability\ICanLoadAddons; use Friendica\Core\Config\Factory\Config; use Friendica\Core\Container; +use Friendica\Core\Logger\LoggerManager; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Definition\DbaDefinition; @@ -26,8 +28,10 @@ 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\Logger\Capability\LogChannel; +use Friendica\Core\Logger\Handler\ErrorHandler; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\System; use Friendica\Core\Update; @@ -134,7 +138,13 @@ class App ], ]); - $this->container->setup(LogChannel::APP, false); + $this->setupContainerForAddons(); + + $this->setupLogChannel(LogChannel::APP); + + $this->setupLegacyServiceLocator(); + + $this->registerErrorHandler(); $this->requestId = $this->container->create(Request::class)->getRequestId(); $this->auth = $this->container->create(Authentication::class); @@ -168,9 +178,30 @@ class App ); } + public function processConsole(array $argv): void + { + $this->setupContainerForAddons(); + + $this->setupLogChannel($this->determineLogChannel($argv)); + + $this->setupLegacyServiceLocator(); + + $this->registerErrorHandler(); + + $this->registerTemplateEngine(); + + (\Friendica\Core\Console::create($this->container, $argv))->execute(); + } + public function processEjabberd(): void { - $this->container->setup(LogChannel::AUTH_JABBERED, false); + $this->setupContainerForAddons(); + + $this->setupLogChannel(LogChannel::AUTH_JABBERED); + + $this->setupLegacyServiceLocator(); + + $this->registerErrorHandler(); /** @var BasePath */ $basePath = $this->container->create(BasePath::class); @@ -187,6 +218,52 @@ class App } } + private function setupContainerForAddons(): void + { + /** @var ICanLoadAddons $addonLoader */ + $addonLoader = $this->container->create(ICanLoadAddons::class); + + foreach ($addonLoader->getActiveAddonConfig('dependencies') as $name => $rule) { + $this->container->addRule($name, $rule); + } + } + + private function determineLogChannel(array $argv): string + { + $command = strtolower($argv[1] ?? ''); + + if ($command === 'daemon' || $command === 'jetstream') { + return LogChannel::DAEMON; + } + + if ($command === 'worker') { + return LogChannel::WORKER; + } + + // @TODO Add support for jetstream + + return LogChannel::CONSOLE; + } + + private function setupLogChannel(string $logChannel): void + { + /** @var LoggerManager */ + $loggerManager = $this->container->create(LoggerManager::class); + $loggerManager->changeLogChannel($logChannel); + } + + private function setupLegacyServiceLocator(): void + { + if ($this->container instanceof DiceContainer) { + DI::init($this->container->getDice()); + } + } + + private function registerErrorHandler(): void + { + ErrorHandler::register($this->container->create(LoggerInterface::class)); + } + private function registerTemplateEngine(): void { Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine'); diff --git a/src/Console/AbstractConsole.php b/src/Console/AbstractConsole.php index f9c413b915..0b8c1d6eb8 100644 --- a/src/Console/AbstractConsole.php +++ b/src/Console/AbstractConsole.php @@ -32,7 +32,7 @@ abstract class AbstractConsole extends Console */ protected function checkDeprecated(string $command): void { - if (substr($this->executable, -strlen(CoreConsole::getDefaultExecutable())) === CoreConsole::getDefaultExecutable()) { + if (substr($this->executable, -strlen(CoreConsole::getDefaultExecutable())) !== CoreConsole::getDefaultExecutable()) { $this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php %s' instead", $this->executable, $command)); } } diff --git a/src/Console/Addon.php b/src/Console/Addon.php index 8066853246..e4bdeb052b 100644 --- a/src/Console/Addon.php +++ b/src/Console/Addon.php @@ -60,9 +60,9 @@ HELP; { parent::__construct($argv); - $this->appMode = $appMode; - $this->l10n = $l10n; - $this->dba = $dba; + $this->appMode = $appMode; + $this->l10n = $l10n; + $this->dba = $dba; AddonCore::loadAddons(); } @@ -121,27 +121,28 @@ HELP; $this->out($this->getHelp()); return false; } + foreach (AddonCore::getAvailableList() as $addon) { $addon_name = $addon[0]; - $enabled = AddonCore::isEnabled($addon_name) ? "enabled" : "disabled"; - switch ($subCmd) { - case 'all': - $table->addRow([$addon_name, $enabled]); - break; - case 'enabled': - if (!$enabled) { - continue 2; - } - $table->addRow([$addon_name]); - case 'disabled': - if ($enabled) { - continue 2; - } - $table->addRow([$addon_name]); - break; + $enabled = AddonCore::isEnabled($addon_name); + + if ($subCmd === 'all') { + $table->addRow([$addon_name, $enabled ? 'enabled' : 'disabled']); + + continue; } + if ($subCmd === 'enabled' && $enabled === true) { + $table->addRow([$addon_name]); + continue; + } + + if ($subCmd === 'disabled' && $enabled === false) { + $table->addRow([$addon_name]); + continue; + } } + $this->out($table->getTable()); return 0; diff --git a/src/Core/Console.php b/src/Core/Console.php index d138a9dfa9..5dec5be257 100644 --- a/src/Core/Console.php +++ b/src/Core/Console.php @@ -9,7 +9,6 @@ namespace Friendica\Core; use Friendica; use Friendica\App; -use Friendica\Core\Logger\Capability\LogChannel; /** * Description of Console @@ -187,12 +186,6 @@ HELP; $className = $this->subConsoles[$command]; - if (is_subclass_of($className, Friendica\Console\AbstractConsole::class)) { - $this->container->setup($className::LOG_CHANNEL); - } else { - $this->container->setup(LogChannel::CONSOLE); - } - /** @var Console $subconsole */ $subconsole = $this->container->create($className, [$subargs]); diff --git a/src/Core/Container.php b/src/Core/Container.php index 12a9b625a7..1017590a85 100644 --- a/src/Core/Container.php +++ b/src/Core/Container.php @@ -9,57 +9,11 @@ declare(strict_types=1); namespace Friendica\Core; -use Dice\Dice; -use Friendica\Core\Addon\Capability\ICanLoadAddons; -use Friendica\Core\Logger\Capability\LogChannel; -use Friendica\Core\Logger\Handler\ErrorHandler; -use Friendica\DI; -use Psr\Log\LoggerInterface; - /** - * Wrapper for the Dice class to make some basic setups + * Dependency Injection Container */ -class Container +interface Container { - private Dice $container; - - protected function __construct(Dice $container) - { - $this->container = $container; - } - - /** - * Creates an instance with Dice - * - * @param Dice $container - * - * @return self - */ - public static function fromDice(Dice $container): self - { - return new self($container); - } - - /** - * Initialize the container with the given parameters - * - * @param string $logChannel The Log Channel of this call - * @param bool $withTemplateEngine true, if the template engine should be set too - * - * @return void - */ - public function setup(string $logChannel = LogChannel::DEFAULT, bool $withTemplateEngine = true) - { - $this->setupContainerForAddons(); - $this->setupContainerForLogger($logChannel); - $this->setupLegacyServiceLocator(); - $this->registerErrorHandler(); - - if ($withTemplateEngine) { - $this->registerTemplateEngine(); - } - } - /** * Returns a fully constructed object based on $name using $args and $share as constructor arguments if supplied * @param string $name name The name of the class to instantiate @@ -69,10 +23,7 @@ class Container * * @see Dice::create() */ - public function create(string $name, array $args = [], array $share = []): object - { - return $this->container->create($name, $args, $share); - } + public function create(string $name, array $args = [], array $share = []): object; /** * Add a rule $rule to the class $name @@ -81,38 +32,5 @@ class Container * * @see Dice::addRule() */ - public function addRule(string $name, array $rule): void - { - $this->container = $this->container->addRule($name, $rule); - } - - private function setupContainerForAddons(): void - { - /** @var ICanLoadAddons $addonLoader */ - $addonLoader = $this->container->create(ICanLoadAddons::class); - - $this->container = $this->container->addRules($addonLoader->getActiveAddonConfig('dependencies')); - } - - private function setupContainerForLogger(string $logChannel): void - { - $this->container = $this->container->addRule(LoggerInterface::class, [ - 'constructParams' => [$logChannel], - ]); - } - - private function setupLegacyServiceLocator(): void - { - DI::init($this->container); - } - - private function registerErrorHandler(): void - { - ErrorHandler::register($this->container->create(LoggerInterface::class)); - } - - private function registerTemplateEngine(): void - { - Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine'); - } + public function addRule(string $name, array $rule): void; } diff --git a/src/Core/DiceContainer.php b/src/Core/DiceContainer.php new file mode 100644 index 0000000000..304c1e411d --- /dev/null +++ b/src/Core/DiceContainer.php @@ -0,0 +1,74 @@ +addRules(require($path)); + + return new self($dice); + } + + private Dice $container; + + private function __construct(Dice $container) + { + $this->container = $container; + } + + /** + * Returns a fully constructed object based on $name using $args and $share as constructor arguments if supplied + * @param string $name name The name of the class to instantiate + * @param array $args An array with any additional arguments to be passed into the constructor upon instantiation + * @param array $share a list of defined in shareInstances for objects higher up the object graph, should only be used internally + * @return object A fully constructed object based on the specified input arguments + * + * @see Dice::create() + */ + public function create(string $name, array $args = [], array $share = []): object + { + return $this->container->create($name, $args, $share); + } + + /** + * Add a rule $rule to the class $name + * @param string $name The name of the class to add the rule for + * @param array $rule The container can be fully configured using rules provided by associative arrays. See {@link https://r.je/dice.html#example3} for a description of the rules. + * + * @see Dice::addRule() + */ + public function addRule(string $name, array $rule): void + { + $this->container = $this->container->addRule($name, $rule); + } + + /** + * Only used to inject Dice into DI class + * + * @see \Friendica\DI + * + * @internal + * + * @deprecated + */ + public function getDice(): Dice + { + return $this->container; + } +} diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 48fd1293b3..a87be78633 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -10,61 +10,20 @@ namespace Friendica\Core; use Friendica\DI; use Friendica\Core\Logger\Type\WorkerLogger; use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; /** * Logger functions + * + * @deprecated 2025.02 Use constructor injection or `DI::logger()` instead */ class Logger { - /** - * LoggerInterface The default Logger type - * - * @var string - */ - const TYPE_LOGGER = LoggerInterface::class; - /** - * WorkerLogger A specific worker logger type, which can be enabled - * - * @var string - */ - const TYPE_WORKER = WorkerLogger::class; - /** - * @var string $type LoggerInterface The current logger type - */ - private static $type = self::TYPE_LOGGER; - /** * @return LoggerInterface|WorkerLogger */ private static function getInstance() { - if (self::$type === self::TYPE_LOGGER) { - return DI::logger(); - } else { - return DI::workerLogger(); - } - } - - /** - * Enable additional logging for worker usage - * - * @param string $functionName The worker function, which got called - * - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ - public static function enableWorker(string $functionName) - { - self::$type = self::TYPE_WORKER; - DI::workerLogger()->setFunctionName($functionName); - } - - /** - * Disable additional logging for worker usage - */ - public static function disableWorker() - { - self::$type = self::TYPE_LOGGER; + return DI::logger(); } /** @@ -191,21 +150,4 @@ class Logger { self::getInstance()->debug($message, $context); } - - /** - * An alternative logger for development. - * - * Works largely as log() but allows developers - * to isolate particular elements they are targeting - * personally without background noise - * - * @param string $message Message to log - * @param string $level Logging level - * @return void - * @throws \Exception - */ - public static function devLog(string $message, string $level = LogLevel::DEBUG) - { - DI::devLogger()->log($level, $message); - } } diff --git a/src/Core/Logger/Factory/LegacyLoggerFactory.php b/src/Core/Logger/Factory/LegacyLoggerFactory.php new file mode 100644 index 0000000000..5c91d11771 --- /dev/null +++ b/src/Core/Logger/Factory/LegacyLoggerFactory.php @@ -0,0 +1,59 @@ +instanceCreator = $instanceCreator; + $this->config = $config; + $this->profiler = $profiler; + } + + /** + * Creates and returns a PSR-3 Logger instance. + * + * Calling this method multiple times with the same parameters SHOULD return the same object. + * + * @param \Psr\Log\LogLevel::* $logLevel The log level + * @param \Friendica\Core\Logger\Capability\LogChannel::* $logChannel The log channel + */ + public function createLogger(string $logLevel, string $logChannel): LoggerInterface + { + $factory = new Logger($logChannel); + + return $factory->create($this->instanceCreator, $this->config, $this->profiler); + } +} diff --git a/src/Core/Logger/Factory/LoggerFactory.php b/src/Core/Logger/Factory/LoggerFactory.php new file mode 100644 index 0000000000..0802540d5d --- /dev/null +++ b/src/Core/Logger/Factory/LoggerFactory.php @@ -0,0 +1,28 @@ +config = $config; + $this->factory = $factory; + + $this->debug = (bool) $config->get('system', 'debugging') ?? false; + $this->logLevel = (string) $config->get('system', 'loglevel') ?? LogLevel::NOTICE; + $this->profiling = (bool) $config->get('system', 'profiling') ?? false; + } + + public function changeLogChannel(string $logChannel): void + { + self::$logChannel = $logChannel; + self::$logger = null; + } + + /** + * (Creates and) Returns the logger instance + */ + public function getLogger(): LoggerInterface + { + if (self::$logger === null) { + self::$logger = $this->createLogger(); + } + + return self::$logger; + } + + private function createLogger(): LoggerInterface + { + // Always create NullLogger if debug is disabled + if ($this->debug === false) { + $logger = new NullLogger(); + } else { + $logger = $this->factory->createLogger($this->logLevel, self::$logChannel); + } + + if ($this->profiling === true) { + $profiler = new Profiler($this->config); + + $logger = new ProfilerLogger($logger, $profiler); + } + + // Decorate Logger as WorkerLogger for BC + if (self::$logChannel === LogChannel::WORKER) { + $logger = new WorkerLogger($logger); + } + + return $logger; + } +} diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 568fa2873f..c84de94f63 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -8,6 +8,8 @@ namespace Friendica\Core; use Friendica\Core\Cache\Enum\Duration; +use Friendica\Core\Logger\Capability\LogChannel; +use Friendica\Core\Logger\Type\WorkerLogger; use Friendica\Core\Worker\Entity\Process; use Friendica\Database\DBA; use Friendica\DI; @@ -537,9 +539,15 @@ class Worker self::coolDown(); - Logger::enableWorker($funcname); + DI::loggerManager()->changeLogChannel(LogChannel::WORKER); - Logger::info('Process start.', ['priority' => $queue['priority'], 'id' => $queue['id']]); + $logger = DI::logger(); + + if ($logger instanceof WorkerLogger) { + $logger->setFunctionName($funcname); + } + + DI::logger()->info('Process start.', ['priority' => $queue['priority'], 'id' => $queue['id']]); $stamp = (float)microtime(true); @@ -559,19 +567,19 @@ class Worker try { call_user_func_array(sprintf('Friendica\Worker\%s::execute', $funcname), $argv); } catch (\Throwable $e) { - Logger::error('Uncaught exception in worker method execution', ['class' => get_class($e), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => $e->getTraceAsString(), 'previous' => $e->getPrevious()]); + DI::logger()->error('Uncaught exception in worker method execution', ['class' => get_class($e), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => $e->getTraceAsString(), 'previous' => $e->getPrevious()]); Worker::defer(); } } else { try { $funcname($argv, count($argv)); } catch (\Throwable $e) { - Logger::error('Uncaught exception in worker execution', ['message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => $e->getTraceAsString(), 'previous' => $e->getPrevious()]); + DI::logger()->error('Uncaught exception in worker execution', ['message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => $e->getTraceAsString(), 'previous' => $e->getPrevious()]); Worker::defer(); } } - Logger::disableWorker(); + DI::loggerManager()->changeLogChannel(LogChannel::DEFAULT); $appHelper->setQueue([]); @@ -591,7 +599,7 @@ class Worker $rest = round(max(0, $up_duration - (self::$db_duration + self::$lock_duration)), 2); $exec = round($duration, 2); - Logger::info('Performance:', ['function' => $funcname, 'state' => self::$state, 'count' => $dbcount, 'stat' => $dbstat, 'write' => $dbwrite, 'lock' => $dblock, 'total' => $dbtotal, 'rest' => $rest, 'exec' => $exec]); + DI::logger()->info('Performance:', ['function' => $funcname, 'state' => self::$state, 'count' => $dbcount, 'stat' => $dbstat, 'write' => $dbwrite, 'lock' => $dblock, 'total' => $dbtotal, 'rest' => $rest, 'exec' => $exec]); self::coolDown(); @@ -603,16 +611,16 @@ class Worker self::$lock_duration = 0; if ($duration > 3600) { - Logger::info('Longer than 1 hour.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); + DI::logger()->info('Longer than 1 hour.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); } elseif ($duration > 600) { - Logger::info('Longer than 10 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); + DI::logger()->info('Longer than 10 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); } elseif ($duration > 300) { - Logger::info('Longer than 5 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); + DI::logger()->info('Longer than 5 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); } elseif ($duration > 120) { - Logger::info('Longer than 2 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); + DI::logger()->info('Longer than 2 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]); } - Logger::info('Process done.', ['function' => $funcname, 'priority' => $queue['priority'], 'retrial' => $queue['retrial'], 'id' => $queue['id'], 'duration' => round($duration, 3)]); + DI::logger()->info('Process done.', ['function' => $funcname, 'priority' => $queue['priority'], 'retrial' => $queue['retrial'], 'id' => $queue['id'], 'duration' => round($duration, 3)]); DI::profiler()->saveLog(DI::logger(), 'ID ' . $queue['id'] . ': ' . $funcname); } diff --git a/src/DI.php b/src/DI.php index 9381d6a782..7d1114ac5c 100644 --- a/src/DI.php +++ b/src/DI.php @@ -9,6 +9,7 @@ namespace Friendica; use Dice\Dice; use Friendica\Core\Logger\Capability\ICheckLoggerSettings; +use Friendica\Core\Logger\LoggerManager; use Friendica\Core\Logger\Util\LoggerSettingsCheck; use Friendica\Core\Session\Capability\IHandleSessions; use Friendica\Core\Session\Capability\IHandleUserSessions; @@ -305,8 +306,8 @@ abstract class DI public static function flushLogger() { $flushDice = self::$dice - ->addRule(LoggerInterface::class, self::$dice->getRule(LoggerInterface::class)) - ->addRule('$devLogger', self::$dice->getRule('$devLogger')); + ->addRule(LoggerInterface::class, self::$dice->getRule(LoggerInterface::class)); + static::init($flushDice); } @@ -324,14 +325,8 @@ abstract class DI } /** - * @return LoggerInterface - */ - public static function devLogger() - { - return self::$dice->create('$devLogger'); - } - - /** + * @deprecated 2025.02 Use `DI::loggerManager()` and `DI::logger()` instead + * * @return \Friendica\Core\Logger\Type\WorkerLogger */ public static function workerLogger() @@ -339,6 +334,11 @@ abstract class DI return self::$dice->create(Core\Logger\Type\WorkerLogger::class); } + public static function loggerManager(): LoggerManager + { + return self::$dice->create(LoggerManager::class); + } + // // "Factory" namespace instances // diff --git a/src/Module/Media/Photo/Upload.php b/src/Module/Media/Photo/Upload.php index 2032c60143..66dc51e9f8 100644 --- a/src/Module/Media/Photo/Upload.php +++ b/src/Module/Media/Photo/Upload.php @@ -163,7 +163,7 @@ class Upload extends \Friendica\BaseModule } $this->logger->info('upload done'); - $this->return(200, "\n\n" . Images::getBBCodeByResource($resource_id, $owner['nickname'], $preview, $image->getExt()) . "\n\n"); + $this->return(200, Images::getBBCodeByResource($resource_id, $owner['nickname'], $preview, $image->getExt())); } /** diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 28ae277c21..f1c2f4e52e 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -157,11 +157,19 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo ], ], \Psr\Log\LoggerInterface::class => [ - 'instanceOf' => \Friendica\Core\Logger\Factory\Logger::class, + 'instanceOf' => \Friendica\Core\Logger\LoggerManager::class, 'call' => [ - ['create', [], Dice::CHAIN_CALL], + ['getLogger', [], Dice::CHAIN_CALL], ], ], + \Friendica\Core\Logger\LoggerManager::class => [ + 'substitutions' => [ + \Friendica\Core\Logger\Factory\LoggerFactory::class => \Friendica\Core\Logger\Factory\LegacyLoggerFactory::class, + ], + ], + \Friendica\Core\Logger\Factory\LoggerFactory::class => [ + 'instanceOf' => \Friendica\Core\Logger\Factory\LegacyLoggerFactory::class, + ], \Friendica\Core\Logger\Type\SyslogLogger::class => [ 'instanceOf' => \Friendica\Core\Logger\Factory\SyslogLogger::class, 'call' => [ @@ -180,12 +188,6 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo \Friendica\Core\Logger\Capability\IHaveCallIntrospections::IGNORE_CLASS_LIST, ], ], - '$devLogger' => [ - 'instanceOf' => \Friendica\Core\Logger\Factory\StreamLogger::class, - 'call' => [ - ['createDev', [], Dice::CHAIN_CALL], - ], - ], \Friendica\Core\Cache\Capability\ICanCache::class => [ 'instanceOf' => \Friendica\Core\Cache\Factory\Cache::class, 'call' => [ diff --git a/static/routes.config.php b/static/routes.config.php index 5ebce2738b..88e642c27a 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -602,6 +602,8 @@ return [ '/{type:users}/{guid}' => [Module\Diaspora\Receive::class, [ R::POST]], ], + '/remote_follow/{nickname}' => [Module\Profile\RemoteFollow::class, [R::GET, R::POST]], + '/security' => [ '/password_too_long' => [Module\Security\PasswordTooLong::class, [R::GET, R::POST]], ], diff --git a/tests/Unit/Core/ContainerTest.php b/tests/Unit/Core/ContainerTest.php deleted file mode 100644 index bb5ccda398..0000000000 --- a/tests/Unit/Core/ContainerTest.php +++ /dev/null @@ -1,48 +0,0 @@ -createMock(Dice::class); - $dice->expects($this->never())->method('create'); - - $container = Container::fromDice($dice); - - $this->assertInstanceOf(Container::class, $container); - } - - public function testCreateFromContainer(): void - { - $dice = $this->createMock(Dice::class); - $dice->expects($this->once())->method('create')->with(LoggerInterface::class)->willReturn(new NullLogger()); - - $container = Container::fromDice($dice); - - $this->assertInstanceOf(NullLogger::class, $container->create(LoggerInterface::class)); - } - - public function testAddRuleFromContainer(): void - { - $dice = $this->createMock(Dice::class); - $dice->expects($this->once())->method('addRule')->with(LoggerInterface::class, ['constructParams' => ['console']])->willReturn($dice); - - $container = Container::fromDice($dice); - $container->addRule(LoggerInterface::class, ['constructParams' => ['console']]); - } -} diff --git a/tests/Unit/Core/DiceContainerTest.php b/tests/Unit/Core/DiceContainerTest.php new file mode 100644 index 0000000000..85d64de728 --- /dev/null +++ b/tests/Unit/Core/DiceContainerTest.php @@ -0,0 +1,52 @@ + [ + 'dependencies.config.php' => 'url()); + + $this->assertInstanceOf(Container::class, $container); + } + + public function testCreateReturnsObject(): void + { + $root = vfsStream::setup('friendica', null, [ + 'static' => [ + 'dependencies.config.php' => <<< PHP + [ + 'instanceOf' => \Psr\Log\NullLogger::class, + ], + ]; + PHP, + ], + ]); + + $container = DiceContainer::fromBasePath($root->url()); + + $this->assertInstanceOf(NullLogger::class, $container->create(LoggerInterface::class)); + } +} diff --git a/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php b/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php new file mode 100644 index 0000000000..9ef920c71f --- /dev/null +++ b/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php @@ -0,0 +1,36 @@ +createStub(ICanCreateInstances::class), + $this->createStub(IManageConfigValues::class), + $this->createStub(Profiler::class), + ); + + $this->assertInstanceOf( + LoggerInterface::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } +} diff --git a/tests/Unit/Core/Logger/LoggerManagerTest.php b/tests/Unit/Core/Logger/LoggerManagerTest.php new file mode 100644 index 0000000000..02f9c0b2e2 --- /dev/null +++ b/tests/Unit/Core/Logger/LoggerManagerTest.php @@ -0,0 +1,129 @@ +setAccessible(true); + $reflectionProperty->setValue(null, null); + + $reflectionProperty = new \ReflectionProperty(LoggerManager::class, 'logChannel'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue(null, LogChannel::DEFAULT); + } + + public function testGetLoggerReturnsPsrLogger(): void + { + $factory = new LoggerManager( + $this->createStub(IManageConfigValues::class), + $this->createStub(LoggerFactory::class) + ); + + $this->assertInstanceOf(LoggerInterface::class, $factory->getLogger()); + } + + public function testGetLoggerReturnsSameObject(): void + { + $factory = new LoggerManager( + $this->createStub(IManageConfigValues::class), + $this->createStub(LoggerFactory::class) + ); + + $this->assertSame($factory->getLogger(), $factory->getLogger()); + } + + public function testGetLoggerWithDebugDisabledReturnsNullLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'debugging', null, false], + ]); + + $factory = new LoggerManager( + $config, + $this->createStub(LoggerFactory::class) + ); + + $this->assertInstanceOf(NullLogger::class, $factory->getLogger()); + } + + public function testGetLoggerWithProfilerEnabledReturnsProfilerLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'debugging', null, false], + ['system', 'profiling', null, true], + ]); + + $factory = new LoggerManager( + $config, + $this->createStub(LoggerFactory::class) + ); + + $this->assertInstanceOf(ProfilerLogger::class, $factory->getLogger()); + } + + public function testChangeLogChannelReturnsDifferentLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'debugging', null, false], + ['system', 'profiling', null, true], + ]); + + $factory = new LoggerManager( + $config, + $this->createStub(LoggerFactory::class) + ); + + $logger1 = $factory->getLogger(); + + $factory->changeLogChannel(LogChannel::CONSOLE); + + $this->assertNotSame($logger1, $factory->getLogger()); + } + + public function testChangeLogChannelToWorkerReturnsWorkerLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'debugging', null, false], + ['system', 'profiling', null, true], + ]); + + $factory = new LoggerManager( + $config, + $this->createStub(LoggerFactory::class) + ); + + $factory->changeLogChannel(LogChannel::WORKER); + + $this->assertInstanceOf(WorkerLogger::class, $factory->getLogger()); + } +} diff --git a/tests/functional/DependencyCheckTest.php b/tests/functional/DependencyCheckTest.php index 866380fbdf..ec27d205d6 100644 --- a/tests/functional/DependencyCheckTest.php +++ b/tests/functional/DependencyCheckTest.php @@ -21,7 +21,7 @@ use Psr\Log\LoggerInterface; class DependencyCheckTest extends FixtureTestCase { - protected function setUp() : void + protected function setUp(): void { parent::setUp(); @@ -118,18 +118,6 @@ class DependencyCheckTest extends FixtureTestCase self::assertInstanceOf(LoggerInterface::class, $logger); } - public function testDevLogger() - { - /** @var IManageConfigValues $config */ - $config = $this->dice->create(IManageConfigValues::class); - $config->set('system', 'dlogfile', $this->root->url() . '/friendica.log'); - - /** @var LoggerInterface $logger */ - $logger = $this->dice->create('$devLogger', ['dev']); - - self::assertInstanceOf(LoggerInterface::class, $logger); - } - public function testCache() { /** @var ICanCache $cache */ diff --git a/view/js/dropzone-factory.js b/view/js/dropzone-factory.js index bdb2353f1d..dcc0468cb2 100644 --- a/view/js/dropzone-factory.js +++ b/view/js/dropzone-factory.js @@ -23,6 +23,10 @@ var DzFactory = function (max_imagesize) { dictRemoveFile: dzStrings.dictRemoveFile, dictMaxFilesExceeded: dzStrings.dictMaxFilesExceeded, accept: function(file, done) { + const targetTextarea = document.getElementById(textareaElementId); + if (targetTextarea.setRangeText) { + targetTextarea.setRangeText("\n[upload-" + file.name + "]\n", targetTextarea.selectionStart, targetTextarea.selectionEnd, "end"); + } done(); }, init: function() { @@ -30,7 +34,8 @@ var DzFactory = function (max_imagesize) { const targetTextarea = document.getElementById(textareaElementId); if (targetTextarea.setRangeText) { //if setRangeText function is supported by current browser - targetTextarea.setRangeText(serverResponse); + let u = "[upload-" + file.name + "]"; + targetTextarea.setRangeText(serverResponse, targetTextarea.value.indexOf(u), targetTextarea.value.indexOf(u) + u.length, "end"); } else { targetTextarea.focus(); document.execCommand('insertText', false /*no UI*/, serverResponse); diff --git a/view/templates/item/compose.tpl b/view/templates/item/compose.tpl index 4cccc924c3..4c7bdebfdb 100644 --- a/view/templates/item/compose.tpl +++ b/view/templates/item/compose.tpl @@ -92,6 +92,9 @@