diff --git a/src/Core/L10n.php b/src/Core/L10n.php index 79d83950a9..d1af1c0e61 100644 --- a/src/Core/L10n.php +++ b/src/Core/L10n.php @@ -51,6 +51,11 @@ class L10n 'zh-cn' => '简体中文', ]; + const LANG_PARENTS = [ + 'en-gb' => 'en', 'da-dk' => 'da', 'fi-fi' => 'fi', + 'nb-no' => 'nb', 'pt-br' => 'pt', 'zh-cn' => 'zh' + ]; + /** @var string Undetermined language */ const UNDETERMINED_LANGUAGE = 'un'; @@ -150,6 +155,11 @@ class L10n $a = new \stdClass(); $a->strings = []; + $child = array_search($lang, $this::LANG_PARENTS); + if ($child) { + $lang = $child; + } + // load enabled addons strings $addons = array_keys($this->config->get('addons') ?? []); foreach ($addons as $addon) { @@ -203,6 +213,8 @@ class L10n // start with quality zero (every guessed language is more acceptable ..) $current_q = 0; + $supported = self::getSupportedLanguages(); + foreach ($acceptedLanguages as $acceptedLanguage) { $res = preg_match( '/^([a-z]{1,8}(?:-[a-z]{1,8})*)(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i', @@ -230,8 +242,7 @@ class L10n while (count($lang_code)) { // try to mix them so we can get double-code parts too $match_lang = strtolower(join('-', $lang_code)); - if (file_exists(__DIR__ . "/../../view/lang/$match_lang") && - is_dir(__DIR__ . "/../../view/lang/$match_lang")) { + if (in_array($match_lang, $supported)) { if ($lang_quality > $current_q) { $current_lang = $match_lang; $current_q = $lang_quality; @@ -247,6 +258,20 @@ class L10n return $current_lang; } + private static function getSupportedLanguages(): array + { + $languages = []; + foreach (glob('view/lang/*/strings.php') as $language) { + $code = str_replace(['view/lang/', '/strings.php'], [], $language); + if (!empty(self::LANG_PARENTS[$code])) { + $languages[] = self::LANG_PARENTS[$code]; + } + $languages[] = $code; + } + + return $languages; + } + /** * Return the localized version of the provided string with optional string interpolation * @@ -402,8 +427,10 @@ class L10n ]; if (in_array('cld2', get_loaded_extensions())) { - $additional_langs = array_merge($additional_langs, - ['dv', 'kn', 'lo', 'ml', 'or', 'pa', 'sd', 'si', 'te', 'yi']); + $additional_langs = array_merge( + $additional_langs, + ['dv', 'kn', 'lo', 'ml', 'or', 'pa', 'sd', 'si', 'te', 'yi'] + ); } $langs = array_merge($additional_langs, array_keys($this->getAvailableLanguages())); @@ -419,7 +446,7 @@ class L10n */ public function getLanguageCodes(bool $international = false): array { - $iso639 = new \Matriphe\ISO639\ISO639; + $iso639 = new \Matriphe\ISO639\ISO639(); // In ISO 639-2 undetermined languages have got the code "und". // There is no official code for ISO 639-1, but "un" is not assigned to any language. @@ -477,13 +504,17 @@ class L10n */ public function getDay(string $s): string { - $ret = str_replace(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], + $ret = str_replace( + ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], [$this->t('Monday'), $this->t('Tuesday'), $this->t('Wednesday'), $this->t('Thursday'), $this->t('Friday'), $this->t('Saturday'), $this->t('Sunday')], - $s); + $s + ); - $ret = str_replace(['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + $ret = str_replace( + ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], [$this->t('January'), $this->t('February'), $this->t('March'), $this->t('April'), $this->t('May'), $this->t('June'), $this->t('July'), $this->t('August'), $this->t('September'), $this->t('October'), $this->t('November'), $this->t('December')], - $ret); + $ret + ); return $ret; } @@ -496,13 +527,17 @@ class L10n */ public function getDayShort(string $s): string { - $ret = str_replace(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + $ret = str_replace( + ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], [$this->t('Mon'), $this->t('Tue'), $this->t('Wed'), $this->t('Thu'), $this->t('Fri'), $this->t('Sat'), $this->t('Sun')], - $s); + $s + ); - $ret = str_replace(['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + $ret = str_replace( + ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], [$this->t('Jan'), $this->t('Feb'), $this->t('Mar'), $this->t('Apr'), $this->t('May'), $this->t('Jun'), $this->t('Jul'), $this->t('Aug'), $this->t('Sep'), $this->t('Oct'), $this->t('Nov'), $this->t('Dec')], - $ret); + $ret + ); return $ret; } diff --git a/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php b/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php index 08a9559279..98c05e187c 100644 --- a/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php +++ b/src/Core/Logger/Factory/AbstractLoggerTypeFactory.php @@ -12,6 +12,8 @@ use Psr\Log\LogLevel; /** * Abstract class for creating logger types, which includes common necessary logic/content + * + * @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead */ abstract class AbstractLoggerTypeFactory { @@ -25,6 +27,8 @@ abstract class AbstractLoggerTypeFactory */ public function __construct(IHaveCallIntrospections $introspection, string $channel) { + @trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + $this->channel = $channel; $this->introspection = $introspection; } @@ -44,21 +48,21 @@ abstract class AbstractLoggerTypeFactory // legacy WARNING case "0": return LogLevel::ERROR; - // legacy INFO + // legacy INFO case "1": return LogLevel::WARNING; - // legacy TRACE + // legacy TRACE case "2": return LogLevel::NOTICE; - // legacy DEBUG + // legacy DEBUG case "3": return LogLevel::INFO; - // legacy DATA + // legacy DATA case "4": - // legacy ALL + // legacy ALL case "5": return LogLevel::DEBUG; - // default if nothing set + // default if nothing set default: return $level; } diff --git a/src/Core/Logger/Factory/DelegatingLoggerFactory.php b/src/Core/Logger/Factory/DelegatingLoggerFactory.php new file mode 100644 index 0000000000..f0001132dd --- /dev/null +++ b/src/Core/Logger/Factory/DelegatingLoggerFactory.php @@ -0,0 +1,73 @@ + */ + private array $factories = []; + + public function __construct(IManageConfigValues $config) + { + $this->config = $config; + } + + public function registerFactory(string $name, LoggerFactory $factory): void + { + $this->factories[$name] = $factory; + } + + /** + * 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 + { + $factoryName = $this->config->get('system', 'logger_config') ?? ''; + + /** + * @deprecated 2025.02 The value `monolog` for `system.logger_config` inside the `config/local.config.php` file is deprecated, please use `stream` or `syslog` instead. + */ + if ($factoryName === 'monolog') { + @trigger_error('The config `system.logger_config` with value `monolog` is deprecated since 2025.02 and will stop working in 5 months, please change the value to `stream` or `syslog` in the `config/local.config.php` file.', \E_USER_DEPRECATED); + + $factoryName = 'stream'; + } + + if (!array_key_exists($factoryName, $this->factories)) { + return new NullLogger(); + } + + $factory = $this->factories[$factoryName]; + + try { + $logger = $factory->createLogger($logLevel, $logChannel); + } catch (\Throwable $th) { + return new NullLogger(); + } + + return $logger; + } +} diff --git a/src/Core/Logger/Factory/LegacyLoggerFactory.php b/src/Core/Logger/Factory/LegacyLoggerFactory.php deleted file mode 100644 index 2c7b6c0237..0000000000 --- a/src/Core/Logger/Factory/LegacyLoggerFactory.php +++ /dev/null @@ -1,61 +0,0 @@ -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/Logger.php b/src/Core/Logger/Factory/Logger.php index fbee580544..78451e713d 100644 --- a/src/Core/Logger/Factory/Logger.php +++ b/src/Core/Logger/Factory/Logger.php @@ -18,6 +18,8 @@ use Throwable; /** * The logger factory for the core logging instances + * + * @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead */ class Logger { @@ -26,6 +28,8 @@ class Logger public function __construct(string $channel = LogChannel::DEFAULT) { + @trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + $this->channel = $channel; } diff --git a/src/Core/Logger/Factory/StreamLogger.php b/src/Core/Logger/Factory/StreamLogger.php index e14fe8258f..b2c6de7f3e 100644 --- a/src/Core/Logger/Factory/StreamLogger.php +++ b/src/Core/Logger/Factory/StreamLogger.php @@ -20,6 +20,8 @@ use Psr\Log\NullLogger; /** * The logger factory for the StreamLogger instance * + * @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @see StreamLoggerFactory * @see StreamLoggerClass */ class StreamLogger extends AbstractLoggerTypeFactory @@ -38,6 +40,8 @@ class StreamLogger extends AbstractLoggerTypeFactory */ public function create(IManageConfigValues $config, string $logfile = null, string $channel = null): LoggerInterface { + @trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + $fileSystem = new FileSystem(); $logfile = $logfile ?? $config->get('system', 'logfile'); diff --git a/src/Core/Logger/Factory/StreamLoggerFactory.php b/src/Core/Logger/Factory/StreamLoggerFactory.php new file mode 100644 index 0000000000..8119c40430 --- /dev/null +++ b/src/Core/Logger/Factory/StreamLoggerFactory.php @@ -0,0 +1,76 @@ +config = $config; + $this->introspection = $introspection; + $this->fileSystem = $fileSystem; + } + + /** + * 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 + * + * @throws LoggerArgumentException + * @throws LogLevelException + */ + public function createLogger(string $logLevel, string $logChannel): LoggerInterface + { + $logfile = $this->config->get('system', 'logfile'); + + if (!file_exists($logfile) || !is_writable($logfile)) { + throw new LoggerArgumentException(sprintf('"%s" is not a valid logfile.', $logfile)); + } + + if (! array_key_exists($logLevel, StreamLogger::levelToInt)) { + throw new LogLevelException(sprintf('The log level "%s" is not supported by "%s".', $logLevel, StreamLogger::class)); + } + + return new StreamLogger( + $logChannel, + $this->introspection, + $this->fileSystem->createStream($logfile), + StreamLogger::levelToInt[$logLevel], + getmypid() + ); + } +} diff --git a/src/Core/Logger/Factory/SyslogLogger.php b/src/Core/Logger/Factory/SyslogLogger.php index e9b59f1186..d9f98f05fd 100644 --- a/src/Core/Logger/Factory/SyslogLogger.php +++ b/src/Core/Logger/Factory/SyslogLogger.php @@ -16,6 +16,8 @@ use Psr\Log\LoggerInterface; /** * The logger factory for the SyslogLogger instance * + * @deprecated 2025.02 Implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead + * @see SyslogLoggerFactory * @see SyslogLoggerClass */ class SyslogLogger extends AbstractLoggerTypeFactory @@ -31,6 +33,8 @@ class SyslogLogger extends AbstractLoggerTypeFactory */ public function create(IManageConfigValues $config): LoggerInterface { + @trigger_error('Class `' . __CLASS__ . '` is deprecated since 2025.02 and will be removed after 5 months, implement `\Friendica\Core\Logger\Factory\LoggerFactory` instead.', E_USER_DEPRECATED); + $logOpts = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS; $logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY; $loglevel = SyslogLogger::mapLegacyConfigDebugLevel($config->get('system', 'loglevel')); diff --git a/src/Core/Logger/Factory/SyslogLoggerFactory.php b/src/Core/Logger/Factory/SyslogLoggerFactory.php new file mode 100644 index 0000000000..24a884a5f9 --- /dev/null +++ b/src/Core/Logger/Factory/SyslogLoggerFactory.php @@ -0,0 +1,66 @@ +config = $config; + $this->introspection = $introspection; + } + + /** + * 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 + * + * @throws LogLevelException + */ + public function createLogger(string $logLevel, string $logChannel): LoggerInterface + { + $logOpts = (string) $this->config->get('system', 'syslog_flags') ?? SyslogLogger::DEFAULT_FLAGS; + $logFacility = (string) $this->config->get('system', 'syslog_facility') ?? SyslogLogger::DEFAULT_FACILITY; + + if (!array_key_exists($logLevel, SyslogLogger::logLevels)) { + throw new LogLevelException(sprintf('The log level "%s" is not supported by "%s".', $logLevel, SyslogLogger::class)); + } + + return new SyslogLogger( + $logChannel, + $this->introspection, + (string) SyslogLogger::logLevels[$logLevel], + $logOpts, + $logFacility + ); + } +} diff --git a/src/Core/Logger/Util/FileSystem.php b/src/Core/Logger/Util/FileSystem.php index 2d05faf50d..97162dacb8 100644 --- a/src/Core/Logger/Util/FileSystem.php +++ b/src/Core/Logger/Util/FileSystem.php @@ -12,7 +12,7 @@ use Friendica\Core\Logger\Exception\LoggerUnusableException; /** * Util class for filesystem manipulation for Logger classes */ -class FileSystem +class FileSystem implements FileSystemUtil { /** * @var string a error message @@ -31,7 +31,7 @@ class FileSystem public function createDir(string $file): string { $dirname = null; - $pos = strpos($file, '://'); + $pos = strpos($file, '://'); if (!$pos) { $dirname = realpath(dirname($file)); diff --git a/src/Core/Logger/Util/FileSystemUtil.php b/src/Core/Logger/Util/FileSystemUtil.php new file mode 100644 index 0000000000..1c1bbc2726 --- /dev/null +++ b/src/Core/Logger/Util/FileSystemUtil.php @@ -0,0 +1,40 @@ + Protocol::BLUESKY, 'url' => $profile->did, - 'alias' => ATProtocol::WEB . '/profile/' . $nick, + 'alias' => ATProtocol::WEB . '/profile/' . $profile->did, 'name' => $name ?: $nick, 'nick' => $nick, 'addr' => $nick, diff --git a/src/Protocol/ATProtocol/Actor.php b/src/Protocol/ATProtocol/Actor.php index 862d10eeea..db310813b3 100755 --- a/src/Protocol/ATProtocol/Actor.php +++ b/src/Protocol/ATProtocol/Actor.php @@ -117,7 +117,7 @@ class Actor $name = $profile->displayName ?? $nick; $fields = [ - 'alias' => ATProtocol::WEB . '/profile/' . $nick, + 'alias' => ATProtocol::WEB . '/profile/' . $profile->did, 'name' => $name ?: $nick, 'nick' => $nick, 'addr' => $nick, diff --git a/src/Protocol/ATProtocol/Processor.php b/src/Protocol/ATProtocol/Processor.php index 502b31ea4a..d7a26f78cf 100755 --- a/src/Protocol/ATProtocol/Processor.php +++ b/src/Protocol/ATProtocol/Processor.php @@ -72,7 +72,7 @@ class Processor public function processIdentity(stdClass $data) { $fields = [ - 'alias' => ATProtocol::WEB . '/profile/' . $data->identity->handle, + 'alias' => ATProtocol::WEB . '/profile/' . $data->identity->did, 'nick' => $data->identity->handle, 'addr' => $data->identity->handle, 'updated' => DateTimeFormat::utc($data->identity->time, DateTimeFormat::MYSQL), diff --git a/static/defaults.config.php b/static/defaults.config.php index d821ff1813..df84d66899 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -334,7 +334,8 @@ return [ 'lock_driver' => '', // logger_config (String) - // Sets the logging adapter of Friendica globally (monolog, syslog, stream) + // Sets the logging adapter of Friendica globally (syslog, stream) + // @deprecated 2025.02 The value `monolog` is deprecated, please use `stream` or `syslog` instead. 'logger_config' => 'stream', // syslog_flags (Integer) diff --git a/static/dependencies.config.php b/static/dependencies.config.php index 5924ae512e..644cb5f765 100644 --- a/static/dependencies.config.php +++ b/static/dependencies.config.php @@ -171,11 +171,24 @@ return (function(string $basepath, array $getVars, array $serverVars, array $coo ], \Friendica\Core\Logger\LoggerManager::class => [ 'substitutions' => [ - \Friendica\Core\Logger\Factory\LoggerFactory::class => \Friendica\Core\Logger\Factory\LegacyLoggerFactory::class, + \Friendica\Core\Logger\Factory\LoggerFactory::class => \Friendica\Core\Logger\Factory\DelegatingLoggerFactory::class, ], ], \Friendica\Core\Logger\Factory\LoggerFactory::class => [ - 'instanceOf' => \Friendica\Core\Logger\Factory\LegacyLoggerFactory::class, + 'instanceOf' => \Friendica\Core\Logger\Factory\DelegatingLoggerFactory::class, + 'call' => [ + ['registerFactory', ['stream', [Dice::INSTANCE => '$StreamLoggerFactory']]], + ['registerFactory', ['syslog', [Dice::INSTANCE => '$SyslogLoggerFactory']]], + ], + ], + '$StreamLoggerFactory' => [ + 'instanceOf' => \Friendica\Core\Logger\Factory\StreamLoggerFactory::class, + 'substitutions' => [ + \Friendica\Core\Logger\Util\FileSystemUtil::class => \Friendica\Core\Logger\Util\FileSystem::class, + ], + ], + '$SyslogLoggerFactory' => [ + 'instanceOf' => \Friendica\Core\Logger\Factory\SyslogLoggerFactory::class, ], \Friendica\Core\Logger\Type\SyslogLogger::class => [ 'instanceOf' => \Friendica\Core\Logger\Factory\SyslogLogger::class, diff --git a/tests/Unit/Core/Logger/Factory/DelegatingLoggerFactoryTest.php b/tests/Unit/Core/Logger/Factory/DelegatingLoggerFactoryTest.php new file mode 100644 index 0000000000..b0fd92cafd --- /dev/null +++ b/tests/Unit/Core/Logger/Factory/DelegatingLoggerFactoryTest.php @@ -0,0 +1,75 @@ +createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logger_config', null, 'test'], + ]); + + $factory = new DelegatingLoggerFactory($config); + + $factory->registerFactory('test', $this->createStub(LoggerFactory::class)); + + $this->assertInstanceOf( + LoggerInterface::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } + + public function testCreateLoggerWithoutRegisteredFactoryReturnsNullLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logger_config', null, 'not-existing-factory'], + ]); + + $factory = new DelegatingLoggerFactory($config); + + $this->assertInstanceOf( + NullLogger::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } + + public function testCreateLoggerWithExceptionThrowingFactoryReturnsNullLogger(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logger_config', null, 'test'], + ]); + + $factory = new DelegatingLoggerFactory($config); + + $brokenFactory = $this->createStub(LoggerFactory::class); + $brokenFactory->method('createLogger')->willThrowException(new Exception()); + + $factory->registerFactory('test', $brokenFactory); + + $this->assertInstanceOf( + NullLogger::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } +} diff --git a/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php b/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php deleted file mode 100644 index 9ef920c71f..0000000000 --- a/tests/Unit/Core/Logger/Factory/LegacyLoggerFactoryTest.php +++ /dev/null @@ -1,36 +0,0 @@ -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/Factory/StreamLoggerFactoryTest.php b/tests/Unit/Core/Logger/Factory/StreamLoggerFactoryTest.php new file mode 100644 index 0000000000..744d597f19 --- /dev/null +++ b/tests/Unit/Core/Logger/Factory/StreamLoggerFactoryTest.php @@ -0,0 +1,81 @@ +createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logfile', null, dirname(__DIR__, 4) . '/datasets/log/empty.friendica.log.txt'], + ]); + + $factory = new StreamLoggerFactory( + $config, + $this->createStub(IHaveCallIntrospections::class), + $this->createStub(FileSystemUtil::class), + ); + + $this->assertInstanceOf( + LoggerInterface::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } + + public function testCreateLoggerWithInvalidLogfileThrowsException(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logfile', null, dirname(__DIR__, 1) . '/not-existing-logfile.txt'], + ]); + + $factory = new StreamLoggerFactory( + $config, + $this->createStub(IHaveCallIntrospections::class), + $this->createStub(FileSystemUtil::class), + ); + + $this->expectException(LoggerArgumentException::class); + $this->expectExceptionMessage('tests/Unit/Core/Logger/not-existing-logfile.txt" is not a valid logfile.'); + + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT); + } + + public function testCreateLoggerWithInvalidLoglevelThrowsException(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'logfile', null, dirname(__DIR__, 4) . '/datasets/log/empty.friendica.log.txt'], + ]); + + $factory = new StreamLoggerFactory( + $config, + $this->createStub(IHaveCallIntrospections::class), + $this->createStub(FileSystemUtil::class), + ); + + $this->expectException(LogLevelException::class); + $this->expectExceptionMessage('The log level "unsupported-loglevel" is not supported by "Friendica\Core\Logger\Type\StreamLogger".'); + + $factory->createLogger('unsupported-loglevel', LogChannel::DEFAULT); + } +} diff --git a/tests/Unit/Core/Logger/Factory/SyslogLoggerFactoryTest.php b/tests/Unit/Core/Logger/Factory/SyslogLoggerFactoryTest.php new file mode 100644 index 0000000000..7f94c66fcd --- /dev/null +++ b/tests/Unit/Core/Logger/Factory/SyslogLoggerFactoryTest.php @@ -0,0 +1,61 @@ +createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'syslog_flags', null, SyslogLogger::DEFAULT_FLAGS], + ['system', 'syslog_facility', null, SyslogLogger::DEFAULT_FACILITY], + ]); + + $factory = new SyslogLoggerFactory( + $config, + $this->createStub(IHaveCallIntrospections::class), + ); + + $this->assertInstanceOf( + LoggerInterface::class, + $factory->createLogger(LogLevel::DEBUG, LogChannel::DEFAULT) + ); + } + + public function testCreateLoggerWithInvalidLoglevelThrowsException(): void + { + $config = $this->createStub(IManageConfigValues::class); + $config->method('get')->willReturnMap([ + ['system', 'syslog_flags', null, SyslogLogger::DEFAULT_FLAGS], + ['system', 'syslog_facility', null, SyslogLogger::DEFAULT_FACILITY], + ]); + + $factory = new SyslogLoggerFactory( + $config, + $this->createStub(IHaveCallIntrospections::class), + ); + + $this->expectException(LogLevelException::class); + $this->expectExceptionMessage('The log level "unsupported-loglevel" is not supported by "Friendica\Core\Logger\Type\SyslogLogger".'); + + $factory->createLogger('unsupported-loglevel', LogChannel::DEFAULT); + } +} diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index 6aa876a002..37edb7118a 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -61,7 +61,7 @@ {{if $nav.network}}