Преглед на файлове

Add phpstan strict rules and deprecation rules, fix all related issues

Jordi Boggiano преди 3 години
родител
ревизия
6627c092d8
променени са 62 файла, в които са добавени 335 реда и са изтрити 186 реда
  1. 5 3
      composer.json
  2. 51 1
      phpstan-baseline.neon
  3. 2 0
      phpstan.neon.dist
  4. 6 6
      src/Monolog/ErrorHandler.php
  5. 2 2
      src/Monolog/Formatter/ChromePHPFormatter.php
  6. 3 3
      src/Monolog/Formatter/GelfMessageFormatter.php
  7. 3 3
      src/Monolog/Formatter/HtmlFormatter.php
  8. 3 3
      src/Monolog/Formatter/LineFormatter.php
  9. 6 6
      src/Monolog/Formatter/LogmaticFormatter.php
  10. 3 6
      src/Monolog/Formatter/LogstashFormatter.php
  11. 1 1
      src/Monolog/Formatter/NormalizerFormatter.php
  12. 1 1
      src/Monolog/Handler/AbstractProcessingHandler.php
  13. 1 3
      src/Monolog/Handler/AmqpHandler.php
  14. 4 4
      src/Monolog/Handler/BrowserConsoleHandler.php
  15. 1 1
      src/Monolog/Handler/BufferHandler.php
  16. 2 2
      src/Monolog/Handler/ChromePHPHandler.php
  17. 21 2
      src/Monolog/Handler/CouchDBHandler.php
  18. 9 9
      src/Monolog/Handler/CubeHandler.php
  19. 1 1
      src/Monolog/Handler/Curl/Util.php
  20. 3 3
      src/Monolog/Handler/DeduplicationHandler.php
  21. 1 1
      src/Monolog/Handler/DynamoDbHandler.php
  22. 16 1
      src/Monolog/Handler/ElasticaHandler.php
  23. 16 1
      src/Monolog/Handler/ElasticsearchHandler.php
  24. 2 2
      src/Monolog/Handler/FallbackGroupHandler.php
  25. 1 1
      src/Monolog/Handler/FilterHandler.php
  26. 1 1
      src/Monolog/Handler/FingersCrossedHandler.php
  27. 1 1
      src/Monolog/Handler/FirePHPHandler.php
  28. 2 2
      src/Monolog/Handler/GroupHandler.php
  29. 10 7
      src/Monolog/Handler/LogglyHandler.php
  30. 7 7
      src/Monolog/Handler/LogmaticHandler.php
  31. 1 1
      src/Monolog/Handler/MailHandler.php
  32. 2 2
      src/Monolog/Handler/MandrillHandler.php
  33. 3 6
      src/Monolog/Handler/NativeMailerHandler.php
  34. 2 2
      src/Monolog/Handler/NewRelicHandler.php
  35. 64 14
      src/Monolog/Handler/PHPConsoleHandler.php
  36. 2 2
      src/Monolog/Handler/ProcessHandler.php
  37. 1 1
      src/Monolog/Handler/ProcessableHandlerTrait.php
  38. 2 2
      src/Monolog/Handler/PsrHandler.php
  39. 2 2
      src/Monolog/Handler/PushoverHandler.php
  40. 2 2
      src/Monolog/Handler/RedisHandler.php
  41. 1 1
      src/Monolog/Handler/RotatingFileHandler.php
  42. 1 1
      src/Monolog/Handler/SamplingHandler.php
  43. 11 11
      src/Monolog/Handler/Slack/SlackRecord.php
  44. 1 1
      src/Monolog/Handler/SlackHandler.php
  45. 8 8
      src/Monolog/Handler/SocketHandler.php
  46. 2 6
      src/Monolog/Handler/StreamHandler.php
  47. 6 2
      src/Monolog/Handler/SyslogUdp/UdpSocket.php
  48. 4 2
      src/Monolog/Handler/SyslogUdpHandler.php
  49. 3 3
      src/Monolog/Handler/TelegramBotHandler.php
  50. 1 1
      src/Monolog/Handler/TestHandler.php
  51. 2 2
      src/Monolog/Handler/WhatFailureGroupHandler.php
  52. 10 10
      src/Monolog/Logger.php
  53. 3 3
      src/Monolog/Processor/GitProcessor.php
  54. 2 2
      src/Monolog/Processor/IntrospectionProcessor.php
  55. 2 2
      src/Monolog/Processor/MercurialProcessor.php
  56. 2 2
      src/Monolog/Processor/PsrLogMessageProcessor.php
  57. 1 1
      src/Monolog/Processor/WebProcessor.php
  58. 1 1
      src/Monolog/Registry.php
  59. 1 2
      src/Monolog/SignalHandler.php
  60. 2 2
      src/Monolog/Test/TestCase.php
  61. 4 4
      src/Monolog/Utils.php
  62. 1 1
      tests/Monolog/Formatter/LogmaticFormatterTest.php

+ 5 - 3
composer.json

@@ -20,15 +20,17 @@
         "aws/aws-sdk-php": "^3.0",
         "doctrine/couchdb": "~1.0@dev",
         "elasticsearch/elasticsearch": "^7",
-        "mongodb/mongodb": "^1.8",
         "graylog2/gelf-php": "^1.4.2",
+        "mongodb/mongodb": "^1.8",
         "php-amqplib/php-amqplib": "~2.4 || ^3",
         "php-console/php-console": "^3.1.3",
         "phpspec/prophecy": "^1.6.1",
+        "phpstan/phpstan": "^1.4",
+        "phpstan/phpstan-deprecation-rules": "^1.0",
+        "phpstan/phpstan-strict-rules": "^1.1",
         "phpunit/phpunit": "^9.5.16",
         "predis/predis": "^1.1",
-        "ruflin/elastica": ">=0.90@dev",
-        "phpstan/phpstan": "^1.4"
+        "ruflin/elastica": ">=0.90@dev"
     },
     "suggest": {
         "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",

+ 51 - 1
phpstan-baseline.neon

@@ -10,6 +10,31 @@ parameters:
 			count: 1
 			path: src/Monolog/Formatter/WildfireFormatter.php
 
+		-
+			message: "#^Return type \\(array\\<array\\|bool\\|float\\|int\\|string\\|null\\>\\|bool\\|float\\|int\\|object\\|string\\|null\\) of method Monolog\\\\Formatter\\\\WildfireFormatter\\:\\:normalize\\(\\) should be covariant with return type \\(array\\<array\\|bool\\|float\\|int\\|string\\|null\\>\\|bool\\|float\\|int\\|string\\|null\\) of method Monolog\\\\Formatter\\\\NormalizerFormatter\\:\\:normalize\\(\\)$#"
+			count: 1
+			path: src/Monolog/Formatter/WildfireFormatter.php
+
+		-
+			message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
+			count: 1
+			path: src/Monolog/Handler/BrowserConsoleHandler.php
+
+		-
+			message: "#^Instanceof between Monolog\\\\Handler\\\\HandlerInterface and Monolog\\\\Handler\\\\HandlerInterface will always evaluate to true\\.$#"
+			count: 1
+			path: src/Monolog/Handler/FilterHandler.php
+
+		-
+			message: "#^Instanceof between Monolog\\\\Handler\\\\HandlerInterface and Monolog\\\\Handler\\\\HandlerInterface will always evaluate to true\\.$#"
+			count: 1
+			path: src/Monolog/Handler/FingersCrossedHandler.php
+
+		-
+			message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
+			count: 1
+			path: src/Monolog/Handler/FingersCrossedHandler.php
+
 		-
 			message: "#^Call to method setBody\\(\\) on an unknown class Swift_Message\\.$#"
 			count: 1
@@ -30,9 +55,14 @@ parameters:
 			count: 1
 			path: src/Monolog/Handler/MandrillHandler.php
 
+		-
+			message: "#^Instanceof between Swift_Message and Swift_Message will always evaluate to true\\.$#"
+			count: 1
+			path: src/Monolog/Handler/MandrillHandler.php
+
 		-
 			message: "#^Parameter \\$message of method Monolog\\\\Handler\\\\MandrillHandler\\:\\:__construct\\(\\) has invalid type Swift_Message\\.$#"
-			count: 2
+			count: 3
 			path: src/Monolog/Handler/MandrillHandler.php
 
 		-
@@ -40,6 +70,26 @@ parameters:
 			count: 1
 			path: src/Monolog/Handler/MandrillHandler.php
 
+		-
+			message: "#^Method Monolog\\\\Handler\\\\PHPConsoleHandler\\:\\:initOptions\\(\\) should return array\\{enabled\\: bool, classesPartialsTraceIgnore\\: array\\<string\\>, debugTagsKeysInContext\\: array\\<int\\|string\\>, useOwnErrorsHandler\\: bool, useOwnExceptionsHandler\\: bool, sourcesBasePath\\: string\\|null, registerHelper\\: bool, serverEncoding\\: string\\|null, \\.\\.\\.\\} but returns non\\-empty\\-array\\<'classesPartialsTrac…'\\|'dataStorage'\\|'debugTagsKeysInCont…'\\|'detectDumpTraceAndS…'\\|'dumperDetectCallbac…'\\|'dumperDumpSizeLimit'\\|'dumperItemsCountLim…'\\|'dumperItemSizeLimit'\\|'dumperLevelLimit'\\|'enabled'\\|'enableEvalListener'\\|'enableSslOnlyMode'\\|'headersLimit'\\|'ipMasks'\\|'password'\\|'registerHelper'\\|'serverEncoding'\\|'sourcesBasePath'\\|'useOwnErrorsHandler'\\|'useOwnExceptionsHan…', array\\<int\\|string\\>\\|bool\\|int\\|PhpConsole\\\\Storage\\|string\\|null\\>\\.$#"
+			count: 1
+			path: src/Monolog/Handler/PHPConsoleHandler.php
+
+		-
+			message: "#^Instanceof between Monolog\\\\Handler\\\\HandlerInterface and Monolog\\\\Handler\\\\HandlerInterface will always evaluate to true\\.$#"
+			count: 1
+			path: src/Monolog/Handler/SamplingHandler.php
+
+		-
+			message: "#^Variable property access on \\$this\\(Monolog\\\\LogRecord\\)\\.$#"
+			count: 5
+			path: src/Monolog/LogRecord.php
+
+		-
+			message: "#^Parameter \\#1 \\$level \\('alert'\\|'critical'\\|'debug'\\|'emergency'\\|'error'\\|'info'\\|'notice'\\|'warning'\\|Monolog\\\\Level\\|Monolog\\\\LevelName\\) of method Monolog\\\\Logger\\:\\:log\\(\\) should be contravariant with parameter \\$level \\(mixed\\) of method Psr\\\\Log\\\\LoggerInterface\\:\\:log\\(\\)$#"
+			count: 1
+			path: src/Monolog/Logger.php
+
 		-
 			message: "#^Comparison operation \"\\<\" between int\\<1, 32\\> and 1 is always false\\.$#"
 			count: 1

+ 2 - 0
phpstan.neon.dist

@@ -24,3 +24,5 @@ parameters:
 
 includes:
     - phpstan-baseline.neon
+    - vendor/phpstan/phpstan-strict-rules/rules.neon
+    - vendor/phpstan/phpstan-deprecation-rules/rules.neon

+ 6 - 6
src/Monolog/ErrorHandler.php

@@ -97,7 +97,7 @@ class ErrorHandler
                 $this->uncaughtExceptionLevelMap[$class] = $level;
             }
         }
-        if ($callPrevious && $prev) {
+        if ($callPrevious && null !== $prev) {
             $this->previousExceptionHandler = $prev(...);
         }
 
@@ -189,11 +189,11 @@ class ErrorHandler
             ['exception' => $e]
         );
 
-        if ($this->previousExceptionHandler) {
+        if (null !== $this->previousExceptionHandler) {
             ($this->previousExceptionHandler)($e);
         }
 
-        if (!headers_sent() && !ini_get('display_errors')) {
+        if (!headers_sent() && !(bool) ini_get('display_errors')) {
             http_response_code(500);
         }
 
@@ -202,7 +202,7 @@ class ErrorHandler
 
     private function handleError(int $code, string $message, string $file = '', int $line = 0): bool
     {
-        if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) {
+        if ($this->handleOnlyReportedErrors && 0 === (error_reporting() & $code)) {
             return false;
         }
 
@@ -219,7 +219,7 @@ class ErrorHandler
         if ($this->previousErrorHandler === true) {
             return false;
         }
-        if ($this->previousErrorHandler) {
+        if ($this->previousErrorHandler instanceof Closure) {
             return (bool) ($this->previousErrorHandler)($code, $message, $file, $line);
         }
 
@@ -234,7 +234,7 @@ class ErrorHandler
         $this->reservedMemory = '';
 
         $lastError = error_get_last();
-        if ($lastError && in_array($lastError['type'], self::FATAL_ERRORS, true)) {
+        if (is_array($lastError) && in_array($lastError['type'], self::FATAL_ERRORS, true)) {
             $this->logger->log(
                 $this->fatalLevel,
                 'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],

+ 2 - 2
src/Monolog/Formatter/ChromePHPFormatter.php

@@ -53,10 +53,10 @@ class ChromePHPFormatter implements FormatterInterface
         }
 
         $message = ['message' => $record->message];
-        if ($record->context) {
+        if (\count($record->context) > 0) {
             $message['context'] = $record->context;
         }
-        if ($record->extra) {
+        if (\count($record->extra) > 0) {
             $message['extra'] = $record->extra;
         }
         if (count($message) === 1) {

+ 3 - 3
src/Monolog/Formatter/GelfMessageFormatter.php

@@ -96,12 +96,12 @@ class GelfMessageFormatter extends NormalizerFormatter
         $message = new Message();
         $message
             ->setTimestamp($record->datetime)
-            ->setShortMessage((string) $record->message)
+            ->setShortMessage($record->message)
             ->setHost($this->systemName)
             ->setLevel($this->getGraylog2Priority($record->level));
 
         // message length + system name length + 200 for padding / metadata
-        $len = 200 + strlen((string) $record->message) + strlen($this->systemName);
+        $len = 200 + strlen($record->message) + strlen($this->systemName);
 
         if ($len > $this->maxLength) {
             $message->setShortMessage(Utils::substr($record->message, 0, $this->maxLength));
@@ -143,7 +143,7 @@ class GelfMessageFormatter extends NormalizerFormatter
 
         /** @phpstan-ignore-next-line */
         if (null === $message->getFile() && isset($context['exception']['file'])) {
-            if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
+            if (1 === preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
                 $message->setFile($matches[1]);
                 $message->setLine($matches[2]);
             }

+ 3 - 3
src/Monolog/Formatter/HtmlFormatter.php

@@ -88,10 +88,10 @@ class HtmlFormatter extends NormalizerFormatter
         $output = $this->addTitle($record->levelName->value, $record->level);
         $output .= '<table cellspacing="1" width="100%" class="monolog-output">';
 
-        $output .= $this->addRow('Message', (string) $record->message);
+        $output .= $this->addRow('Message', $record->message);
         $output .= $this->addRow('Time', $this->formatDate($record->datetime));
         $output .= $this->addRow('Channel', $record->channel);
-        if ($record->context) {
+        if (\count($record->context) > 0) {
             $embeddedTable = '<table cellspacing="1" width="100%">';
             foreach ($record->context as $key => $value) {
                 $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
@@ -99,7 +99,7 @@ class HtmlFormatter extends NormalizerFormatter
             $embeddedTable .= '</table>';
             $output .= $this->addRow('Context', $embeddedTable, false);
         }
-        if ($record->extra) {
+        if (\count($record->extra) > 0) {
             $embeddedTable = '<table cellspacing="1" width="100%">';
             foreach ($record->extra as $key => $value) {
                 $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));

+ 3 - 3
src/Monolog/Formatter/LineFormatter.php

@@ -92,12 +92,12 @@ class LineFormatter extends NormalizerFormatter
         }
 
         if ($this->ignoreEmptyContextAndExtra) {
-            if (empty($vars['context'])) {
+            if (\count($vars['context']) === 0) {
                 unset($vars['context']);
                 $output = str_replace('%context%', '', $output);
             }
 
-            if (empty($vars['extra'])) {
+            if (\count($vars['extra']) === 0) {
                 unset($vars['extra']);
                 $output = str_replace('%extra%', '', $output);
             }
@@ -144,7 +144,7 @@ class LineFormatter extends NormalizerFormatter
     {
         $str = $this->formatException($e);
 
-        if ($previous = $e->getPrevious()) {
+        if (($previous = $e->getPrevious()) instanceof \Throwable) {
             do {
                 $str .= "\n[previous exception] " . $this->formatException($previous);
             } while ($previous = $previous->getPrevious());

+ 6 - 6
src/Monolog/Formatter/LogmaticFormatter.php

@@ -24,7 +24,7 @@ class LogmaticFormatter extends JsonFormatter
 
     protected string $hostname = '';
 
-    protected string $appname = '';
+    protected string $appName = '';
 
     public function setHostname(string $hostname): self
     {
@@ -33,9 +33,9 @@ class LogmaticFormatter extends JsonFormatter
         return $this;
     }
 
-    public function setAppname(string $appname): self
+    public function setAppName(string $appName): self
     {
-        $this->appname = $appname;
+        $this->appName = $appName;
 
         return $this;
     }
@@ -50,11 +50,11 @@ class LogmaticFormatter extends JsonFormatter
     {
         $record = parent::normalizeRecord($record);
 
-        if (!empty($this->hostname)) {
+        if ($this->hostname !== '') {
             $record["hostname"] = $this->hostname;
         }
-        if (!empty($this->appname)) {
-            $record["appname"] = $this->appname;
+        if ($this->appName !== '') {
+            $record["appname"] = $this->appName;
         }
 
         $record["@marker"] = static::MARKERS;

+ 3 - 6
src/Monolog/Formatter/LogstashFormatter.php

@@ -67,9 +67,6 @@ class LogstashFormatter extends NormalizerFormatter
     {
         $recordData = parent::format($record);
 
-        if (empty($recordData['datetime'])) {
-            $recordData['datetime'] = gmdate('c');
-        }
         $message = [
             '@timestamp' => $recordData['datetime'],
             '@version' => 1,
@@ -88,13 +85,13 @@ class LogstashFormatter extends NormalizerFormatter
         if (isset($recordData['level'])) {
             $message['monolog_level'] = $recordData['level'];
         }
-        if ($this->applicationName) {
+        if ('' !== $this->applicationName) {
             $message['type'] = $this->applicationName;
         }
-        if (!empty($recordData['extra'])) {
+        if (\count($recordData['extra']) > 0) {
             $message[$this->extraKey] = $recordData['extra'];
         }
-        if (!empty($recordData['context'])) {
+        if (\count($recordData['context']) > 0) {
             $message[$this->contextKey] = $recordData['context'];
         }
 

+ 1 - 1
src/Monolog/Formatter/NormalizerFormatter.php

@@ -254,7 +254,7 @@ class NormalizerFormatter implements FormatterInterface
             }
         }
 
-        if ($previous = $e->getPrevious()) {
+        if (($previous = $e->getPrevious()) instanceof \Throwable) {
             $data['previous'] = $this->normalizeException($previous, $depth + 1);
         }
 

+ 1 - 1
src/Monolog/Handler/AbstractProcessingHandler.php

@@ -35,7 +35,7 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc
             return false;
         }
 
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 

+ 1 - 3
src/Monolog/Handler/AmqpHandler.php

@@ -34,9 +34,7 @@ class AmqpHandler extends AbstractProcessingHandler
     {
         if ($exchange instanceof AMQPChannel) {
             $this->exchangeName = (string) $exchangeName;
-        } elseif (!$exchange instanceof AMQPExchange) {
-            throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required');
-        } elseif ($exchangeName) {
+        } elseif ($exchangeName !== null) {
             @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
         }
         $this->exchange = $exchange;

+ 4 - 4
src/Monolog/Handler/BrowserConsoleHandler.php

@@ -76,10 +76,10 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
             return;
         }
 
-        if (count(static::$records)) {
+        if (count(static::$records) > 0) {
             if ($format === self::FORMAT_HTML) {
                 static::writeOutput('<script>' . self::generateScript() . '</script>');
-            } elseif ($format === self::FORMAT_JS) {
+            } else { // js format
                 static::writeOutput(self::generateScript());
             }
             static::resetStatic();
@@ -172,7 +172,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
             $context = self::dump('Context', $record->context);
             $extra = self::dump('Extra', $record->extra);
 
-            if (empty($context) && empty($extra)) {
+            if (\count($context) === 0 && \count($extra) === 0) {
                 $script[] = self::call_array('log', self::handleStyles($record->formatted));
             } else {
                 $script = array_merge(
@@ -247,7 +247,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler
     {
         $script = [];
         $dict = array_filter($dict);
-        if (empty($dict)) {
+        if (\count($dict) === 0) {
             return $script;
         }
         $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title));

+ 1 - 1
src/Monolog/Handler/BufferHandler.php

@@ -79,7 +79,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa
             }
         }
 
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 

+ 2 - 2
src/Monolog/Handler/ChromePHPHandler.php

@@ -90,7 +90,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
             $messages[] = $message;
         }
 
-        if (!empty($messages)) {
+        if (\count($messages) > 0) {
             $messages = $this->getFormatter()->formatBatch($messages);
             self::$json['rows'] = array_merge(self::$json['rows'], $messages);
             $this->send();
@@ -180,7 +180,7 @@ class ChromePHPHandler extends AbstractProcessingHandler
      */
     protected function headersAccepted(): bool
     {
-        if (empty($_SERVER['HTTP_USER_AGENT'])) {
+        if (!isset($_SERVER['HTTP_USER_AGENT'])) {
             return false;
         }
 

+ 21 - 2
src/Monolog/Handler/CouchDBHandler.php

@@ -20,14 +20,33 @@ use Monolog\LogRecord;
  * CouchDB handler
  *
  * @author Markus Bachmann <markus.bachmann@bachi.biz>
+ * @phpstan-type Options array{
+ *     host: string,
+ *     port: int,
+ *     dbname: string,
+ *     username: string|null,
+ *     password: string|null
+ * }
+ * @phpstan-type InputOptions array{
+ *     host?: string,
+ *     port?: int,
+ *     dbname?: string,
+ *     username?: string|null,
+ *     password?: string|null
+ * }
  */
 class CouchDBHandler extends AbstractProcessingHandler
 {
-    /** @var mixed[] */
+    /**
+     * @var mixed[]
+     * @phpstan-var Options
+     */
     private array $options;
 
     /**
      * @param mixed[] $options
+     *
+     * @phpstan-param InputOptions $options
      */
     public function __construct(array $options = [], $level = Level::Debug, bool $bubble = true)
     {
@@ -48,7 +67,7 @@ class CouchDBHandler extends AbstractProcessingHandler
     protected function write(LogRecord $record): void
     {
         $basicAuth = null;
-        if ($this->options['username']) {
+        if (null !== $this->options['username'] && null !== $this->options['password']) {
             $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
         }
 

+ 9 - 9
src/Monolog/Handler/CubeHandler.php

@@ -46,7 +46,7 @@ class CubeHandler extends AbstractProcessingHandler
             throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
         }
 
-        if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
+        if (!in_array($urlInfo['scheme'], $this->acceptedSchemes, true)) {
             throw new \UnexpectedValueException(
                 'Invalid protocol (' . $urlInfo['scheme']  . ').'
                 . ' Valid options are ' . implode(', ', $this->acceptedSchemes)
@@ -55,7 +55,7 @@ class CubeHandler extends AbstractProcessingHandler
 
         $this->scheme = $urlInfo['scheme'];
         $this->host = $urlInfo['host'];
-        $this->port = (int) $urlInfo['port'];
+        $this->port = $urlInfo['port'];
 
         parent::__construct($level, $bubble);
     }
@@ -113,16 +113,16 @@ class CubeHandler extends AbstractProcessingHandler
         $date = $record->datetime;
 
         $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')];
-        unset($record->datetime);
+        $context = $record->context;
 
-        if (isset($record->context['type'])) {
-            $data['type'] = $record->context['type'];
-            unset($record->context['type']);
+        if (isset($context['type'])) {
+            $data['type'] = $context['type'];
+            unset($context['type']);
         } else {
             $data['type'] = $record->channel;
         }
 
-        $data['data'] = $record->context;
+        $data['data'] = $context;
         $data['data']['level'] = $record->level;
 
         if ($this->scheme === 'http') {
@@ -134,7 +134,7 @@ class CubeHandler extends AbstractProcessingHandler
 
     private function writeUdp(string $data): void
     {
-        if (!$this->udpConnection) {
+        if (null === $this->udpConnection) {
             $this->connectUdp();
         }
 
@@ -147,7 +147,7 @@ class CubeHandler extends AbstractProcessingHandler
 
     private function writeHttp(string $data): void
     {
-        if (!$this->httpConnection) {
+        if (null === $this->httpConnection) {
             $this->connectHttp();
         }
 

+ 1 - 1
src/Monolog/Handler/Curl/Util.php

@@ -44,7 +44,7 @@ final class Util
             if ($curlResponse === false) {
                 $curlErrno = curl_errno($ch);
 
-                if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) {
+                if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || $retries === 0) {
                     $curlError = curl_error($ch);
 
                     if ($closeAfterDone) {

+ 3 - 3
src/Monolog/Handler/DeduplicationHandler.php

@@ -75,7 +75,7 @@ class DeduplicationHandler extends BufferHandler
 
         foreach ($this->buffer as $record) {
             if ($record->level->value >= $this->deduplicationLevel->value) {
-                $passthru = $passthru || !$this->isDuplicate($record);
+                $passthru = $passthru === true || !$this->isDuplicate($record);
                 if ($passthru) {
                     $this->appendRecord($record);
                 }
@@ -132,7 +132,7 @@ class DeduplicationHandler extends BufferHandler
 
         $handle = fopen($this->deduplicationStore, 'rw+');
 
-        if (!$handle) {
+        if (false === $handle) {
             throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
         }
 
@@ -143,7 +143,7 @@ class DeduplicationHandler extends BufferHandler
 
         while (!feof($handle)) {
             $log = fgets($handle);
-            if ($log && substr($log, 0, 10) >= $timestampValidity) {
+            if (is_string($log) && '' !== $log && substr($log, 0, 10) >= $timestampValidity) {
                 $validLogs[] = $log;
             }
         }

+ 1 - 1
src/Monolog/Handler/DynamoDbHandler.php

@@ -66,7 +66,7 @@ class DynamoDbHandler extends AbstractProcessingHandler
     protected function filterEmptyFields(array $record): array
     {
         return array_filter($record, function ($value) {
-            return !empty($value) || false === $value || 0 === $value;
+            return [] !== $value;
         });
     }
 

+ 16 - 1
src/Monolog/Handler/ElasticaHandler.php

@@ -34,6 +34,16 @@ use Monolog\LogRecord;
  *    $log->pushHandler($handler);
  *
  * @author Jelle Vink <jelle.vink@gmail.com>
+ * @phpstan-type Options array{
+ *     index: string,
+ *     type: string,
+ *     ignore_error: bool
+ * }
+ * @phpstan-type InputOptions array{
+ *     index?: string,
+ *     type?: string,
+ *     ignore_error?: bool
+ * }
  */
 class ElasticaHandler extends AbstractProcessingHandler
 {
@@ -41,12 +51,15 @@ class ElasticaHandler extends AbstractProcessingHandler
 
     /**
      * @var mixed[] Handler config options
+     * @phpstan-var Options
      */
-    protected array $options = [];
+    protected array $options;
 
     /**
      * @param Client  $client  Elastica Client object
      * @param mixed[] $options Handler configuration
+     *
+     * @phpstan-param InputOptions $options
      */
     public function __construct(Client $client, array $options = [], $level = Level::Debug, bool $bubble = true)
     {
@@ -84,6 +97,8 @@ class ElasticaHandler extends AbstractProcessingHandler
 
     /**
      * @return mixed[]
+     *
+     * @phpstan-return Options
      */
     public function getOptions(): array
     {

+ 16 - 1
src/Monolog/Handler/ElasticsearchHandler.php

@@ -41,6 +41,16 @@ use Monolog\LogRecord;
  *    $log->pushHandler($handler);
  *
  * @author Avtandil Kikabidze <akalongman@gmail.com>
+ * @phpstan-type Options array{
+ *     index: string,
+ *     type: string,
+ *     ignore_error: bool
+ * }
+ * @phpstan-type InputOptions array{
+ *     index?: string,
+ *     type?: string,
+ *     ignore_error?: bool
+ * }
  */
 class ElasticsearchHandler extends AbstractProcessingHandler
 {
@@ -48,12 +58,15 @@ class ElasticsearchHandler extends AbstractProcessingHandler
 
     /**
      * @var mixed[] Handler config options
+     * @phpstan-var Options
      */
-    protected array $options = [];
+    protected array $options;
 
     /**
      * @param Client  $client  Elasticsearch Client object
      * @param mixed[] $options Handler configuration
+     *
+     * @phpstan-param InputOptions $options
      */
     public function __construct(Client $client, array $options = [], $level = Level::Debug, bool $bubble = true)
     {
@@ -93,6 +106,8 @@ class ElasticsearchHandler extends AbstractProcessingHandler
      * Getter options
      *
      * @return mixed[]
+     *
+     * @phpstan-return Options
      */
     public function getOptions(): array
     {

+ 2 - 2
src/Monolog/Handler/FallbackGroupHandler.php

@@ -28,7 +28,7 @@ class FallbackGroupHandler extends GroupHandler
      */
     public function handle(LogRecord $record): bool
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
         foreach ($this->handlers as $handler) {
@@ -48,7 +48,7 @@ class FallbackGroupHandler extends GroupHandler
      */
     public function handleBatch(array $records): void
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $processed = [];
             foreach ($records as $record) {
                 $processed[] = $this->processRecord($record);

+ 1 - 1
src/Monolog/Handler/FilterHandler.php

@@ -119,7 +119,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese
             return false;
         }
 
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 

+ 1 - 1
src/Monolog/Handler/FingersCrossedHandler.php

@@ -125,7 +125,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa
      */
     public function handle(LogRecord $record): bool
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 

+ 1 - 1
src/Monolog/Handler/FirePHPHandler.php

@@ -165,7 +165,7 @@ class FirePHPHandler extends AbstractProcessingHandler
      */
     protected function headersAccepted(): bool
     {
-        if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
+        if (isset($_SERVER['HTTP_USER_AGENT']) && 1 === preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
             return true;
         }
 

+ 2 - 2
src/Monolog/Handler/GroupHandler.php

@@ -63,7 +63,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
      */
     public function handle(LogRecord $record): bool
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 
@@ -79,7 +79,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset
      */
     public function handleBatch(array $records): void
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $processed = [];
             foreach ($records as $record) {
                 $processed[] = $this->processRecord($record);

+ 10 - 7
src/Monolog/Handler/LogglyHandler.php

@@ -90,10 +90,13 @@ class LogglyHandler extends AbstractProcessingHandler
     /**
      * @param string[]|string $tag
      */
-    public function setTag($tag): self
+    public function setTag(string|array $tag): self
     {
-        $tag = !empty($tag) ? $tag : [];
-        $this->tag = is_array($tag) ? $tag : [$tag];
+        if ('' === $tag || [] === $tag) {
+            $this->tag = [];
+        } else {
+            $this->tag = is_array($tag) ? $tag : [$tag];
+        }
 
         return $this;
     }
@@ -101,9 +104,9 @@ class LogglyHandler extends AbstractProcessingHandler
     /**
      * @param string[]|string $tag
      */
-    public function addTag($tag): self
+    public function addTag(string|array $tag): self
     {
-        if (!empty($tag)) {
+        if ('' !== $tag) {
             $tag = is_array($tag) ? $tag : [$tag];
             $this->tag = array_unique(array_merge($this->tag, $tag));
         }
@@ -124,7 +127,7 @@ class LogglyHandler extends AbstractProcessingHandler
             return ($record->level >= $level);
         });
 
-        if ($records) {
+        if (\count($records) > 0) {
             $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
         }
     }
@@ -135,7 +138,7 @@ class LogglyHandler extends AbstractProcessingHandler
 
         $headers = ['Content-Type: application/json'];
 
-        if (!empty($this->tag)) {
+        if (\count($this->tag) > 0) {
             $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag);
         }
 

+ 7 - 7
src/Monolog/Handler/LogmaticHandler.php

@@ -25,12 +25,12 @@ class LogmaticHandler extends SocketHandler
 
     private string $hostname;
 
-    private string $appname;
+    private string $appName;
 
     /**
      * @param string $token    Log token supplied by Logmatic.
      * @param string $hostname Host name supplied by Logmatic.
-     * @param string $appname  Application name supplied by Logmatic.
+     * @param string $appName  Application name supplied by Logmatic.
      * @param bool   $useSSL   Whether or not SSL encryption should be used.
      *
      * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
@@ -38,7 +38,7 @@ class LogmaticHandler extends SocketHandler
     public function __construct(
         string $token,
         string $hostname = '',
-        string $appname = '',
+        string $appName = '',
         bool $useSSL = true,
         $level = Level::Debug,
         bool $bubble = true,
@@ -68,7 +68,7 @@ class LogmaticHandler extends SocketHandler
 
         $this->logToken = $token;
         $this->hostname = $hostname;
-        $this->appname  = $appname;
+        $this->appName  = $appName;
     }
 
     /**
@@ -86,11 +86,11 @@ class LogmaticHandler extends SocketHandler
     {
         $formatter = new LogmaticFormatter();
 
-        if (!empty($this->hostname)) {
+        if ($this->hostname !== '') {
             $formatter->setHostname($this->hostname);
         }
-        if (!empty($this->appname)) {
-            $formatter->setAppname($this->appname);
+        if ($this->appName !== '') {
+            $formatter->setAppName($this->appName);
         }
 
         return $formatter;

+ 1 - 1
src/Monolog/Handler/MailHandler.php

@@ -38,7 +38,7 @@ abstract class MailHandler extends AbstractProcessingHandler
             $messages[] = $message;
         }
 
-        if (!empty($messages)) {
+        if (\count($messages) > 0) {
             $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
         }
     }

+ 2 - 2
src/Monolog/Handler/MandrillHandler.php

@@ -31,11 +31,11 @@ class MandrillHandler extends MailHandler
      * @param string                 $apiKey  A valid Mandrill API key
      * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
      */
-    public function __construct(string $apiKey, $message, $level = Level::Error, bool $bubble = true)
+    public function __construct(string $apiKey, callable|Swift_Message $message, $level = Level::Error, bool $bubble = true)
     {
         parent::__construct($level, $bubble);
 
-        if (!$message instanceof Swift_Message && is_callable($message)) {
+        if (!$message instanceof Swift_Message) {
             $message = $message();
         }
         if (!$message instanceof Swift_Message) {

+ 3 - 6
src/Monolog/Handler/NativeMailerHandler.php

@@ -109,7 +109,7 @@ class NativeMailerHandler extends MailHandler
      */
     protected function send(string $content, array $records): void
     {
-        $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
+        $contentType = $this->getContentType() ?? ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
 
         if ($contentType !== 'text/html') {
             $content = wordwrap($content, $this->maxColumnWidth);
@@ -121,11 +121,8 @@ class NativeMailerHandler extends MailHandler
             $headers .= 'MIME-Version: 1.0' . "\r\n";
         }
 
-        $subject = $this->subject;
-        if ($records) {
-            $subjectFormatter = new LineFormatter($this->subject);
-            $subject = $subjectFormatter->format($this->getHighestRecord($records));
-        }
+        $subjectFormatter = new LineFormatter($this->subject);
+        $subject = $subjectFormatter->format($this->getHighestRecord($records));
 
         $parameters = implode(' ', $this->parameters);
         foreach ($this->to as $to) {

+ 2 - 2
src/Monolog/Handler/NewRelicHandler.php

@@ -64,11 +64,11 @@ class NewRelicHandler extends AbstractProcessingHandler
             throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
         }
 
-        if ($appName = $this->getAppName($record->context)) {
+        if (null !== ($appName = $this->getAppName($record->context))) {
             $this->setNewRelicAppName($appName);
         }
 
-        if ($transactionName = $this->getTransactionName($record->context)) {
+        if (null !== ($transactionName = $this->getTransactionName($record->context))) {
             $this->setNewRelicTransactionName($transactionName);
             unset($record->formatted['context']['transaction_name']);
         }

+ 64 - 14
src/Monolog/Handler/PHPConsoleHandler.php

@@ -19,6 +19,7 @@ use PhpConsole\Connector;
 use PhpConsole\Handler as VendorPhpConsoleHandler;
 use PhpConsole\Helper;
 use Monolog\LogRecord;
+use PhpConsole\Storage;
 
 /**
  * Monolog handler for Google Chrome extension "PHP Console"
@@ -38,10 +39,56 @@ use Monolog\LogRecord;
  *      PC::debug($_SERVER); // PHP Console debugger for any type of vars
  *
  * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
+ * @phpstan-type Options array{
+ *     enabled: bool,
+ *     classesPartialsTraceIgnore: string[],
+ *     debugTagsKeysInContext: array<int|string>,
+ *     useOwnErrorsHandler: bool,
+ *     useOwnExceptionsHandler: bool,
+ *     sourcesBasePath: string|null,
+ *     registerHelper: bool,
+ *     serverEncoding: string|null,
+ *     headersLimit: int|null,
+ *     password: string|null,
+ *     enableSslOnlyMode: bool,
+ *     ipMasks: string[],
+ *     enableEvalListener: bool,
+ *     dumperDetectCallbacks: bool,
+ *     dumperLevelLimit: int,
+ *     dumperItemsCountLimit: int,
+ *     dumperItemSizeLimit: int,
+ *     dumperDumpSizeLimit: int,
+ *     detectDumpTraceAndSource: bool,
+ *     dataStorage: Storage|null
+ * }
+ * @phpstan-type InputOptions array{
+ *     enabled?: bool,
+ *     classesPartialsTraceIgnore?: string[],
+ *     debugTagsKeysInContext?: array<int|string>,
+ *     useOwnErrorsHandler?: bool,
+ *     useOwnExceptionsHandler?: bool,
+ *     sourcesBasePath?: string|null,
+ *     registerHelper?: bool,
+ *     serverEncoding?: string|null,
+ *     headersLimit?: int|null,
+ *     password?: string|null,
+ *     enableSslOnlyMode?: bool,
+ *     ipMasks?: string[],
+ *     enableEvalListener?: bool,
+ *     dumperDetectCallbacks?: bool,
+ *     dumperLevelLimit?: int,
+ *     dumperItemsCountLimit?: int,
+ *     dumperItemSizeLimit?: int,
+ *     dumperDumpSizeLimit?: int,
+ *     detectDumpTraceAndSource?: bool,
+ *     dataStorage?: Storage|null
+ * }
  */
 class PHPConsoleHandler extends AbstractProcessingHandler
 {
-    /** @var array<string, mixed> */
+    /**
+     * @phpstan-var Options
+     */
     private array $options = [
         'enabled' => true, // bool Is PHP Console server enabled
         'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with...
@@ -71,6 +118,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
      * @param  array<string, mixed> $options   See \Monolog\Handler\PHPConsoleHandler::$options for more details
      * @param  Connector|null       $connector Instance of \PhpConsole\Connector class (optional)
      * @throws \RuntimeException
+     * @phpstan-param InputOptions $options
      */
     public function __construct(array $options = [], ?Connector $connector = null, $level = Level::Debug, bool $bubble = true)
     {
@@ -83,14 +131,16 @@ class PHPConsoleHandler extends AbstractProcessingHandler
     }
 
     /**
-     * @param array<string, mixed> $options
-     *
+     * @param  array<string, mixed> $options
      * @return array<string, mixed>
+     *
+     * @phpstan-param InputOptions $options
+     * @phpstan-return Options
      */
     private function initOptions(array $options): array
     {
         $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
-        if ($wrongOptions) {
+        if (\count($wrongOptions) > 0) {
             throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
         }
 
@@ -99,8 +149,8 @@ class PHPConsoleHandler extends AbstractProcessingHandler
 
     private function initConnector(?Connector $connector = null): Connector
     {
-        if (!$connector) {
-            if ($this->options['dataStorage']) {
+        if (null === $connector) {
+            if ($this->options['dataStorage'] instanceof Storage) {
                 Connector::setPostponeStorage($this->options['dataStorage']);
             }
             $connector = Connector::getInstance();
@@ -117,22 +167,22 @@ class PHPConsoleHandler extends AbstractProcessingHandler
                 $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
                 $handler->start();
             }
-            if ($this->options['sourcesBasePath']) {
+            if (null !== $this->options['sourcesBasePath']) {
                 $connector->setSourcesBasePath($this->options['sourcesBasePath']);
             }
-            if ($this->options['serverEncoding']) {
+            if (null !== $this->options['serverEncoding']) {
                 $connector->setServerEncoding($this->options['serverEncoding']);
             }
-            if ($this->options['password']) {
+            if (null !== $this->options['password']) {
                 $connector->setPassword($this->options['password']);
             }
             if ($this->options['enableSslOnlyMode']) {
                 $connector->enableSslOnlyMode();
             }
-            if ($this->options['ipMasks']) {
+            if (\count($this->options['ipMasks']) > 0) {
                 $connector->setAllowedIpMasks($this->options['ipMasks']);
             }
-            if ($this->options['headersLimit']) {
+            if (null !== $this->options['headersLimit'] && $this->options['headersLimit'] > 0) {
                 $connector->setHeadersLimit($this->options['headersLimit']);
             }
             if ($this->options['detectDumpTraceAndSource']) {
@@ -192,7 +242,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
     {
         [$tags, $filteredContext] = $this->getRecordTags($record);
         $message = $record->message;
-        if ($filteredContext) {
+        if (\count($filteredContext) > 0) {
             $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($filteredContext)), null, true);
         }
         $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
@@ -226,7 +276,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
         if ($record->context !== []) {
             $filteredContext = $record->context;
             foreach ($this->options['debugTagsKeysInContext'] as $key) {
-                if (!empty($filteredContext[$key])) {
+                if (isset($filteredContext[$key])) {
                     $tags = $filteredContext[$key];
                     if ($key === 0) {
                         array_shift($filteredContext);
@@ -238,7 +288,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler
             }
         }
 
-        return [$tags ?: strtolower($record->levelName->value), $filteredContext];
+        return [$tags ?? strtolower($record->levelName->value), $filteredContext];
     }
 
     /**

+ 2 - 2
src/Monolog/Handler/ProcessHandler.php

@@ -85,7 +85,7 @@ class ProcessHandler extends AbstractProcessingHandler
         $this->writeProcessInput($record->formatted);
 
         $errors = $this->readProcessErrors();
-        if (empty($errors) === false) {
+        if ($errors !== '') {
             throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
         }
     }
@@ -129,7 +129,7 @@ class ProcessHandler extends AbstractProcessingHandler
 
         $errors = $this->readProcessErrors();
 
-        if (is_resource($this->process) === false || empty($errors) === false) {
+        if (is_resource($this->process) === false || $errors !== '') {
             throw new \UnexpectedValueException(
                 sprintf('The process "%s" could not be opened: ' . $errors, $this->command)
             );

+ 1 - 1
src/Monolog/Handler/ProcessableHandlerTrait.php

@@ -43,7 +43,7 @@ trait ProcessableHandlerTrait
      */
     public function popProcessor(): callable
     {
-        if (!$this->processors) {
+        if (\count($this->processors) === 0) {
             throw new \LogicException('You tried to pop from an empty processor stack.');
         }
 

+ 2 - 2
src/Monolog/Handler/PsrHandler.php

@@ -53,7 +53,7 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
             return false;
         }
 
-        if ($this->formatter) {
+        if ($this->formatter !== null) {
             $formatted = $this->formatter->format($record);
             $this->logger->log(strtolower($record->levelName->value), (string) $formatted, $record->context);
         } else {
@@ -78,7 +78,7 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
      */
     public function getFormatter(): FormatterInterface
     {
-        if (!$this->formatter) {
+        if ($this->formatter === null) {
             throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
         }
 

+ 2 - 2
src/Monolog/Handler/PushoverHandler.php

@@ -129,7 +129,7 @@ class PushoverHandler extends SocketHandler
 
         $this->token = $token;
         $this->users = (array) $users;
-        $this->title = $title ?: (string) gethostname();
+        $this->title = $title ?? (string) gethostname();
         $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
         $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
         $this->retry = $retry;
@@ -177,7 +177,7 @@ class PushoverHandler extends SocketHandler
         $dataArray = array_merge($extra, $context, $dataArray);
 
         // Only pass sounds that are supported by the API
-        if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) {
+        if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds, true)) {
             unset($dataArray['sound']);
         }
 

+ 2 - 2
src/Monolog/Handler/RedisHandler.php

@@ -56,7 +56,7 @@ class RedisHandler extends AbstractProcessingHandler
      */
     protected function write(LogRecord $record): void
     {
-        if ($this->capSize) {
+        if ($this->capSize > 0) {
             $this->writeCapped($record);
         } else {
             $this->redisClient->rpush($this->redisKey, $record->formatted);
@@ -72,7 +72,7 @@ class RedisHandler extends AbstractProcessingHandler
         if ($this->redisClient instanceof Redis) {
             $mode = defined('Redis::MULTI') ? Redis::MULTI : 1;
             $this->redisClient->multi($mode)
-                ->rpush($this->redisKey, $record->formatted)
+                ->rPush($this->redisKey, $record->formatted)
                 ->ltrim($this->redisKey, -$this->capSize, -1)
                 ->exec();
         } else {

+ 1 - 1
src/Monolog/Handler/RotatingFileHandler.php

@@ -80,7 +80,7 @@ class RotatingFileHandler extends StreamHandler
 
     public function setFilenameFormat(string $filenameFormat, string $dateFormat): self
     {
-        if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
+        if (0 === preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
             throw new InvalidArgumentException(
                 'Invalid date format - format must be one of '.
                 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.

+ 1 - 1
src/Monolog/Handler/SamplingHandler.php

@@ -63,7 +63,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter
     public function handle(LogRecord $record): bool
     {
         if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
-            if ($this->processors) {
+            if (\count($this->processors) > 0) {
                 $record = $this->processRecord($record);
             }
 

+ 11 - 11
src/Monolog/Handler/Slack/SlackRecord.php

@@ -113,15 +113,15 @@ class SlackRecord
     {
         $dataArray = [];
 
-        if ($this->username) {
+        if ($this->username !== null) {
             $dataArray['username'] = $this->username;
         }
 
-        if ($this->channel) {
+        if ($this->channel !== null) {
             $dataArray['channel'] = $this->channel;
         }
 
-        if ($this->formatter && !$this->useAttachment) {
+        if ($this->formatter !== null && !$this->useAttachment) {
             $message = $this->formatter->format($record);
         } else {
             $message = $record->message;
@@ -150,13 +150,13 @@ class SlackRecord
 
             if ($this->includeContextAndExtra) {
                 foreach (['extra', 'context'] as $key) {
-                    if (empty($recordData[$key])) {
+                    if (!isset($recordData[$key]) || \count($recordData[$key]) === 0) {
                         continue;
                     }
 
                     if ($this->useShortAttachment) {
                         $attachment['fields'][] = $this->generateAttachmentField(
-                            (string) $key,
+                            $key,
                             $recordData[$key]
                         );
                     } else {
@@ -174,9 +174,9 @@ class SlackRecord
             $dataArray['text'] = $message;
         }
 
-        if ($this->userIcon) {
-            if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) {
-                $dataArray['icon_url'] = $this->userIcon;
+        if ($this->userIcon !== null) {
+            if (false !== ($iconUrl = filter_var($this->userIcon, FILTER_VALIDATE_URL))) {
+                $dataArray['icon_url'] = $iconUrl;
             } else {
                 $dataArray['icon_emoji'] = ":{$this->userIcon}:";
             }
@@ -209,10 +209,10 @@ class SlackRecord
         /** @var array<mixed> $normalized */
         $normalized = $this->normalizerFormatter->normalizeValue($fields);
 
-        $hasSecondDimension = count(array_filter($normalized, 'is_array'));
-        $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
+        $hasSecondDimension = \count(array_filter($normalized, 'is_array')) > 0;
+        $hasOnlyNonNumericKeys = \count(array_filter(array_keys($normalized), 'is_numeric')) === 0;
 
-        return $hasSecondDimension || $hasNonNumericKeys
+        return $hasSecondDimension || $hasOnlyNonNumericKeys
             ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS)
             : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
     }

+ 1 - 1
src/Monolog/Handler/SlackHandler.php

@@ -129,7 +129,7 @@ class SlackHandler extends SocketHandler
         $dataArray = $this->slackRecord->getSlackData($record);
         $dataArray['token'] = $this->token;
 
-        if (!empty($dataArray['attachments'])) {
+        if (isset($dataArray['attachments']) && is_array($dataArray['attachments']) && \count($dataArray['attachments']) > 0) {
             $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
         }
 

+ 8 - 8
src/Monolog/Handler/SocketHandler.php

@@ -268,9 +268,9 @@ class SocketHandler extends AbstractProcessingHandler
      *
      * @see http://php.net/manual/en/function.stream-set-chunk-size.php
      *
-     * @return int|bool
+     * @return int|false
      */
-    protected function streamSetChunkSize()
+    protected function streamSetChunkSize(): int|bool
     {
         if (!is_resource($this->resource)) {
             throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
@@ -286,9 +286,9 @@ class SocketHandler extends AbstractProcessingHandler
     /**
      * Wrapper to allow mocking
      *
-     * @return int|bool
+     * @return int|false
      */
-    protected function fwrite(string $data)
+    protected function fwrite(string $data): int|bool
     {
         if (!is_resource($this->resource)) {
             throw new \LogicException('fwrite called but $this->resource is not a resource');
@@ -302,7 +302,7 @@ class SocketHandler extends AbstractProcessingHandler
      *
      * @return mixed[]|bool
      */
-    protected function streamGetMetadata()
+    protected function streamGetMetadata(): array|bool
     {
         if (!is_resource($this->resource)) {
             throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
@@ -368,7 +368,7 @@ class SocketHandler extends AbstractProcessingHandler
 
     private function setStreamChunkSize(): void
     {
-        if ($this->chunkSize && !$this->streamSetChunkSize()) {
+        if (null !== $this->chunkSize && false === $this->streamSetChunkSize()) {
             throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
         }
     }
@@ -389,7 +389,7 @@ class SocketHandler extends AbstractProcessingHandler
             }
             $sent += $chunk;
             $socketInfo = $this->streamGetMetadata();
-            if (is_array($socketInfo) && $socketInfo['timed_out']) {
+            if (is_array($socketInfo) && (bool) $socketInfo['timed_out']) {
                 throw new \RuntimeException("Write timed-out");
             }
 
@@ -418,7 +418,7 @@ class SocketHandler extends AbstractProcessingHandler
             usleep(100);
         }
 
-        if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) {
+        if ((microtime(true) - (float) $this->lastWritingAt) >= $this->writingTimeout) {
             $this->closeSocket();
 
             return true;

+ 2 - 6
src/Monolog/Handler/StreamHandler.php

@@ -80,7 +80,7 @@ class StreamHandler extends AbstractProcessingHandler
      */
     public function close(): void
     {
-        if ($this->url && is_resource($this->stream)) {
+        if (null !== $this->url && is_resource($this->stream)) {
             fclose($this->stream);
         }
         $this->stream = null;
@@ -138,10 +138,6 @@ class StreamHandler extends AbstractProcessingHandler
         }
 
         $stream = $this->stream;
-        if (!is_resource($stream)) {
-            throw new \LogicException('No stream was opened yet' . Utils::getRecordMessageForException($record));
-        }
-
         if ($this->useLocking) {
             // ignoring errors here, there's not much we can do about them
             flock($stream, LOCK_EX);
@@ -187,7 +183,7 @@ class StreamHandler extends AbstractProcessingHandler
     private function createDir(string $url): void
     {
         // Do not try to create dir if it has already been tried.
-        if ($this->dirCreated) {
+        if (true === $this->dirCreated) {
             return;
         }
 

+ 6 - 2
src/Monolog/Handler/SyslogUdp/UdpSocket.php

@@ -20,7 +20,7 @@ class UdpSocket
 
     protected string $ip;
     protected int $port;
-    protected ?Socket $socket;
+    protected ?Socket $socket = null;
 
     public function __construct(string $ip, int $port = 514)
     {
@@ -33,7 +33,11 @@ class UdpSocket
             $domain = AF_UNIX;
             $protocol = IPPROTO_IP;
         }
-        $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null;
+
+        $socket = socket_create($domain, SOCK_DGRAM, $protocol);
+        if ($socket instanceof Socket) {
+            $this->socket = $socket;
+        }
     }
 
     public function write(string $line, string $header = ""): void

+ 4 - 2
src/Monolog/Handler/SyslogUdpHandler.php

@@ -109,11 +109,13 @@ class SyslogUdpHandler extends AbstractSyslogHandler
     {
         $priority = $severity + $this->facility;
 
-        if (!$pid = getmypid()) {
+        $pid = getmypid();
+        if (false === $pid) {
             $pid = '-';
         }
 
-        if (!$hostname = gethostname()) {
+        $hostname = gethostname();
+        if (false === $hostname) {
             $hostname = '-';
         }
 

+ 3 - 3
src/Monolog/Handler/TelegramBotHandler.php

@@ -123,7 +123,7 @@ class TelegramBotHandler extends AbstractProcessingHandler
 
     public function setParseMode(string $parseMode = null): self
     {
-        if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
+        if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES, true)) {
             throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
         }
 
@@ -181,14 +181,14 @@ class TelegramBotHandler extends AbstractProcessingHandler
                 continue;
             }
 
-            if ($this->processors) {
+            if (\count($this->processors) > 0) {
                 $record = $this->processRecord($record);
             }
 
             $messages[] = $record;
         }
 
-        if (!empty($messages)) {
+        if (\count($messages) > 0) {
             $this->send((string) $this->getFormatter()->formatBatch($messages));
         }
     }

+ 1 - 1
src/Monolog/Handler/TestHandler.php

@@ -158,7 +158,7 @@ class TestHandler extends AbstractProcessingHandler
         }
 
         foreach ($this->recordsByLevel[$level->value] as $i => $rec) {
-            if ($predicate($rec, $i)) {
+            if ((bool) $predicate($rec, $i)) {
                 return true;
             }
         }

+ 2 - 2
src/Monolog/Handler/WhatFailureGroupHandler.php

@@ -27,7 +27,7 @@ class WhatFailureGroupHandler extends GroupHandler
      */
     public function handle(LogRecord $record): bool
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $record = $this->processRecord($record);
         }
 
@@ -47,7 +47,7 @@ class WhatFailureGroupHandler extends GroupHandler
      */
     public function handleBatch(array $records): void
     {
-        if ($this->processors) {
+        if (\count($this->processors) > 0) {
             $processed = [];
             foreach ($records as $record) {
                 $processed[] = $this->processRecord($record);

+ 10 - 10
src/Monolog/Logger.php

@@ -142,7 +142,7 @@ class Logger implements LoggerInterface, ResettableInterface
         $this->name = $name;
         $this->setHandlers($handlers);
         $this->processors = $processors;
-        $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
+        $this->timezone = $timezone ?? new DateTimeZone(date_default_timezone_get());
     }
 
     public function getName(): string
@@ -483,7 +483,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function debug(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::DEBUG, (string) $message, $context);
+        $this->addRecord(Level::Debug, (string) $message, $context);
     }
 
     /**
@@ -496,7 +496,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function info(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::INFO, (string) $message, $context);
+        $this->addRecord(Level::Info, (string) $message, $context);
     }
 
     /**
@@ -509,7 +509,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function notice(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::NOTICE, (string) $message, $context);
+        $this->addRecord(Level::Notice, (string) $message, $context);
     }
 
     /**
@@ -522,7 +522,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function warning(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::WARNING, (string) $message, $context);
+        $this->addRecord(Level::Warning, (string) $message, $context);
     }
 
     /**
@@ -535,7 +535,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function error(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::ERROR, (string) $message, $context);
+        $this->addRecord(Level::Error, (string) $message, $context);
     }
 
     /**
@@ -548,7 +548,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function critical(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::CRITICAL, (string) $message, $context);
+        $this->addRecord(Level::Critical, (string) $message, $context);
     }
 
     /**
@@ -561,7 +561,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function alert(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::ALERT, (string) $message, $context);
+        $this->addRecord(Level::Alert, (string) $message, $context);
     }
 
     /**
@@ -574,7 +574,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     public function emergency(string|\Stringable $message, array $context = []): void
     {
-        $this->addRecord(static::EMERGENCY, (string) $message, $context);
+        $this->addRecord(Level::Emergency, (string) $message, $context);
     }
 
     /**
@@ -601,7 +601,7 @@ class Logger implements LoggerInterface, ResettableInterface
      */
     protected function handleException(Throwable $e, LogRecord $record): void
     {
-        if (!$this->exceptionHandler) {
+        if (null === $this->exceptionHandler) {
             throw $e;
         }
 

+ 3 - 3
src/Monolog/Processor/GitProcessor.php

@@ -59,12 +59,12 @@ class GitProcessor implements ProcessorInterface
      */
     private static function getGitInfo(): array
     {
-        if (self::$cache) {
+        if (self::$cache !== null) {
             return self::$cache;
         }
 
-        $branches = `git branch -v --no-abbrev`;
-        if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
+        $branches = shell_exec('git branch -v --no-abbrev');
+        if (is_string($branches) && 1 === preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
             return self::$cache = [
                 'branch' => $matches[1],
                 'commit' => $matches[2],

+ 2 - 2
src/Monolog/Processor/IntrospectionProcessor.php

@@ -83,7 +83,7 @@ class IntrospectionProcessor implements ProcessorInterface
                         continue 2;
                     }
                 }
-            } elseif (in_array($trace[$i]['function'], self::SKIP_FUNCTIONS)) {
+            } elseif (in_array($trace[$i]['function'], self::SKIP_FUNCTIONS, true)) {
                 $i++;
 
                 continue;
@@ -118,6 +118,6 @@ class IntrospectionProcessor implements ProcessorInterface
             return false;
         }
 
-        return isset($trace[$index]['class']) || in_array($trace[$index]['function'], self::SKIP_FUNCTIONS);
+        return isset($trace[$index]['class']) || in_array($trace[$index]['function'], self::SKIP_FUNCTIONS, true);
     }
 }

+ 2 - 2
src/Monolog/Processor/MercurialProcessor.php

@@ -58,11 +58,11 @@ class MercurialProcessor implements ProcessorInterface
      */
     private static function getMercurialInfo(): array
     {
-        if (self::$cache) {
+        if (self::$cache !== null) {
             return self::$cache;
         }
 
-        $result = explode(' ', trim(`hg id -nb`));
+        $result = explode(' ', trim((string) shell_exec('hg id -nb')));
 
         if (count($result) >= 3) {
             return self::$cache = [

+ 2 - 2
src/Monolog/Processor/PsrLogMessageProcessor.php

@@ -60,12 +60,12 @@ class PsrLogMessageProcessor implements ProcessorInterface
             if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
                 $replacements[$placeholder] = $val;
             } elseif ($val instanceof \DateTimeInterface) {
-                if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
+                if (null === $this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
                     // handle monolog dates using __toString if no specific dateFormat was asked for
                     // so that it follows the useMicroseconds flag
                     $replacements[$placeholder] = (string) $val;
                 } else {
-                    $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
+                    $replacements[$placeholder] = $val->format($this->dateFormat ?? static::SIMPLE_DATE);
                 }
             } elseif (is_object($val)) {
                 $replacements[$placeholder] = '[object '.Utils::getClass($val).']';

+ 1 - 1
src/Monolog/Processor/WebProcessor.php

@@ -65,7 +65,7 @@ class WebProcessor implements ProcessorInterface
         }
         if (isset($extraFields[0])) {
             foreach (array_keys($this->extraFields) as $fieldName) {
-                if (!in_array($fieldName, $extraFields)) {
+                if (!in_array($fieldName, $extraFields, true)) {
                     unset($this->extraFields[$fieldName]);
                 }
             }

+ 1 - 1
src/Monolog/Registry.php

@@ -54,7 +54,7 @@ class Registry
      */
     public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false): void
     {
-        $name = $name ?: $logger->getName();
+        $name = $name ?? $logger->getName();
 
         if (isset(self::$loggers[$name]) && !$overwrite) {
             throw new InvalidArgumentException('Logger with the given name already exists');

+ 1 - 2
src/Monolog/SignalHandler.php

@@ -77,8 +77,7 @@ class SignalHandler
 
         if (!$signals && extension_loaded('pcntl')) {
             $pcntl = new ReflectionExtension('pcntl');
-            // HHVM 3.24.2 returns an empty array.
-            foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) {
+            foreach ($pcntl->getConstants() as $name => $value) {
                 if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
                     $signals[$value] = $name;
                 }

+ 2 - 2
src/Monolog/Test/TestCase.php

@@ -61,9 +61,9 @@ class TestCase extends \PHPUnit\Framework\TestCase
     protected function getIdentityFormatter(): FormatterInterface
     {
         $formatter = $this->createMock(FormatterInterface::class);
-        $formatter->expects($this->any())
+        $formatter->expects(self::any())
             ->method('format')
-            ->will($this->returnCallback(function ($record) {
+            ->will(self::returnCallback(function ($record) {
                 return $record->message;
             }));
 

+ 4 - 4
src/Monolog/Utils.php

@@ -196,7 +196,7 @@ final class Utils
      */
     private static function detectAndCleanUtf8(&$data): void
     {
-        if (is_string($data) && !preg_match('//u', $data)) {
+        if (is_string($data) && preg_match('//u', $data) !== 1) {
             $data = preg_replace_callback(
                 '/[\x80-\xFF]+/',
                 function ($m) {
@@ -234,7 +234,7 @@ final class Utils
             return (int) $val;
         }
 
-        if (!preg_match('/^\s*(?<val>\d+)(?:\.\d+)?\s*(?<unit>[gmk]?)\s*$/i', $val, $match)) {
+        if (preg_match('/^\s*(?<val>\d+)(?:\.\d+)?\s*(?<unit>[gmk]?)\s*$/i', $val, $match) !== 1) {
             return false;
         }
 
@@ -259,10 +259,10 @@ final class Utils
         $extra = '';
 
         try {
-            if ($record->context) {
+            if (\count($record->context) > 0) {
                 $context = "\nContext: " . json_encode($record->context, JSON_THROW_ON_ERROR);
             }
-            if ($record->extra) {
+            if (\count($record->extra) > 0) {
                 $extra = "\nExtra: " . json_encode($record->extra, JSON_THROW_ON_ERROR);
             }
         } catch (\Throwable $e) {

+ 1 - 1
tests/Monolog/Formatter/LogmaticFormatterTest.php

@@ -25,7 +25,7 @@ class LogmaticFormatterTest extends TestCase
     {
         $formatter = new LogmaticFormatter();
         $formatter->setHostname('testHostname');
-        $formatter->setAppname('testAppname');
+        $formatter->setAppName('testAppname');
         $record = $this->getRecord();
         $formatted_decoded = json_decode($formatter->format($record), true);
         $this->assertArrayHasKey('hostname', $formatted_decoded);