diff --git a/.gitignore b/.gitignore index ebc03a9c..1fdc4a93 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ coverage.json bin .php_cs.cache .vscode/ -build/logs/* \ No newline at end of file +build/logs/* +.idea/ \ No newline at end of file diff --git a/composer.json b/composer.json index 2b066c3a..b8657581 100644 --- a/composer.json +++ b/composer.json @@ -35,14 +35,12 @@ } ], "require": { - "php": "^8.2", - "laminas/laminas-db": "^2.20.0", - "laminas/laminas-diactoros": "^2.26", - "laminas/laminas-log": "^2.17.1", - "laminas/laminas-mail": "^2.25.1", - "laminas/laminas-psr7bridge": "^1.11", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "laminas/laminas-diactoros": "^2.26 || ^3.5.0", + "laminas/laminas-psr7bridge": "^1.12", "laminas/laminas-uri": "^2.13", "psr/container": "^1.1.2 || 2.0", + "psr/log": "^1.1 || ^2.0", "samsonasik/array-lookup": "^2.0", "seld/jsonlint": "^1.11", "webmozart/assert": "^1.11" @@ -57,26 +55,30 @@ }, "require-dev": { "doctrine/dbal": "^3.9.3", - "doctrine/doctrine-orm-module": "^4.2.1 || ^5.3", + "doctrine/doctrine-orm-module": "^4.2.1 || ^5.3 || ^6.0", "kahlan/kahlan": "^5.2.8", "laminas/laminas-cli": "^1.11", - "laminas/laminas-coding-standard": "^2.5", + "laminas/laminas-coding-standard": "^3.0", "laminas/laminas-form": "^2.16 || ^3.21", "laminas/laminas-mvc": "^3.8", - "laminas/laminas-servicemanager": "^3.23", + "laminas/laminas-servicemanager": "^3.23 || ^4.0", "mezzio/mezzio": "^3.20.1", "mezzio/mezzio-laminasviewrenderer": "^2.16", + "monolog/monolog": "^3.9", "php-coveralls/php-coveralls": "^2.7.0", "phpstan/phpstan": "^2.0.4", "phpstan/phpstan-webmozart-assert": "^2.0", "pimple/pimple": "^3.5", "rector/rector": "dev-main", - "symfony/dependency-injection": "^5.4.48" + "symfony/dependency-injection": "^5.4.48", + "symfony/mailer": "^7.2" }, "suggest": { "mezzio/mezzio-laminasviewrenderer": "^2.0 to be able to use laminas-view template engine in mezzio ^3.0", "mezzio/mezzio-platesrenderer": "^2.0 to be able to use plates template engine in mezzio ^3.0", - "mezzio/mezzio-twigrenderer": "^2.0 to be able to use twig template engine in mezzio ^3.0" + "mezzio/mezzio-twigrenderer": "^2.0 to be able to use twig template engine in mezzio ^3.0", + "monolog/monolog": "Sends your logs to files, sockets, inboxes, databases and various web services", + "symfony/mailer": "Symfony's Mailer & Mime components form a powerful system for creating and sending emails" }, "config": { "bin-dir": "bin", diff --git a/config/error-hero-module.local.php.dist b/config/error-hero-module.local.php.dist index 59901ce9..155c926f 100644 --- a/config/error-hero-module.local.php.dist +++ b/config/error-hero-module.local.php.dist @@ -1,45 +1,9 @@ [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - 'formatter' => [ - 'name' => 'db', - 'options' => [ - 'dateTimeFormat' => 'Y-m-d H:i:s', - ], - ], - ], - ], - - ], - ], - ], - 'error-hero-module' => [ // it's for the enable/disable the logger functionality 'enable' => true, @@ -116,11 +80,8 @@ json // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', diff --git a/config/mezzio-error-hero-module.local.php.dist b/config/mezzio-error-hero-module.local.php.dist index 769c7efc..91c2e18d 100644 --- a/config/mezzio-error-hero-module.local.php.dist +++ b/config/mezzio-error-hero-module.local.php.dist @@ -3,58 +3,19 @@ namespace ErrorHeroModule; use App\Exception\MyException; +use Psr\Log\LoggerInterface; use RuntimeException; use Error; use ErrorHeroModule\Command\BaseLoggingCommandInitializer; -use ErrorHeroModule\Compat\LoggerAbstractServiceFactory; use ErrorHeroModule\Middleware\Mezzio; use ErrorHeroModule\Middleware\MezzioFactory; use ErrorHeroModule\ErrorHeroModule\Middleware\Routed\Preview\ErrorPreviewAction; use ErrorHeroModule\Handler\Logging; use ErrorHeroModule\Handler\LoggingFactory; -use ErrorHeroModule\Command\BaseLoggingCommand; use ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Log; use Laminas\ServiceManager\Factory\InvokableFactory; return [ - - 'log' => [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - 'formatter' => [ - 'name' => 'db', - 'options' => [ - 'dateTimeFormat' => 'Y-m-d H:i:s', - ], - ], - ], - ], - - ], - ], - ], - 'error-hero-module' => [ // it's for the enable/disable the logger functionality 'enable' => true, @@ -96,6 +57,11 @@ return [ 'view' => 'error-hero-module::error-default' ], + // if enable and display_errors = 0, and on console env, the console will bring message for laminas-mvc + 'console' => [ + 'message' => 'We have encountered a problem and we can not fulfill your request. An error report has been generated and sent to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience.', + ], + // for Mezzio, when container doesn't has \Mezzio\Template\TemplateRendererInterface service // if enable, and display_errors = 0, then show a message under no_template config 'no_template' => [ @@ -132,11 +98,8 @@ json // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -152,9 +115,6 @@ json ], 'dependencies' => [ - 'abstract_factories' => [ - LoggerAbstractServiceFactory::class, - ], 'factories' => [ Mezzio::class => MezzioFactory::class, ErrorPreviewAction::class => InvokableFactory::class, @@ -162,6 +122,8 @@ json Logging::class => LoggingFactory::class, ErrorPreviewConsoleCommand::class => InvokableFactory::class, + + 'ErrorHeroModuleLogger' => fn (): LoggerInterface => new \Monolog\Logger('error-hero-module'), ], 'initializers' => [ BaseLoggingCommandInitializer::class, diff --git a/config/module.config.php b/config/module.config.php index 2e1ab484..4cf54dad 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -4,13 +4,14 @@ use ErrorHeroModule\Command\BaseLoggingCommandInitializer; use ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand; -use ErrorHeroModule\Compat\LoggerAbstractServiceFactory; use ErrorHeroModule\Controller\ErrorPreviewController; use ErrorHeroModule\Listener\Mvc; use ErrorHeroModule\Listener\MvcFactory; use ErrorHeroModule\Handler\Logging; use ErrorHeroModule\Handler\LoggingFactory; use Laminas\ServiceManager\Factory\InvokableFactory; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; return [ @@ -39,12 +40,12 @@ 'service_manager' => [ 'abstract_factories' => [ - LoggerAbstractServiceFactory::class, ], 'factories' => [ Mvc::class => MvcFactory::class, Logging::class => LoggingFactory::class, ErrorPreviewConsoleCommand::class => InvokableFactory::class, + 'ErrorHeroModuleLogger' => fn (): LoggerInterface => new \Monolog\Logger('error-hero-module'), ], 'initializers' => [ BaseLoggingCommandInitializer::class, diff --git a/spec/Fixture/config/autoload/error-hero-module.local.php b/spec/Fixture/config/autoload/error-hero-module.local.php index 61b7b436..6ff27a4b 100644 --- a/spec/Fixture/config/autoload/error-hero-module.local.php +++ b/spec/Fixture/config/autoload/error-hero-module.local.php @@ -3,7 +3,7 @@ namespace ErrorHeroModule\Spec\Fixture\config\autoload; use PDO; -use Laminas\Db\Adapter\AdapterInterface; + return [ 'db' => [ @@ -16,41 +16,6 @@ ], ], - 'log' => [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - 'formatter' => [ - 'name' => 'db', - 'options' => [ - 'dateTimeFormat' => 'Y-m-d H:i:s', - ], - ], - ], - ], - - ], - ], - ], - 'error-hero-module' => [ 'enable' => true, 'display-settings' => [ @@ -82,11 +47,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', diff --git a/spec/Fixture/config/module.local.php b/spec/Fixture/config/module.local.php index 034e6297..53b2e6c3 100644 --- a/spec/Fixture/config/module.local.php +++ b/spec/Fixture/config/module.local.php @@ -7,7 +7,6 @@ use ErrorHeroModule\Handler\LoggingFactory; use ErrorHeroModule\Listener\Mvc; use ErrorHeroModule\Listener\MvcFactory; -use ErrorHeroModule\Compat\LoggerAbstractServiceFactory; use Laminas\ServiceManager\Factory\InvokableFactory; return [ @@ -35,7 +34,6 @@ 'service_manager' => [ 'abstract_factories' => [ - LoggerAbstractServiceFactory::class, ], 'factories' => [ Mvc::class => MvcFactory::class, diff --git a/spec/Fixture/view/error-hero-module/error-preview/warning.phtml b/spec/Fixture/view/error-hero-module/error-preview/warning.phtml new file mode 100644 index 00000000..e69de29b diff --git a/spec/Handler/Formatter/JsonSpec.php b/spec/Handler/Formatter/JsonSpec.php deleted file mode 100644 index 686a6532..00000000 --- a/spec/Handler/Formatter/JsonSpec.php +++ /dev/null @@ -1,70 +0,0 @@ -format()', function (): void { - - it('format json', function (): void { - - $event = [ - 'timestamp' => DateTime::__set_state([ - 'date' => '2016-12-30 00:42:49.558706', - 'timezone_type' => 3, - 'timezone' => 'Asia/Jakarta', - ]), - 'priority' => 3, - 'priorityName' => 'ERR', - 'message' => '1: a sample exception preview', - 'extra' => [ - 'url' => 'http://localhost/error-preview?foo=bar&page=1', - 'file' => '/path/to/app/vendor/samsonasik/error-hero-module/src/Controller/ErrorPreviewController.php', - 'line' => 11, - 'error_type' => 'Exception', - 'trace' => '#0 /path/to/app/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(78): ErrorHeroModule\\Controller\\ErrorPreviewController->exceptionAction() - #1 /path/to/app/vendor/laminas/laminas-eventmanager/src/EventManager.php(322): Laminas\\Mvc\\Controller\\AbstractActionController->onDispatch(Object(Laminas\\Mvc\\MvcEvent)) - #2 /path/to/app/vendor/laminas/laminas-eventmanager/src/EventManager.php(179): Laminas\\EventManager\\EventManager->triggerListeners(Object(Laminas\\Mvc\\MvcEvent), Object(Closure)) - #3 /path/to/app/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(105): Laminas\\EventManager\\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\\Mvc\\MvcEvent)) - #4 /path/to/app/vendor/laminas/laminas-mvc/src/DispatchListener.php(119): Laminas\\Mvc\\Controller\\AbstractController->dispatch(Object(Laminas\\Http\\PhpEnvironment\\Request), Object(Laminas\\Http\\PhpEnvironment\\Response)) - #5 /path/to/app/vendor/laminas/laminas-eventmanager/src/EventManager.php(322): Laminas\\Mvc\\DispatchListener->onDispatch(Object(Laminas\\Mvc\\MvcEvent)) - #6 /path/to/app/vendor/laminas/laminas-eventmanager/src/EventManager.php(179): Laminas\\EventManager\\EventManager->triggerListeners(Object(Laminas\\Mvc\\MvcEvent), Object(Closure)) - #7 /path/to/app/vendor/laminas/laminas-mvc/src/Application.php(332): Laminas\\EventManager\\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\\Mvc\\MvcEvent)) - #8 /path/to/app/public/index.php(40): Laminas\\Mvc\\Application->run() - #9 {main}', - 'request_data' => [ - 'request_method' => 'GET', - 'query_data' => [ - 'foo' => 'bar', - 'page' => '1', - ], - 'body_data' => [], - 'raw_data' => '', - 'files_data' => [], - 'cookie_data' => [], - 'ip_address' => '10.1.1.1', - ], - ], - ]; - - expect('json_encode')->toBeCalled(); - $actualOld = (new Json())->format($event); - - // idempotent format call will use old timestamp - $event['timestamp'] = DateTime::__set_state([ - 'date' => '2016-12-30 00:42:55.558706', - 'timezone_type' => 3, - 'timezone' => 'Asia/Jakarta', - ]); - - $actualNew = (new Json())->format($event); - expect($actualNew)->toBe($actualOld); - - }); - - }); - -}); diff --git a/spec/Handler/LoggingFactorySpec.php b/spec/Handler/LoggingFactorySpec.php index f0198d95..515cec8a 100644 --- a/spec/Handler/LoggingFactorySpec.php +++ b/spec/Handler/LoggingFactorySpec.php @@ -2,14 +2,11 @@ namespace ErrorHeroModule\Spec\Handler; -use ErrorHeroModule\Compat\Logger; use ErrorHeroModule\Handler\Logging; use ErrorHeroModule\Handler\LoggingFactory; use Kahlan\Plugin\Double; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Mail\Message; -use Laminas\Mail\Transport\TransportInterface; use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use RuntimeException; describe('LoggingFactorySpec', function (): void { @@ -17,34 +14,6 @@ given('factory', fn() : LoggingFactory => new LoggingFactory()); given('config', fn() : array => [ - 'log' => [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ], - ], - ], 'error-hero-module' => [ 'enable' => true, @@ -77,11 +46,7 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'MailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'MailTransportService', + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -107,7 +72,7 @@ allow($container)->toReceive('get')->with('config') ->andReturn($config); - $logger = Double::instance(['extends' => Logger::class]); + $logger = Double::instance(['extends' => LoggerInterface::class]); allow($container)->toReceive('get')->with('ErrorHeroModuleLogger') ->andReturn($logger); @@ -124,7 +89,7 @@ allow($container)->toReceive('get')->with('config') ->andReturn($config); - $logger = Double::instance(['extends' => Logger::class]); + $logger = Double::instance(['extends' => LoggerInterface::class]); allow($container)->toReceive('get')->with('ErrorHeroModuleLogger') ->andReturn($logger); @@ -142,7 +107,7 @@ allow($container)->toReceive('get')->with('config') ->andReturn($config); - $logger = Double::instance(['extends' => Logger::class]); + $logger = Double::instance(['extends' => LoggerInterface::class]); allow($container)->toReceive('get')->with('ErrorHeroModuleLogger') ->andReturn($logger); @@ -163,13 +128,10 @@ allow($container)->toReceive('get')->with('config') ->andReturn($config); - $logger = Double::instance(['extends' => Logger::class]); + $logger = Double::instance(['extends' => LoggerInterface::class]); allow($container)->toReceive('get')->with('ErrorHeroModuleLogger') ->andReturn($logger); - allow($container)->toReceive('get')->with('MailMessageService') - ->andReturn(new Message()); - $closure = function () use ($container): void { $this->factory($container); }; @@ -187,16 +149,10 @@ allow($container)->toReceive('get')->with('config') ->andReturn($config); - $logger = Double::instance(['extends' => Logger::class]); + $logger = Double::instance(['extends' => LoggerInterface::class]); allow($container)->toReceive('get')->with('ErrorHeroModuleLogger') ->andReturn($logger); - allow($container)->toReceive('get')->with('MailMessageService') - ->andReturn(new Message()); - - allow($container)->toReceive('get')->with('MailTransportService') - ->andReturn(Double::instance(['implements' => TransportInterface::class])); - $actual = $this->factory($container); expect($actual)->toBeAnInstanceOf(Logging::class); diff --git a/spec/Handler/LoggingSpec.php b/spec/Handler/LoggingSpec.php index 2320905a..898b1d31 100644 --- a/spec/Handler/LoggingSpec.php +++ b/spec/Handler/LoggingSpec.php @@ -3,23 +3,17 @@ namespace ErrorHeroModule\Spec\Handler; use ErrorException; -use ErrorHeroModule\Compat\Logger; use ErrorHeroModule\Handler\Logging; use Exception; use Kahlan\Plugin\Double; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Db\ResultSet\ResultSet; -use Laminas\Db\Sql\Select; -use Laminas\Db\Sql\Sql; -use Laminas\Db\TableGateway\TableGateway; use Laminas\Http\PhpEnvironment\Request; -use Laminas\Log\Writer\Db; +use Psr\Log\LoggerInterface; use ReflectionProperty; describe('LoggingSpec', function (): void { beforeAll(function (): void { - $this->logger = Double::instance(['extends' => Logger::class]); + $this->logger = Double::instance(['extends' => LoggerInterface::class]); $this->request = new Request(); $this->request->setUri('http://www.example.com'); @@ -54,11 +48,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -72,106 +63,25 @@ ], ], ]; - $this->logWritersConfig = [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ]; - - $this->dbWriter = Double::instance(['extends' => Db::class, 'methods' => '__construct']); - $reflectionProperty = new ReflectionProperty($this->dbWriter, 'db'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->dbWriter, Double::instance(['implements' => AdapterInterface::class])); - - $this->logger->addWriter($this->dbWriter); }); given('logging', fn() : Logging => new Logging( $this->logger, - $this->errorHeroModuleLocalConfig, - $this->logWritersConfig, - null, - null, true )); describe('->handleErrorException()', function (): void { it('not log if exists', function (): void { - - $sql = Double::instance(['extends' => Sql::class, 'methods' => '__construct']); - allow(TableGateway::class)->toReceive('getSql')->andReturn($sql); - - $select = Double::instance(['extends' => Select::class, 'methods' => '__construct']); - allow($select)->toReceive('where'); - allow($select)->toReceive('order'); - allow($select)->toReceive('limit'); - allow($sql)->toReceive('select')->andReturn($select); - - $resultSet = Double::instance(['extends' => ResultSet::class, 'methods' => '__construct']); - - allow($resultSet)->toReceive('count')->andReturn(1); - allow($resultSet)->toReceive('current')->andReturn( - [ - 'date' => \date('Y-m-d H:i:s'), - ] - ); - allow(TableGateway::class)->toReceive('selectWith')->with($select)->andReturn($resultSet); - - expect($this->logger)->not->toReceive('log'); - $exception = new Exception(); $this->logging->handleErrorException($exception, $this->request); }); it('not log if exists and exception instanceof ErrorException', function (): void { - - $sql = Double::instance(['extends' => Sql::class, 'methods' => '__construct']); - allow(TableGateway::class)->toReceive('getSql')->andReturn($sql); - - $select = Double::instance(['extends' => Select::class, 'methods' => '__construct']); - allow($select)->toReceive('where'); - allow($select)->toReceive('order'); - allow($select)->toReceive('limit'); - allow($sql)->toReceive('select')->andReturn($select); - - $resultSet = Double::instance(['extends' => ResultSet::class, 'methods' => '__construct']); - - allow($resultSet)->toReceive('current')->andReturn( - [ - 'date' => \date('Y-m-d H:i:s'), - ] - ); - allow($resultSet)->toReceive('count')->andReturn(1); - allow(TableGateway::class)->toReceive('selectWith')->with($select)->andReturn($resultSet); - - expect($this->logger)->not->toReceive('log'); - $exception = new ErrorException(); $this->logging->handleErrorException($exception, $this->request); }); - }); - }); diff --git a/spec/Handler/Writer/Checker/DbSpec.php b/spec/Handler/Writer/Checker/DbSpec.php deleted file mode 100644 index 3e51a8b2..00000000 --- a/spec/Handler/Writer/Checker/DbSpec.php +++ /dev/null @@ -1,152 +0,0 @@ -dbWriter = Double::instance(['extends' => DbWriter::class, 'methods' => '__construct']); - $reflectionProperty = new ReflectionProperty($this->dbWriter, 'db'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($this->dbWriter, Double::instance(['implements' => AdapterInterface::class, 'methods' => '__construct'])); - - $this->configLoggingSettings = [ - 'same-error-log-time-range' => 86400, - ]; - $this->logWritersConfig = [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ]; - }); - - given('writerHandler', fn() : Db => new Db( - $this->dbWriter, - $this->configLoggingSettings, - $this->logWritersConfig - )); - - describe('__construct', function (): void { - - it('instanceof '. Db::class, function (): void { - - $actual = $this->writerHandler; - expect($actual)->toBeAnInstanceOf(Db::class); - - }); - - }); - - describe('->isExists()', function (): void { - - it('return false if no current data', function (): void { - - $sql = Double::instance(['extends' => Sql::class, 'methods' => '__construct']); - allow(TableGateway::class)->toReceive('getSql')->andReturn($sql); - - $select = Double::instance(['extends' => Select::class, 'methods' => '__construct']); - allow($select)->toReceive('columns')->with(['date']); - allow($select)->toReceive('where'); - allow($select)->toReceive('order'); - allow($select)->toReceive('limit'); - allow($sql)->toReceive('select')->andReturn($select); - - $resultSet = Double::instance(['extends' => ResultSet::class, 'methods' => '__construct']); - allow($resultSet)->toReceive('current')->andReturn(null); - allow(TableGateway::class)->toReceive('selectWith')->with($select)->andReturn($resultSet); - - $actual = $this->writerHandler->isExists('file', 1, 'Undefined array key 1', 'http://serverUrl/uri', 'E_WARNING'); - expect($actual)->toBe(false); - - }); - - it('return false if has current data but timestamp is expired', function (): void { - - $sql = Double::instance(['extends' => Sql::class, 'methods' => '__construct']); - allow(TableGateway::class)->toReceive('getSql')->andReturn($sql); - - $select = Double::instance(['extends' => Select::class, 'methods' => '__construct']); - allow($select)->toReceive('columns')->with(['date']); - allow($select)->toReceive('where'); - allow($select)->toReceive('order'); - allow($select)->toReceive('limit'); - allow($sql)->toReceive('select')->andReturn($select); - - $resultSet = Double::instance(['extends' => ResultSet::class, 'methods' => '__construct']); - - $current = \date('Y-m-d'); - $date = \date_create($current); - \date_sub($date, \date_interval_create_from_date_string("40 days")); - $date = \date_format($date,"Y-m-d H:i:s"); - - allow($resultSet)->toReceive('current')->andReturn( - [ - 'date' => $date, - ] - ); - allow(TableGateway::class)->toReceive('selectWith')->with($select)->andReturn($resultSet); - - $actual = $this->writerHandler->isExists('file', 1, 'Undefined array key 1', 'http://serverUrl/uri', 'E_WARNING'); - expect($actual)->toBe(false); - - }); - - it('return true if has current data but timestamp === current time', function (): void { - - $sql = Double::instance(['extends' => Sql::class, 'methods' => '__construct']); - allow(TableGateway::class)->toReceive('getSql')->andReturn($sql); - - $select = Double::instance(['extends' => Select::class, 'methods' => '__construct']); - allow($select)->toReceive('columns')->with(['date']); - allow($select)->toReceive('where'); - allow($select)->toReceive('order'); - allow($select)->toReceive('limit'); - allow($sql)->toReceive('select')->andReturn($select); - - $resultSet = Double::instance(['extends' => ResultSet::class, 'methods' => '__construct']); - - allow($resultSet)->toReceive('current')->andReturn( - [ - 'date' => \date('Y-m-d H:i:s'), - ] - ); - allow(TableGateway::class)->toReceive('selectWith')->with($select)->andReturn($resultSet); - - $actual = $this->writerHandler->isExists('file', 1, 'Undefined array key 1', 'http://serverUrl/uri', 'E_WARNING'); - expect($actual)->toBe(true); - - }); - - }); - -}); diff --git a/spec/Handler/Writer/MailSpec.php b/spec/Handler/Writer/MailSpec.php deleted file mode 100644 index 142e3aec..00000000 --- a/spec/Handler/Writer/MailSpec.php +++ /dev/null @@ -1,130 +0,0 @@ -mailMessage = Double::instance(['extends' => Message::class]); - $this->transport = Double::instance(['implements' => TransportInterface::class]); - - $this->writer = new Mail( - $this->mailMessage, - $this->transport, - [ - "fileupload" => [ - 'name' => 'foo.html', - 'tmp_name' => __DIR__ . '/../../Fixture/data/foo.html', - 'error' => 0, - 'size' => 1, - 'type' => 'text/html' - ], - ] - ); - }); - - describe('->shutdown', function (): void { - - it('bring multiple collection upload, then transport->send()', function (): void { - - $writer = new Mail( - $this->mailMessage, - $this->transport, - [ - "file-collection" => [ - [ - 'name' => 'foo.html', - 'tmp_name' => __DIR__ . '/../../Fixture/data/foo.html', - 'error' => 0, - 'size' => 1, - 'type' => 'text/html' - ], - ], - "file-collection2" => [ - "name" => [ - [ - 'name' => 'foo.html', - 'tmp_name' => __DIR__ . '/../../Fixture/data/foo.html', - 'error' => 0, - 'size' => 1, - 'type' => 'text/html' - ] - ], - ], - ] - ); - - $r = new ReflectionProperty($this->writer, 'eventsToMail'); - $r->setAccessible(true); - $r->setValue($writer, ["timestamp" => "2017-02-25T02:08:46+07:00"]); - - allow($this->transport)->toReceive('send'); - - $writer->shutdown(); - - expect($this->transport)->toReceive('send'); - - }); - - it('bring deeper multiple collection upload, then transport->send()', function (): void { - - $writer = new Mail( - $this->mailMessage, - $this->transport, - [ - "file-collection" => [ - 'file-collection-deeper' => [ - 'file-collection-deeper-deep' => [ - [ - 'name' => 'foo.html', - 'tmp_name' => __DIR__ . '/../../Fixture/data/foo.html', - 'error' => 0, - 'size' => 1, - 'type' => 'text/html' - ], - ], - ], - ], - ] - ); - - $r = new ReflectionProperty($this->writer, 'eventsToMail'); - $r->setAccessible(true); - $r->setValue($writer, ["timestamp" => "2017-02-25T02:08:46+07:00"]); - - allow($this->transport)->toReceive('send'); - - $writer->shutdown(); - - expect($this->transport)->toReceive('send'); - - }); - - it('transport->send() trigger error', function (): void { - - $r = new ReflectionProperty($this->writer, 'eventsToMail'); - $r->setAccessible(true); - $r->setValue($this->writer, ["timestamp" => "2017-02-25T02:08:46+07:00"]); - - allow($this->transport)->toReceive('send')->andRun(function (): never { throw new Exception('root'); }); - - try { - $this->writer->shutdown(); - expect($this->transport)->toReceive('send'); - } catch (Throwable $throwable) { - expect($throwable)->toBeAnInstanceOf(Exception::class); - } - - }); - - }); - -}); diff --git a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandDisplayErrorsSpec.php b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandDisplayErrorsSpec.php index a366f49c..d4a4586d 100644 --- a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandDisplayErrorsSpec.php +++ b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandDisplayErrorsSpec.php @@ -3,9 +3,6 @@ namespace ErrorHeroModule\Spec\Integration; use ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Db\ResultSet\ResultSet; -use Laminas\Db\TableGateway\TableGateway; use Laminas\Mvc\Application; use Symfony\Component\Console\Tester\CommandTester; use Throwable; @@ -17,7 +14,6 @@ $application = Application::init([ 'modules' => [ 'Laminas\Router', - 'Laminas\Db', 'ErrorHeroModule', ], 'module_listener_options' => [ @@ -28,11 +24,6 @@ ], ]); - $serviceManager = $application->getServiceManager(); - $db = $serviceManager->get(AdapterInterface::class); - $tableGateway = new TableGateway('log', $db, null, new ResultSet()); - $tableGateway->delete([]); - return $application; }); diff --git a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandExcludeExceptionSpec.php b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandExcludeExceptionSpec.php index ac4da61f..9a3a8f26 100644 --- a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandExcludeExceptionSpec.php +++ b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandExcludeExceptionSpec.php @@ -3,9 +3,6 @@ namespace ErrorHeroModule\Spec\Integration; use ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Db\ResultSet\ResultSet; -use Laminas\Db\TableGateway\TableGateway; use Laminas\Mvc\Application; use Symfony\Component\Console\Tester\CommandTester; use Throwable; @@ -17,7 +14,6 @@ $application = Application::init([ 'modules' => [ 'Laminas\Router', - 'Laminas\Db', 'ErrorHeroModule', ], 'module_listener_options' => [ @@ -28,13 +24,7 @@ ], ]); - $serviceManager = $application->getServiceManager(); - $db = $serviceManager->get(AdapterInterface::class); - $tableGateway = new TableGateway('log', $db, null, new ResultSet()); - $tableGateway->delete([]); - return $application; - }); describe('error-preview error excluded', function(): void { diff --git a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandSpec.php b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandSpec.php index 18000f20..15698a45 100644 --- a/spec/Integration/IntegrationViaErrorPreviewConsoleCommandSpec.php +++ b/spec/Integration/IntegrationViaErrorPreviewConsoleCommandSpec.php @@ -3,9 +3,6 @@ namespace ErrorHeroModule\Spec\Integration; use ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand; -use Laminas\Db\Adapter\AdapterInterface; -use Laminas\Db\ResultSet\ResultSet; -use Laminas\Db\TableGateway\TableGateway; use Laminas\Mvc\Application; use Symfony\Component\Console\Tester\CommandTester; @@ -16,7 +13,6 @@ $application = Application::init([ 'modules' => [ 'Laminas\Router', - 'Laminas\Db', 'ErrorHeroModule', ], 'module_listener_options' => [ @@ -27,11 +23,6 @@ ], ]); - $serviceManager = $application->getServiceManager(); - $db = $serviceManager->get(AdapterInterface::class); - $tableGateway = new TableGateway('log', $db, null, new ResultSet()); - $tableGateway->delete([]); - return $application; }); diff --git a/spec/Listener/MvcFactorySpec.php b/spec/Listener/MvcFactorySpec.php index 3c910db6..f529c60f 100644 --- a/spec/Listener/MvcFactorySpec.php +++ b/spec/Listener/MvcFactorySpec.php @@ -49,11 +49,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', diff --git a/spec/Listener/MvcSpec.php b/spec/Listener/MvcSpec.php index f4b1c977..dfc8c8ea 100644 --- a/spec/Listener/MvcSpec.php +++ b/spec/Listener/MvcSpec.php @@ -4,16 +4,12 @@ use Closure; use ErrorException; -use ErrorHeroModule\Compat\Logger; use ErrorHeroModule\Handler\Logging; use ErrorHeroModule\Listener\Mvc; use Exception; use Kahlan\Plugin\Double; -use Laminas\Db\Adapter\Adapter; -use Laminas\Db\Adapter\AdapterInterface; use Laminas\EventManager\EventManagerInterface; use Laminas\Http\PhpEnvironment\Request; -use Laminas\Log\Writer\Db; use Laminas\Mvc\MvcEvent; use Laminas\Uri\Uri; use Laminas\View\Renderer\PhpRenderer; @@ -59,11 +55,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -271,70 +264,10 @@ 'line' => 2 ]); - $dbAdapter = new Adapter([ - 'username' => 'root', - 'password' => '', - 'driver' => 'Pdo', - 'dsn' => 'mysql:dbname=errorheromodule;host=127.0.0.1', - 'driver_options' => [ - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", - ], - ]); - - $writer = new Db( - [ - 'db' => $dbAdapter, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ] - ); - $logger = new Logger(); - $logger->addWriter($writer); - - $logWritersConfig = [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ]; $logging = new Logging( $logger, - $this->config, - $logWritersConfig, - null, - null, true ); diff --git a/spec/Middleware/MezzioFactorySpec.php b/spec/Middleware/MezzioFactorySpec.php index f4be5d18..08373990 100644 --- a/spec/Middleware/MezzioFactorySpec.php +++ b/spec/Middleware/MezzioFactorySpec.php @@ -29,27 +29,6 @@ given('config', fn() : array => [ - 'db' => [ - 'username' => 'root', - 'password' => '', - 'driver' => 'pdo_mysql', - 'dsn' => 'mysql:host=localhost;dbname=errorheromodule', - 'driver_options' => [ - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", - ], - 'adapters' => [ - 'my-adapter' => [ - 'driver' => 'pdo_mysql', - 'dsn' => 'mysql:host=localhost;dbname=errorheromodule', - 'username' => 'root', - 'password' => '', - 'driver_options' => [ - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", - ], - ], - ], - ], - 'error-hero-module' => [ 'enable' => true, 'display-settings' => [ @@ -76,11 +55,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -92,35 +68,6 @@ ], ], - 'log' => [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'error_log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ], - ], - ], - ]); describe('__invoke()', function (): void { @@ -231,7 +178,6 @@ unset($config['db']['adapters']); foreach ($this->mapCreateContainers as $mapCreateContainer) { - $config['log']['ErrorHeroModuleLogger']['writers'][0]['options']['db'] = AdapterInterface::class; allow($mapCreateContainer)->toReceive('get')->with('config') ->andReturn($config); diff --git a/spec/Middleware/MezzioSpec.php b/spec/Middleware/MezzioSpec.php index 2dd8803e..f410af02 100644 --- a/spec/Middleware/MezzioSpec.php +++ b/spec/Middleware/MezzioSpec.php @@ -4,17 +4,13 @@ use Closure; use ErrorException; -use ErrorHeroModule\Compat\Logger; use ErrorHeroModule\Handler\Logging; use ErrorHeroModule\Middleware\Mezzio; use Exception; use Kahlan\Plugin\Double; -use Laminas\Db\Adapter\Adapter; -use Laminas\Db\Adapter\AdapterInterface; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Uri; -use Laminas\Log\Writer\Db; use Laminas\View\Renderer\PhpRenderer; use Laminas\View\Resolver\AggregateResolver; use Laminas\View\Resolver\TemplateMapResolver; @@ -22,6 +18,7 @@ use PDO; use Psr\Http\Message\ResponseInterface; use Psr\Http\Server\RequestHandlerInterface; +use Psr\Log\LoggerInterface; describe('Mezzio', function (): void { @@ -46,43 +43,8 @@ }); - given('logger', function (): Logger { - - $dbAdapter = new Adapter([ - 'username' => 'root', - 'password' => '', - 'driver' => 'Pdo', - 'dsn' => 'mysql:dbname=errorheromodule;host=127.0.0.1', - 'driver_options' => [ - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", - ], - ]); - - $writer = new Db( - [ - 'db' => $dbAdapter, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ] - ); - - $logger = new Logger(); - $logger->addWriter($writer); - - return $logger; - + given('logger', function (): LoggerInterface { + return new \Monolog\Logger('error-hero-module'); }); given('config', fn() : array => [ @@ -135,11 +97,8 @@ // set to true to activate email notification on log error 'enable' => false, - // Laminas\Mail\Message instance registered at service manager - 'mail-message' => 'YourMailMessageService', - - // Laminas\Mail\Transport\TransportInterface instance registered at service manager - 'mail-transport' => 'YourMailTransportService', + // DSN for mailer + 'mail-dsn' => 'smtp://localhost:25', // email sender 'email-from' => 'Sender Name ', @@ -151,63 +110,6 @@ ], ]); - given('logWritersConfig', fn() : array => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - - ]); - - given('dbWriter', function (): Db { - $dbAdapter = new Adapter([ - 'username' => 'root', - 'password' => '', - 'driver' => 'Pdo', - 'dsn' => 'mysql:dbname=errorheromodule;host=127.0.0.1', - 'driver_options' => [ - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", - ], - ]); - - return new Db( - [ - 'db' => $dbAdapter, - 'table' => 'log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ] - ); - }); - given('request', fn() : ServerRequest => new ServerRequest( [], [], @@ -263,10 +165,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -292,10 +190,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -319,10 +213,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -356,10 +246,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -393,10 +279,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -428,10 +310,6 @@ $logging = new Logging( $this->logger, - $config, - $this->logWritersConfig, - null, - null, true ); @@ -506,15 +384,10 @@ 'line' => 2 ]); - $logger = new Logger(); - $logger->addWriter($this->dbWriter); + $logger = new \Monolog\Logger('error-hero-module'); $logging = new Logging( $logger, - $this->config, - $this->logWritersConfig, - null, - null, true ); @@ -539,8 +412,7 @@ ], 'email-notification-settings' => [ 'enable' => false, - 'mail-message' => 'YourMailMessageService', - 'mail-transport' => 'YourMailTransportService', + 'mail-dsn' => 'smtp://localhost:25', 'email-from' => 'Sender Name ', 'email-to-send' => [ 'developer1@foo.com', @@ -579,15 +451,10 @@ 'line' => 2 ]); - $logger = new Logger(); - $logger->addWriter($this->dbWriter); + $logger = new \Monolog\Logger('error-hero-module'); $logging = new Logging( $logger, - $this->config, - $this->logWritersConfig, - null, - null, true ); @@ -612,8 +479,7 @@ ], 'email-notification-settings' => [ 'enable' => false, - 'mail-message' => 'YourMailMessageService', - 'mail-transport' => 'YourMailTransportService', + 'mail-dsn' => 'smtp://localhost:25', 'email-from' => 'Sender Name ', 'email-to-send' => [ 'developer1@foo.com', diff --git a/spec/ModuleSpec.php b/spec/ModuleSpec.php index 37b46f48..47c67171 100644 --- a/spec/ModuleSpec.php +++ b/spec/ModuleSpec.php @@ -7,7 +7,6 @@ use Doctrine\ORM\EntityManager; use ErrorHeroModule\Module; use Kahlan\Plugin\Double; -use Laminas\Db\Adapter\AdapterInterface; use Laminas\EventManager\EventManagerInterface; use Laminas\ModuleManager\Listener\ConfigListener; use Laminas\ModuleManager\ModuleEvent; @@ -20,34 +19,7 @@ given('module', fn() : Module => new Module()); given('config', fn() : array => [ - 'log' => [ - 'ErrorHeroModuleLogger' => [ - 'writers' => [ - - [ - 'name' => 'db', - 'options' => [ - 'db' => AdapterInterface::class, - 'table' => 'error_log', - 'column' => [ - 'timestamp' => 'date', - 'priority' => 'type', - 'message' => 'event', - 'extra' => [ - 'url' => 'url', - 'file' => 'file', - 'line' => 'line', - 'error_type' => 'error_type', - 'trace' => 'trace', - 'request_data' => 'request_data', - ], - ], - ], - ], - ], - ], - ], ]); describe('->getConfig()', function (): void { diff --git a/src/Command/Preview/ErrorPreviewConsoleCommand.php b/src/Command/Preview/ErrorPreviewConsoleCommand.php index a7457208..fc598638 100644 --- a/src/Command/Preview/ErrorPreviewConsoleCommand.php +++ b/src/Command/Preview/ErrorPreviewConsoleCommand.php @@ -20,7 +20,7 @@ protected function configure(): void ->addArgument('type', InputArgument::OPTIONAL, 'Type of preview: exception, error, warning, fatal'); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $type = $input->getArgument('type'); @@ -41,5 +41,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $y = new class implements stdClass { }; } + + return 0; } } diff --git a/src/Compat/Logger.php b/src/Compat/Logger.php deleted file mode 100644 index df54c177..00000000 --- a/src/Compat/Logger.php +++ /dev/null @@ -1,740 +0,0 @@ - self::NOTICE, - E_USER_NOTICE => self::NOTICE, - E_WARNING => self::WARN, - E_CORE_WARNING => self::WARN, - E_USER_WARNING => self::WARN, - E_ERROR => self::ERR, - E_USER_ERROR => self::ERR, - E_CORE_ERROR => self::ERR, - E_RECOVERABLE_ERROR => self::ERR, - E_PARSE => self::ERR, - E_COMPILE_ERROR => self::ERR, - E_COMPILE_WARNING => self::ERR, - // E_STRICT is deprecated in php 8.4 - 2048 => self::DEBUG, - E_DEPRECATED => self::DEBUG, - E_USER_DEPRECATED => self::DEBUG, - ]; - - /** - * Registered error handler - * - * @var bool - */ - protected static $registeredErrorHandler = false; - - /** - * Registered shutdown error handler - * - * @var bool - */ - protected static $registeredFatalErrorShutdownFunction = false; - - /** - * Registered exception handler - * - * @var bool - */ - protected static $registeredExceptionHandler = false; - - /** - * List of priority code => priority (short) name - * - * @var array - */ - protected $priorities = [ - self::EMERG => 'EMERG', - self::ALERT => 'ALERT', - self::CRIT => 'CRIT', - self::ERR => 'ERR', - self::WARN => 'WARN', - self::NOTICE => 'NOTICE', - self::INFO => 'INFO', - self::DEBUG => 'DEBUG', - ]; - - /** - * Writers - * - * @var SplPriorityQueue - */ - protected $writers; - - /** - * Processors - */ - protected SplPriorityQueue $processors; - - /** - * Writer writerPlugins - * - * @var WriterPluginManager - */ - protected $writerPlugins; - - /** - * Processor writerPlugins - * - * @var ProcessorPluginManager - */ - protected $processorPlugins; - - /** - * Constructor - * - * Set options for a logger. Accepted options are: - * - writers: array of writers to add to this logger - * - exceptionhandler: if true register this logger as exceptionhandler - * - errorhandler: if true register this logger as errorhandler - * - * @param array|Traversable $options - * @throws InvalidArgumentException - */ - public function __construct($options = null) - { - $this->writers = new SplPriorityQueue(); - $this->processors = new SplPriorityQueue(); - - if ($options instanceof Traversable) { - $options = ArrayUtils::iteratorToArray($options); - } - - if (! $options) { - return; - } - - if (! is_array($options)) { - throw new InvalidArgumentException( - 'Options must be an array or an object implementing \Traversable ' - ); - } - - // Inject writer plugin manager, if available - if ( - isset($options['writer_plugin_manager']) - && $options['writer_plugin_manager'] instanceof AbstractPluginManager - ) { - $this->setWriterPluginManager($options['writer_plugin_manager']); - } - - // Inject processor plugin manager, if available - if ( - isset($options['processor_plugin_manager']) - && $options['processor_plugin_manager'] instanceof AbstractPluginManager - ) { - $this->setProcessorPluginManager($options['processor_plugin_manager']); - } - - if (isset($options['writers']) && is_array($options['writers'])) { - foreach ($options['writers'] as $writer) { - if (! isset($writer['name'])) { - throw new InvalidArgumentException('Options must contain a name for the writer'); - } - - $priority = $writer['priority'] ?? null; - $writerOptions = $writer['options'] ?? null; - - $this->addWriter($writer['name'], $priority, $writerOptions); - } - } - - if (isset($options['processors']) && is_array($options['processors'])) { - foreach ($options['processors'] as $processor) { - if (! isset($processor['name'])) { - throw new InvalidArgumentException('Options must contain a name for the processor'); - } - - $priority = $processor['priority'] ?? null; - $processorOptions = $processor['options'] ?? null; - - $this->addProcessor($processor['name'], $priority, $processorOptions); - } - } - - if (isset($options['exceptionhandler']) && $options['exceptionhandler'] === true) { - static::registerExceptionHandler($this); - } - - if (isset($options['errorhandler']) && $options['errorhandler'] === true) { - static::registerErrorHandler($this); - } - - if (isset($options['fatal_error_shutdownfunction']) && $options['fatal_error_shutdownfunction'] === true) { - static::registerFatalErrorShutdownFunction($this); - } - } - - /** - * Shutdown all writers - * - * @return void - */ - public function __destruct() - { - foreach ($this->writers as $writer) { - try { - $writer->shutdown(); - } catch (Exception) { - } - } - } - - /** - * Get writer plugin manager - * - * @return WriterPluginManager - */ - public function getWriterPluginManager() - { - if (null === $this->writerPlugins) { - $this->setWriterPluginManager(new WriterPluginManager(new ServiceManager())); - } - - return $this->writerPlugins; - } - - /** - * Set writer plugin manager - */ - public function setWriterPluginManager(WriterPluginManager $writerPluginManager): static - { - $this->writerPlugins = $writerPluginManager; - return $this; - } - - /** - * Get writer instance - * - * @param string $name - * @return WriterInterface - */ - public function writerPlugin($name, ?array $options = null) - { - return $this->getWriterPluginManager()->get($name, $options); - } - - /** - * Add a writer to a logger - * - * @param string|WriterInterface $writer - * @param int $priority - * @throws InvalidArgumentException - */ - public function addWriter($writer, $priority = 1, ?array $options = null): static - { - if (is_string($writer)) { - $writer = $this->writerPlugin($writer, $options); - } elseif (! $writer instanceof WriterInterface) { - throw new InvalidArgumentException(sprintf( - 'Writer must implement %s\Writer\WriterInterface; received "%s"', - __NAMESPACE__, - get_debug_type($writer) - )); - } - - $this->writers->insert($writer, $priority); - - return $this; - } - - /** - * Get writers - * - * @return SplPriorityQueue - */ - public function getWriters() - { - return $this->writers; - } - - /** - * Set the writers - * - * @throws InvalidArgumentException - */ - public function setWriters(SplPriorityQueue $splPriorityQueue): static - { - foreach ($splPriorityQueue->toArray() as $writer) { - if (! $writer instanceof WriterInterface) { - throw new InvalidArgumentException( - 'Writers must be a SplPriorityQueue of Laminas\Log\Writer' - ); - } - } - - $this->writers = $splPriorityQueue; - return $this; - } - - /** - * Get processor plugin manager - * - * @return ProcessorPluginManager - */ - public function getProcessorPluginManager() - { - if (null === $this->processorPlugins) { - $this->setProcessorPluginManager(new ProcessorPluginManager(new ServiceManager())); - } - - return $this->processorPlugins; - } - - /** - * Set processor plugin manager - * - * @param string|ProcessorPluginManager $plugins - * @throws InvalidArgumentException - */ - public function setProcessorPluginManager($plugins): static - { - if (is_string($plugins)) { - $plugins = new $plugins(); - } - - if (! $plugins instanceof ProcessorPluginManager) { - throw new InvalidArgumentException(sprintf( - 'processor plugin manager must extend %s\ProcessorPluginManager; received %s', - __NAMESPACE__, - get_debug_type($plugins) - )); - } - - $this->processorPlugins = $plugins; - return $this; - } - - /** - * Get processor instance - * - * @param string $name - * @return ProcessorInterface - */ - public function processorPlugin($name, ?array $options = null) - { - return $this->getProcessorPluginManager()->get($name, $options); - } - - /** - * Add a processor to a logger - * - * @param string|ProcessorInterface $processor - * @param int $priority - * @throws InvalidArgumentException - */ - public function addProcessor($processor, $priority = 1, ?array $options = null): static - { - if (is_string($processor)) { - $processor = $this->processorPlugin($processor, $options); - } elseif (! $processor instanceof ProcessorInterface) { - throw new InvalidArgumentException(sprintf( - 'Processor must implement Laminas\Log\ProcessorInterface; received "%s"', - get_debug_type($processor) - )); - } - - $this->processors->insert($processor, $priority); - - return $this; - } - - /** - * Get processors - */ - public function getProcessors(): SplPriorityQueue - { - return $this->processors; - } - - /** - * Add a message as a log entry - * - * @param int $priority - * @param mixed $message - * @param array|Traversable $extra - * @throws InvalidArgumentException If message can't be cast to string. - * @throws InvalidArgumentException If extra can't be iterated over. - * @throws RuntimeException If no log writer specified. - */ - public function log($priority, $message, $extra = []): static - { - if (! is_int($priority) || ($priority < 0) || ($priority >= count($this->priorities))) { - throw new InvalidArgumentException(sprintf( - '$priority must be an integer >= 0 and < %d; received %s', - count($this->priorities), - var_export($priority, true) - )); - } - - if (is_object($message) && ! method_exists($message, '__toString')) { - throw new InvalidArgumentException( - '$message must implement magic __toString() method' - ); - } - - if (! is_array($extra) && ! $extra instanceof Traversable) { - throw new InvalidArgumentException( - '$extra must be an array or implement Traversable' - ); - } elseif ($extra instanceof Traversable) { - $extra = ArrayUtils::iteratorToArray($extra); - } - - if ($this->writers->count() === 0) { - throw new RuntimeException('No log writer specified'); - } - - $timestamp = new DateTime(); - - if (is_array($message)) { - $message = var_export($message, true); - } - - $event = [ - 'timestamp' => $timestamp, - 'priority' => $priority, - 'priorityName' => $this->priorities[$priority], - 'message' => (string) $message, - 'extra' => $extra, - ]; - - /** @var ProcessorInterface $processor */ - foreach ($this->processors->toArray() as $processor) { - $event = $processor->process($event); - } - - /** @var WriterInterface $writer */ - foreach ($this->writers->toArray() as $writer) { - $writer->write($event); - } - - return $this; - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function emerg($message, $extra = []) - { - return $this->log(self::EMERG, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function alert($message, $extra = []) - { - return $this->log(self::ALERT, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function crit($message, $extra = []) - { - return $this->log(self::CRIT, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function err($message, $extra = []) - { - return $this->log(self::ERR, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function warn($message, $extra = []) - { - return $this->log(self::WARN, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function notice($message, $extra = []) - { - return $this->log(self::NOTICE, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function info($message, $extra = []) - { - return $this->log(self::INFO, $message, $extra); - } - - /** - * @param string $message - * @param array|Traversable $extra - * @return Logger - */ - public function debug($message, $extra = []) - { - return $this->log(self::DEBUG, $message, $extra); - } - - /** - * Register logging system as an error handler to log PHP errors - * - * @link http://www.php.net/manual/function.set-error-handler.php - * - * @param bool $continueNativeHandler - * @return mixed Returns result of set_error_handler - */ - public static function registerErrorHandler(Logger $logger, $continueNativeHandler = false): false|callable|null - { - // Only register once per instance - if (static::$registeredErrorHandler) { - return false; - } - - $errorPriorityMap = static::$errorPriorityMap; - - $previous = set_error_handler( - function ($level, $message, $file, $line) use ($logger, $errorPriorityMap, $continueNativeHandler): bool { - $iniLevel = error_reporting(); - - if (($iniLevel & $level) !== 0) { - $priority = $errorPriorityMap[$level] ?? Logger::INFO; - - $logger->log($priority, $message, [ - 'errno' => $level, - 'file' => $file, - 'line' => $line, - ]); - } - - return ! $continueNativeHandler; - } - ); - - static::$registeredErrorHandler = true; - return $previous; - } - - /** - * Unregister error handler - */ - public static function unregisterErrorHandler(): void - { - restore_error_handler(); - static::$registeredErrorHandler = false; - } - - /** - * Register a shutdown handler to log fatal errors - * - * @link http://www.php.net/manual/function.register-shutdown-function.php - */ - public static function registerFatalErrorShutdownFunction(Logger $logger): bool - { - // Only register once per instance - if (static::$registeredFatalErrorShutdownFunction) { - return false; - } - - $errorPriorityMap = static::$errorPriorityMap; - - register_shutdown_function(function () use ($logger, $errorPriorityMap): void { - $error = error_get_last(); - - if ( - null === $error - || ! in_array( - $error['type'], - [ - E_ERROR, - E_PARSE, - E_CORE_ERROR, - E_CORE_WARNING, - E_COMPILE_ERROR, - E_COMPILE_WARNING, - ], - true - ) - ) { - return; - } - - $logger->log( - $errorPriorityMap[$error['type']], - $error['message'], - [ - 'file' => $error['file'], - 'line' => $error['line'], - ] - ); - }); - - static::$registeredFatalErrorShutdownFunction = true; - - return true; - } - - /** - * Register logging system as an exception handler to log PHP exceptions - * - * @link http://www.php.net/manual/en/function.set-exception-handler.php - */ - public static function registerExceptionHandler(Logger $logger): bool - { - // Only register once per instance - if (static::$registeredExceptionHandler) { - return false; - } - - $errorPriorityMap = static::$errorPriorityMap; - - set_exception_handler(function ($exception) use ($logger, $errorPriorityMap): void { - $logMessages = []; - - do { - $priority = Logger::ERR; - if ($exception instanceof ErrorException && isset($errorPriorityMap[$exception->getSeverity()])) { - $priority = $errorPriorityMap[$exception->getSeverity()]; - } - - $extra = [ - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - 'trace' => $exception->getTrace(), - ]; - if (property_exists($exception, 'xdebug_message') && $exception->xdebug_message !== null) { - $extra['xdebug'] = $exception->xdebug_message; - } - - $logMessages[] = [ - 'priority' => $priority, - 'message' => $exception->getMessage(), - 'extra' => $extra, - ]; - $exception = $exception->getPrevious(); - } while ($exception); - - foreach (array_reverse($logMessages) as $logMessage) { - $logger->log($logMessage['priority'], $logMessage['message'], $logMessage['extra']); - } - }); - - static::$registeredExceptionHandler = true; - return true; - } - - /** - * Unregister exception handler - */ - public static function unregisterExceptionHandler(): void - { - restore_exception_handler(); - static::$registeredExceptionHandler = false; - } -} diff --git a/src/Compat/LoggerAbstractServiceFactory.php b/src/Compat/LoggerAbstractServiceFactory.php deleted file mode 100644 index 50e655f4..00000000 --- a/src/Compat/LoggerAbstractServiceFactory.php +++ /dev/null @@ -1,23 +0,0 @@ -getConfig($container); - $config = $config[$requestedName]; - - $this->processConfig($config, $container); - - return new Logger($config); - } -} diff --git a/src/Handler/Formatter/Json.php b/src/Handler/Formatter/Json.php deleted file mode 100644 index 6c77d6fd..00000000 --- a/src/Handler/Formatter/Json.php +++ /dev/null @@ -1,44 +0,0 @@ - $event event data - * @return string formatted line to write to the log - */ - public function format($event): string - { - static $timestamp; - - if (! $timestamp && isset($event[self::TIMESTAMP]) && $event[self::TIMESTAMP] instanceof DateTime) { - $timestamp = $event[self::TIMESTAMP]->format($this->getDateTimeFormat()); - } - - $event[self::TIMESTAMP] = $timestamp; - - return str_replace( - '\n', - PHP_EOL, - (string) json_encode($event, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) - ); - } -} diff --git a/src/Handler/Logging.php b/src/Handler/Logging.php index 3502a01f..147474c7 100644 --- a/src/Handler/Logging.php +++ b/src/Handler/Logging.php @@ -5,19 +5,14 @@ namespace ErrorHeroModule\Handler; use ErrorException; -use ErrorHeroModule\Compat\Logger; -use ErrorHeroModule\Handler\Formatter\Json; -use ErrorHeroModule\Handler\Writer\Mail; use ErrorHeroModule\HeroConstant; use Laminas\Diactoros\Stream; use Laminas\Http\Header\Cookie; use Laminas\Http\PhpEnvironment\RemoteAddress; use Laminas\Http\PhpEnvironment\Request as HttpRequest; -use Laminas\Log\Writer\Db; -use Laminas\Mail\Message; -use Laminas\Mail\Transport\TransportInterface; use Laminas\Stdlib\ParametersInterface; use Laminas\Stdlib\RequestInterface; +use Psr\Log\LoggerInterface; use RuntimeException; use Throwable; use Webmozart\Assert\Assert; @@ -29,16 +24,69 @@ use function php_uname; use function str_replace; +use const E_COMPILE_ERROR; +use const E_COMPILE_WARNING; +use const E_CORE_ERROR; +use const E_CORE_WARNING; +use const E_DEPRECATED; +use const E_ERROR; +use const E_NOTICE; +use const E_PARSE; +use const E_RECOVERABLE_ERROR; +use const E_USER_DEPRECATED; +use const E_USER_ERROR; +use const E_USER_NOTICE; +use const E_USER_WARNING; +use const E_WARNING; use const PHP_BINARY; use const PHP_EOL; final class Logging { - private array $configLoggingSettings = []; + /** + * @link http://tools.ietf.org/html/rfc3164 + * + * @const int defined from the BSD Syslog message severities + */ + public const EMERGENCY = 0; + + public const ALERT = 1; + + public const CRITICAL = 2; - private array $emailReceivers = []; + public const ERROR = 3; - private readonly string $emailSender; + public const WARNING = 4; + + public const NOTICE = 5; + + public const INFO = 6; + + public const DEBUG = 7; + + /** + * Map native PHP errors to priority + * + * @var array + */ + public static $errorPriorityMap = [ + E_NOTICE => self::NOTICE, + E_USER_NOTICE => self::NOTICE, + E_WARNING => self::WARNING, + E_CORE_WARNING => self::WARNING, + E_USER_WARNING => self::WARNING, + E_ERROR => self::ERROR, + E_USER_ERROR => self::ERROR, + E_CORE_ERROR => self::ERROR, + E_RECOVERABLE_ERROR => self::ERROR, + E_PARSE => self::ERROR, + E_COMPILE_ERROR => self::ERROR, + E_COMPILE_WARNING => self::ERROR, + // E_STRICT is deprecated in php 8.4 + 2048 => self::DEBUG, + E_DEPRECATED => self::DEBUG, + E_USER_DEPRECATED => self::DEBUG, + ]; /** @var string */ private const PRIORITY = 'priority'; @@ -62,16 +110,9 @@ final class Logging private const SERVER_URL = 'server_url'; public function __construct( - private readonly Logger $logger, - array $errorHeroModuleLocalConfig, - private readonly array $logWritersConfig, - private readonly ?Message $message = null, - private readonly ?TransportInterface $mailMessageTransport = null, + private readonly LoggerInterface $logger, private readonly bool $includeFilesToAttachments = true ) { - $this->configLoggingSettings = $errorHeroModuleLocalConfig['logging-settings']; - $this->emailReceivers = $errorHeroModuleLocalConfig['email-notification-settings']['email-to-send']; - $this->emailSender = $errorHeroModuleLocalConfig['email-notification-settings']['email-from']; } /** @@ -137,12 +178,12 @@ private function collectErrorExceptionData(Throwable $throwable): array { if ( $throwable instanceof ErrorException - && isset(Logger::$errorPriorityMap[$severity = $throwable->getSeverity()]) + && isset(self::$errorPriorityMap[$severity = $throwable->getSeverity()]) ) { - $priority = Logger::$errorPriorityMap[$severity]; + $priority = self::$errorPriorityMap[$severity]; $errorType = HeroConstant::ERROR_TYPE[$severity]; } else { - $priority = Logger::ERR; + $priority = self::ERROR; $errorType = $throwable::class; } @@ -200,91 +241,15 @@ private function collectErrorExceptionExtraData(array $collectedExceptionData, ? ]; } - /** - * @throws RuntimeException When cannot connect to DB in the first place. - */ - private function isExists( - string $errorFile, - int $errorLine, - string $errorMessage, - string $url, - string $errorType - ): bool { - $writers = $this->logger->getWriters()->toArray(); - foreach ($writers as $writer) { - if ($writer instanceof Db) { - try { - $handlerWriterDb = new Writer\Checker\Db( - $writer, - $this->configLoggingSettings, - $this->logWritersConfig - ); - if ($handlerWriterDb->isExists($errorFile, $errorLine, $errorMessage, $url, $errorType)) { - return true; - } - - break; - } catch (RuntimeException $runtimeException) { - // use \Laminas\Db\Adapter\Exception\RuntimeException but do here - // to avoid too much deep trace from Laminas\Db classes - throw new ${! ${''} = $runtimeException::class}($runtimeException->getMessage()); - } - } - } - - return false; - } - - private function sendMail(int $priority, string $errorMessage, array $extra, string $subject): void - { - if (! $this->message instanceof Message || ! $this->mailMessageTransport instanceof TransportInterface) { - return; - } - - if ($this->emailReceivers === []) { - return; - } - - $this->message->setFrom($this->emailSender); - $this->message->setSubject($subject); - - $filesData = $extra['request_data']['files_data'] ?? []; - foreach ($this->emailReceivers as $emailReceiver) { - $this->message->setTo($emailReceiver); - $writer = new Mail( - $this->message, - $this->mailMessageTransport, - $filesData - ); - $writer->setFormatter(new Json()); - - (new Logger())->addWriter($writer) - ->log($priority, $errorMessage, $extra); - } - } - public function handleErrorException(Throwable $throwable, ?RequestInterface $request = null): void { $collectedExceptionData = $this->collectErrorExceptionData($throwable); /** * @var array{url: string, server_url: string, mixed} $extra */ - $extra = $this->collectErrorExceptionExtraData($collectedExceptionData, $request); - $serverUrl = $extra[self::SERVER_URL]; + $extra = $this->collectErrorExceptionExtraData($collectedExceptionData, $request); try { - if ( - $this->isExists( - $collectedExceptionData[self::ERROR_FILE], - $collectedExceptionData[self::ERROR_LINE], - $collectedExceptionData[self::ERROR_MESSAGE], - $extra['url'], - $collectedExceptionData[self::ERROR_TYPE] - ) - ) { - return; - } - unset($extra[self::SERVER_URL]); $this->logger->log( $collectedExceptionData[self::PRIORITY], @@ -296,12 +261,5 @@ public function handleErrorException(Throwable $throwable, ?RequestInterface $re $extra = $this->collectErrorExceptionExtraData($collectedExceptionData, $request); unset($extra[self::SERVER_URL]); } - - $this->sendMail( - $collectedExceptionData[self::PRIORITY], - $collectedExceptionData[self::ERROR_MESSAGE], - $extra, - '[' . $serverUrl . '] ' . $collectedExceptionData[self::ERROR_TYPE] . ' has thrown' - ); } } diff --git a/src/Handler/LoggingFactory.php b/src/Handler/LoggingFactory.php index dda88edd..8af89053 100644 --- a/src/Handler/LoggingFactory.php +++ b/src/Handler/LoggingFactory.php @@ -4,61 +4,25 @@ namespace ErrorHeroModule\Handler; -use ErrorHeroModule\Compat\Logger; -use Laminas\Mail\Message; -use Laminas\Mail\Transport\TransportInterface; use Psr\Container\ContainerInterface; -use RuntimeException; - -use function sprintf; +use Psr\Log\LoggerInterface; final class LoggingFactory { - /** - * @throws RuntimeException When mail config is enabled - * but mail-message and/or mail-transport config is not a service instance of Message. - */ public function __invoke(ContainerInterface $container): Logging { /** @var array $config */ $config = $container->get('config'); - /** @var Logger $errorHeroModuleLogger */ + /** @var LoggerInterface $errorHeroModuleLogger */ $errorHeroModuleLogger = $container->get('ErrorHeroModuleLogger'); $errorHeroModuleLocalConfig = $config['error-hero-module']; - $logWritersConfig = $config['log']['ErrorHeroModuleLogger']['writers']; - - $mailConfig = $errorHeroModuleLocalConfig['email-notification-settings']; - $mailMessageService = null; - $mailMessageTransport = null; - - if ($mailConfig['enable'] === true) { - $mailMessageService = $container->get($mailConfig['mail-message']); - if (! $mailMessageService instanceof Message) { - throw new RuntimeException(sprintf( - 'You are enabling email log writer, your "mail-message" config must be instanceof %s', - Message::class - )); - } - - $mailMessageTransport = $container->get($mailConfig['mail-transport']); - if (! $mailMessageTransport instanceof TransportInterface) { - throw new RuntimeException(sprintf( - 'You are enabling email log writer, your "mail-transport" config must implements %s', - TransportInterface::class - )); - } - } - - $includeFilesToAttachments = $mailConfig['include-files-to-attachments'] ?? true; + $mailConfig = $errorHeroModuleLocalConfig['email-notification-settings']; + $includeFilesToAttachments = $mailConfig['include-files-to-attachments'] ?? true; return new Logging( $errorHeroModuleLogger, - $errorHeroModuleLocalConfig, - $logWritersConfig, - $mailMessageService, - $mailMessageTransport, - $includeFilesToAttachments + $includeFilesToAttachments, ); } } diff --git a/src/Handler/Writer/Checker/Db.php b/src/Handler/Writer/Checker/Db.php deleted file mode 100644 index 722c0941..00000000 --- a/src/Handler/Writer/Checker/Db.php +++ /dev/null @@ -1,89 +0,0 @@ - $dbWriter->db, null, $this->dbWriter)($this->dbWriter); - - foreach ($this->logWritersConfig as $logWriterConfig) { - if ($logWriterConfig['name'] === 'db') { - // table definition - $table = $logWriterConfig[self::OPTIONS]['table']; - - // columns definition - $timestamp = $logWriterConfig[self::OPTIONS][self::COLUMN]['timestamp']; - $message = $logWriterConfig[self::OPTIONS][self::COLUMN]['message']; - $file = $logWriterConfig[self::OPTIONS][self::COLUMN][self::EXTRA]['file']; - $line = $logWriterConfig[self::OPTIONS][self::COLUMN][self::EXTRA]['line']; - $url = $logWriterConfig[self::OPTIONS][self::COLUMN][self::EXTRA]['url']; - $error_type = $logWriterConfig[self::OPTIONS][self::COLUMN][self::EXTRA]['error_type']; - - $tableGateway = new TableGateway($table, $db, null, new ResultSet()); - $select = $tableGateway->getSql()->select(); - $select->columns([$timestamp]); - $select->where([ - $message => $errorMessage, - $line => $errorLine, - $url => $errorUrl, - $file => $errorFile, - $error_type => $errorType, - ]); - $select->order($timestamp . ' DESC'); - $select->limit(1); - - /** @var ResultSet $resultSet */ - $resultSet = $tableGateway->selectWith($select); - if (! ($current = $resultSet->current())) { - return false; - } - - $first = $current[$timestamp]; - $last = date('Y-m-d H:i:s'); - - $diff = strtotime($last) - strtotime((string) $first); - if ($diff <= $this->configLoggingSettings['same-error-log-time-range']) { - return true; - } - - break; - } - } - - return false; - } -} diff --git a/src/Handler/Writer/Mail.php b/src/Handler/Writer/Mail.php deleted file mode 100644 index 39c58881..00000000 --- a/src/Handler/Writer/Mail.php +++ /dev/null @@ -1,118 +0,0 @@ -eventsToMail); - - if ($this->filesData === []) { - $this->mail->setBody($body); - } else { - $mimePart = new Part($body); - $mimePart->type = Mime::TYPE_TEXT; - $mimePart->charset = 'utf-8'; - $mimePart->encoding = Mime::ENCODING_8BIT; - - $body = new MimeMessage(); - $body->addPart($mimePart); - - $body = $this->bodyAddPart($body, $this->filesData); - $this->mail->setBody($body); - - $headers = $this->mail->getHeaders(); - /** @var ContentType $contentTypeHeader */ - $contentTypeHeader = $headers->get('Content-Type'); - $contentTypeHeader->setType('multipart/alternative'); - } - - // Finally, send the mail. If an exception occurs, convert it into a - // warning-level message so we can avoid an exception thrown without a - // stack frame. - try { - $this->transport->send($this->mail); - } catch (Exception $exception) { - /** @var string $message */ - $message = $exception->getMessage(); - /** @var int $code */ - $code = $exception->getCode(); - - trigger_error( - "unable to send log entries via email; " - . sprintf('message = %s; ', $message) - . sprintf('code = %d; ', $code) - . "exception class = " . $exception::class, - E_USER_WARNING - ); - } - } - - private function bodyAddPart(MimeMessage $mimeMessage, array $data): MimeMessage - { - foreach ($data as $singleData) { - if (key($singleData) === self::NAME && ! is_array($singleData[self::NAME])) { - $mimeMessage = $this->singleBodyAddPart($mimeMessage, $singleData); - continue; - } - - $mimeMessage = $this->bodyAddPart($mimeMessage, $singleData); - } - - return $mimeMessage; - } - - private function singleBodyAddPart(MimeMessage $mimeMessage, array $data): MimeMessage - { - $mimePart = new Part(fopen($data['tmp_name'], 'r')); - $mimePart->type = $data['type']; - $mimePart->filename = $data[self::NAME]; - $mimePart->disposition = Mime::DISPOSITION_ATTACHMENT; - $mimePart->encoding = Mime::ENCODING_BASE64; - - return $mimeMessage->addPart($mimePart); - } -}