From f21f77e4dbd77141be5be85c49013e63c9246139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Br=C3=BCckner?= Date: Mon, 19 Dec 2022 16:19:31 +0100 Subject: [PATCH 1/3] Adds missing installation page to the documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Frank Brückner Signed-off-by: Ionut Cioflan --- docs/book/installation.md | 5 +++++ mkdocs.yml | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 docs/book/installation.md diff --git a/docs/book/installation.md b/docs/book/installation.md new file mode 100644 index 00000000..be1198c9 --- /dev/null +++ b/docs/book/installation.md @@ -0,0 +1,5 @@ +# This Is Only a Placeholder + +The content of this page can be found under: + +https://github.com/laminas/documentation-theme/blob/master/theme/pages/installation.html diff --git a/mkdocs.yml b/mkdocs.yml index c18d290e..5ab4eba9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,6 +3,7 @@ site_dir: docs/html nav: - Home: index.md - Introduction: intro.md + - Installation: installation.md - Reference: - Writers: writers.md - Filters: filters.md @@ -15,3 +16,6 @@ site_description: 'Robust, composite logger with filtering, formatting, and PSR- repo_url: 'https://github.com/laminas/laminas-log' extra: project: Components + installation: + config_provider_class: 'Laminas\Log\ConfigProvider' + module_class: 'Laminas\Log\Module' From f7ad9c5b68499d31b0ea6e53d4afd68779435b64 Mon Sep 17 00:00:00 2001 From: Ionut Cioflan Date: Fri, 9 Jun 2023 16:44:46 +0300 Subject: [PATCH 2/3] Extend compatibility to psr/log: "^1.1.2|^2.0|^3.0" - Remove dependency to \Psr\Log\Test\LoggerInterfaceTest Signed-off-by: Ionut Cioflan --- .gitignore | 1 + composer.json | 2 +- composer.lock | 20 +++--- src/PsrLoggerAdapter.php | 23 +++---- test/Psr/DummyTest.php | 20 ++++++ test/PsrLoggerAdapterTest.php | 119 +++++++++++++++++++++++++++++++--- 6 files changed, 153 insertions(+), 32 deletions(-) create mode 100644 test/Psr/DummyTest.php diff --git a/.gitignore b/.gitignore index 5d9bb2a2..24aa7980 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /vendor/ .phpunit.result.cache .phpcs-cache +.idea diff --git a/composer.json b/composer.json index 62538d23..591a7e91 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "php": "~8.0.0 || ~8.1.0 || ~8.2.0", "laminas/laminas-servicemanager": "^3.3.0", "laminas/laminas-stdlib": "^3.0", - "psr/log": "^1.1.2" + "psr/log": "^1.1.2|^2.0|^3.0" }, "require-dev": { "ext-dom": "*", diff --git a/composer.lock b/composer.lock index 0f55ca5f..e19ec166 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "225c1c4ebbde2b3093d19d273678a3d3", + "content-hash": "9f1898a76450206b1104909e71b2b15b", "packages": [ { "name": "container-interop/container-interop", @@ -237,30 +237,30 @@ }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -281,9 +281,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.0" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2021-07-14T16:46:02+00:00" } ], "packages-dev": [ diff --git a/src/PsrLoggerAdapter.php b/src/PsrLoggerAdapter.php index 271f9b1f..bb70e386 100644 --- a/src/PsrLoggerAdapter.php +++ b/src/PsrLoggerAdapter.php @@ -22,17 +22,15 @@ class PsrLoggerAdapter extends PsrAbstractLogger { /** * Laminas\Log logger - * - * @var LoggerInterface */ - protected $logger; + protected LoggerInterface $logger; /** * Map PSR-3 LogLevels to priority * * @var array */ - protected $psrPriorityMap = [ + protected array $psrPriorityMap = [ LogLevel::EMERGENCY => Logger::EMERG, LogLevel::ALERT => Logger::ALERT, LogLevel::CRITICAL => Logger::CRIT, @@ -53,10 +51,8 @@ public function __construct(LoggerInterface $logger) /** * Returns composed LoggerInterface instance. - * - * @return LoggerInterface */ - public function getLogger() + public function getLogger(): LoggerInterface { return $this->logger; } @@ -67,16 +63,17 @@ public function getLogger() * @param mixed $level * @param string $message * @param array $context - * @return void * @throws InvalidArgumentException If log level is not recognized. */ - public function log($level, $message, array $context = []) + public function log($level, $message, array $context = []): void { if (! array_key_exists($level, $this->psrPriorityMap)) { - throw new InvalidArgumentException(sprintf( - '$level must be one of PSR-3 log levels; received %s', - var_export($level, true) - )); + throw new InvalidArgumentException( + sprintf( + '$level must be one of PSR-3 log levels; received %s', + var_export($level, true) + ) + ); } $priority = $this->psrPriorityMap[$level]; diff --git a/test/Psr/DummyTest.php b/test/Psr/DummyTest.php new file mode 100644 index 00000000..36c8a669 --- /dev/null +++ b/test/Psr/DummyTest.php @@ -0,0 +1,20 @@ + */ -class PsrLoggerAdapterTest extends LoggerInterfaceTest +class PsrLoggerAdapterTest extends TestCase { /** @var array */ - protected $psrPriorityMap = [ + protected array $psrPriorityMap = [ LogLevel::EMERGENCY => Logger::EMERG, LogLevel::ALERT => Logger::ALERT, LogLevel::CRITICAL => Logger::CRIT, @@ -32,17 +37,20 @@ class PsrLoggerAdapterTest extends LoggerInterfaceTest LogLevel::DEBUG => Logger::DEBUG, ]; + private ?MockWriter $mockWriter = null; + /** * Provides logger for LoggerInterface compat tests * * @return PsrLoggerAdapter */ - public function getLogger() + public function getLogger(): PsrLoggerInterface { $this->mockWriter = new MockWriter(); $logger = new Logger(); $logger->addProcessor('psrplaceholder'); $logger->addWriter($this->mockWriter); + return new PsrLoggerAdapter($logger); } @@ -55,18 +63,20 @@ public function getLogger() * * @return string[] */ - public function getLogs() + public function getLogs(): array { $prefixMap = array_flip($this->psrPriorityMap); + return array_map(function ($event) use ($prefixMap) { $prefix = $prefixMap[$event['priority']]; + return $prefix . ' ' . $event['message']; }, $this->mockWriter->events); } protected function tearDown(): void { - unset($this->mockWriter); + $this->mockWriter = null; } /** @@ -91,7 +101,7 @@ public function testPsrLogLevelsMapsToPriorities($logLevel, $priority): void $context = ['bar' => 'baz']; $logger = $this->getMockBuilder(Logger::class) - ->setMethods(['log']) + ->onlyMethods(['log']) ->getMock(); $logger->expects($this->once()) ->method('log') @@ -110,7 +120,7 @@ public function testPsrLogLevelsMapsToPriorities($logLevel, $priority): void * * @return array */ - public function logLevelsToPriorityProvider() + public function logLevelsToPriorityProvider(): array { $return = []; foreach ($this->psrPriorityMap as $level => $priority) { @@ -125,4 +135,97 @@ public function testThrowsOnInvalidLevel() $this->expectException(InvalidArgumentException::class); $logger->log('invalid level', 'Foo'); } + + public function testImplements() + { + $this->assertInstanceOf(PsrLoggerInterface::class, $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, ['user' => 'Bob']); + $logger->log($level, $message, ['user' => 'Bob']); + + $expected = [ + $level . ' message of level ' . $level . ' with context: Bob', + $level . ' message of level ' . $level . ' with context: Bob', + ]; + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages(): array + { + return [ + LogLevel::EMERGENCY => [LogLevel::EMERGENCY, 'message of level emergency with context: {user}'], + LogLevel::ALERT => [LogLevel::ALERT, 'message of level alert with context: {user}'], + LogLevel::CRITICAL => [LogLevel::CRITICAL, 'message of level critical with context: {user}'], + LogLevel::ERROR => [LogLevel::ERROR, 'message of level error with context: {user}'], + LogLevel::WARNING => [LogLevel::WARNING, 'message of level warning with context: {user}'], + LogLevel::NOTICE => [LogLevel::NOTICE, 'message of level notice with context: {user}'], + LogLevel::INFO => [LogLevel::INFO, 'message of level info with context: {user}'], + LogLevel::DEBUG => [LogLevel::DEBUG, 'message of level debug with context: {user}'], + ]; + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', ['user' => 'Bob', 'foo.bar' => 'Bar']); + + $expected = ['info {Message {nothing} Bob Bar a}']; + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + $dummy = $this->createPartialMock(Psr\DummyTest::class, ['__toString']); + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = ['warning DUMMY']; + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $closed = fopen('php://memory', 'r'); + fclose($closed); + + $context = [ + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => ['with object' => new Psr\DummyTest()], + 'object' => new DateTime(), + 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, + ]; + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = ['warning Crazy context data']; + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', ['exception' => 'oops']); + $logger->critical('Uncaught Exception!', ['exception' => new LogicException('Fail')]); + + $expected = [ + 'warning Random message', + 'critical Uncaught Exception!', + ]; + $this->assertEquals($expected, $this->getLogs()); + } } From 8fa35f963d7d7a6659c902b83fe76ab666530575 Mon Sep 17 00:00:00 2001 From: Ionut Cioflan Date: Fri, 9 Jun 2023 20:07:15 +0300 Subject: [PATCH 3/3] Code sniffer fix: String "Laminas\Log\Writer\Firephp" contains class reference, use ::class instead Signed-off-by: Ionut Cioflan --- test/WriterPluginManagerTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/WriterPluginManagerTest.php b/test/WriterPluginManagerTest.php index 195c60a4..b47a33a2 100644 --- a/test/WriterPluginManagerTest.php +++ b/test/WriterPluginManagerTest.php @@ -4,6 +4,7 @@ namespace LaminasTest\Log; +use Laminas\Log\Writer\FirePhp; use Laminas\Log\WriterPluginManager; use Laminas\ServiceManager\ServiceManager; use PHPUnit\Framework\TestCase; @@ -21,6 +22,6 @@ protected function setUp(): void public function testInvokableClassFirephp(): void { $firephp = $this->plugins->get('firephp'); - $this->assertInstanceOf('Laminas\Log\Writer\Firephp', $firephp); + $this->assertInstanceOf(FirePhp::class, $firephp); } }