From 82ab6a5f4f9ad081856eee4c9458efed5ecd7156 Mon Sep 17 00:00:00 2001 From: Juan Morales Date: Fri, 23 Jul 2021 09:16:39 +0200 Subject: [PATCH] Fixes php8 non-backward compatible changes (#1568) * Utils method added to resolve PCRE error messages properly --- src/Monolog/Formatter/LineFormatter.php | 3 +- src/Monolog/Handler/BrowserConsoleHandler.php | 3 +- src/Monolog/Handler/ErrorLogHandler.php | 4 ++- src/Monolog/Handler/SyslogUdpHandler.php | 4 ++- src/Monolog/Utils.php | 22 ++++++++++++- tests/Monolog/UtilsTest.php | 32 +++++++++++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/Monolog/Formatter/LineFormatter.php b/src/Monolog/Formatter/LineFormatter.php index 1cc9f539..6ed817ab 100644 --- a/src/Monolog/Formatter/LineFormatter.php +++ b/src/Monolog/Formatter/LineFormatter.php @@ -111,7 +111,8 @@ class LineFormatter extends NormalizerFormatter if (false !== strpos($output, '%')) { $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output); if (null === $output) { - throw new \RuntimeException('Failed to run preg_replace: ' . preg_last_error() . ' / ' . preg_last_error_msg()); + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } } diff --git a/src/Monolog/Handler/BrowserConsoleHandler.php b/src/Monolog/Handler/BrowserConsoleHandler.php index 4c938426..8d908b26 100644 --- a/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/src/Monolog/Handler/BrowserConsoleHandler.php @@ -212,7 +212,8 @@ class BrowserConsoleHandler extends AbstractProcessingHandler }, $style); if (null === $style) { - throw new \RuntimeException('Failed to run preg_replace_callback: ' . preg_last_error() . ' / ' . preg_last_error_msg()); + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } return $style; diff --git a/src/Monolog/Handler/ErrorLogHandler.php b/src/Monolog/Handler/ErrorLogHandler.php index d1479746..f2e22036 100644 --- a/src/Monolog/Handler/ErrorLogHandler.php +++ b/src/Monolog/Handler/ErrorLogHandler.php @@ -14,6 +14,7 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; use Monolog\Logger; +use Monolog\Utils; /** * Stores to PHP error_log() handler. @@ -80,7 +81,8 @@ class ErrorLogHandler extends AbstractProcessingHandler $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); if ($lines === false) { - throw new \RuntimeException('Failed to preg_split formatted string: '.preg_last_error().' / '.preg_last_error_msg()); + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode)); } foreach ($lines as $line) { error_log($line, $this->messageType); diff --git a/src/Monolog/Handler/SyslogUdpHandler.php b/src/Monolog/Handler/SyslogUdpHandler.php index 0b68922a..abc6d44d 100644 --- a/src/Monolog/Handler/SyslogUdpHandler.php +++ b/src/Monolog/Handler/SyslogUdpHandler.php @@ -14,6 +14,7 @@ namespace Monolog\Handler; use DateTimeInterface; use Monolog\Logger; use Monolog\Handler\SyslogUdp\UdpSocket; +use Monolog\Utils; /** * A Handler for logging to a remote syslogd server. @@ -89,7 +90,8 @@ class SyslogUdpHandler extends AbstractSyslogHandler $lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY); if (false === $lines) { - throw new \RuntimeException('Could not preg_split: '.preg_last_error().' / '.preg_last_error_msg()); + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } return $lines; diff --git a/src/Monolog/Utils.php b/src/Monolog/Utils.php index 2fd901ad..8812f007 100644 --- a/src/Monolog/Utils.php +++ b/src/Monolog/Utils.php @@ -140,6 +140,25 @@ final class Utils return $json; } + /** + * @internal + */ + public static function pcreLastErrorMessage(int $code): string + { + if (PHP_VERSION_ID >= 80000) { + return preg_last_error_msg(); + } + + $constants = (get_defined_constants(true))['pcre']; + $constants = array_filter($constants, function ($key) { + return substr($key, -6) == '_ERROR'; + }, ARRAY_FILTER_USE_KEY); + + $constants = array_flip($constants); + + return $constants[$code] ?? 'UNDEFINED_ERROR'; + } + /** * Throws an exception according to a given code with a customized message * @@ -197,7 +216,8 @@ final class Utils $data ); if (!is_string($data)) { - throw new \RuntimeException('Failed to preg_replace_callback: '.preg_last_error().' / '.preg_last_error_msg()); + $pcreErrorCode = preg_last_error(); + throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode)); } $data = str_replace( ['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'], diff --git a/tests/Monolog/UtilsTest.php b/tests/Monolog/UtilsTest.php index 3d66b960..bc216467 100644 --- a/tests/Monolog/UtilsTest.php +++ b/tests/Monolog/UtilsTest.php @@ -109,4 +109,36 @@ class UtilsTest extends \PHPUnit_Framework_TestCase 'object' => [$obj, $obj], ]; } + + /** + * @dataProvider providesPcreLastErrorMessage + * @param int $code + * @param string $msg + */ + public function testPcreLastErrorMessage($code, $msg) + { + if (PHP_VERSION_ID >= 80000) { + $this->assertSame('No error', Utils::pcreLastErrorMessage($code)); + return; + } + + $this->assertEquals($msg, Utils::pcreLastErrorMessage($code)); + } + + /** + * @return array[] + */ + public function providesPcreLastErrorMessage() + { + return [ + [0, 'PREG_NO_ERROR'], + [1, 'PREG_INTERNAL_ERROR'], + [2, 'PREG_BACKTRACK_LIMIT_ERROR'], + [3, 'PREG_RECURSION_LIMIT_ERROR'], + [4, 'PREG_BAD_UTF8_ERROR'], + [5, 'PREG_BAD_UTF8_OFFSET_ERROR'], + [6, 'PREG_JIT_STACKLIMIT_ERROR'], + [-1, 'UNDEFINED_ERROR'], + ]; + } }