diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 96b26790..4241f1ff 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -10,6 +10,8 @@ on: - 'phpunit.xml.dist' push: + branches: + - master paths-ignore: - 'docs/**' - 'README.md' @@ -28,4 +30,12 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1'] + ['8.0', '8.1', '8.2'] + psalm83: + uses: yiisoft/actions/.github/workflows/psalm.yml@master + with: + psalm-config: 'psalm-8.3.xml' + os: >- + ['ubuntu-latest'] + php: >- + ['8.3'] diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a6bc6d8..9b3ffa87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ## 2.0.1 under development - Bug #84: Change the type of the `$level` parameter in the `Message` constructor to `string` (@dood-) +- New #104: Add new static methods `Logger::assertLevelIsValid()`, `Logger::assertLevelIsString()` and + `Logger::assertLevelIsSupported()` (@vjik) +- Chg #104: Deprecate method `Logger::validateLevel()` (@vjik) ## 2.0.0 May 22, 2022 diff --git a/composer.json b/composer.json index a7a83089..d5a35a83 100644 --- a/composer.json +++ b/composer.json @@ -37,10 +37,10 @@ "require-dev": { "maglnet/composer-require-checker": "^4.4", "phpunit/phpunit": "^9.5", - "rector/rector": "^1.0.0", + "rector/rector": "1.0.*", "roave/infection-static-analysis-plugin": "^1.18", "spatie/phpunit-watcher": "^1.23", - "vimeo/psalm": "^4.22" + "vimeo/psalm": "^4.30|^5.24" }, "provide": { "psr/log-implementation": "1.0.0" diff --git a/psalm-8.3.xml b/psalm-8.3.xml new file mode 100644 index 00000000..b2cc7e41 --- /dev/null +++ b/psalm-8.3.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/psalm.xml b/psalm.xml index 2f9469cb..95805489 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,5 +13,8 @@ + + + diff --git a/src/Logger.php b/src/Logger.php index fdd1424b..cbc385c7 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -116,6 +116,7 @@ public function __construct(array $targets = []) * @throws \Psr\Log\InvalidArgumentException for invalid log message level. * * @return string The text display of the level. + * @deprecated since 2.1, to be removed in 3.0. Use {@see LogLevel::assertLevelIsValid()} instead. */ public static function validateLevel(mixed $level): string { @@ -146,12 +147,13 @@ public function getTargets(): array } /** - * @param string $level * @psalm-param LogMessageContext $context - * @psalm-suppress MoreSpecificImplementedParamType + * @psalm-suppress MoreSpecificImplementedParamType,MixedArgumentTypeCoercion */ public function log(mixed $level, string|Stringable $message, array $context = []): void { + self::assertLevelIsString($level); + $context['time'] ??= microtime(true); $context['trace'] ??= $this->collectTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); $context['memory'] ??= memory_get_usage(); @@ -230,6 +232,61 @@ public function setExcludedTracePaths(array $excludedTracePaths): self return $this; } + /** + * Asserts that the log message level is valid. + * + * @param mixed $level The message level. + * + * @throws \Psr\Log\InvalidArgumentException When the log message level is not a string or is not supported. + */ + public static function assertLevelIsValid(mixed $level): void + { + self::assertLevelIsString($level); + self::assertLevelIsSupported($level); + } + + /** + * Asserts that the log message level is a string. + * + * @param mixed $level The message level. + * + * @throws \Psr\Log\InvalidArgumentException When the log message level is not a string. + * + * @psalm-assert string $level + */ + public static function assertLevelIsString(mixed $level): void + { + if (is_string($level)) { + return; + } + + throw new \Psr\Log\InvalidArgumentException( + sprintf('The log message level must be a string, %s provided.', gettype($level)) + ); + } + + /** + * Asserts that the log message level is supported. + * + * @param string $level The message level. + * + * @throws \Psr\Log\InvalidArgumentException When the log message level is not supported. + */ + public static function assertLevelIsSupported(string $level): void + { + if (in_array($level, self::LEVELS, true)) { + return; + } + + throw new \Psr\Log\InvalidArgumentException( + sprintf( + 'Invalid log message level "%s" provided. The following values are supported: "%s".', + $level, + implode('", "', self::LEVELS) + ) + ); + } + /** * Sets a target to {@see Logger::$targets}. * diff --git a/src/Message.php b/src/Message.php index d1e49bd3..910f6833 100644 --- a/src/Message.php +++ b/src/Message.php @@ -68,7 +68,8 @@ final class Message */ public function __construct(string $level, string|Stringable $message, array $context = []) { - $this->level = Logger::validateLevel($level); + Logger::assertLevelIsSupported($level); + $this->level = $level; $this->message = $this->parse($message, $context); $this->context = $context; } diff --git a/src/Message/Formatter.php b/src/Message/Formatter.php index a3d41fe8..e7979c62 100644 --- a/src/Message/Formatter.php +++ b/src/Message/Formatter.php @@ -250,7 +250,7 @@ private function getTrace(Message $message): string /** * Converts a value to a string. * - * @param mixed $value The value to convert + * @param mixed $value The value to convert. * * @return string Converted string. */ diff --git a/src/Target.php b/src/Target.php index 1f7c402e..792caffc 100644 --- a/src/Target.php +++ b/src/Target.php @@ -160,7 +160,8 @@ public function setExcept(array $except): self public function setLevels(array $levels): self { foreach ($levels as $key => $level) { - $levels[$key] = Logger::validateLevel($level); + Logger::assertLevelIsValid($level); + $levels[$key] = $level; } $this->levels = $levels; diff --git a/tests/TargetTest.php b/tests/TargetTest.php index 13eae6a4..50dfa3fa 100644 --- a/tests/TargetTest.php +++ b/tests/TargetTest.php @@ -132,8 +132,6 @@ public function invalidCallableEnabledProvider(): array /** * @dataProvider invalidCallableEnabledProvider - * - * @param mixed $value */ public function testIsEnabledThrowExceptionForCallableReturnNotBoolean(callable $value): void {