From 1ec60231b256637a44bc4816954d8b37de8ad046 Mon Sep 17 00:00:00 2001 From: sasezaki Date: Sat, 25 Oct 2025 11:25:42 +0900 Subject: [PATCH] Add optional PSR-3 message placeholder interpolation to TestLogger --- src/Test/TestLogger.php | 34 ++++++++++++++++++++++++++++++++++ tests/Test/TestLoggerTest.php | 8 ++++++++ 2 files changed, 42 insertions(+) diff --git a/src/Test/TestLogger.php b/src/Test/TestLogger.php index e3af87f..6ac6f7f 100644 --- a/src/Test/TestLogger.php +++ b/src/Test/TestLogger.php @@ -17,11 +17,22 @@ class TestLogger implements LoggerInterface public array $records = []; public array $recordsByLevel = []; + private bool $placeholderInterpolation; + + public function __construct(bool $placeholderInterpolation = false) + { + $this->placeholderInterpolation = $placeholderInterpolation; + } + /** * @inheritdoc */ public function log($level, string|\Stringable $message, array $context = []): void { + if ($this->placeholderInterpolation === true) { + $message = $this->interpolate($message, $context); + } + $record = [ 'level' => $level, 'message' => $message, @@ -325,4 +336,27 @@ public function reset() $this->records = []; $this->recordsByLevel = []; } + + /** + * Interpolates context values into the message placeholders. + * + * @param string|\Stringable $message + * @param array $context + * @return string + */ + private function interpolate($message, array $context = []) : string + { + // build a replacement array with braces around the context keys + $replace = array(); + foreach ($context as $key => $val) { + // check that the value can be cast to string + if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { + $replace['{' . $key . '}'] = $val; + } + } + + // interpolate replacement values into the message and return + return strtr($message, $replace); + } + } diff --git a/tests/Test/TestLoggerTest.php b/tests/Test/TestLoggerTest.php index 05cc47a..f866f8e 100644 --- a/tests/Test/TestLoggerTest.php +++ b/tests/Test/TestLoggerTest.php @@ -116,4 +116,12 @@ public function testFalseHasRecord(): void $this->assertFalse($logger->hasDebugThatMatches('/warning message/')); $this->assertFalse($logger->hasDebugThatPasses(fn (array $record) => 'warning message' === $record['message'])); } + + public function testPlaceholderInterpolation() : void + { + $logger = new TestLogger(true); + $message = 'User {username} created'; + $logger->debug($message, ['username' => 'bolivar']); + $this->assertTrue($logger->hasDebugThatContains('User bolivar created')); + } }