From 08520c2083f60663c6574ee500891528a45702ed Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 3 May 2022 15:17:10 +0200 Subject: [PATCH 01/26] feat: php 8 language level mitigations --- src/Config.php | 15 +- src/DataBuilder.php | 109 ++++++------- src/Defaults.php | 102 ++++++------- src/ErrorWrapper.php | 2 +- src/Handlers/FatalHandler.php | 2 +- src/LevelFactory.php | 2 +- src/Rollbar.php | 2 +- src/RollbarJsHelper.php | 4 +- src/Scrubber.php | 10 +- src/Truncation/AbstractStrategy.php | 2 +- src/Truncation/FramesStrategy.php | 2 +- src/Truncation/IStrategy.php | 2 +- src/Truncation/MinBodyStrategy.php | 2 +- src/Truncation/RawStrategy.php | 2 +- src/Truncation/StringsStrategy.php | 2 +- src/Truncation/Truncation.php | 13 +- src/Utilities.php | 2 +- tests/AgentTest.php | 10 +- tests/BaseRollbarTest.php | 4 +- tests/BodyTest.php | 17 ++- tests/ConfigTest.php | 143 ++++++++++-------- tests/ContextTest.php | 8 +- tests/CurlSenderTest.php | 17 +-- tests/DataBuilderTest.php | 107 ++++++------- tests/DataTest.php | 70 +++++---- tests/DefaultsTest.php | 86 +++++------ tests/ErrorWrapperTest.php | 4 +- tests/ExceptionInfoTest.php | 6 +- tests/FakeDataBuilder.php | 6 +- tests/FakeLog.php | 2 +- tests/FluentTest.php | 2 +- tests/FrameTest.php | 30 ++-- tests/Handlers/ErrorHandlerTest.php | 19 +-- tests/Handlers/ExceptionHandlerTest.php | 20 +-- tests/JsHelperTest.php | 38 ++--- tests/LevelFactoryTest.php | 12 +- tests/LevelTest.php | 6 +- tests/MessageTest.php | 6 +- tests/NotifierTest.php | 10 +- tests/Payload/EncodedPayloadTest.php | 4 +- tests/PayloadTest.php | 25 +-- tests/Performance/MassivePayload.php | 6 +- .../TestHelpers/EncodedPayload.php | 6 +- tests/Performance/TestHelpers/Truncation.php | 14 +- tests/Performance/TruncationTest.php | 20 +-- tests/PersonTest.php | 12 +- tests/ReadmeTest.php | 10 +- tests/RequestTest.php | 24 +-- tests/ResponseTest.php | 10 +- tests/RollbarLoggerTest.php | 116 +++++++------- tests/RollbarTest.php | 61 ++++---- tests/ScrubberTest.php | 28 ++-- tests/ServerTest.php | 12 +- tests/TestHelpers/CustomSerializable.php | 6 +- tests/TestHelpers/CustomTruncation.php | 6 +- .../ChildCycleCheckSerializable.php | 2 +- .../CycleCheck/ParentCycleCheck.php | 2 +- .../ParentCycleCheckSerializable.php | 4 +- .../MalformedPayloadDataTransformer.php | 7 +- tests/TestHelpers/MockPhpStream.php | 14 +- tests/TraceChainTest.php | 21 +-- tests/TraceTest.php | 25 +-- tests/Truncation/FramesStrategyTest.php | 8 +- tests/Truncation/MinBodyStrategyTest.php | 10 +- tests/Truncation/RawStrategyTest.php | 6 +- tests/Truncation/StringsStrategyTest.php | 20 +-- tests/Truncation/TruncationTest.php | 17 ++- tests/UtilitiesTest.php | 28 ++-- tests/VerbosityTest.php | 135 +++++++++-------- 69 files changed, 792 insertions(+), 765 deletions(-) diff --git a/src/Config.php b/src/Config.php index 296542e3..21864901 100644 --- a/src/Config.php +++ b/src/Config.php @@ -17,6 +17,9 @@ use Rollbar\TransformerInterface; use Rollbar\UtilitiesTrait; use Throwable; +use Rollbar\ResponseHandlerInterface; +use Rollbar\Senders\FluentSender; +use Rollbar\FilterInterface; class Config { @@ -425,7 +428,7 @@ private function setMinimumLevel(array $config): void { $this->minimumLevel = \Rollbar\Defaults::get()->minimumLevel(); - $override = array_key_exists('minimum_level', $config) ? $config['minimum_level'] : null; + $override = $config['minimum_level'] ?? null; $override = array_key_exists('minimumLevel', $config) ? $config['minimumLevel'] : $override; if ($override instanceof Level) { @@ -454,7 +457,7 @@ private function setReportSuppressed(array $config): void private function setFilters(array $config): void { - $this->setupWithOptions($config, "filter", "Rollbar\FilterInterface"); + $this->setupWithOptions($config, "filter", FilterInterface::class); } private function setSender(array $config): void @@ -606,7 +609,7 @@ private function setFluentSenderOptions(array &$config, mixed $default): mixed if (!isset($config['handler']) || $config['handler'] != 'fluent') { return $default; } - $default = "Rollbar\Senders\FluentSender"; + $default = FluentSender::class; if (isset($config['fluent_host'])) { $config['senderOptions']['fluentHost'] = $config['fluent_host']; @@ -625,7 +628,7 @@ private function setFluentSenderOptions(array &$config, mixed $default): mixed private function setResponseHandler(array $config): void { - $this->setupWithOptions($config, "responseHandler", "Rollbar\ResponseHandlerInterface"); + $this->setupWithOptions($config, "responseHandler", ResponseHandlerInterface::class); } private function setCheckIgnoreFunction(array $config): void @@ -694,9 +697,7 @@ protected function setupWithOptions( if ($passWholeConfig) { $options = $config; } else { - $options = isset($config[$keyName . "Options"]) ? - $config[$keyName . "Options"] : - array(); + $options = $config[$keyName . "Options"] ?? array(); } $this->$keyName = new $class($options); } else { diff --git a/src/DataBuilder.php b/src/DataBuilder.php index 80a11587..4fe93d9a 100644 --- a/src/DataBuilder.php +++ b/src/DataBuilder.php @@ -114,109 +114,109 @@ public function __construct($config) protected function setCaptureIP($config) { - $fromConfig = isset($config['capture_ip']) ? $config['capture_ip'] : null; + $fromConfig = $config['capture_ip'] ?? null; $this->captureIP = self::$defaults->captureIP($fromConfig); } protected function setCaptureEmail($config) { - $fromConfig = isset($config['capture_email']) ? $config['capture_email'] : null; + $fromConfig = $config['capture_email'] ?? null; $this->captureEmail = self::$defaults->captureEmail($fromConfig); } protected function setCaptureUsername($config) { - $fromConfig = isset($config['capture_username']) ? $config['capture_username'] : null; + $fromConfig = $config['capture_username'] ?? null; $this->captureUsername = self::$defaults->captureUsername($fromConfig); } protected function setEnvironment($config) { - $fromConfig = isset($config['environment']) ? $config['environment'] : self::$defaults->get()->environment(); + $fromConfig = $config['environment'] ?? self::$defaults->get()->environment(); $this->utilities->validateString($fromConfig, "config['environment']", null, false); $this->environment = $fromConfig; } protected function setDefaultMessageLevel($config) { - $fromConfig = isset($config['messageLevel']) ? $config['messageLevel'] : null; + $fromConfig = $config['messageLevel'] ?? null; $this->messageLevel = self::$defaults->messageLevel($fromConfig); } protected function setDefaultExceptionLevel($config) { - $fromConfig = isset($config['exceptionLevel']) ? $config['exceptionLevel'] : null; + $fromConfig = $config['exceptionLevel'] ?? null; $this->exceptionLevel = self::$defaults->exceptionLevel($fromConfig); } protected function setDefaultPsrLevels($config) { - $fromConfig = isset($config['psrLevels']) ? $config['psrLevels'] : null; + $fromConfig = $config['psrLevels'] ?? null; $this->psrLevels = self::$defaults->psrLevels($fromConfig); } protected function setErrorLevels($config) { - $fromConfig = isset($config['errorLevels']) ? $config['errorLevels'] : null; + $fromConfig = $config['errorLevels'] ?? null; $this->errorLevels = self::$defaults->errorLevels($fromConfig); } protected function setSendMessageTrace($config) { - $fromConfig = isset($config['send_message_trace']) ? $config['send_message_trace'] : null; + $fromConfig = $config['send_message_trace'] ?? null; $this->sendMessageTrace = self::$defaults->sendMessageTrace($fromConfig); } protected function setRawRequestBody($config) { - $fromConfig = isset($config['include_raw_request_body']) ? $config['include_raw_request_body'] : null; + $fromConfig = $config['include_raw_request_body'] ?? null; $this->rawRequestBody = self::$defaults->rawRequestBody($fromConfig); } protected function setLocalVarsDump($config) { - $fromConfig = isset($config['local_vars_dump']) ? $config['local_vars_dump'] : null; + $fromConfig = $config['local_vars_dump'] ?? null; $this->localVarsDump = self::$defaults->localVarsDump($fromConfig); if ($this->localVarsDump && !empty(ini_get('zend.exception_ignore_args'))) { ini_set('zend.exception_ignore_args', 'Off'); - assert(empty(ini_get('zend.exception_ignore_args'))); + assert(empty(ini_get('zend.exception_ignore_args')) || ini_get('zend.exception_ignore_args') === "Off"); } } protected function setCaptureErrorStacktraces($config) { - $fromConfig = isset($config['capture_error_stacktraces']) ? $config['capture_error_stacktraces'] : null; + $fromConfig = $config['capture_error_stacktraces'] ?? null; $this->captureErrorStacktraces = self::$defaults->captureErrorStacktraces($fromConfig); } protected function setCodeVersion($config) { - $fromConfig = isset($config['codeVersion']) ? $config['codeVersion'] : null; + $fromConfig = $config['codeVersion'] ?? null; if (!isset($fromConfig)) { - $fromConfig = isset($config['code_version']) ? $config['code_version'] : null; + $fromConfig = $config['code_version'] ?? null; } $this->codeVersion = self::$defaults->codeVersion($fromConfig); } protected function setPlatform($config) { - $fromConfig = isset($config['platform']) ? $config['platform'] : null; + $fromConfig = $config['platform'] ?? null; $this->platform = self::$defaults->platform($fromConfig); } protected function setFramework($config) { - $this->framework = isset($config['framework']) ? $config['framework'] : null; + $this->framework = $config['framework'] ?? null; } protected function setContext($config) { - $this->context = isset($config['context']) ? $config['context'] : null; + $this->context = $config['context'] ?? null; } protected function setRequestParams($config) { - $this->requestParams = isset($config['requestParams']) ? $config['requestParams'] : null; + $this->requestParams = $config['requestParams'] ?? null; } /* @@ -225,7 +225,7 @@ protected function setRequestParams($config) protected function setRequestBody($config) { - $this->requestBody = isset($config['requestBody']) ? $config['requestBody'] : null; + $this->requestBody = $config['requestBody'] ?? null; if (!$this->requestBody && $this->rawRequestBody) { $this->requestBody = file_get_contents("php://input"); @@ -234,46 +234,42 @@ protected function setRequestBody($config) protected function setRequestExtras($config) { - $this->requestExtras = isset($config["requestExtras"]) ? $config["requestExtras"] : null; + $this->requestExtras = $config["requestExtras"] ?? null; } protected function setPerson($config) { - $this->person = isset($config['person']) ? $config['person'] : null; + $this->person = $config['person'] ?? null; } protected function setPersonFunc($config) { - $this->personFunc = isset($config['person_fn']) ? $config['person_fn'] : null; + $this->personFunc = $config['person_fn'] ?? null; } protected function setServerRoot($config) { - $fromConfig = isset($config['serverRoot']) ? $config['serverRoot'] : null; + $fromConfig = $config['serverRoot'] ?? null; if (!isset($fromConfig)) { - $fromConfig = isset($config['root']) ? $config['root'] : null; + $fromConfig = $config['root'] ?? null; } $this->serverRoot = self::$defaults->serverRoot($fromConfig); } protected function setServerBranch($config) { - $fromConfig = isset($config['serverBranch']) ? $config['serverBranch'] : null; + $fromConfig = $config['serverBranch'] ?? null; if (!isset($fromConfig)) { - $fromConfig = isset($config['branch']) ? $config['branch'] : null; + $fromConfig = $config['branch'] ?? null; } $this->serverBranch = self::$defaults->branch($fromConfig); if ($this->serverBranch === null) { - $autodetectBranch = isset($config['autodetect_branch']) ? - $config['autodetect_branch'] : - self::$defaults->autodetectBranch(); + $autodetectBranch = $config['autodetect_branch'] ?? self::$defaults->autodetectBranch(); if ($autodetectBranch) { - $allowExec = isset($config['allow_exec']) ? - $config['allow_exec'] : - self::$defaults->allowExec(); + $allowExec = $config['allow_exec'] ?? self::$defaults->allowExec(); $this->serverBranch = $this->detectGitBranch($allowExec); } @@ -282,64 +278,62 @@ protected function setServerBranch($config) protected function setServerCodeVersion($config) { - $this->serverCodeVersion = isset($config['serverCodeVersion']) ? $config['serverCodeVersion'] : null; + $this->serverCodeVersion = $config['serverCodeVersion'] ?? null; } protected function setServerExtras($config) { - $this->serverExtras = isset($config['serverExtras']) ? $config['serverExtras'] : null; + $this->serverExtras = $config['serverExtras'] ?? null; } public function setCustom($config) { - $this->custom = isset($config['custom']) ? $config['custom'] : \Rollbar\Defaults::get()->custom(); + $this->custom = $config['custom'] ?? \Rollbar\Defaults::get()->custom(); } public function setCustomDataMethod($config) { - $this->customDataMethod = isset($config['custom_data_method']) ? - $config['custom_data_method'] : - \Rollbar\Defaults::get()->customDataMethod(); + $this->customDataMethod = $config['custom_data_method'] ?? \Rollbar\Defaults::get()->customDataMethod(); } protected function setFingerprint($config) { - $this->fingerprint = isset($config['fingerprint']) ? $config['fingerprint'] : null; + $this->fingerprint = $config['fingerprint'] ?? null; } protected function setTitle($config) { - $this->title = isset($config['title']) ? $config['title'] : null; + $this->title = $config['title'] ?? null; } protected function setNotifier($config) { - $fromConfig = isset($config['notifier']) ? $config['notifier'] : null; + $fromConfig = $config['notifier'] ?? null; $this->notifier = self::$defaults->notifier($fromConfig); } protected function setBaseException($config) { - $fromConfig = isset($config['baseException']) ? $config['baseException'] : null; + $fromConfig = $config['baseException'] ?? null; $this->baseException = self::$defaults->baseException($fromConfig); } protected function setIncludeCodeContext($config) { - $fromConfig = isset($config['include_error_code_context']) ? $config['include_error_code_context'] : null; + $fromConfig = $config['include_error_code_context'] ?? null; $this->includeCodeContext = self::$defaults->includeCodeContext($fromConfig); } protected function setIncludeExcCodeContext($config) { $fromConfig = - isset($config['include_exception_code_context']) ? $config['include_exception_code_context'] : null; + $config['include_exception_code_context'] ?? null; $this->includeExcCodeContext = self::$defaults->includeExcCodeContext($fromConfig); } protected function setLevelFactory($config) { - $this->levelFactory = isset($config['levelFactory']) ? $config['levelFactory'] : null; + $this->levelFactory = $config['levelFactory'] ?? null; if (!$this->levelFactory) { throw new \InvalidArgumentException( 'Missing dependency: LevelFactory not provided to the DataBuilder.' @@ -349,7 +343,7 @@ protected function setLevelFactory($config) protected function setUtilities($config) { - $this->utilities = isset($config['utilities']) ? $config['utilities'] : null; + $this->utilities = $config['utilities'] ?? null; if (!$this->utilities) { throw new \InvalidArgumentException( 'Missing dependency: Utilities not provided to the DataBuilder.' @@ -359,7 +353,7 @@ protected function setUtilities($config) protected function setHost($config) { - $this->host = isset($config['host']) ? $config['host'] : self::$defaults->host(); + $this->host = $config['host'] ?? self::$defaults->host(); } /** @@ -615,8 +609,8 @@ protected function getRequest() ->setUserIp($this->getUserIp()); if (isset($_SERVER)) { - $request->setMethod(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null) - ->setQueryString(isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : null); + $request->setMethod($_SERVER['REQUEST_METHOD'] ?? null) + ->setQueryString($_SERVER['QUERY_STRING'] ?? null); } if (isset($_GET)) { @@ -682,11 +676,11 @@ public function parseForwardedString($forwarded) if (stripos($fpPart, 'for=') !== false) { // Parse 'for' forwarded pair - $result['for'] = isset($result['for']) ? $result['for'] : array(); + $result['for'] = $result['for'] ?? array(); $result['for'][] = substr($fpPart, strlen('for=')); } elseif (stripos($fpPart, 'by=') !== false) { // Parse 'by' forwarded pair - $result['by'] = isset($result['by']) ? $result['by'] : array(); + $result['by'] = $result['by'] ?? array(); $result['by'][] = substr($fpPart, strlen('by=')); } } @@ -784,7 +778,7 @@ public function getUrl() } if (isset($_SERVER)) { - $path = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; + $path = $_SERVER['REQUEST_URI'] ?? '/'; $url .= $path; } @@ -940,10 +934,7 @@ protected function getServer() protected function getHost() { - if (isset($this->host)) { - return $this->host; - } - return gethostname(); + return $this->host ?? gethostname(); } protected function getServerRoot() @@ -1065,7 +1056,7 @@ public function removeCustom($key) protected function getFingerprint($context) { - return isset($context['fingerprint']) ? $context['fingerprint'] : $this->fingerprint; + return $context['fingerprint'] ?? $this->fingerprint; } protected function getTitle() @@ -1193,7 +1184,7 @@ private function hasXdebugGetFunctionStack() // in XDebug 3 and later, the function is defined but disabled unless // the xdebug mode parameter includes it - return false === strpos(ini_get('xdebug.mode'), 'develop') ? false : true; + return !str_contains(ini_get('xdebug.mode'), 'develop') ? false : true; } private function fetchErrorTrace() diff --git a/src/Defaults.php b/src/Defaults.php index bef9318d..a84a5cfd 100644 --- a/src/Defaults.php +++ b/src/Defaults.php @@ -57,7 +57,7 @@ public function __construct() 'csrf_token', 'access_token' ); - $this->serverRoot = isset($_ENV["HEROKU_APP_DIR"]) ? $_ENV["HEROKU_APP_DIR"] : null; + $this->serverRoot = $_ENV["HEROKU_APP_DIR"] ?? null; $this->platform = php_uname('a'); $this->notifier = Notifier::defaultNotifier(); $this->baseException = Throwable::class; @@ -86,252 +86,252 @@ public function fromSnakeCase($option) public function psrLevels($value = null) { - return $value !== null ? $value : $this->psrLevels; + return $value ?? $this->psrLevels; } public function errorLevels($value = null) { - return $value !== null ? $value : $this->errorLevels; + return $value ?? $this->errorLevels; } public function autodetectBranch($value = null) { - return $value !== null ? $value : $this->autodetectBranch; + return $value ?? $this->autodetectBranch; } public function branch($value = null) { - return $value !== null ? $value : $this->branch; + return $value ?? $this->branch; } public function serverRoot($value = null) { - return $value !== null ? $value : $this->serverRoot; + return $value ?? $this->serverRoot; } public function platform($value = null) { - return $value !== null ? $value : $this->platform; + return $value ?? $this->platform; } public function notifier($value = null) { - return $value !== null ? $value : $this->notifier; + return $value ?? $this->notifier; } public function baseException($value = null) { - return $value !== null ? $value : $this->baseException; + return $value ?? $this->baseException; } public function codeVersion($value = null) { - return $value !== null ? $value : $this->codeVersion; + return $value ?? $this->codeVersion; } public function sendMessageTrace($value = null) { - return $value !== null ? $value : $this->sendMessageTrace; + return $value ?? $this->sendMessageTrace; } public function includeCodeContext($value = null) { - return $value !== null ? $value : $this->includeCodeContext; + return $value ?? $this->includeCodeContext; } public function includeExcCodeContext($value = null) { - return $value !== null ? $value : $this->includeExcCodeContext; + return $value ?? $this->includeExcCodeContext; } public function rawRequestBody($value = null) { - return $value !== null ? $value : $this->rawRequestBody; + return $value ?? $this->rawRequestBody; } public function localVarsDump($value = null) { - return $value !== null ? $value : $this->localVarsDump; + return $value ?? $this->localVarsDump; } public function errorSampleRates($value = null) { - return $value !== null ? $value : $this->errorSampleRates; + return $value ?? $this->errorSampleRates; } public function exceptionSampleRates($value = null) { - return $value !== null ? $value : $this->exceptionSampleRates; + return $value ?? $this->exceptionSampleRates; } public function includedErrno($value = null) { - return $value !== null ? $value : $this->includedErrno; + return $value ?? $this->includedErrno; } public function includeErrorCodeContext($value = null) { - return $value !== null ? $value : $this->includeErrorCodeContext; + return $value ?? $this->includeErrorCodeContext; } public function includeExceptionCodeContext($value = null) { - return $value !== null ? $value : $this->includeExceptionCodeContext; + return $value ?? $this->includeExceptionCodeContext; } public function agentLogLocation($value = null) { - return $value !== null ? $value : $this->agentLogLocation; + return $value ?? $this->agentLogLocation; } public function allowExec($value = null) { - return $value !== null ? $value : $this->allowExec; + return $value ?? $this->allowExec; } public function messageLevel($value = null) { - return $value !== null ? $value : $this->messageLevel; + return $value ?? $this->messageLevel; } public function exceptionLevel($value = null) { - return $value !== null ? $value : $this->exceptionLevel; + return $value ?? $this->exceptionLevel; } public function endpoint($value = null) { - return $value !== null ? $value : $this->endpoint; + return $value ?? $this->endpoint; } public function captureErrorStacktraces($value = null) { - return $value !== null ? $value : $this->captureErrorStacktraces; + return $value ?? $this->captureErrorStacktraces; } public function checkIgnore($value = null) { - return $value !== null ? $value : $this->checkIgnore; + return $value ?? $this->checkIgnore; } public function custom($value = null) { - return $value !== null ? $value : $this->custom; + return $value ?? $this->custom; } public function customDataMethod($value = null) { - return $value !== null ? $value : $this->customDataMethod; + return $value ?? $this->customDataMethod; } public function enabled($value = null) { - return $value !== null ? $value : $this->enabled; + return $value ?? $this->enabled; } public function transmit($value = null) { - return $value !== null ? $value : $this->transmit; + return $value ?? $this->transmit; } public function logPayload($value = null) { - return $value !== null ? $value : $this->logPayload; + return $value ?? $this->logPayload; } public function verbose($value = null) { - return $value !== null ? $value : $this->verbose; + return $value ?? $this->verbose; } public function environment($value = null) { - return $value !== null ? $value : $this->environment; + return $value ?? $this->environment; } public function fluentHost($value = null) { - return $value !== null ? $value : $this->fluentHost; + return $value ?? $this->fluentHost; } public function fluentPort($value = null) { - return $value !== null ? $value : $this->fluentPort; + return $value ?? $this->fluentPort; } public function fluentTag($value = null) { - return $value !== null ? $value : $this->fluentTag; + return $value ?? $this->fluentTag; } public function handler($value = null) { - return $value !== null ? $value : $this->handler; + return $value ?? $this->handler; } public function host($value = null) { - return $value !== null ? $value : $this->host; + return $value ?? $this->host; } public function timeout($value = null) { - return $value !== null ? $value : $this->timeout; + return $value ?? $this->timeout; } public function reportSuppressed($value = null) { - return $value !== null ? $value : $this->reportSuppressed; + return $value ?? $this->reportSuppressed; } public function useErrorReporting($value = null) { - return $value !== null ? $value : $this->useErrorReporting; + return $value ?? $this->useErrorReporting; } public function captureIP($value = null) { - return $value !== null ? $value : $this->captureIP; + return $value ?? $this->captureIP; } public function captureEmail($value = null) { - return $value !== null ? $value : $this->captureEmail; + return $value ?? $this->captureEmail; } public function captureUsername($value = null) { - return $value !== null ? $value : $this->captureUsername; + return $value ?? $this->captureUsername; } public function scrubFields($value = null) { - return $value !== null ? $value : $this->scrubFields; + return $value ?? $this->scrubFields; } public function customTruncation($value = null) { - return $value !== null ? $value : $this->customTruncation; + return $value ?? $this->customTruncation; } public function maxNestingDepth($value = null) { - return $value !== null ? $value : $this->maxNestingDepth; + return $value ?? $this->maxNestingDepth; } public function maxItems($value = null) { - return $value !== null ? $value : $this->maxItems; + return $value ?? $this->maxItems; } public function minimumLevel($value = null) { - return $value !== null ? $value : $this->minimumLevel; + return $value ?? $this->minimumLevel; } public function raiseOnError($value = null) { - return $value !== null ? $value : $this->raiseOnError; + return $value ?? $this->raiseOnError; } private $psrLevels; diff --git a/src/ErrorWrapper.php b/src/ErrorWrapper.php index 4c0a92a9..cbeca008 100644 --- a/src/ErrorWrapper.php +++ b/src/ErrorWrapper.php @@ -29,7 +29,7 @@ private static function getConstName($const) E_USER_DEPRECATED => "E_USER_DEPRECATED" ); } - return isset(self::$constName[$const]) ? self::$constName[$const] : null; + return self::$constName[$const] ?? null; } public function __construct( diff --git a/src/Handlers/FatalHandler.php b/src/Handlers/FatalHandler.php index 6551a7b7..a25532ff 100644 --- a/src/Handlers/FatalHandler.php +++ b/src/Handlers/FatalHandler.php @@ -58,6 +58,6 @@ protected function isFatal($lastError) in_array($lastError['type'], self::$fatalErrors, true) && // don't log uncaught exceptions as they were handled by exceptionHandler() !(isset($lastError['message']) && - strpos($lastError['message'], 'Uncaught') === 0); + str_starts_with($lastError['message'], 'Uncaught')); } } diff --git a/src/LevelFactory.php b/src/LevelFactory.php index d3b76c34..fff7d839 100644 --- a/src/LevelFactory.php +++ b/src/LevelFactory.php @@ -37,7 +37,7 @@ public function fromName($name) { self::init(); $name = strtolower($name); - return array_key_exists($name, self::$values) ? self::$values[$name] : null; + return self::$values[$name] ?? null; } /** diff --git a/src/Rollbar.php b/src/Rollbar.php index cd8a9d57..cbe2b0c0 100644 --- a/src/Rollbar.php +++ b/src/Rollbar.php @@ -54,7 +54,7 @@ private static function setLogger($configOrLogger) return; } - self::$logger = isset($logger) ? $logger : new RollbarLogger($configOrLogger); + self::$logger = $logger ?? new RollbarLogger($configOrLogger); } public static function enable() diff --git a/src/RollbarJsHelper.php b/src/RollbarJsHelper.php index 1a602f4b..f6229eb0 100644 --- a/src/RollbarJsHelper.php +++ b/src/RollbarJsHelper.php @@ -140,8 +140,8 @@ public function hasAttachment($headers) public function shouldAppendNonce($headers) { foreach ($headers as $header) { - if (strpos($header, 'Content-Security-Policy') !== false && - strpos($header, "'unsafe-inline'") !== false) { + if (str_contains($header, 'Content-Security-Policy') && + str_contains($header, "'unsafe-inline'")) { return true; } } diff --git a/src/Scrubber.php b/src/Scrubber.php index 8ae9a7e7..0bb74d39 100644 --- a/src/Scrubber.php +++ b/src/Scrubber.php @@ -17,9 +17,9 @@ public function __construct($config) protected function setScrubFields($config) { - $fromConfig = isset($config['scrubFields']) ? $config['scrubFields'] : null; + $fromConfig = $config['scrubFields'] ?? null; if (!isset($fromConfig)) { - $fromConfig = isset($config['scrub_fields']) ? $config['scrub_fields'] : null; + $fromConfig = $config['scrub_fields'] ?? null; } $this->scrubFields = self::$defaults->scrubFields($fromConfig); } @@ -31,11 +31,11 @@ public function getScrubFields() protected function setSafelist($config) { - $fromConfig = isset($config['scrubSafelist']) ? $config['scrubSafelist'] : null; + $fromConfig = $config['scrubSafelist'] ?? null; if (!isset($fromConfig)) { - $fromConfig = isset($config['scrub_safelist']) ? $config['scrub_safelist'] : null; + $fromConfig = $config['scrub_safelist'] ?? null; } - $this->safelist = $fromConfig ? $fromConfig : array(); + $this->safelist = $fromConfig ?: array(); } public function getSafelist() diff --git a/src/Truncation/AbstractStrategy.php b/src/Truncation/AbstractStrategy.php index 7a7956bf..bb69a634 100644 --- a/src/Truncation/AbstractStrategy.php +++ b/src/Truncation/AbstractStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; class AbstractStrategy implements IStrategy { diff --git a/src/Truncation/FramesStrategy.php b/src/Truncation/FramesStrategy.php index 16a7675a..63fe270f 100644 --- a/src/Truncation/FramesStrategy.php +++ b/src/Truncation/FramesStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; class FramesStrategy extends AbstractStrategy { diff --git a/src/Truncation/IStrategy.php b/src/Truncation/IStrategy.php index cce2e4eb..ac75aff0 100644 --- a/src/Truncation/IStrategy.php +++ b/src/Truncation/IStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; interface IStrategy { diff --git a/src/Truncation/MinBodyStrategy.php b/src/Truncation/MinBodyStrategy.php index 1f1d52ef..3ff30f61 100644 --- a/src/Truncation/MinBodyStrategy.php +++ b/src/Truncation/MinBodyStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; class MinBodyStrategy extends AbstractStrategy { diff --git a/src/Truncation/RawStrategy.php b/src/Truncation/RawStrategy.php index b6389233..2c5aa6c4 100644 --- a/src/Truncation/RawStrategy.php +++ b/src/Truncation/RawStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; class RawStrategy extends AbstractStrategy { diff --git a/src/Truncation/StringsStrategy.php b/src/Truncation/StringsStrategy.php index ba413bab..cd5e73aa 100644 --- a/src/Truncation/StringsStrategy.php +++ b/src/Truncation/StringsStrategy.php @@ -2,7 +2,7 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\EncodedPayload; class StringsStrategy extends AbstractStrategy { diff --git a/src/Truncation/Truncation.php b/src/Truncation/Truncation.php index fb59890e..2328bbd3 100644 --- a/src/Truncation/Truncation.php +++ b/src/Truncation/Truncation.php @@ -2,16 +2,19 @@ namespace Rollbar\Truncation; -use \Rollbar\Payload\EncodedPayload; -use \Rollbar\Config; +use Rollbar\Payload\EncodedPayload; +use Rollbar\Config; +use Rollbar\Truncation\AbstractStrategy; +use Rollbar\Truncation\StringsStrategy; +use Rollbar\Truncation\FramesStrategy; class Truncation { const MAX_PAYLOAD_SIZE = 131072; // 128 * 1024 protected static $truncationStrategies = array( - "Rollbar\Truncation\FramesStrategy", - "Rollbar\Truncation\StringsStrategy" + FramesStrategy::class, + StringsStrategy::class ); public function __construct(private Config $config) @@ -23,7 +26,7 @@ public function __construct(private Config $config) public function registerStrategy($type) { - if (!class_exists($type) || !is_subclass_of($type, "Rollbar\Truncation\AbstractStrategy")) { + if (!class_exists($type) || !is_subclass_of($type, AbstractStrategy::class)) { throw new \Exception( "Truncation strategy '$type' doesn't exist or is not a subclass " . "of Rollbar\Truncation\AbstractStrategy" diff --git a/src/Utilities.php b/src/Utilities.php index bc1ae4af..5a838af3 100644 --- a/src/Utilities.php +++ b/src/Utilities.php @@ -63,7 +63,7 @@ public static function validateInteger( return; } - if (!is_integer($input)) { + if (!is_int($input)) { throw new \InvalidArgumentException("\$$name must be an integer"); } if (!is_null($minValue) && $input < $minValue) { diff --git a/tests/AgentTest.php b/tests/AgentTest.php index 953aa57f..4d2f797e 100644 --- a/tests/AgentTest.php +++ b/tests/AgentTest.php @@ -4,14 +4,14 @@ use Rollbar; -function microtime() +function microtime(): int { return 2; } class AgentTest extends Rollbar\BaseRollbarTest { - private $path = '/tmp/rollbar-php'; + private string $path = '/tmp/rollbar-php'; protected function setUp(): void { @@ -20,7 +20,7 @@ protected function setUp(): void } } - public function testAgent() + public function testAgent(): void { Rollbar\Rollbar::init(array( 'access_token' => $this->getTestAccessToken(), @@ -30,7 +30,7 @@ public function testAgent() ), false, false, false); $logger = Rollbar\Rollbar::logger(); $logger->info("this is a test"); - $file = fopen($this->path . '/rollbar-relay.' . getmypid() . '.' . microtime(true) . '.rollbar', 'r'); + $file = fopen($this->path . '/rollbar-relay.' . getmypid() . '.' . microtime() . '.rollbar', 'r'); $line = fgets($file); $this->assertStringContainsString('this is a test', $line); } @@ -41,7 +41,7 @@ public function tearDown(): void $this->rrmdir($this->path); } - private function rrmdir($dir) + private function rrmdir($dir): void { if (!is_dir($dir)) { return; diff --git a/tests/BaseRollbarTest.php b/tests/BaseRollbarTest.php index 32bd5c9e..62f0f0f3 100644 --- a/tests/BaseRollbarTest.php +++ b/tests/BaseRollbarTest.php @@ -15,8 +15,6 @@ public function tearDown(): void public function getTestAccessToken() { - return isset($_ENV['ROLLBAR_TEST_TOKEN']) ? - $_ENV['ROLLBAR_TEST_TOKEN'] : - static::DEFAULT_ACCESS_TOKEN; + return $_ENV['ROLLBAR_TEST_TOKEN'] ?? static::DEFAULT_ACCESS_TOKEN; } } diff --git a/tests/BodyTest.php b/tests/BodyTest.php index 061bbe30..16251625 100644 --- a/tests/BodyTest.php +++ b/tests/BodyTest.php @@ -1,23 +1,24 @@ assertEquals($value, $body->getValue()); - $mock2 = m::mock("Rollbar\Payload\ContentInterface"); + $mock2 = m::mock(ContentInterface::class); $this->assertEquals($mock2, $body->setValue($mock2)->getValue()); } - public function testExtra() + public function testExtra(): void { - $value = m::mock("Rollbar\Payload\ContentInterface") + $value = m::mock(ContentInterface::class) ->shouldReceive("serialize") ->andReturn("{CONTENT}") ->shouldReceive("getKey") @@ -30,9 +31,9 @@ public function testExtra() $this->assertEquals($body->getExtra(), $expected); } - public function testSerialize() + public function testSerialize(): void { - $value = m::mock("Rollbar\Payload\ContentInterface") + $value = m::mock(ContentInterface::class) ->shouldReceive("serialize") ->andReturn("{CONTENT}") ->shouldReceive("getKey") diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index e23396f8..35dc4e0f 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -1,7 +1,7 @@ $this->getTestAccessToken(), @@ -54,7 +63,7 @@ public function testAccessToken() $this->assertEquals($this->getTestAccessToken(), $config->getAccessToken()); } - public function testEnabled() + public function testEnabled(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -70,7 +79,7 @@ public function testEnabled() $this->assertFalse($config->enabled()); } - public function testTransmit() + public function testTransmit(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -86,7 +95,7 @@ public function testTransmit() $this->assertFalse($config->transmitting()); } - public function testLogPayload() + public function testLogPayload(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -102,9 +111,9 @@ public function testLogPayload() $this->assertTrue($config->loggingPayload()); } - public function testLoggingPayload() + public function testLoggingPayload(): void { - $logPayloadLoggerMock = $this->getMockBuilder('\Psr\Log\LoggerInterface')->getMock(); + $logPayloadLoggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock(); $logPayloadLoggerMock->expects($this->once()) ->method('debug') ->with( @@ -112,7 +121,7 @@ public function testLoggingPayload() '/Sending payload with .*:\n\{"data":/' ) ); - $senderMock = $this->getMockBuilder('\Rollbar\Senders\SenderInterface') + $senderMock = $this->getMockBuilder(SenderInterface::class) ->getMock(); $senderMock->method('send')->willReturn(null); @@ -129,16 +138,16 @@ public function testLoggingPayload() $config->send($payload, $this->getTestAccessToken()); } - public function testConfigureLogPayloadLogger() + public function testConfigureLogPayloadLogger(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), 'environment' => $this->env )); - $this->assertInstanceOf('\Monolog\Logger', $config->logPayloadLogger()); + $this->assertInstanceOf(Logger::class, $config->logPayloadLogger()); $handlers = $config->logPayloadLogger()->getHandlers(); $handler = $handlers[0]; - $this->assertInstanceOf('\Monolog\Handler\ErrorLogHandler', $handler); + $this->assertInstanceOf(ErrorLogHandler::class, $handler); $this->assertEquals(\Monolog\Logger::DEBUG, $handler->getLevel()); $config = new Config(array( @@ -146,10 +155,10 @@ public function testConfigureLogPayloadLogger() 'environment' => $this->env, 'log_payload_logger' => new \Psr\Log\NullLogger() )); - $this->assertInstanceOf('\Psr\Log\NullLogger', $config->logPayloadLogger()); + $this->assertInstanceOf(NullLogger::class, $config->logPayloadLogger()); } - public function testVerbose() + public function testVerbose(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -157,11 +166,11 @@ public function testVerbose() )); // assert the appropriate default logger $this->assertEquals(Config::VERBOSE_NONE, $config->verbose()); - $this->assertInstanceOf('\Monolog\Logger', $config->verboseLogger()); + $this->assertInstanceOf(Logger::class, $config->verboseLogger()); // assert the appropriate default handler $handlers = $config->verboseLogger()->getHandlers(); $handler = $handlers[0]; - $this->assertInstanceOf('\Monolog\Handler\ErrorLogHandler', $handler); + $this->assertInstanceOf(ErrorLogHandler::class, $handler); // assert the appropriate default handler level $this->assertEquals($config->verboseInteger(), $handler->getLevel()); @@ -172,7 +181,7 @@ public function testVerbose() $this->assertEquals($config->verboseInteger(), $handler->getLevel()); } - public function testVerboseInfo() + public function testVerboseInfo(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -180,7 +189,7 @@ public function testVerboseInfo() 'verbose' => \Psr\Log\LogLevel::INFO )); - $handlerMock = $this->getMockBuilder('\Monolog\Handler\ErrorLogHandler') + $handlerMock = $this->getMockBuilder(ErrorLogHandler::class) ->setMethods(array('handle')) ->getMock(); @@ -191,7 +200,7 @@ public function testVerboseInfo() $config->verboseLogger()->info('Test trace'); } - public function testVerboseInteger() + public function testVerboseInteger(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -204,23 +213,23 @@ public function testVerboseInteger() $this->assertEquals(100, $config->verboseInteger()); } - public function testConfigureVerboseLogger() + public function testConfigureVerboseLogger(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), 'environment' => $this->env )); - $this->assertInstanceOf('\Monolog\Logger', $config->verboseLogger()); + $this->assertInstanceOf(Logger::class, $config->verboseLogger()); $config = new Config(array( 'access_token' => $this->getTestAccessToken(), 'environment' => $this->env, 'verbose_logger' => new \Psr\Log\NullLogger() )); - $this->assertInstanceOf('\Psr\Log\NullLogger', $config->verboseLogger()); + $this->assertInstanceOf(NullLogger::class, $config->verboseLogger()); } - public function testAccessTokenFromEnvironment() + public function testAccessTokenFromEnvironment(): void { $_ENV['ROLLBAR_ACCESS_TOKEN'] = $this->getTestAccessToken(); $config = new Config(array( @@ -229,17 +238,17 @@ public function testAccessTokenFromEnvironment() $this->assertEquals($this->getTestAccessToken(), $config->getAccessToken()); } - public function testDataBuilder() + public function testDataBuilder(): void { $arr = array( "access_token" => $this->getTestAccessToken(), "environment" => $this->env ); $config = new Config($arr); - $this->assertInstanceOf('Rollbar\DataBuilder', $config->getDataBuilder()); + $this->assertInstanceOf(DataBuilder::class, $config->getDataBuilder()); } - public function testExtend() + public function testExtend(): void { $arr = array( "access_token" => $this->getTestAccessToken(), @@ -256,7 +265,7 @@ public function testExtend() $this->assertEquals($expected, $extended); } - public function testConfigure() + public function testConfigure(): void { $arr = array( "access_token" => $this->getTestAccessToken(), @@ -273,7 +282,7 @@ public function testConfigure() $this->assertEquals($expected, $config->getConfigArray()); } - public function testExplicitDataBuilder() + public function testExplicitDataBuilder(): void { $fdb = new FakeDataBuilder(array()); $arr = array( @@ -287,11 +296,11 @@ public function testExplicitDataBuilder() $this->assertEquals($expected, array_pop(FakeDataBuilder::$logged)); } - public function testTransformer() + public function testTransformer(): void { - $p = m::mock("Rollbar\Payload\Payload"); - $pPrime = m::mock("Rollbar\Payload\Payload"); - $transformer = m::mock("Rollbar\TransformerInterface"); + $p = m::mock(Payload::class); + $pPrime = m::mock(Payload::class); + $transformer = m::mock(TransformerInterface::class); $transformer->shouldReceive('transform') ->once() ->with($p, "error", "message", [ "extra_data" ]) @@ -305,7 +314,7 @@ public function testTransformer() $this->assertEquals($pPrime, $config->transform($p, "error", "message", [ "extra_data" ])); } - public function testMinimumLevel() + public function testMinimumLevel(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -329,19 +338,19 @@ public function testMinimumLevel() $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(Level::ERROR())); } - public function assertPayloadIgnored($config, $payload) + public function assertPayloadIgnored($config, $payload): void { $this->assertTrue($config->checkIgnored($payload, 'access-token', $this->error, false)); } - public function assertPayloadNotIgnored($config, $payload) + public function assertPayloadNotIgnored($config, $payload): void { $this->assertFalse($config->checkIgnored($payload, 'access-token', $this->error, false)); } - private function prepareMockPayload($level) + private function prepareMockPayload($level): Payload { - $data = m::mock("Rollbar\Payload\Data") + $data = m::mock(Data::class) ->shouldReceive('getLevel') ->andReturn($level) ->mock(); @@ -364,7 +373,7 @@ private function prepareMockPayload($level) * [0, "report_suppressed", true, false] * [1, "report_suppressed", false, false] */ - public function testReportSuppressed($errorReporting, $configKey, $configValue, $shouldSuppressExpect) + public function testReportSuppressed($errorReporting, $configKey, $configValue, $shouldSuppressExpect): void { $oldErrorReporting = error_reporting($errorReporting); try { @@ -381,17 +390,17 @@ public function testReportSuppressed($errorReporting, $configKey, $configValue, } } - public function testFilter() + public function testFilter(): void { - $d = m::mock("Rollbar\Payload\Data") + $d = m::mock(Data::class) ->shouldReceive("getLevel") ->andReturn(Level::CRITICAL()) ->mock(); - $p = m::mock("Rollbar\Payload\Payload") + $p = m::mock(Payload::class) ->shouldReceive("getData") ->andReturn($d) ->mock(); - $filter = m::mock("Rollbar\FilterInterface") + $filter = m::mock(FilterInterface::class) ->shouldReceive("shouldSend") ->twice() ->andReturn(true, false) @@ -405,10 +414,10 @@ public function testFilter() $this->assertFalse($c->checkIgnored($p, "fake_access_token", $this->error, false)); } - public function testSender() + public function testSender(): void { - $p = m::mock("Rollbar\Payload\EncodedPayload"); - $sender = m::mock("Rollbar\Senders\SenderInterface") + $p = m::mock(EncodedPayload::class); + $sender = m::mock(SenderInterface::class) ->shouldReceive("send") ->with($p, $this->getTestAccessToken()) ->once() @@ -421,7 +430,7 @@ public function testSender() $c->send($p, $this->getTestAccessToken()); } - public function testEndpoint() + public function testEndpoint(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -435,7 +444,7 @@ public function testEndpoint() ); } - public function testCustom() + public function testCustom(): void { $expectedCustom = array( "foo" => "bar", @@ -458,7 +467,7 @@ public function testCustom() $this->assertSame($expectedCustom, $actualCustom); } - public function testCustomPrimitive() + public function testCustomPrimitive(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -477,7 +486,7 @@ public function testCustomPrimitive() $this->assertSame(array('message' => true), $custom); } - public function testCustomPrimitiveFalsy() + public function testCustomPrimitiveFalsy(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -496,7 +505,7 @@ public function testCustomPrimitiveFalsy() $this->assertSame(array(), $custom); } - public function testCustomObject() + public function testCustomObject(): void { $expectedCustom = array( "foo" => "bar", @@ -531,7 +540,7 @@ public function testCustomObject() $this->assertSame($expectedCustom, $actualCustom); } - public function testCustomSerializable() + public function testCustomSerializable(): void { $expectedCustom = array( "foo" => "bar", @@ -567,7 +576,7 @@ public function testCustomSerializable() $this->assertSame($expectedCustom, $actualCustom); } - public function testMaxItems() + public function testMaxItems(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken() @@ -583,7 +592,7 @@ public function testMaxItems() $this->assertEquals(Defaults::get()->maxItems()+1, $config->getMaxItems()); } - public function testCustomDataMethod() + public function testCustomDataMethod(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -609,7 +618,7 @@ public function testCustomDataMethod() $this->assertEquals('bar', $result['data_from_my_custom_method']); } - public function testEndpointDefault() + public function testEndpointDefault(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -622,7 +631,7 @@ public function testEndpointDefault() ); } - public function testBaseApiUrl() + public function testBaseApiUrl(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -636,7 +645,7 @@ public function testBaseApiUrl() ); } - public function testBaseApiUrlDefault() + public function testBaseApiUrlDefault(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -649,7 +658,7 @@ public function testBaseApiUrlDefault() ); } - public function testRaiseOnError() + public function testRaiseOnError(): void { $config = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -660,7 +669,7 @@ public function testRaiseOnError() $this->assertTrue($config->getRaiseOnError()); } - public function testSendMessageTrace() + public function testSendMessageTrace(): void { $c = new Config(array( "access_token" => $this->getTestAccessToken(), @@ -678,7 +687,7 @@ public function testSendMessageTrace() $this->assertFalse($c->getSendMessageTrace()); } - public function testCheckIgnore() + public function testCheckIgnore(): void { $called = false; $config = new Config(array( @@ -706,7 +715,7 @@ public function testCheckIgnore() $this->assertTrue($called); } - public function testCheckIgnoreParameters() + public function testCheckIgnoreParameters(): void { $called = false; $isUncaughtPassed = null; @@ -749,7 +758,7 @@ public function testCheckIgnoreParameters() $this->assertEquals($this->error, $errorPassed); } - public function testCaptureErrorStacktraces() + public function testCaptureErrorStacktraces(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -771,7 +780,7 @@ public function testCaptureErrorStacktraces() /** * @dataProvider useErrorReportingProvider */ - public function testUseErrorReporting($use_error_reporting, $error_reporting, $expected) + public function testUseErrorReporting($use_error_reporting, $error_reporting, $expected): void { $called = false; @@ -801,7 +810,7 @@ public function testUseErrorReporting($use_error_reporting, $error_reporting, $e } } - public function useErrorReportingProvider() + public function useErrorReportingProvider(): array { return array( "use_error_reporting off" => array( @@ -825,7 +834,7 @@ public function useErrorReportingProvider() /** * @dataProvider providerExceptionSampleRate */ - public function testExceptionSampleRate($exception, $expected) + public function testExceptionSampleRate($exception, $expected): void { $config = new Config(array( "access_token" => "ad865e76e7fb496fab096ac07b1dbabb", @@ -840,7 +849,7 @@ public function testExceptionSampleRate($exception, $expected) $this->assertEquals($expected, $sampleRate); } - public function providerExceptionSampleRate() + public function providerExceptionSampleRate(): array { return array( array( diff --git a/tests/ContextTest.php b/tests/ContextTest.php index cc66db67..75717105 100644 --- a/tests/ContextTest.php +++ b/tests/ContextTest.php @@ -1,11 +1,11 @@ assertEquals($pre2, $context->setPre($pre2)->getPre()); } - public function testContextPost() + public function testContextPost(): void { $post = array("four", "five"); $context = new Context(array(), $post); @@ -25,7 +25,7 @@ public function testContextPost() $this->assertEquals($post2, $context->setPost($post2)->getPost()); } - public function testEncode() + public function testEncode(): void { $context = new Context(array(), array()); $encoded = json_encode($context->serialize()); diff --git a/tests/CurlSenderTest.php b/tests/CurlSenderTest.php index 63ce274f..90c01f15 100644 --- a/tests/CurlSenderTest.php +++ b/tests/CurlSenderTest.php @@ -7,7 +7,7 @@ class CurlSenderTest extends BaseRollbarTest { - public function testCurlError() + public function testCurlError(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -16,15 +16,12 @@ public function testCurlError() )); $response = $logger->log(Level::WARNING, "Testing PHP Notifier", array()); - $this->assertTrue( - in_array( - $response->getInfo(), - array( - "Couldn't resolve host 'fake-endpointitem'", // hack for PHP 5.3 - "Could not resolve host: fake-endpointitem", - "Could not resolve: fake-endpointitem (Domain name not found)", - "Empty reply from server" - ) + $this->assertContains( + $response->getInfo(), array( + "Couldn't resolve host 'fake-endpointitem'", // hack for PHP 5.3 + "Could not resolve host: fake-endpointitem", + "Could not resolve: fake-endpointitem (Domain name not found)", + "Empty reply from server" ) ); } diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index f0daa338..36a797d8 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -7,11 +7,10 @@ class DataBuilderTest extends BaseRollbarTest { - /** * @var DataBuilder */ - private $dataBuilder; + private DataBuilder $dataBuilder; public function setUp(): void { @@ -33,13 +32,13 @@ public function setUp(): void * @testWith [ "bogus", null ] * [ "error", "error" ] */ - public function testMakeDataLevel($given, $resolved) + public function testMakeDataLevel($given, $resolved): void { $output = $this->dataBuilder->makeData($given, "testing", array()); $this->assertEquals($resolved, $output->getLevel()); } - public function testMakeData() + public function testMakeData(): void { $output = $this->dataBuilder->makeData(Level::ERROR, "testing", array()); $this->assertEquals('tests', $output->getEnvironment()); @@ -48,7 +47,7 @@ public function testMakeData() /** * @dataProvider getUrlProvider */ - public function testGetUrl($protoData, $hostData, $portData) + public function testGetUrl($protoData, $hostData, $portData): void { // Set up proto $pre_SERVER = $_SERVER; @@ -82,7 +81,7 @@ public function testGetUrl($protoData, $hostData, $portData) $this->assertEquals($expected, $result); } - public function getUrlProvider() + public function getUrlProvider(): array { $protoData = $this->getUrlProtoProvider(); $hostData = $this->getUrlHostProvider(); @@ -116,13 +115,13 @@ public function getUrlProvider() /** * @dataProvider parseForwardedStringProvider */ - public function testParseForwardedString($forwaded, $expected) + public function testParseForwardedString($forwaded, $expected): void { $output = $this->dataBuilder->parseForwardedString($forwaded); $this->assertEquals($expected, $output); } - public function parseForwardedStringProvider() + public function parseForwardedStringProvider(): array { return array( array( // test 1 @@ -174,7 +173,7 @@ public function parseForwardedStringProvider() /** * @dataProvider getUrlProtoProvider */ - public function testGetUrlProto($data, $expected) + public function testGetUrlProto($data, $expected): void { $pre_SERVER = $_SERVER; $_SERVER = array_merge($_SERVER, $data); @@ -186,7 +185,7 @@ public function testGetUrlProto($data, $expected) $_SERVER = $pre_SERVER; } - public function getUrlProtoProvider() + public function getUrlProtoProvider(): array { return array( array( // test 1: HTTP_FORWARDED @@ -229,7 +228,7 @@ public function getUrlProtoProvider() /** * @dataProvider getUrlHostProvider */ - public function testGetUrlHost($data, $expected) + public function testGetUrlHost($data, $expected): void { $pre_SERVER = $_SERVER; $_SERVER = array_merge($_SERVER, $data); @@ -241,7 +240,7 @@ public function testGetUrlHost($data, $expected) $this->assertEquals($expected, $output); } - public function getUrlHostProvider() + public function getUrlHostProvider(): array { return array( array( // test 1: HTTP_FORWARDED @@ -281,7 +280,7 @@ public function getUrlHostProvider() ); } - public function testGetHeaders() + public function testGetHeaders(): void { $pre_SERVER = $_SERVER; $_SERVER = array( @@ -301,13 +300,13 @@ public function testGetHeaders() /** * @dataProvider getUrlPortProvider */ - public function testGetUrlPort($data, $expected) + public function testGetUrlPort($data, $expected): void { $pre_SERVER = $_SERVER; $_SERVER = array_merge($_SERVER, $data); $output = $this->dataBuilder->getUrlPort( - isset($_SERVER['$proto']) ? $_SERVER['$proto'] : null + $_SERVER['$proto'] ?? null ); $_SERVER = $pre_SERVER; @@ -315,7 +314,7 @@ public function testGetUrlPort($data, $expected) $this->assertEquals($expected, $output); } - public function getUrlPortProvider() + public function getUrlPortProvider(): array { return array( array( // test 1: HTTP_X_FORWARDED @@ -343,7 +342,7 @@ public function getUrlPortProvider() ); } - public function testBranchKey() + public function testBranchKey(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -357,7 +356,7 @@ public function testBranchKey() $this->assertEquals('test-branch', $output->getServer()->getBranch()); } - public function testCodeVersion() + public function testCodeVersion(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -370,7 +369,7 @@ public function testCodeVersion() $this->assertEquals('3.4.1', $output->getCodeVersion()); } - public function testHost() + public function testHost(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -383,7 +382,7 @@ public function testHost() $this->assertEquals('my host', $output->getServer()->getHost()); } - public function testGetMessage() + public function testGetMessage(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -396,7 +395,7 @@ public function testGetMessage() $this->assertNull($result->getBody()->getValue()->getBacktrace()); } - public function testGetMessageSendMessageTrace() + public function testGetMessageSendMessageTrace(): void { $dataBuilder = new DataBuilder(array( @@ -411,7 +410,7 @@ public function testGetMessageSendMessageTrace() $this->assertNotEmpty($result->getBody()->getValue()->getBacktrace()); } - public function testGetMessageTraceArguments() + public function testGetMessageTraceArguments(): void { // Negative test $c = new Config(array( @@ -450,7 +449,7 @@ public function testGetMessageTraceArguments() ); } - public function testStackFramesAreUnavailableWhenLocalVarsDumpConfigUnset() + public function testStackFramesAreUnavailableWhenLocalVarsDumpConfigUnset(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -470,7 +469,7 @@ public function testStackFramesAreUnavailableWhenLocalVarsDumpConfigUnset() * @testWith [0] * [1] */ - public function testStackFramesAreAvailableWhenLocalVarsDumpRequested($valueOfZendExceptionIgnoreArgs) + public function testStackFramesAreAvailableWhenLocalVarsDumpRequested($valueOfZendExceptionIgnoreArgs): void { ini_set('zend.exception_ignore_args', $valueOfZendExceptionIgnoreArgs); @@ -501,12 +500,12 @@ public function testStackFramesAreAvailableWhenLocalVarsDumpRequested($valueOfZe * * @return \Exception */ - private function exceptionTraceArgsHelper($message) + private function exceptionTraceArgsHelper(string $message): \Exception { return new \Exception($message); } - public function testExceptionFramesWithoutContext() + public function testExceptionFramesWithoutContext(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -520,7 +519,7 @@ public function testExceptionFramesWithoutContext() $this->assertNull($output[1]->getContext()); } - public function testExceptionFramesWithoutContextDefault() + public function testExceptionFramesWithoutContextDefault(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -532,7 +531,7 @@ public function testExceptionFramesWithoutContextDefault() $this->assertNull($output[1]->getContext()); } - public function testExceptionFramesWithContext() + public function testExceptionFramesWithContext(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -545,7 +544,7 @@ public function testExceptionFramesWithContext() $this->assertNotEmpty($output[count($output)-1]->getContext()); } - public function testFramesWithoutContext() + public function testFramesWithoutContext(): void { $utilities = new Utilities; @@ -584,7 +583,7 @@ public function testFramesWithoutContext() $this->assertNull($output[0]->getContext()); } - public function testFramesWithContext() + public function testFramesWithContext(): void { $utilities = new Utilities; @@ -616,10 +615,10 @@ public function testFramesWithContext() $lineNumber++; $line = fgets($file); - if ($line == ' public function testFramesWithoutContext() + if ($line === ' public function testFramesWithoutContext(): void ') { $backTrace[0]['line'] = $lineNumber; - } elseif ($line == ' public function testFramesWithContext() + } elseif ($line === ' public function testFramesWithContext() ') { $backTrace[1]['line'] = $lineNumber; } @@ -651,7 +650,7 @@ public function testFramesWithContext() ); } - public function testFramesWithoutContextDefault() + public function testFramesWithoutContextDefault(): void { $testFilePath = __DIR__ . '/DataBuilderTest.php'; @@ -704,7 +703,7 @@ public function testFramesWithoutContextDefault() $this->assertNull($output[0]->getContext()); } - public function testPerson() + public function testPerson(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -723,7 +722,7 @@ public function testPerson() $this->assertNull($output->getPerson()->getEmail()); } - public function testPersonCaptureEmailUsername() + public function testPersonCaptureEmailUsername(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -745,7 +744,7 @@ public function testPersonCaptureEmailUsername() $this->assertEquals('test@test.com', $output->getPerson()->getEmail()); } - public function testPersonFunc() + public function testPersonFunc(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -763,7 +762,7 @@ public function testPersonFunc() $this->assertEquals('123', $output->getPerson()->getId()); } - public function testPersonIntID() + public function testPersonIntID(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -782,7 +781,7 @@ public function testPersonIntID() $this->assertNull($output->getPerson()->getEmail()); } - public function testPersonFuncException() + public function testPersonFuncException(): void { \Rollbar\Rollbar::init(array( 'access_token' => $this->getTestAccessToken(), @@ -802,7 +801,7 @@ public function testPersonFuncException() } } - public function testRoot() + public function testRoot(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -815,14 +814,14 @@ public function testRoot() $this->assertEquals('/var/www/app', $output->getServer()->getRoot()); } - public function testSetRequestBody() + public function testSetRequestBody(): void { $_POST['arg1'] = "val1"; $_POST['arg2'] = "val2"; $streamInput = http_build_query($_POST); stream_wrapper_unregister("php"); - stream_wrapper_register("php", "\Rollbar\TestHelpers\MockPhpStream"); + stream_wrapper_register("php", MockPhpStream::class); file_put_contents('php://input', $streamInput); @@ -841,7 +840,7 @@ public function testSetRequestBody() stream_wrapper_restore("php"); } - public function testPostDataPutRequest() + public function testPostDataPutRequest(): void { $_SERVER['REQUEST_METHOD'] = 'PUT'; @@ -851,7 +850,7 @@ public function testPostDataPutRequest() )); stream_wrapper_unregister("php"); - stream_wrapper_register("php", "\Rollbar\TestHelpers\MockPhpStream"); + stream_wrapper_register("php", MockPhpStream::class); file_put_contents('php://input', $streamInput); @@ -874,11 +873,11 @@ public function testPostDataPutRequest() stream_wrapper_restore("php"); } - public function testGenerateErrorWrapper() + public function testGenerateErrorWrapper(): void { $result = $this->dataBuilder->generateErrorWrapper(E_ERROR, 'bork', null, null); - $this->assertTrue($result instanceof ErrorWrapper); + $this->assertInstanceOf(ErrorWrapper::class, $result); } /** @@ -887,7 +886,8 @@ public function testGenerateErrorWrapper() public function testCaptureErrorStacktracesException( $captureErrorStacktraces, $expected - ) { + ): void + { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -907,7 +907,7 @@ public function testCaptureErrorStacktracesException( $this->assertEquals($expected, count($frames) === 0); } - public function testFramesOrder() + public function testFramesOrder(): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -936,7 +936,8 @@ public function testFramesOrder() public function testCaptureErrorStacktracesError( $captureErrorStacktraces, $expected - ) { + ): void + { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -952,7 +953,7 @@ public function testCaptureErrorStacktracesError( $this->assertEquals($expected, count($frames) == 0); } - public function captureErrorStacktracesProvider() + public function captureErrorStacktracesProvider(): array { return array( array(false,true), @@ -963,7 +964,7 @@ public function captureErrorStacktracesProvider() /** * @dataProvider getUserIpProvider */ - public function testGetUserIp($ipAddress, $expected, $captureIP) + public function testGetUserIp($ipAddress, $expected, $captureIP): void { $_SERVER['REMOTE_ADDR'] = $ipAddress; @@ -1002,7 +1003,7 @@ public function testGetUserIp($ipAddress, $expected, $captureIP) unset($_SERVER['HTTP_X_REAL_IP']); } - public function getUserIpProvider() + public function getUserIpProvider(): array { return array( array('127.0.0.1', '127.0.0.1', null), @@ -1021,7 +1022,7 @@ public function getUserIpProvider() ); } - public function testGitBranch() + public function testGitBranch(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), @@ -1034,7 +1035,7 @@ public function testGitBranch() $this->assertEquals($val, $dataBuilder->detectGitBranch()); } - public function testGitBranchNoExec() + public function testGitBranchNoExec(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), diff --git a/tests/DataTest.php b/tests/DataTest.php index b431df7d..bc2a2147 100644 --- a/tests/DataTest.php +++ b/tests/DataTest.php @@ -1,21 +1,26 @@ body = m::mock("Rollbar\Payload\Body"); + $this->body = m::mock(Body::class); $this->data = new Data("test", $this->body); } - public function testEnvironmentMustBeString() + public function testEnvironmentMustBeString(): void { $data = new Data("env", $this->body); $this->assertEquals("env", $data->getEnvironment()); @@ -23,16 +28,16 @@ public function testEnvironmentMustBeString() $this->assertEquals("test", $data->setEnvironment("test")->getEnvironment()); } - public function testBody() + public function testBody(): void { $data = new Data("env", $this->body); $this->assertEquals($this->body, $data->getBody()); - $body2 = m::mock("Rollbar\Payload\Body"); + $body2 = m::mock(Body::class); $this->assertEquals($body2, $data->setBody($body2)->getBody()); } - public function testLevel() + public function testLevel(): void { $levelFactory = new LevelFactory; $level = Level::ERROR; @@ -43,62 +48,61 @@ public function testLevel() ); } - public function testTimestamp() + public function testTimestamp(): void { $timestamp = time(); $this->assertEquals($timestamp, $this->data->setTimestamp($timestamp)->getTimestamp()); } - public function testCodeVersion() + public function testCodeVersion(): void { $codeVersion = "v0.18.1"; $this->assertEquals($codeVersion, $this->data->setCodeVersion($codeVersion)->getCodeVersion()); } - public function testPlatform() + public function testPlatform(): void { $platform = "Linux"; $this->assertEquals($platform, $this->data->setPlatform($platform)->getPlatform()); } - public function testLanguage() + public function testLanguage(): void { $language = "PHP"; $this->assertEquals($language, $this->data->setLanguage($language)->getLanguage()); } - public function testFramework() + public function testFramework(): void { $framework = "Laravel"; $this->assertEquals($framework, $this->data->setFramework($framework)->getFramework()); } - public function testContext() + public function testContext(): void { $context = "SuperController->getResource()"; $this->assertEquals($context, $this->data->setContext($context)->getContext()); } - public function testRequest() + public function testRequest(): void { - $request = m::mock("Rollbar\Payload\Request"); + $request = m::mock(Request::class); $this->assertEquals($request, $this->data->setRequest($request)->getRequest()); } - public function testPerson() + public function testPerson(): void { - $person = m::mock("Rollbar\Payload\Person"); - ; + $person = m::mock(Person::class); $this->assertEquals($person, $this->data->setPerson($person)->getPerson()); } - public function testServer() + public function testServer(): void { - $server = m::mock("Rollbar\Payload\Server"); + $server = m::mock(Server::class); $this->assertEquals($server, $this->data->setServer($server)->getServer()); } - public function testCustom() + public function testCustom(): void { $custom = array( "x" => 1, @@ -108,39 +112,39 @@ public function testCustom() $this->assertEquals($custom, $this->data->setCustom($custom)->getCustom()); } - public function testFingerprint() + public function testFingerprint(): void { $fingerprint = "bad-error-with-database"; $this->assertEquals($fingerprint, $this->data->setFingerprint($fingerprint)->getFingerprint()); } - public function testTitle() + public function testTitle(): void { $title = "End of the World as we know it"; $this->assertEquals($title, $this->data->setTitle($title)->getTitle()); } - public function testUuid() + public function testUuid(): void { $uuid = "21EC2020-3AEA-4069-A2DD-08002B30309D"; $this->assertEquals($uuid, $this->data->setUuid($uuid)->getUuid()); } - public function testNotifier() + public function testNotifier(): void { - $notifier = m::mock("Rollbar\Payload\Notifier"); + $notifier = m::mock(Notifier::class); $this->assertEquals($notifier, $this->data->setNotifier($notifier)->getNotifier()); } - public function testEncode() + public function testEncode(): void { $time = time(); - $level = $this->mockSerialize("Rollbar\Payload\Level", "{LEVEL}"); + $level = $this->mockSerialize(Level::class, "{LEVEL}"); $body = $this->mockSerialize($this->body, "{BODY}"); - $request = $this->mockSerialize("Rollbar\Payload\Request", "{REQUEST}"); - $person = $this->mockSerialize("Rollbar\Payload\Person", "{PERSON}"); - $server = $this->mockSerialize("Rollbar\Payload\Server", "{SERVER}"); - $notifier = $this->mockSerialize("Rollbar\Payload\Notifier", "{NOTIFIER}"); + $request = $this->mockSerialize(Request::class, "{REQUEST}"); + $person = $this->mockSerialize(Person::class, "{PERSON}"); + $server = $this->mockSerialize(Server::class, "{SERVER}"); + $notifier = $this->mockSerialize(Notifier::class, "{NOTIFIER}"); $data = $this->data ->setEnvironment("testing") diff --git a/tests/DefaultsTest.php b/tests/DefaultsTest.php index 107cc83b..779d96ec 100644 --- a/tests/DefaultsTest.php +++ b/tests/DefaultsTest.php @@ -12,32 +12,32 @@ class DefaultsTest extends BaseRollbarTest /** * @var Defaults */ - private $defaults; + private \Rollbar\Defaults $defaults; public function setUp(): void { $this->defaults = new Defaults; } - public function testGet() + public function testGet(): void { $defaults = Defaults::get(); - $this->assertInstanceOf("Rollbar\Defaults", $defaults); + $this->assertInstanceOf(Defaults::class, $defaults); } - public function testMessageLevel() + public function testMessageLevel(): void { $this->assertEquals("warning", $this->defaults->messageLevel()); $this->assertEquals("error", $this->defaults->messageLevel(Level::ERROR)); } - public function testExceptionLevel() + public function testExceptionLevel(): void { $this->assertEquals("error", $this->defaults->exceptionLevel()); $this->assertEquals("warning", $this->defaults->exceptionLevel(Level::WARNING)); } - public function testErrorLevels() + public function testErrorLevels(): void { $expected = array( E_ERROR => "error", @@ -59,7 +59,7 @@ public function testErrorLevels() $this->assertEquals($expected, $this->defaults->errorLevels()); } - public function testPsrLevels() + public function testPsrLevels(): void { $expected = $this->defaultPsrLevels = array( LogLevel::EMERGENCY => "critical", @@ -74,37 +74,37 @@ public function testPsrLevels() $this->assertEquals($expected, $this->defaults->psrLevels()); } - public function testBranch() + public function testBranch(): void { $val = 'some-branch'; $this->assertEquals($val, $this->defaults->branch($val)); } - public function testServerRoot() + public function testServerRoot(): void { $_ENV["HEROKU_APP_DIR"] = "abc123"; $defaults = new Defaults; $this->assertEquals("abc123", $defaults->serverRoot()); } - public function testPlatform() + public function testPlatform(): void { $this->assertEquals(php_uname('a'), $this->defaults->platform()); } - public function testNotifier() + public function testNotifier(): void { $this->assertEquals(Notifier::defaultNotifier(), $this->defaults->notifier()); } - public function testBaseException() + public function testBaseException(): void { $expected = Throwable::class; $base = $this->defaults->baseException(); $this->assertEquals($expected, $base); } - public function testScrubFields() + public function testScrubFields(): void { $expected = array( 'passwd', @@ -119,102 +119,102 @@ public function testScrubFields() $this->assertEquals($expected, $this->defaults->scrubFields()); } - public function testSendMessageTrace() + public function testSendMessageTrace(): void { $this->assertFalse($this->defaults->sendMessageTrace()); } - public function testAgentLogLocation() + public function testAgentLogLocation(): void { $this->assertEquals('/var/tmp', $this->defaults->agentLogLocation()); } - public function testAllowExec() + public function testAllowExec(): void { $this->assertEquals(true, $this->defaults->allowExec()); } - public function testEndpoint() + public function testEndpoint(): void { $this->assertEquals('https://api.rollbar.com/api/1/', $this->defaults->endpoint()); } - public function testCaptureErrorStacktraces() + public function testCaptureErrorStacktraces(): void { $this->assertTrue($this->defaults->captureErrorStacktraces()); } - public function testCheckIgnore() + public function testCheckIgnore(): void { $this->assertNull($this->defaults->checkIgnore()); } - public function testCodeVersion() + public function testCodeVersion(): void { $this->assertEquals("", $this->defaults->codeVersion()); } - public function testCustom() + public function testCustom(): void { $this->assertNull($this->defaults->custom()); } - public function testEnabled() + public function testEnabled(): void { $this->assertTrue($this->defaults->enabled()); } - public function testTransmit() + public function testTransmit(): void { $this->assertTrue($this->defaults->transmit()); } - public function testLogPayload() + public function testLogPayload(): void { $this->assertFalse($this->defaults->logPayload()); } - public function testEnvironment() + public function testEnvironment(): void { $this->assertEquals('production', $this->defaults->environment()); } - public function testErrorSampleRates() + public function testErrorSampleRates(): void { $this->assertEmpty($this->defaults->errorSampleRates()); } - public function testExceptionSampleRates() + public function testExceptionSampleRates(): void { $this->assertEmpty($this->defaults->exceptionSampleRates()); } - public function testFluentHost() + public function testFluentHost(): void { $this->assertEquals('127.0.0.1', $this->defaults->fluentHost()); } - public function testFluentPort() + public function testFluentPort(): void { $this->assertEquals(24224, $this->defaults->fluentPort()); } - public function testFluentTag() + public function testFluentTag(): void { $this->assertEquals('rollbar', $this->defaults->fluentTag()); } - public function testHandler() + public function testHandler(): void { $this->assertEquals('blocking', $this->defaults->handler()); } - public function testHost() + public function testHost(): void { $this->assertNull($this->defaults->host()); } - public function testIncludedErrnoDefault() + public function testIncludedErrnoDefault(): void { $expected = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR; $this->assertEquals( @@ -232,7 +232,7 @@ public function testIncludedErrnoDefault() * @runInSeparateProcess * @preserveGlobalState disabled */ - public function testIncludedErrnoDefineOverride() + public function testIncludedErrnoDefineOverride(): void { // unlike other tests that use `$this->defaults`, we must make our // own Defaults object now, _after_ defining the bitmask: in the @@ -244,37 +244,37 @@ public function testIncludedErrnoDefineOverride() ); } - public function testTimeout() + public function testTimeout(): void { $this->assertEquals(3, $this->defaults->timeout()); } - public function testReportSuppressed() + public function testReportSuppressed(): void { $this->assertFalse($this->defaults->reportSuppressed()); } - public function testUseErrorReporting() + public function testUseErrorReporting(): void { $this->assertFalse($this->defaults->useErrorReporting()); } - public function testCaptureEmail() + public function testCaptureEmail(): void { $this->assertFalse($this->defaults->captureEmail()); } - public function testCaptureUsername() + public function testCaptureUsername(): void { $this->assertFalse($this->defaults->captureUsername()); } - public function testMaxItems() + public function testMaxItems(): void { $this->assertEquals(10, $this->defaults->maxItems()); } - public function testRaiseOnError() + public function testRaiseOnError(): void { $this->assertEquals(false, $this->defaults->raiseOnError()); } @@ -283,7 +283,7 @@ public function testRaiseOnError() * @testWith ["message_level", "warning"] * ["MESSAGE_LEVEL", "warning"] */ - public function testFromSnakeCaseGetsExpectedValueForValidOption($option, $value) + public function testFromSnakeCaseGetsExpectedValueForValidOption($option, $value): void { $this->assertEquals( $value, @@ -291,7 +291,7 @@ public function testFromSnakeCaseGetsExpectedValueForValidOption($option, $value ); } - public function testFromSnakeCaseThrowsOnInvalidOption() + public function testFromSnakeCaseThrowsOnInvalidOption(): void { $this->expectException(Exception::class); \Rollbar\Defaults::get()->fromSnakeCase('no_such_option'); diff --git a/tests/ErrorWrapperTest.php b/tests/ErrorWrapperTest.php index 726abc56..678c6bc4 100644 --- a/tests/ErrorWrapperTest.php +++ b/tests/ErrorWrapperTest.php @@ -4,7 +4,7 @@ class ErrorWrapperTest extends BaseRollbarTest { - public function testBacktrace() + public function testBacktrace(): void { $errWrapper = new ErrorWrapper( E_ERROR, @@ -17,7 +17,7 @@ public function testBacktrace() $this->assertEquals("FAKE BACKTRACE", $errWrapper->getBacktrace()); } - public function testGetClassName() + public function testGetClassName(): void { $errWrapper = new ErrorWrapper( E_ERROR, diff --git a/tests/ExceptionInfoTest.php b/tests/ExceptionInfoTest.php index 310966da..4a2de9ef 100644 --- a/tests/ExceptionInfoTest.php +++ b/tests/ExceptionInfoTest.php @@ -4,7 +4,7 @@ class ExceptionInfoTest extends Rollbar\BaseRollbarTest { - public function testClass() + public function testClass(): void { $class = "HelloWorld"; $exc = new ExceptionInfo($class, "message"); @@ -13,7 +13,7 @@ public function testClass() $this->assertEquals("TestClass", $exc->setClass("TestClass")->getClass()); } - public function testMessage() + public function testMessage(): void { $message = "A message"; $exc = new ExceptionInfo("C", $message); @@ -22,7 +22,7 @@ public function testMessage() $this->assertEquals("Another", $exc->setMessage("Another")->getMessage()); } - public function testDescription() + public function testDescription(): void { $description = "long form"; $exc = new ExceptionInfo("C", "s", $description); diff --git a/tests/FakeDataBuilder.php b/tests/FakeDataBuilder.php index 181b8f30..51d70b5f 100644 --- a/tests/FakeDataBuilder.php +++ b/tests/FakeDataBuilder.php @@ -8,8 +8,8 @@ class FakeDataBuilder implements DataBuilderInterface { - public static $args = array(); - public static $logged = array(); + public static array $args = array(); + public static array $logged = array(); public function __construct($arr) { @@ -23,7 +23,7 @@ public function makeData(string $level, Throwable|string $toLog, array $context) return new Data('test', new Body(new Message('test'))); } - public function setCustom() + public function setCustom(): void { } } diff --git a/tests/FakeLog.php b/tests/FakeLog.php index ef22bd52..d90e49cf 100644 --- a/tests/FakeLog.php +++ b/tests/FakeLog.php @@ -5,7 +5,7 @@ class FakeLog { // log($level, $message) - public function log() + public function log(): void { } } diff --git a/tests/FluentTest.php b/tests/FluentTest.php index 5ca905c0..8438ca35 100644 --- a/tests/FluentTest.php +++ b/tests/FluentTest.php @@ -7,7 +7,7 @@ class FluentTest extends BaseRollbarTest { - public function testFluent() + public function testFluent(): void { if (!class_exists('Fluent\Logger\FluentLogger')) { $this->markTestSkipped( diff --git a/tests/FrameTest.php b/tests/FrameTest.php index 09032d84..f1281b84 100644 --- a/tests/FrameTest.php +++ b/tests/FrameTest.php @@ -1,20 +1,22 @@ exception = m::mock("Rollbar\Payload\ExceptionInfo"); - $this->frame = new Frame("tests/FrameTest.php", $this->exception); + $this->exception = m::mock(ExceptionInfo::class); + $this->frame = new Frame("tests/FrameTest.php"); } - public function testFilename() + public function testFilename(): void { $frame = new Frame("filename.php"); $this->assertEquals("filename.php", $frame->getFilename()); @@ -22,38 +24,38 @@ public function testFilename() $this->assertEquals("other.php", $frame->getFilename()); } - public function testLineno() + public function testLineno(): void { $this->frame->setLineno(5); $this->assertEquals(5, $this->frame->getLineno()); } - public function testColno() + public function testColno(): void { $this->frame->setColno(5); $this->assertEquals(5, $this->frame->getColno()); } - public function testMethod() + public function testMethod(): void { $this->frame->setMethod("method"); $this->assertEquals("method", $this->frame->getMethod()); } - public function testCode() + public function testCode(): void { $this->frame->setCode("code->whatever()"); $this->assertEquals("code->whatever()", $this->frame->getCode()); } - public function testContext() + public function testContext(): void { - $context = m::mock("Rollbar\Payload\Context"); + $context = m::mock(Context::class); $this->frame->setContext($context); $this->assertEquals($context, $this->frame->getContext()); } - public function testArgs() + public function testArgs(): void { $this->frame->setArgs(array()); $this->assertEquals(array(), $this->frame->getArgs()); @@ -62,7 +64,7 @@ public function testArgs() $this->assertEquals(array(1, "hi"), $this->frame->getArgs()); } - public function testEncode() + public function testEncode(): void { $context = m::mock("Rollbar\Payload\Context, Rollbar\SerializerInterface") ->shouldReceive("serialize") diff --git a/tests/Handlers/ErrorHandlerTest.php b/tests/Handlers/ErrorHandlerTest.php index 798df1e4..72535782 100644 --- a/tests/Handlers/ErrorHandlerTest.php +++ b/tests/Handlers/ErrorHandlerTest.php @@ -1,8 +1,9 @@ useErrorHandler to deal with stopping the @@ -19,9 +20,9 @@ public function __construct($name = null, $data = array(), $dataName = null) parent::__construct($name, $data, $dataName); } - private static $simpleConfig = array(); + private static array $simpleConfig = array(); - public function testPreviousErrorHandler() + public function testPreviousErrorHandler(): void { $testCase = $this; @@ -37,9 +38,9 @@ public function testPreviousErrorHandler() @trigger_error(E_USER_ERROR); } - public function testRegister() + public function testRegister(): void { - $handler = $this->getMockBuilder('Rollbar\\Handlers\\ErrorHandler') + $handler = $this->getMockBuilder(ErrorHandler::class) ->setConstructorArgs(array(new RollbarLogger(self::$simpleConfig))) ->setMethods(array('handle')) ->getMock(); @@ -52,9 +53,9 @@ public function testRegister() trigger_error(E_USER_ERROR); } - public function testHandle() + public function testHandle(): void { - $logger = $this->getMockBuilder('Rollbar\\RollbarLogger') + $logger = $this->getMockBuilder(RollbarLogger::class) ->setConstructorArgs(array(self::$simpleConfig)) ->setMethods(array('log')) ->getMock(); diff --git a/tests/Handlers/ExceptionHandlerTest.php b/tests/Handlers/ExceptionHandlerTest.php index e6e1a8fb..29e559c7 100644 --- a/tests/Handlers/ExceptionHandlerTest.php +++ b/tests/Handlers/ExceptionHandlerTest.php @@ -1,9 +1,9 @@ getMockBuilder('Rollbar\\Handlers\\ExceptionHandler') + $handler = $this->getMockBuilder(ExceptionHandler::class) ->setConstructorArgs(array(new RollbarLogger(self::$simpleConfig))) ->setMethods(array('handle')) ->getMock(); @@ -66,12 +66,12 @@ public function testSetup() $handler->$method(); } - public function testHandle() + public function testHandle(): void { set_exception_handler(function () { }); - $logger = $this->getMockBuilder('Rollbar\\RollbarLogger') + $logger = $this->getMockBuilder(RollbarLogger::class) ->setConstructorArgs(array(self::$simpleConfig)) ->setMethods(array('log')) ->getMock(); diff --git a/tests/JsHelperTest.php b/tests/JsHelperTest.php index 6c421689..ff48b057 100644 --- a/tests/JsHelperTest.php +++ b/tests/JsHelperTest.php @@ -2,8 +2,8 @@ class JsHelperTest extends BaseRollbarTest { - protected $jsHelper; - protected $testSnippetPath; + protected RollbarJsHelper $jsHelper; + protected string|false $testSnippetPath; public function setUp(): void { @@ -11,7 +11,7 @@ public function setUp(): void $this->testSnippetPath = realpath(__DIR__ . "/../data/rollbar.snippet.js"); } - public function testSnippetPath() + public function testSnippetPath(): void { $this->assertEquals( $this->testSnippetPath, @@ -22,9 +22,9 @@ public function testSnippetPath() /** * @dataProvider shouldAddJsProvider */ - public function testShouldAddJs($setup, $expected) + public function testShouldAddJs($setup, $expected): void { - $mock = \Mockery::mock('Rollbar\RollbarJsHelper'); + $mock = \Mockery::mock(\Rollbar\RollbarJsHelper::class); $status = $setup['status']; @@ -40,7 +40,7 @@ public function testShouldAddJs($setup, $expected) $this->assertEquals($expected, $mock->shouldAddJs($status, array())); } - public function shouldAddJsProvider() + public function shouldAddJsProvider(): array { return array( array( @@ -81,7 +81,7 @@ public function shouldAddJsProvider() /** * @dataProvider isHtmlProvider */ - public function testIsHtml($headers, $expected) + public function testIsHtml($headers, $expected): void { $this->assertEquals( $expected, @@ -89,7 +89,7 @@ public function testIsHtml($headers, $expected) ); } - public function isHtmlProvider() + public function isHtmlProvider(): array { return array( array( @@ -110,7 +110,7 @@ public function isHtmlProvider() /** * @dataProvider hasAttachmentProvider */ - public function testHasAttachment($headers, $expected) + public function testHasAttachment($headers, $expected): void { $this->assertEquals( $expected, @@ -118,7 +118,7 @@ public function testHasAttachment($headers, $expected) ); } - public function hasAttachmentProvider() + public function hasAttachmentProvider(): array { return array( array( @@ -135,7 +135,7 @@ public function hasAttachmentProvider() ); } - public function testJsSnippet() + public function testJsSnippet(): void { $expected = file_get_contents($this->testSnippetPath); @@ -145,7 +145,7 @@ public function testJsSnippet() /** * @dataProvider shouldAppendNonceProvider */ - public function testShouldAppendNonce($headers, $expected) + public function testShouldAppendNonce($headers, $expected): void { $this->assertEquals( $expected, @@ -153,7 +153,7 @@ public function testShouldAppendNonce($headers, $expected) ); } - public function shouldAppendNonceProvider() + public function shouldAppendNonceProvider(): array { return array( array( @@ -180,7 +180,7 @@ public function shouldAppendNonceProvider() /** * @dataProvider scriptTagProvider */ - public function testScriptTag($content, $headers, $nonce, $expected) + public function testScriptTag($content, $headers, $nonce, $expected): void { if ($expected === 'Exception') { try { @@ -198,7 +198,7 @@ public function testScriptTag($content, $headers, $nonce, $expected) } } - public function scriptTagProvider() + public function scriptTagProvider(): array { return array( 'nonce script' => array( @@ -226,7 +226,7 @@ public function scriptTagProvider() ); } - public function testConfigJsTag() + public function testConfigJsTag(): void { $config = array( 'config1' => 'value 1' @@ -244,7 +244,7 @@ public function testConfigJsTag() /** * @dataProvider addJsProvider */ - public function testBuildJs($config, $headers, $nonce, $expected) + public function testBuildJs($config, $headers, $nonce, $expected): void { $result = RollbarJsHelper::buildJs( $config, @@ -259,7 +259,7 @@ public function testBuildJs($config, $headers, $nonce, $expected) /** * @dataProvider addJsProvider */ - public function testAddJs($config, $headers, $nonce, $expected) + public function testAddJs($config, $headers, $nonce, $expected): void { $helper = new RollbarJsHelper($config); @@ -272,7 +272,7 @@ public function testAddJs($config, $headers, $nonce, $expected) $this->assertEquals($expected, $result); } - public function addJsProvider() + public function addJsProvider(): array { $this->setUp(); $expectedJs = file_get_contents($this->testSnippetPath); diff --git a/tests/LevelFactoryTest.php b/tests/LevelFactoryTest.php index d8fff42f..cc8a2373 100644 --- a/tests/LevelFactoryTest.php +++ b/tests/LevelFactoryTest.php @@ -4,7 +4,7 @@ class LevelFactoryTest extends BaseRollbarTest { - private $levelFactory; + private LevelFactory $levelFactory; public function setUp(): void { @@ -14,7 +14,7 @@ public function setUp(): void /** * @dataProvider isValidLevelProvider */ - public function testIsValidLevelProvider($level, $expected) + public function testIsValidLevelProvider($level, $expected): void { $this->assertEquals( $expected, @@ -22,7 +22,7 @@ public function testIsValidLevelProvider($level, $expected) ); } - public function isValidLevelProvider() + public function isValidLevelProvider(): array { $data = $this->fromNameProvider(); foreach ($data as &$testParams) { @@ -35,15 +35,15 @@ public function isValidLevelProvider() /** * @dataProvider fromNameProvider */ - public function testFromName($level) + public function testFromName($level): void { $this->assertInstanceOf( - 'Rollbar\Payload\Level', + Level::class, $this->levelFactory->fromName($level) ); } - public function fromNameProvider() + public function fromNameProvider(): array { return array( array(Level::EMERGENCY), diff --git a/tests/LevelTest.php b/tests/LevelTest.php index a97b2d8a..c43a516a 100644 --- a/tests/LevelTest.php +++ b/tests/LevelTest.php @@ -1,17 +1,17 @@ expectException(\Exception::class); $level = Level::TEST(); } - public function testLevel() + public function testLevel(): void { $level = Level::CRITICAL(); $this->assertNotNull($level); diff --git a/tests/MessageTest.php b/tests/MessageTest.php index 902904ec..8a5c5e26 100644 --- a/tests/MessageTest.php +++ b/tests/MessageTest.php @@ -4,14 +4,14 @@ class MessageTest extends Rollbar\BaseRollbarTest { - public function testBacktrace() + public function testBacktrace(): void { $expected = array('trace 1' => 'value 1'); $msg = new Message("Test", $expected); $this->assertEquals($expected, $msg->getBacktrace()); } - public function testBody() + public function testBody(): void { $msg = new Message("Test"); $this->assertEquals("Test", $msg->getBody()); @@ -19,7 +19,7 @@ public function testBody() $this->assertEquals("Test2", $msg->setBody("Test2")->getBody()); } - public function testMessageKey() + public function testMessageKey(): void { $msg = new Message("Test"); $this->assertEquals("message", $msg->getKey()); diff --git a/tests/NotifierTest.php b/tests/NotifierTest.php index da273bf3..fd3ed455 100644 --- a/tests/NotifierTest.php +++ b/tests/NotifierTest.php @@ -1,11 +1,11 @@ assertEquals($name2, $notifier->setName($name2)->getName()); } - public function testVersion() + public function testVersion(): void { $version = Notifier::VERSION; $notifier = new Notifier("PHP-Rollbar", $version); @@ -25,7 +25,7 @@ public function testVersion() $this->assertEquals($version2, $notifier->setVersion($version2)->getVersion()); } - public function testDefaultNotifierIsRepresentableAsJson() + public function testDefaultNotifierIsRepresentableAsJson(): void { $notifier = Notifier::defaultNotifier()->serialize(); $encoding = json_encode($notifier, flags: JSON_THROW_ON_ERROR|JSON_FORCE_OBJECT); @@ -34,7 +34,7 @@ public function testDefaultNotifierIsRepresentableAsJson() $this->assertObjectHasAttribute('version', $decoding); } - public function testDefaultNotifierVersionIsSemVerCompliant() + public function testDefaultNotifierVersionIsSemVerCompliant(): void { // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string $semVerRegex = '/ diff --git a/tests/Payload/EncodedPayloadTest.php b/tests/Payload/EncodedPayloadTest.php index ea1da1bb..e1fcaeac 100644 --- a/tests/Payload/EncodedPayloadTest.php +++ b/tests/Payload/EncodedPayloadTest.php @@ -2,7 +2,7 @@ class EncodedPayloadTest extends \Rollbar\BaseRollbarTest { - public function testEncode() + public function testEncode(): void { $expected = '{"foo":"bar"}'; @@ -24,7 +24,7 @@ public function testEncode() /** * @requires PHP 5.5 */ - public function testEncodeMalformedData() + public function testEncodeMalformedData(): void { $encoded = new EncodedPayload(array( 'data' => array( diff --git a/tests/PayloadTest.php b/tests/PayloadTest.php index 4e280d01..6393ee69 100644 --- a/tests/PayloadTest.php +++ b/tests/PayloadTest.php @@ -1,15 +1,18 @@ shouldReceive('getAccessToken') ->andReturn('012345678901234567890123456789ab') ->mock(); @@ -18,15 +21,15 @@ public function testPayloadData() $this->assertEquals($data, $payload->getData()); - $data2 = m::mock("Rollbar\Payload\Data"); + $data2 = m::mock(Data::class); $this->assertEquals($data2, $payload->setData($data2)->getData()); } - public function testPayloadAccessToken() + public function testPayloadAccessToken(): void { $accessToken = "012345678901234567890123456789ab"; - $data = m::mock("Rollbar\Payload\Data"); - $config = m::mock("Rollbar\Config") + $data = m::mock(Data::class); + $config = m::mock(Config::class) ->shouldReceive('getAccessToken') ->andReturn($accessToken) ->mock(); @@ -35,7 +38,7 @@ public function testPayloadAccessToken() $this->assertEquals($accessToken, $payload->getAccessToken()); $accessToken = "012345678901234567890123456789ab"; - $config = m::mock("Rollbar\Config") + $config = m::mock(Config::class) ->shouldReceive('getAccessToken') ->andReturn($accessToken) ->mock(); @@ -46,14 +49,14 @@ public function testPayloadAccessToken() $this->assertEquals($at2, $payload->setAccessToken($at2)->getAccessToken()); } - public function testEncode() + public function testEncode(): void { $accessToken = $this->getTestAccessToken(); $data = m::mock('Rollbar\Payload\Data, Rollbar\SerializerInterface') ->shouldReceive('serialize') ->andReturn(new \ArrayObject()) ->mock(); - m::mock('Rollbar\DataBuilder') + m::mock(DataBuilder::class) ->shouldReceive('getScrubFields') ->andReturn(array()) ->shouldReceive('scrub') diff --git a/tests/Performance/MassivePayload.php b/tests/Performance/MassivePayload.php index 7d97e7a6..5bf5ef34 100644 --- a/tests/Performance/MassivePayload.php +++ b/tests/Performance/MassivePayload.php @@ -2,10 +2,10 @@ namespace Rollbar\Performance; -use \Rollbar\Truncation\StringsStrategyTest; -use \Rollbar\Truncation\FramesStrategyTest; +use Rollbar\Truncation\StringsStrategyTest; +use Rollbar\Truncation\FramesStrategyTest; -use \Rollbar\Truncation\StringsStrategy; +use Rollbar\Truncation\StringsStrategy; class MassivePayload { diff --git a/tests/Performance/TestHelpers/EncodedPayload.php b/tests/Performance/TestHelpers/EncodedPayload.php index 853542e1..f5987b53 100644 --- a/tests/Performance/TestHelpers/EncodedPayload.php +++ b/tests/Performance/TestHelpers/EncodedPayload.php @@ -2,7 +2,7 @@ class EncodedPayload extends \Rollbar\Payload\EncodedPayload { - protected static $encodingCount = 0; + protected static int $encodingCount = 0; public function encode(?array $data = null): void { @@ -10,12 +10,12 @@ public function encode(?array $data = null): void self::$encodingCount++; } - public static function getEncodingCount() + public static function getEncodingCount(): int { return self::$encodingCount; } - public static function resetEncodingCount() + public static function resetEncodingCount(): void { self::$encodingCount = 0; } diff --git a/tests/Performance/TestHelpers/Truncation.php b/tests/Performance/TestHelpers/Truncation.php index 76a01106..6f91e6e5 100644 --- a/tests/Performance/TestHelpers/Truncation.php +++ b/tests/Performance/TestHelpers/Truncation.php @@ -5,10 +5,10 @@ class Truncation extends \Rollbar\Truncation\Truncation protected $memoryUsage = 0; protected $timeUsage = 0; protected $payloadSize = 0; - protected $lastRunOutput = ""; - protected $strategiesUsed = array(); + protected string $lastRunOutput = ""; + protected array $strategiesUsed = array(); - public function truncate(\Rollbar\Payload\EncodedPayload $payload) + public function truncate(\Rollbar\Payload\EncodedPayload $payload): \Rollbar\Payload\EncodedPayload { $this->strategiesUsed = array(); @@ -33,7 +33,7 @@ public function truncate(\Rollbar\Payload\EncodedPayload $payload) return $result; } - public function needsTruncating(\Rollbar\Payload\EncodedPayload $payload, $strategy) + public function needsTruncating(\Rollbar\Payload\EncodedPayload $payload, $strategy): bool { $result = parent::needsTruncating($payload, $strategy); @@ -44,12 +44,12 @@ public function needsTruncating(\Rollbar\Payload\EncodedPayload $payload, $strat return $result; } - public function getLastRun() + public function getLastRun(): string { return $this->lastRunOutput; } - public function composeLastRunOutput() + public function composeLastRunOutput(): string { $output = "\n"; @@ -58,7 +58,7 @@ public function composeLastRunOutput() round($this->payloadSize / 1024 / 1024, 2) . " MB \n"; $output .= "Strategies used: \n" . - (count($this->strategiesUsed) ? join(", \n", $this->strategiesUsed) : "none") . "\n"; + (count($this->strategiesUsed) ? implode(", \n", $this->strategiesUsed) : "none") . "\n"; $output .= "Encoding triggered: " . \Rollbar\Performance\TestHelpers\EncodedPayload::getEncodingCount() . "\n"; diff --git a/tests/Performance/TruncationTest.php b/tests/Performance/TruncationTest.php index 7c5b6ff7..28cc1d6d 100644 --- a/tests/Performance/TruncationTest.php +++ b/tests/Performance/TruncationTest.php @@ -2,16 +2,16 @@ namespace Rollbar\Performance; -use \Rollbar\Performance\MassivePayload; -use \Rollbar\Performance\TestHelpers\Truncation; -use \Rollbar\Performance\TestHelpers\EncodedPayload; +use Rollbar\Performance\MassivePayload; +use Rollbar\Performance\TestHelpers\Truncation; +use Rollbar\Performance\TestHelpers\EncodedPayload; -use \Rollbar\Truncation\StringsStrategyTest; -use \Rollbar\Truncation\FramesStrategyTest; -use \Rollbar\Truncation\MinBodyStrategyTest; +use Rollbar\Truncation\StringsStrategyTest; +use Rollbar\Truncation\FramesStrategyTest; +use Rollbar\Truncation\MinBodyStrategyTest; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; class TruncationTest extends BaseRollbarTest { @@ -176,7 +176,7 @@ public function setUp(): void /** * @dataProvider truncateProvider */ - public function testTruncate($dataName, $data, array $assertions = array()) + public function testTruncate($dataName, $data, array $assertions = array()): void { $payload = new EncodedPayload($data); $payload->encode(); @@ -193,7 +193,7 @@ public function testTruncate($dataName, $data, array $assertions = array()) } } - public function truncateProvider() + public function truncateProvider(): array { $stringsTest = new StringsStrategyTest(); $framesTest = new FramesStrategyTest(); diff --git a/tests/PersonTest.php b/tests/PersonTest.php index ddd5c50e..98078bd3 100644 --- a/tests/PersonTest.php +++ b/tests/PersonTest.php @@ -1,11 +1,11 @@ assertEquals($id2, $person->setId($id2)->getId()); } - public function testUsername() + public function testUsername(): void { $username = "user@rollbar.com"; $person = new Person("15", $username); @@ -25,7 +25,7 @@ public function testUsername() $this->assertEquals($username2, $person->setUsername($username2)->getUsername()); } - public function testEmail() + public function testEmail(): void { $email = "1.0.0"; $person = new Person("Rollbar_Master", null, $email); @@ -35,14 +35,14 @@ public function testEmail() $this->assertEquals($email2, $person->setEmail($email2)->getEmail()); } - public function testExtra() + public function testExtra(): void { $person = new Person("42"); $person->test = "testing"; $this->assertEquals("testing", $person->test); } - public function testEncode() + public function testEncode(): void { $person = new Person("1024"); $person->setUsername("username") diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php index 405b7286..958162bb 100644 --- a/tests/ReadmeTest.php +++ b/tests/ReadmeTest.php @@ -13,7 +13,7 @@ function do_something() class ReadmeTest extends BaseRollbarTest { - public function testQuickStart() + public function testQuickStart(): void { // installs global error and exception handlers Rollbar::init( @@ -53,7 +53,7 @@ public function testQuickStart() throw new \Exception('testing exception handler'); } - public function testSetup1() + public function testSetup1(): void { $config = array( // required @@ -68,7 +68,7 @@ public function testSetup1() $this->assertTrue(true); } - public function testSetup2() + public function testSetup2(): void { $config = array( // required @@ -86,7 +86,7 @@ public function testSetup2() $this->assertTrue(true); } - public function testBasicUsage() + public function testBasicUsage(): void { Rollbar::init( array( @@ -107,7 +107,7 @@ public function testBasicUsage() $this->assertEquals(200, $result2->getStatus()); } - public function testBasicUsage2() + public function testBasicUsage2(): void { Rollbar::init( array( diff --git a/tests/RequestTest.php b/tests/RequestTest.php index c79ebdb7..e370b988 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -1,11 +1,11 @@ assertEquals($url2, $request->setUrl($url2)->getUrl()); } - public function testMethod() + public function testMethod(): void { $method = "POST"; $request = new Request(); @@ -27,7 +27,7 @@ public function testMethod() $this->assertEquals($method2, $request->setMethod($method2)->getMethod()); } - public function testHeaders() + public function testHeaders(): void { $headers = array("Auth-X" => "abc352", "Hello" => "World"); $request = new Request(); @@ -38,7 +38,7 @@ public function testHeaders() $this->assertEquals($headers2, $request->setHeaders($headers2)->getHeaders()); } - public function testParams() + public function testParams(): void { $params = array( "controller" => "project", @@ -52,7 +52,7 @@ public function testParams() $this->assertEquals($params2, $request->setParams($params2)->getParams()); } - public function testGet() + public function testGet(): void { $get = array("query" => "where's waldo?", "page" => 15); $request = new Request(); @@ -63,7 +63,7 @@ public function testGet() $this->assertEquals($get2, $request->setGet($get2)->getGet()); } - public function testQueryString() + public function testQueryString(): void { $queryString = "?slug=Rollbar&update=true"; $request = new Request(); @@ -75,7 +75,7 @@ public function testQueryString() $this->assertEquals($queryString2, $actual); } - public function testPost() + public function testPost(): void { $post = array("Big" => "Data"); $request = new Request(); @@ -91,7 +91,7 @@ public function testPost() $this->assertEquals($post2, $request->setPost($post2)->getPost()); } - public function testBody() + public function testBody(): void { $body = "a long string\nwith new lines and stuff"; $request = new Request(); @@ -102,7 +102,7 @@ public function testBody() $this->assertEquals($body2, $request->setBody($body2)->getBody()); } - public function testUserIp() + public function testUserIp(): void { $userIp = "192.0.1.12"; $request = new Request(); @@ -113,7 +113,7 @@ public function testUserIp() $this->assertEquals($userIp2, $request->setUserIp($userIp2)->getUserIp()); } - public function testExtra() + public function testExtra(): void { $request = new Request(); $request->setExtras(array("test" => "testing")); @@ -121,7 +121,7 @@ public function testExtra() $this->assertEquals("testing", $extras["test"]); } - public function testEncode() + public function testEncode(): void { $request = new Request(); $request->setUrl("www.rollbar.com/account/project") diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php index c8da2fb2..43654575 100644 --- a/tests/ResponseTest.php +++ b/tests/ResponseTest.php @@ -4,25 +4,25 @@ class ResponseTest extends BaseRollbarTest { - public function testStatus() + public function testStatus(): void { $r = new Response(200, array("whatever"=>5)); $this->assertEquals(200, $r->getStatus()); } - public function testInfo() + public function testInfo(): void { $r = new Response(200, "FAKE INFO"); $this->assertEquals("FAKE INFO", $r->getInfo()); } - public function testUuid() + public function testUuid(): void { $r = new Response(200, "FAKE INFO", "abc123"); $this->assertEquals("abc123", $r->getUuid()); } - public function testWasSuccessful() + public function testWasSuccessful(): void { $response = new Response(200, null); $this->assertTrue($response->wasSuccessful()); @@ -36,7 +36,7 @@ public function testWasSuccessful() * @testWith ["abc123", "https://rollbar.com/occurrence/uuid/?uuid=abc123"] * ["a bar", "https://rollbar.com/occurrence/uuid/?uuid=a+bar"] */ - public function testUrl(string $uuid, string $expectedOccurrenceUrl) + public function testUrl(string $uuid, string $expectedOccurrenceUrl): void { $response = new Response(200, "fake", $uuid); $this->assertEquals($expectedOccurrenceUrl, $response->getOccurrenceUrl()); diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index aa86ba20..2d3b7cc8 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -7,6 +7,11 @@ use Rollbar\Payload\Payload; use Rollbar\TestHelpers\Exceptions\SilentExceptionSampleRate; use StdClass; +use Rollbar\Payload\EncodedPayload; +use Rollbar\Senders\SenderInterface; +use Rollbar\TestHelpers\MalformedPayloadDataTransformer; +use Monolog\Handler\ErrorLogHandler; +use Psr\Log\LoggerInterface; class RollbarLoggerTest extends BaseRollbarTest { @@ -23,7 +28,7 @@ public function tearDown(): void parent::tearDown(); } - public function testAddCustom() + public function testAddCustom(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -65,7 +70,7 @@ public function testAddCustom() $this->assertEquals("bar", $customData["foo"]); } - public function testRemoveCustom() + public function testRemoveCustom(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -91,7 +96,7 @@ public function testRemoveCustom() $this->assertEquals("xyz", $customData["bar"]); } - public function testGetCustom() + public function testGetCustom(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -108,7 +113,7 @@ public function testGetCustom() $this->assertEquals("xyz", $custom["bar"]); } - public function testConfigure() + public function testConfigure(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -119,7 +124,7 @@ public function testConfigure() $this->assertEquals(15, $extended['extraData']); } - public function testLog() + public function testLog(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -129,9 +134,9 @@ public function testLog() $this->assertEquals(200, $response->getStatus()); } - public function testNotLoggingPayload() + public function testNotLoggingPayload(): void { - $logPayloadLoggerMock = $this->getMockBuilder('\Psr\Log\LoggerInterface')->getMock(); + $logPayloadLoggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock(); $logPayloadLoggerMock->expects($this->never())->method('debug'); $logger = new RollbarLogger(array( @@ -145,12 +150,12 @@ public function testNotLoggingPayload() $this->assertEquals(200, $response->getStatus()); } - public function testDefaultVerbose() + public function testDefaultVerbose(): void { - return $this->testNotVerbose(); + $this->testNotVerbose(); } - public function testNotVerbose() + public function testNotVerbose(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -162,7 +167,7 @@ public function testNotVerbose() $originalHandler = $verboseLogger->getHandlers(); $originalHandler = $originalHandler[0]; - $handlerMock = $this->getMockBuilder('\Monolog\Handler\ErrorLogHandler') + $handlerMock = $this->getMockBuilder(ErrorLogHandler::class) ->setMethods(array('handle')) ->getMock(); @@ -175,7 +180,7 @@ public function testNotVerbose() $logger->info('Internal message'); } - public function testVerbose() + public function testVerbose(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -187,7 +192,7 @@ public function testVerbose() $originalHandler = $verboseLogger->getHandlers(); $originalHandler = $originalHandler[0]; - $handlerMock = $this->getMockBuilder('\Monolog\Handler\ErrorLogHandler') + $handlerMock = $this->getMockBuilder(ErrorLogHandler::class) ->setMethods(array('handle')) ->getMock(); $handlerMock->setLevel($originalHandler->getLevel()); @@ -199,7 +204,7 @@ public function testVerbose() $logger->info('Internal message'); } - public function testEnabled() + public function testEnabled(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -219,7 +224,7 @@ public function testEnabled() $this->assertEquals("Disabled", $response->getInfo()); } - public function testTransmit() + public function testTransmit(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -238,9 +243,9 @@ public function testTransmit() $this->assertEquals("Not transmitting (transmitting disabled in configuration)", $response->getInfo()); } - public function testTransmitBatched() + public function testTransmitBatched(): void { - $senderMock = $this->getMockBuilder('Rollbar\Senders\SenderInterface')->getMock(); + $senderMock = $this->getMockBuilder(SenderInterface::class)->getMock(); $senderMock->expects($this->once())->method('sendBatch'); // transmit on (default) @@ -256,7 +261,7 @@ public function testTransmitBatched() $logger->flush(); // transmit off - $senderMock = $this->getMockBuilder('Rollbar\Senders\SenderInterface')->getMock(); + $senderMock = $this->getMockBuilder(SenderInterface::class)->getMock(); $senderMock->expects($this->never())->method('sendBatch'); $logger->configure(array( @@ -272,12 +277,12 @@ public function testTransmitBatched() $this->assertEquals("Not transmitting (transmitting disabled in configuration)", $response->getInfo()); } - public function testLogMalformedPayloadData() + public function testLogMalformedPayloadData(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), "environment" => "testing-php", - "transformer" => '\Rollbar\TestHelpers\MalformedPayloadDataTransformer' + "transformer" => MalformedPayloadDataTransformer::class )); $response = $logger->log( @@ -289,11 +294,11 @@ public function testLogMalformedPayloadData() $this->assertEquals(400, $response->getStatus()); } - public function testFlush() + public function testFlush(): void { - $senderMock = $this->getMockBuilder('Rollbar\Senders\SenderInterface')->getMock(); + $senderMock = $this->getMockBuilder(SenderInterface::class)->getMock(); $senderMock->expects($this->once())->method('sendBatch')->with( - $this->containsOnlyInstancesOf('Rollbar\Payload\EncodedPayload'), + $this->containsOnlyInstancesOf(EncodedPayload::class), $this->anything() ); @@ -315,7 +320,7 @@ public function testFlush() $response = $logger->flush(); } - public function testContext() + public function testContext(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -331,7 +336,7 @@ public function testContext() $this->assertEquals(200, $response->getStatus()); } - public function testLogStaticLevel() + public function testLogStaticLevel(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -341,7 +346,7 @@ public function testLogStaticLevel() $this->assertEquals(200, $response->getStatus()); } - public function testErrorSampleRates() + public function testErrorSampleRates(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -365,13 +370,13 @@ public function testErrorSampleRates() $this->assertEquals(0, $response->getStatus()); } - public function testExceptionSampleRates() + public function testExceptionSampleRates(): void { $l = new RollbarLogger(array( "access_token" => "ad865e76e7fb496fab096ac07b1dbabb", "environment" => "testing-php", "exception_sample_rates" => array( - 'Rollbar\TestHelpers\Exceptions\SilentExceptionSampleRate' => 0.0 + SilentExceptionSampleRate::class => 0.0 ) )); $response = $l->log(Level::ERROR, new SilentExceptionSampleRate); @@ -383,7 +388,7 @@ public function testExceptionSampleRates() $this->assertEquals(200, $response->getStatus()); } - public function testIncludedErrNo() + public function testIncludedErrNo(): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -437,12 +442,13 @@ private function scrubTestHelper($config = array(), $context = array()) * @param string $replacement Character used for scrubbing */ private function scrubTestAssert( - $dataName, - $result, - $scrubField = 'sensitive', - $recursive = true, - $replacement = '*' - ) { + string $dataName, + array $result, + string $scrubField = 'sensitive', + bool $recursive = true, + string $replacement = '*' + ): void + { $this->assertEquals( str_repeat($replacement, 8), @@ -459,7 +465,7 @@ private function scrubTestAssert( } } - public function scrubDataProvider() + public function scrubDataProvider(): array { return array( array( // test 1 @@ -478,7 +484,7 @@ public function scrubDataProvider() /** * @dataProvider scrubDataProvider */ - public function testScrubGET($testData) + public function testScrubGET($testData): void { $_GET = $testData; $result = $this->scrubTestHelper(); @@ -489,7 +495,7 @@ public function testScrubGET($testData) /** * @dataProvider scrubDataProvider */ - public function testGetRequestScrubPOST($testData) + public function testGetRequestScrubPOST($testData): void { $_POST = $testData; $result = $this->scrubTestHelper(); @@ -499,14 +505,14 @@ public function testGetRequestScrubPOST($testData) /** * @dataProvider scrubDataProvider */ - public function testGetRequestScrubSession($testData) + public function testGetRequestScrubSession($testData): void { $_SESSION = $testData; $result = $this->scrubTestHelper(); $this->scrubTestAssert('$_SESSION', $result['data']['request']['session']); } - public function testGetScrubbedHeaders() + public function testGetScrubbedHeaders(): void { $_SERVER['HTTP_CONTENT_TYPE'] = 'text/html; charset=utf-8'; $_SERVER['HTTP_SENSITIVE'] = 'Scrub this'; @@ -525,7 +531,7 @@ public function testGetScrubbedHeaders() /** * @dataProvider scrubDataProvider */ - public function testGetRequestScrubExtras($testData) + public function testGetRequestScrubExtras($testData): void { $extras = array( 'extraField1' => $testData @@ -542,7 +548,7 @@ public function testGetRequestScrubExtras($testData) /** * @dataProvider scrubDataProvider */ - public function testMakeDataScrubServerExtras($testData) + public function testMakeDataScrubServerExtras($testData): void { $extras = array( 'extraField1' => $testData @@ -559,7 +565,7 @@ public function testMakeDataScrubServerExtras($testData) /** * @dataProvider scrubDataProvider */ - public function testMakeDataScrubCustom($testData) + public function testMakeDataScrubCustom($testData): void { $custom = $testData; $result = $this->scrubTestHelper(array('custom' => $custom)); @@ -573,7 +579,7 @@ public function testMakeDataScrubCustom($testData) /** * @dataProvider scrubDataProvider */ - public function testMakeDataScrubPerson($testData) + public function testMakeDataScrubPerson($testData): void { $testData['id'] = '123'; $result = $this->scrubTestHelper( @@ -601,7 +607,7 @@ public function testMakeDataScrubPerson($testData) /** * @dataProvider scrubDataProvider */ - public function testGetRequestScrubBodyContext($testData) + public function testGetRequestScrubBodyContext($testData): void { $bodyContext = array( 'context1' => $testData @@ -618,7 +624,7 @@ public function testGetRequestScrubBodyContext($testData) ); } - public function scrubQueryStringDataProvider() + public function scrubQueryStringDataProvider(): array { $data = $this->scrubDataProvider(); @@ -632,7 +638,7 @@ public function scrubQueryStringDataProvider() /** * @dataProvider scrubQueryStringDataProvider */ - public function testGetUrlScrub($testData) + public function testGetUrlScrub($testData): void { $_SERVER['SERVER_NAME'] = 'localhost'; $_SERVER['REQUEST_URI'] = "/index.php?$testData"; @@ -653,7 +659,7 @@ public function testGetUrlScrub($testData) /** * @dataProvider scrubQueryStringDataProvider */ - public function testGetRequestScrubQueryString($testData) + public function testGetRequestScrubQueryString($testData): void { $_SERVER['QUERY_STRING'] = "?$testData"; @@ -680,7 +686,7 @@ public function testGetRequestScrubQueryString($testData) * ["info"] * ["debug"] */ - public function testPsr3MethodCallsDoNotCrash($method) + public function testPsr3MethodCallsDoNotCrash($method): void { $l = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -695,7 +701,7 @@ public function testPsr3MethodCallsDoNotCrash($method) /** * @dataProvider maxItemsProvider */ - public function testMaxItems($maxItemsConfig) + public function testMaxItems($maxItemsConfig): void { $config = array('access_token' => $this->getTestAccessToken()); if ($maxItemsConfig !== null) { @@ -705,7 +711,7 @@ public function testMaxItems($maxItemsConfig) Rollbar::init($config); $logger = Rollbar::logger(); - $maxItems = $maxItemsConfig === null ? Defaults::get()->maxItems() : $maxItemsConfig; + $maxItems = $maxItemsConfig ?? Defaults::get()->maxItems(); for ($i = 0; $i < $maxItems; $i++) { $response = $logger->log(Level::INFO, 'testing info level'); @@ -723,7 +729,7 @@ public function testMaxItems($maxItemsConfig) ); } - public function maxItemsProvider() + public function maxItemsProvider(): array { return array( 'use default max_items' => array(null), @@ -731,7 +737,7 @@ public function maxItemsProvider() ); } - public function testRaiseOnError() + public function testRaiseOnError(): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -750,7 +756,7 @@ public function testRaiseOnError() /** * @dataProvider providesToLogEntityForUncaughtCheck */ - public function testIsUncaughtLogData(mixed $toLog, bool $expected, string $message) + public function testIsUncaughtLogData(mixed $toLog, bool $expected, string $message): void { $logger = new RollbarLogger(array( "access_token" => $this->getTestAccessToken(), @@ -761,7 +767,7 @@ public function testIsUncaughtLogData(mixed $toLog, bool $expected, string $mess $this->assertSame($logger->isUncaughtLogData($toLog), $expected, $message); } - public static function providesToLogEntityForUncaughtCheck() + public static function providesToLogEntityForUncaughtCheck(): array { $uncaught = new Exception; $uncaught->isUncaught = true; diff --git a/tests/RollbarTest.php b/tests/RollbarTest.php index 7fa389b6..7a7cdc20 100644 --- a/tests/RollbarTest.php +++ b/tests/RollbarTest.php @@ -3,6 +3,7 @@ use Rollbar\Rollbar; use Rollbar\Payload\Payload; use Rollbar\Payload\Level; +use Rollbar\RollbarLogger; /** * Usage of static method Rollbar::logger() is intended here. @@ -18,53 +19,53 @@ public function setUp(): void self::$simpleConfig['environment'] = 'test'; } - private static $simpleConfig = array(); + private static string|array $simpleConfig = array(); public static function setUpBeforeClass(): void { Rollbar::destroy(); } - public function testInitWithConfig() + public function testInitWithConfig(): void { Rollbar::init(self::$simpleConfig); - $this->assertInstanceOf('Rollbar\RollbarLogger', Rollbar::logger()); + $this->assertInstanceOf(RollbarLogger::class, Rollbar::logger()); $this->assertEquals(new Config(self::$simpleConfig), Rollbar::logger()->getConfig()); } - public function testInitWithLogger() + public function testInitWithLogger(): void { - $logger = $this->getMockBuilder('Rollbar\RollbarLogger')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder(RollbarLogger::class)->disableOriginalConstructor()->getMock(); Rollbar::init($logger); $this->assertSame($logger, Rollbar::logger()); } - public function testInitConfigureLogger() + public function testInitConfigureLogger(): void { - $logger = $this->getMockBuilder('Rollbar\RollbarLogger')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder(RollbarLogger::class)->disableOriginalConstructor()->getMock(); $logger->expects($this->once())->method('configure')->with(self::$simpleConfig); Rollbar::init($logger); Rollbar::init(self::$simpleConfig); } - public function testInitReplaceLogger() + public function testInitReplaceLogger(): void { Rollbar::init(self::$simpleConfig); - $this->assertInstanceOf('Rollbar\RollbarLogger', Rollbar::logger()); + $this->assertInstanceOf(RollbarLogger::class, Rollbar::logger()); - $logger = $this->getMockBuilder('Rollbar\RollbarLogger')->disableOriginalConstructor()->getMock(); + $logger = $this->getMockBuilder(RollbarLogger::class)->disableOriginalConstructor()->getMock(); Rollbar::init($logger); $this->assertSame($logger, Rollbar::logger()); } - public function testLogException() + public function testLogException(): void { Rollbar::init(self::$simpleConfig); @@ -77,7 +78,7 @@ public function testLogException() $this->assertTrue(true); } - public function testLogMessage() + public function testLogMessage(): void { Rollbar::init(self::$simpleConfig); @@ -86,7 +87,7 @@ public function testLogMessage() $this->assertTrue(true); } - public function testLogExtraData() + public function testLogExtraData(): void { Rollbar::init(self::$simpleConfig); @@ -113,47 +114,47 @@ public function testLogExtraData() ); } - public function testDebug() + public function testDebug(): void { $this->shortcutMethodTestHelper(Level::DEBUG); } - public function testInfo() + public function testInfo(): void { $this->shortcutMethodTestHelper(Level::INFO); } - public function testNotice() + public function testNotice(): void { $this->shortcutMethodTestHelper(Level::NOTICE); } - public function testWarning() + public function testWarning(): void { $this->shortcutMethodTestHelper(Level::WARNING); } - public function testError() + public function testError(): void { $this->shortcutMethodTestHelper(Level::ERROR); } - public function testCritical() + public function testCritical(): void { $this->shortcutMethodTestHelper(Level::CRITICAL); } - public function testAlert() + public function testAlert(): void { $this->shortcutMethodTestHelper(Level::ALERT); } - public function testEmergency() + public function testEmergency(): void { $this->shortcutMethodTestHelper(Level::EMERGENCY); } - protected function shortcutMethodTestHelper($level) + protected function shortcutMethodTestHelper($level): void { $message = "shortcutMethodTestHelper: $level"; @@ -166,7 +167,7 @@ protected function shortcutMethodTestHelper($level) /** * Below are backwards compatibility tests with v0.18.2 */ - public function testBackwardsSimpleMessageVer() + public function testBackwardsSimpleMessageVer(): void { Rollbar::init(self::$simpleConfig); @@ -174,7 +175,7 @@ public function testBackwardsSimpleMessageVer() $this->assertStringMatchesFormat('%x-%x-%x-%x-%x', $uuid); } - public function testBackwardsSimpleError() + public function testBackwardsSimpleError(): void { set_error_handler(function () { }); // disable PHPUnit's error handler @@ -186,7 +187,7 @@ public function testBackwardsSimpleError() $this->assertFalse($result); } - public function testBackwardsSimpleException() + public function testBackwardsSimpleException(): void { Rollbar::init(self::$simpleConfig); @@ -200,7 +201,7 @@ public function testBackwardsSimpleException() $this->assertStringMatchesFormat('%x-%x-%x-%x-%x', $uuid); } - public function testBackwardsFlush() + public function testBackwardsFlush(): void { Rollbar::init(self::$simpleConfig); @@ -208,7 +209,7 @@ public function testBackwardsFlush() $this->assertTrue(true); } - public function testConfigure() + public function testConfigure(): void { $expected = 'expectedEnv'; @@ -228,7 +229,7 @@ public function testConfigure() $this->assertEquals($expected, $payload->getData()->getEnvironment()); } - public function testEnable() + public function testEnable(): void { Rollbar::init(self::$simpleConfig); $this->assertTrue(Rollbar::enabled()); @@ -252,7 +253,7 @@ public function testEnable() $this->assertTrue(Rollbar::disabled()); } - public function testLogUncaughtUnsetLogger() + public function testLogUncaughtUnsetLogger(): void { $sut = new Rollbar; $result = $sut->logUncaught('level', new \Exception); @@ -260,7 +261,7 @@ public function testLogUncaughtUnsetLogger() $this->assertEquals($expected, $result); } - public function testLogUncaught() + public function testLogUncaught(): void { $sut = new Rollbar; Rollbar::init(self::$simpleConfig); diff --git a/tests/ScrubberTest.php b/tests/ScrubberTest.php index 8ca82181..469b46ae 100644 --- a/tests/ScrubberTest.php +++ b/tests/ScrubberTest.php @@ -7,7 +7,7 @@ class ScrubberTest extends BaseRollbarTest { - public function scrubUrlDataProvider() + public function scrubUrlDataProvider(): array { return array( 'nothing to scrub' => array( @@ -26,7 +26,7 @@ public function scrubUrlDataProvider() /** * @dataProvider scrubSafelistProvider */ - public function testScrubSafelist($testData, $scrubFields, $safelist, $expected) + public function testScrubSafelist($testData, $scrubFields, $safelist, $expected): void { $scrubber = new Scrubber(array( 'scrubFields' => $scrubFields, @@ -40,7 +40,7 @@ public function testScrubSafelist($testData, $scrubFields, $safelist, $expected) ); } - public function scrubSafelistProvider() + public function scrubSafelistProvider(): array { return array( array( @@ -87,7 +87,7 @@ public function scrubSafelistProvider() /** * @dataProvider scrubDataProvider */ - public function testScrub($testData, $scrubFields, $expected) + public function testScrub($testData, $scrubFields, $expected): void { $scrubber = new Scrubber(array( 'scrubFields' => $scrubFields @@ -96,7 +96,7 @@ public function testScrub($testData, $scrubFields, $expected) $this->assertEquals($expected, $result, "Looks like some fields did not get scrubbed correctly."); } - public function scrubDataProvider() + public function scrubDataProvider(): array { return array_merge(array( 'flat data array' => @@ -112,7 +112,7 @@ public function scrubDataProvider() ), $this->scrubUrlDataProvider(), $this->scrubJSONNumbersProvider()); } - private function scrubJSONNumbersProvider() + private function scrubJSONNumbersProvider(): array { return array( 'plain array' => array( @@ -132,7 +132,7 @@ private function scrubJSONNumbersProvider() ); } - private function scrubFlatDataProvider() + private function scrubFlatDataProvider(): array { return array( array( // $testData @@ -149,7 +149,7 @@ private function scrubFlatDataProvider() ); } - private function scrubRecursiveDataProvider() + private function scrubRecursiveDataProvider(): array { return array( array( // $testData @@ -196,7 +196,7 @@ private function scrubRecursiveDataProvider() ); } - private function scrubFlatStringDataProvider() + private function scrubFlatStringDataProvider(): array { return array( // $testData @@ -221,7 +221,7 @@ private function scrubFlatStringDataProvider() ); } - private function scrubRecursiveStringDataProvider() + private function scrubRecursiveStringDataProvider(): array { return array( // $testData @@ -252,7 +252,7 @@ private function scrubRecursiveStringDataProvider() ); } - private function scrubRecursiveStringRecursiveDataProvider() + private function scrubRecursiveStringRecursiveDataProvider(): array { return array( array( // $testData @@ -315,7 +315,7 @@ private function scrubRecursiveStringRecursiveDataProvider() /** * @dataProvider scrubArrayDataProvider */ - public function testScrubArray($testData, $scrubFields, $expected) + public function testScrubArray($testData, $scrubFields, $expected): void { $scrubber = new Scrubber(array( 'scrubFields' => $scrubFields @@ -324,7 +324,7 @@ public function testScrubArray($testData, $scrubFields, $expected) $this->assertEquals($expected, $result, "Looks like some fields did not get scrubbed correctly."); } - public function scrubArrayDataProvider() + public function scrubArrayDataProvider(): array { return array( 'flat data array' => array( @@ -381,7 +381,7 @@ public function scrubArrayDataProvider() ); } - public function testScrubReplacement() + public function testScrubReplacement(): void { $testData = array('scrubit' => '123'); diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 065555ad..b9a57144 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -4,7 +4,7 @@ class ServerTest extends BaseRollbarTest { - public function testHost() + public function testHost(): void { $val = "TEST"; $server = new Server(); @@ -15,7 +15,7 @@ public function testHost() $this->assertEquals($val2, $server->setHost($val2)->getHost()); } - public function testRoot() + public function testRoot(): void { $val = "TEST"; $server = new Server(); @@ -26,7 +26,7 @@ public function testRoot() $this->assertEquals($val2, $server->setRoot($val2)->getRoot()); } - public function testBranch() + public function testBranch(): void { $val = "TEST"; $server = new Server(); @@ -37,7 +37,7 @@ public function testBranch() $this->assertEquals($val2, $server->setBranch($val2)->getBranch()); } - public function testCodeVersion() + public function testCodeVersion(): void { $val = "TEST"; $server = new Server(); @@ -48,7 +48,7 @@ public function testCodeVersion() $this->assertEquals($val2, $server->setCodeVersion($val2)->getCodeVersion()); } - public function testExtra() + public function testExtra(): void { $server = new Server(); $server->setExtras(array("test" => "testing")); @@ -56,7 +56,7 @@ public function testExtra() $this->assertEquals("testing", $extras["test"]); } - public function testEncode() + public function testEncode(): void { $server = new Server(); $server->setHost("server2-ec-us") diff --git a/tests/TestHelpers/CustomSerializable.php b/tests/TestHelpers/CustomSerializable.php index 6c47cc89..b68e187f 100644 --- a/tests/TestHelpers/CustomSerializable.php +++ b/tests/TestHelpers/CustomSerializable.php @@ -2,19 +2,19 @@ class CustomSerializable implements \Serializable { - public $data; + public array $data; public function __construct($data) { $this->data = $data; } - public function serialize() + public function serialize(): array { return $this->data; } - public function unserialize(string $data) + public function unserialize(string $data): void { throw new \Exception("Not implemented"); } diff --git a/tests/TestHelpers/CustomTruncation.php b/tests/TestHelpers/CustomTruncation.php index 1d63745f..e742fb4e 100644 --- a/tests/TestHelpers/CustomTruncation.php +++ b/tests/TestHelpers/CustomTruncation.php @@ -2,12 +2,12 @@ namespace Rollbar\TestHelpers; -use \Rollbar\Truncation\AbstractStrategy; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Truncation\AbstractStrategy; +use Rollbar\Payload\EncodedPayload; class CustomTruncation extends AbstractStrategy { - public function execute(EncodedPayload $payload) + public function execute(EncodedPayload $payload): EncodedPayload { $payload->encode(array( "data" => array( diff --git a/tests/TestHelpers/CycleCheck/ChildCycleCheckSerializable.php b/tests/TestHelpers/CycleCheck/ChildCycleCheckSerializable.php index 6fba7877..357db7be 100644 --- a/tests/TestHelpers/CycleCheck/ChildCycleCheckSerializable.php +++ b/tests/TestHelpers/CycleCheck/ChildCycleCheckSerializable.php @@ -11,7 +11,7 @@ public function __construct($parent) $this->parent = $parent; } - public function serialize() + public function serialize(): array { return array( "parent" => \Rollbar\Utilities::serializeForRollbarInternal($this->parent) diff --git a/tests/TestHelpers/CycleCheck/ParentCycleCheck.php b/tests/TestHelpers/CycleCheck/ParentCycleCheck.php index edddf9be..bfd6f05f 100644 --- a/tests/TestHelpers/CycleCheck/ParentCycleCheck.php +++ b/tests/TestHelpers/CycleCheck/ParentCycleCheck.php @@ -2,7 +2,7 @@ class ParentCycleCheck { - public $child; + public ChildCycleCheck $child; public function __construct() { diff --git a/tests/TestHelpers/CycleCheck/ParentCycleCheckSerializable.php b/tests/TestHelpers/CycleCheck/ParentCycleCheckSerializable.php index d49ea3bd..aad57406 100644 --- a/tests/TestHelpers/CycleCheck/ParentCycleCheckSerializable.php +++ b/tests/TestHelpers/CycleCheck/ParentCycleCheckSerializable.php @@ -4,14 +4,14 @@ class ParentCycleCheckSerializable implements SerializerInterface { - public $child; + public ChildCycleCheck $child; public function __construct() { $this->child = new ChildCycleCheck($this); } - public function serialize() + public function serialize(): array { return array( "child" => \Rollbar\Utilities::serializeForRollbarInternal($this->child) diff --git a/tests/TestHelpers/MalformedPayloadDataTransformer.php b/tests/TestHelpers/MalformedPayloadDataTransformer.php index 1e648350..81df991c 100644 --- a/tests/TestHelpers/MalformedPayloadDataTransformer.php +++ b/tests/TestHelpers/MalformedPayloadDataTransformer.php @@ -1,7 +1,8 @@ makePartial(); + $mock = \Mockery::mock(Data::class)->makePartial(); $mock->shouldReceive("serialize")->andReturn(false); $levelFactory = new \Rollbar\LevelFactory(); $mock->setLevel($levelFactory->fromName($level)); diff --git a/tests/TestHelpers/MockPhpStream.php b/tests/TestHelpers/MockPhpStream.php index 0b4ec668..bb08980b 100644 --- a/tests/TestHelpers/MockPhpStream.php +++ b/tests/TestHelpers/MockPhpStream.php @@ -5,7 +5,7 @@ class MockPhpStream { - protected static $index = 0; + protected static int $index = 0; protected static $length = null; /** @@ -13,21 +13,21 @@ class MockPhpStream * there are multiple instances of MockPhpStream being used in PHP * to deal with the stream wrapper. */ - protected static $data = ''; + protected static string|Data $data = ''; // @codingStandardsIgnoreStart - public function stream_open() + public function stream_open(): bool { return true; } - public function stream_stat() + public function stream_stat(): array { return array(); } - public function stream_read($count) + public function stream_read($count): string { if (is_null(self::$length) === true) { $this->length = strlen(self::$data); @@ -38,12 +38,12 @@ public function stream_read($count) return $data; } - public function stream_eof() + public function stream_eof(): bool { return (self::$index >= self::$length ? true : false); } - public function stream_write($data) + public function stream_write($data): ?int { self::$data = $data; self::$length = strlen(self::$data); diff --git a/tests/TraceChainTest.php b/tests/TraceChainTest.php index b02d07b4..8636b4c1 100644 --- a/tests/TraceChainTest.php +++ b/tests/TraceChainTest.php @@ -1,22 +1,23 @@ trace1 = m::mock("Rollbar\Payload\Trace"); - $this->trace2 = m::mock("Rollbar\Payload\Trace"); + $this->trace1 = m::mock(Trace::class); + $this->trace2 = m::mock(Trace::class); } - public function testTraces() + public function testTraces(): void { $chain = array($this->trace1); $traceChain = new TraceChain($chain); @@ -28,19 +29,19 @@ public function testTraces() $this->assertEquals($chain, $traceChain->getTraces()); } - public function testKey() + public function testKey(): void { $chain = new TraceChain(array($this->trace1)); $this->assertEquals("trace_chain", $chain->getKey()); } - public function testEncode() + public function testEncode(): void { - $trace1 = m::mock("Rollbar\Payload\Trace") + $trace1 = m::mock(Trace::class) ->shouldReceive("serialize") ->andReturn("TRACE1") ->mock(); - $trace2 = m::mock("Rollbar\Payload\Trace") + $trace2 = m::mock(Trace::class) ->shouldReceive("serialize") ->andReturn("TRACE2") ->mock(); diff --git a/tests/TraceTest.php b/tests/TraceTest.php index 6d502832..6ee4ad91 100644 --- a/tests/TraceTest.php +++ b/tests/TraceTest.php @@ -1,15 +1,16 @@ assertEquals($exc, $trace->getException()); } - public function testFrames() + public function testFrames(): void { $frames = array( new Frame("one.php"), new Frame("two.php") ); - $exc = m::mock("Rollbar\Payload\ExceptionInfo"); + $exc = m::mock(ExceptionInfo::class); $trace = new Trace(array(), $exc); $this->assertEquals($frames, $trace->setFrames($frames)->getFrames()); } - public function testException() + public function testException(): void { - $exc = m::mock("Rollbar\Payload\ExceptionInfo"); + $exc = m::mock(ExceptionInfo::class); $trace = new Trace(array(), $exc); $this->assertEquals($exc, $trace->getException()); - $exc2 = m::mock("Rollbar\Payload\ExceptionInfo"); + $exc2 = m::mock(ExceptionInfo::class); $this->assertEquals($exc2, $trace->setException($exc2)->getException()); } - public function testEncode() + public function testEncode(): void { $value = m::mock("Rollbar\Payload\ExceptionInfo, Rollbar\SerializerInterface") ->shouldReceive("serialize") @@ -53,9 +54,9 @@ public function testEncode() $this->assertEquals("{\"frames\":[],\"exception\":\"{EXCEPTION}\"}", $encoded); } - public function testTraceKey() + public function testTraceKey(): void { - $trace = new Trace(array(), m::mock("Rollbar\Payload\ExceptionInfo")); + $trace = new Trace(array(), m::mock(ExceptionInfo::class)); $this->assertEquals("trace", $trace->getKey()); } } diff --git a/tests/Truncation/FramesStrategyTest.php b/tests/Truncation/FramesStrategyTest.php index e1dbad93..2e9bb0b1 100644 --- a/tests/Truncation/FramesStrategyTest.php +++ b/tests/Truncation/FramesStrategyTest.php @@ -3,15 +3,15 @@ namespace Rollbar\Truncation; use Rollbar\Payload\EncodedPayload; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; class FramesStrategyTest extends BaseRollbarTest { /** * @dataProvider executeProvider */ - public function testExecute($data, $expected) + public function testExecute($data, $expected): void { $config = new Config(array('access_token' => $this->getTestAccessToken())); $truncation = new Truncation($config); @@ -26,7 +26,7 @@ public function testExecute($data, $expected) $this->assertEquals($expected, $result->data()); } - public function executeProvider() + public function executeProvider(): array { $data = array( 'nothing to truncate using trace key' => array( diff --git a/tests/Truncation/MinBodyStrategyTest.php b/tests/Truncation/MinBodyStrategyTest.php index 9c216da4..6b881154 100644 --- a/tests/Truncation/MinBodyStrategyTest.php +++ b/tests/Truncation/MinBodyStrategyTest.php @@ -3,8 +3,8 @@ namespace Rollbar\Truncation; use Rollbar\Payload\EncodedPayload; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; class MinBodyStrategyTest extends BaseRollbarTest { @@ -12,7 +12,7 @@ class MinBodyStrategyTest extends BaseRollbarTest /** * @dataProvider executeProvider */ - public function testExecute($data, $expected) + public function testExecute($data, $expected): void { $config = new Config(array('access_token' => $this->getTestAccessToken())); $truncation = new Truncation($config); @@ -27,7 +27,7 @@ public function testExecute($data, $expected) $this->assertEquals($expected, $result->data()); } - public function executeProvider() + public function executeProvider(): array { $data = array(); @@ -63,7 +63,7 @@ public function executeProvider() return $data; } - protected function payloadStructureProvider($body) + protected function payloadStructureProvider($body): array { return array( "data" => array( diff --git a/tests/Truncation/RawStrategyTest.php b/tests/Truncation/RawStrategyTest.php index 69b9a59b..fd62652d 100644 --- a/tests/Truncation/RawStrategyTest.php +++ b/tests/Truncation/RawStrategyTest.php @@ -3,12 +3,12 @@ namespace Rollbar\Truncation; use Rollbar\Payload\EncodedPayload; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; class RawStrategyTest extends BaseRollbarTest { - public function testExecute() + public function testExecute(): void { $payload = array('test' => 'test data'); diff --git a/tests/Truncation/StringsStrategyTest.php b/tests/Truncation/StringsStrategyTest.php index 747233b9..c7f769b2 100644 --- a/tests/Truncation/StringsStrategyTest.php +++ b/tests/Truncation/StringsStrategyTest.php @@ -3,13 +3,13 @@ namespace Rollbar\Truncation; use Rollbar\Payload\EncodedPayload; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; class StringsStrategyTest extends BaseRollbarTest { - protected function execute($data) + protected function execute($data): array { $config = new Config(array('access_token' => $this->getTestAccessToken())); $truncation = new Truncation($config); @@ -25,13 +25,13 @@ protected function execute($data) /** * @dataProvider executeTruncateNothingProvider */ - public function testExecuteTruncateNothing($data, $expected) + public function testExecuteTruncateNothing($data, $expected): void { $result = $this->execute($data); $this->assertEquals($expected, $result); } - public function executeTruncateNothingProvider() + public function executeTruncateNothingProvider(): array { $data = array(); @@ -46,7 +46,7 @@ public function executeTruncateNothingProvider() /** * @dataProvider executeArrayProvider */ - public function testExecuteArray($data, $expectedThreshold) + public function testExecuteArray($data, $expectedThreshold): void { $result = $this->execute($data); @@ -61,7 +61,7 @@ public function testExecuteArray($data, $expectedThreshold) } } - public function executeArrayProvider() + public function executeArrayProvider(): array { $data = array(); @@ -73,7 +73,7 @@ public function executeArrayProvider() return $data; } - public function thresholdTestProvider($threshold) + public function thresholdTestProvider($threshold): array { $stringLengthToTrim = $threshold*2; @@ -90,7 +90,7 @@ public function thresholdTestProvider($threshold) return array($payload, $threshold); } - public function executeProvider() + public function executeProvider(): array { $data = array(); @@ -107,7 +107,7 @@ public function executeProvider() return $data; } - public function payloadStructureProvider($message) + public function payloadStructureProvider($message): array { return array( "data" => array( diff --git a/tests/Truncation/TruncationTest.php b/tests/Truncation/TruncationTest.php index 2f56fbcf..0cb7b816 100644 --- a/tests/Truncation/TruncationTest.php +++ b/tests/Truncation/TruncationTest.php @@ -2,9 +2,10 @@ namespace Rollbar\Truncation; -use \Rollbar\Config; -use \Rollbar\BaseRollbarTest; -use \Rollbar\Payload\EncodedPayload; +use Rollbar\Config; +use Rollbar\BaseRollbarTest; +use Rollbar\Payload\EncodedPayload; +use Rollbar\TestHelpers\CustomTruncation; class TruncationTest extends BaseRollbarTest { @@ -15,11 +16,11 @@ public function setUp(): void $this->truncate = new \Rollbar\Truncation\Truncation($config); } - public function testCustomTruncation() + public function testCustomTruncation(): void { $config = new Config(array( 'access_token' => $this->getTestAccessToken(), - 'custom_truncation' => 'Rollbar\TestHelpers\CustomTruncation' + 'custom_truncation' => CustomTruncation::class )); $this->truncate = new \Rollbar\Truncation\Truncation($config); @@ -38,13 +39,13 @@ public function testCustomTruncation() $result = $this->truncate->truncate($data); - $this->assertFalse(strpos($data, 'Custom truncation test string') === false); + $this->assertNotFalse(str_contains($data, 'Custom truncation test string')); } /** * @dataProvider truncateProvider */ - public function testTruncateNoPerformance($data) + public function testTruncateNoPerformance($data): void { $data = new \Rollbar\Payload\EncodedPayload($data); @@ -60,7 +61,7 @@ public function testTruncateNoPerformance($data) ); } - public function truncateProvider() + public function truncateProvider(): array { $stringsTest = new StringsStrategyTest(); diff --git a/tests/UtilitiesTest.php b/tests/UtilitiesTest.php index 384e22ca..f0b66706 100644 --- a/tests/UtilitiesTest.php +++ b/tests/UtilitiesTest.php @@ -7,7 +7,7 @@ class UtilitiesTest extends BaseRollbarTest { - public function testValidateString() + public function testValidateString(): void { Utilities::validateString(""); Utilities::validateString("true"); @@ -18,25 +18,25 @@ public function testValidateString() Utilities::validateString(null, "null", null, false); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$null must not be null"); + $this->assertEquals("\$null must not be null", $e->getMessage()); } try { Utilities::validateString(1, "number"); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$number must be a string"); + $this->assertEquals("\$number must be a string", $e->getMessage()); } try { Utilities::validateString("1", "str", 2); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$str must be 2 characters long, was '1'"); + $this->assertEquals("\$str must be 2 characters long, was '1'", $e->getMessage()); } } - public function testValidateInteger() + public function testValidateInteger(): void { Utilities::validateInteger(null); Utilities::validateInteger(0); @@ -46,37 +46,37 @@ public function testValidateInteger() Utilities::validateInteger(null, "null", null, null, false); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$null must not be null"); + $this->assertEquals("\$null must not be null", $e->getMessage()); } try { Utilities::validateInteger(0, "zero", 1); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$zero must be >= 1"); + $this->assertEquals("\$zero must be >= 1", $e->getMessage()); } try { Utilities::validateInteger(0, "zero", null, -1); $this->fail("Above should throw"); } catch (\InvalidArgumentException $e) { - $this->assertEquals($e->getMessage(), "\$zero must be <= -1"); + $this->assertEquals("\$zero must be <= -1", $e->getMessage()); } } - public function testValidateBooleanThrowsExceptionOnNullWhenNullAreNotAllowed() + public function testValidateBooleanThrowsExceptionOnNullWhenNullAreNotAllowed(): void { $this->expectException(\InvalidArgumentException::class); Utilities::validateBoolean(null, "foo", false); } - public function testValidateBooleanWithInvalidBoolean() + public function testValidateBooleanWithInvalidBoolean(): void { $this->expectException(\InvalidArgumentException::class); Utilities::validateBoolean("not a boolean"); } - public function testValidateBoolean() + public function testValidateBoolean(): void { Utilities::validateBoolean(true, "foo", false); Utilities::validateBoolean(true); @@ -84,7 +84,7 @@ public function testValidateBoolean() $this->expectNotToPerformAssertions(); } - public function testSerializeForRollbar() + public function testSerializeForRollbar(): void { $obj = array( "one_two" => array(1, 2), @@ -111,7 +111,7 @@ public function testSerializeForRollbar() $this->assertArrayNotHasKey("my_null_value", $result); } - public function testSerializationCycleChecking() + public function testSerializationCycleChecking(): void { $config = new Config(array("access_token"=>$this->getTestAccessToken())); $data = $config->getRollbarData(\Rollbar\Payload\Level::WARNING, "String", array(new ParentCycleCheck())); @@ -142,7 +142,7 @@ public function testSerializationCycleChecking() ); } - public function testSerializeForRollbarNestingLevels() + public function testSerializeForRollbarNestingLevels(): void { $obj = array( "one" => array( diff --git a/tests/VerbosityTest.php b/tests/VerbosityTest.php index 002e1cd5..f1b8a9d2 100644 --- a/tests/VerbosityTest.php +++ b/tests/VerbosityTest.php @@ -5,6 +5,10 @@ use Rollbar\Payload\Level; use Rollbar\Payload\Payload; use Rollbar\Response; +use Monolog\Handler\AbstractHandler; +use Rollbar\ResponseHandlerInterface; +use Rollbar\FilterInterface; +use Rollbar\Payload\Data; /** * \Rollbar\VerboseTest tests the verbosity of the SDK. @@ -53,7 +57,7 @@ public function tearDown(): void * * @return void */ - public function testRollbarLoggerEnabled() + public function testRollbarLoggerEnabled(): void { $unitTest = $this; $this->rollbarLogTest( @@ -83,7 +87,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerDisabled() + public function testRollbarLoggerDisabled(): void { $unitTest = $this; $this->rollbarLogTest( @@ -105,7 +109,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerInvalidLogLevel() + public function testRollbarLoggerInvalidLogLevel(): void { $unitTest = $this; $this->rollbarLogTest( @@ -136,7 +140,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerInternalCheckIgnored() + public function testRollbarLoggerInternalCheckIgnored(): void { $unitTest = $this; $errorReporting = \error_reporting(); @@ -167,7 +171,7 @@ function () use ($errorReporting) { * * @return void */ - public function testRollbarLoggerCheckIgnored() + public function testRollbarLoggerCheckIgnored(): void { $unitTest = $this; $this->rollbarLogTest( @@ -192,7 +196,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerSendMaxItems() + public function testRollbarLoggerSendMaxItems(): void { $unitTest = $this; $this->rollbarLogTest( @@ -219,7 +223,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerSendBatched() + public function testRollbarLoggerSendBatched(): void { $unitTest = $this; $this->rollbarLogTest( @@ -245,7 +249,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerFlush() + public function testRollbarLoggerFlush(): void { $unitTest = $this; $rollbarLogger = $this->verboseRollbarLogger(array( @@ -276,7 +280,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerResponseStatusZero() + public function testRollbarLoggerResponseStatusZero(): void { $unitTest = $this; $this->rollbarLogTest( @@ -305,7 +309,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerResponseStatusError() + public function testRollbarLoggerResponseStatusError(): void { $unitTest = $this; $this->rollbarLogTest( @@ -332,7 +336,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarLoggerResponseStatusSuccess() + public function testRollbarLoggerResponseStatusSuccess(): void { $unitTest = $this; $this->rollbarLogTest( @@ -358,7 +362,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigInternalCheckIgnoredShouldSuppress() + public function testRollbarConfigInternalCheckIgnoredShouldSuppress(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -400,7 +404,7 @@ function () use ($errorReporting) { * * @return void */ - public function testRollbarConfigInternalCheckIgnoredLevelTooLow() + public function testRollbarConfigInternalCheckIgnoredLevelTooLow(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -433,7 +437,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigShouldIgnoreErrorErrorReporting() + public function testRollbarConfigShouldIgnoreErrorErrorReporting(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -474,7 +478,7 @@ function () use ($errorReporting) { * * @return void */ - public function testRollbarConfigShouldIgnoreErrorIncludedErrno() + public function testRollbarConfigShouldIgnoreErrorIncludedErrno(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -515,7 +519,7 @@ function () use ($errorReporting) { * * @return void */ - public function testRollbarConfigShouldIgnoreErrorErrorSampleRates() + public function testRollbarConfigShouldIgnoreErrorErrorSampleRates(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -549,7 +553,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigShouldIgnoreException() + public function testRollbarConfigShouldIgnoreException(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -583,7 +587,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigCheckIgnored() + public function testRollbarConfigCheckIgnored(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -598,11 +602,11 @@ public function testRollbarConfigCheckIgnored() $config, function () use ($config, $unitTest) { // logic under test - $dataMock = $unitTest->getMockBuilder('\Rollbar\Payload\Data') + $dataMock = $unitTest->getMockBuilder(Data::class) ->disableOriginalConstructor() ->getMock(); $dataMock->method('getLevel')->willReturn(\Rollbar\Payload\Level::INFO()); - $payloadMock = $unitTest->getMockBuilder('\Rollbar\Payload\Payload') + $payloadMock = $unitTest->getMockBuilder(Payload::class) ->disableOriginalConstructor() ->getMock(); $payloadMock->method('getData')->willReturn($dataMock); @@ -630,7 +634,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigCheckIgnoredException() + public function testRollbarConfigCheckIgnoredException(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -666,7 +670,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigCheckIgnoredPayloadLevelTooLow() + public function testRollbarConfigCheckIgnoredPayloadLevelTooLow(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -700,10 +704,10 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigCheckIgnoredFilter() + public function testRollbarConfigCheckIgnoredFilter(): void { $unitTest = $this; - $filterMock = $this->getMockBuilder('\Rollbar\FilterInterface')->getMock(); + $filterMock = $this->getMockBuilder(FilterInterface::class)->getMock(); $filterMock->method('shouldSend')->willReturn(true); $config = $this->verboseRollbarConfig(array( // config @@ -737,7 +741,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigSendTransmit() + public function testRollbarConfigSendTransmit(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -770,7 +774,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigSendBatchTransmit() + public function testRollbarConfigSendBatchTransmit(): void { $unitTest = $this; $config = $this->verboseRollbarConfig(array( // config @@ -804,10 +808,10 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarConfigHandleResponse() + public function testRollbarConfigHandleResponse(): void { $unitTest = $this; - $responseHandlerMock = $this->getMockBuilder('\Rollbar\ResponseHandlerInterface')->getMock(); + $responseHandlerMock = $this->getMockBuilder(ResponseHandlerInterface::class)->getMock(); $config = $this->verboseRollbarConfig(array( // config "access_token" => $this->getTestAccessToken(), "environment" => "testing-php", @@ -843,7 +847,7 @@ function () use ($unitTest) { * * @return void */ - public function testRollbarTruncation() + public function testRollbarTruncation(): void { $unitTest = $this; $rollbarLogger = $this->verboseRollbarLogger(array( @@ -886,10 +890,10 @@ function () use ($unitTest) { * * @param array $config Config array used to configure * the $object. - * @param \Rollbar\RollbarLogger|\Rollbar\Config $object + * @param \Rollbar\Config|\Rollbar\RollbarLogger $object * Object to be set up for the test. */ - private function prepareForLogMocking($config, $object) + private function prepareForLogMocking(array $config, Config|RollbarLogger $object): Config|RollbarLogger { $verboseLogger = new \Monolog\Logger('rollbar.verbose.test'); @@ -897,9 +901,7 @@ private function prepareForLogMocking($config, $object) 'verbose_logger' => $verboseLogger ))); - $verbose = isset($config['verbose']) ? - $config['verbose'] : - \Rollbar\Config::VERBOSE_NONE; + $verbose = $config['verbose'] ?? \Rollbar\Config::VERBOSE_NONE; if ($verbose == \Rollbar\Config::VERBOSE_NONE) { $verbose = \Rollbar\Config::VERBOSE_NONE_INT; @@ -907,7 +909,7 @@ private function prepareForLogMocking($config, $object) $verbose = \Monolog\Logger::toMonologLevel($verbose); } - $handlerMock = $this->getMockBuilder('\Monolog\Handler\AbstractHandler') + $handlerMock = $this->getMockBuilder(AbstractHandler::class) ->setMethods(array('handle')) ->getMock(); $handlerMock->setLevel($verbose); @@ -928,7 +930,7 @@ private function prepareForLogMocking($config, $object) * @param array $config Configuration options for Rollbar * @return \Rollbar\Config */ - private function verboseRollbarConfig($config) + private function verboseRollbarConfig(array $config): Config|RollbarLogger { return $this->prepareForLogMocking( $config, @@ -945,7 +947,7 @@ private function verboseRollbarConfig($config) * @param array $config Configuration options for Rollbar * @return \Rollbar\RollbarLogger */ - private function verboseRollbarLogger($config) + private function verboseRollbarLogger(array $config): Config|RollbarLogger { return $this->prepareForLogMocking( $config, @@ -962,7 +964,7 @@ private function verboseRollbarLogger($config) * @param string $level The level of the log recorded which will * be asserted. */ - private function withLogParams($messageRegEx, $level) + private function withLogParams(string $messageRegEx, string $level): \PHPUnit\Framework\Constraint\Callback { return $this->callback(function ($record) use ($messageRegEx, $level) { return @@ -974,7 +976,7 @@ private function withLogParams($messageRegEx, $level) /** * Convenience method for asserting a log record is in a valid format. */ - private function withLog() + private function withLog(): \PHPUnit\Framework\Constraint\Callback { return $this->callback(function ($record) { return is_array($record); @@ -1035,7 +1037,7 @@ public function expectConsecutiveLog(array ...$constraints): void * @param mock|null $handlerMock (optional) The handler mock on which to set the * expectations. */ - public function expectLog($at, $messageRegEx, $level, $handlerMock = null) + public function expectLog(int $at, string $messageRegEx, string $level, mock $handlerMock = null): void { $this->expectConsecutiveLog([ $at, $messageRegEx, $level ]); } @@ -1046,7 +1048,7 @@ public function expectLog($at, $messageRegEx, $level, $handlerMock = null) * @param mock|null $handlerMock (optional) The handler mock on which to set the * expectations. */ - public function expectQuiet($handlerMock = null) + public function expectQuiet(mock $handlerMock = null): void { if ($handlerMock === null) { $handlerMock = $this->verboseHandlerMock; @@ -1063,21 +1065,22 @@ public function expectQuiet($handlerMock = null) * to the initial config is not needed as the method takes * care of performing assertions in both quiet and verbose scenarios. * - * @param \Rollbar\RollbarLogger|\Rollbar\Config $object Object under test. + * @param \Rollbar\Config|\Rollbar\RollbarLogger $object Object under test. * @param callback $test Logic under test * @param callback $verboseExpectations A callback with * expectations to be set on the verbose logger handler mock * in the verbose scenario. - * @param callback $pre (optional) Logic to be executed before test. - * @param callback $post (optional) Logic to be executed after the test + * @param callback|null $pre (optional) Logic to be executed before test. + * @param callback|null $post (optional) Logic to be executed after the test */ private function configurableObjectVerbosityTest( - $object, - $test, - $verboseExpectations, - $pre = null, - $post = null - ) { + Config|RollbarLogger $object, + callable $test, + callable $verboseExpectations, + callable $pre = null, + callable $post = null + ): void + { $unitTest = $this; // Quiet scenario $this->prepareForLogMocking( @@ -1111,15 +1114,16 @@ function () use ($unitTest) { * * @param callback $test Logic under test. * @param callback $expectations Logic with expectations. - * @param callback $pre (optional) Test set up. - * @param callback $post (optional) Test tear down. + * @param callback|null $pre (optional) Test set up. + * @param callback|null $post (optional) Test tear down. */ private function withTestLambdas( - $test, - $expectations, - $pre = null, - $post = null - ) { + callable $test, + callable $expectations, + callable $pre = null, + callable $post = null + ): void + { if ($pre !== null) { $pre(); } @@ -1145,16 +1149,17 @@ private function withTestLambdas( * set on the verbose logger handler mock. * @param string $messageLevel (optional) The level of the Rollbar log * message invoked. - * @param callback $pre (optional) Logic to be executed before test. - * @param callback $post (optional) Logic to be executed after the test + * @param callback|null $pre (optional) Logic to be executed before test. + * @param callback|null $post (optional) Logic to be executed after the test */ private function rollbarLogTest( - $config, - $expectations, - $messageLevel = Level::WARNING, - $pre = null, - $post = null - ) { + array $config, + callable $expectations, + string $messageLevel = Level::WARNING, + callable $pre = null, + callable $post = null + ): void + { $rollbarLogger = $this->verboseRollbarLogger($config); $this->configurableObjectVerbosityTest( From 9d28d1a3f103f09570adccac8326ca4f0b572bba Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 3 May 2022 15:22:30 +0200 Subject: [PATCH 02/26] feat: php 8 language level mitigations --- tests/CurlSenderTest.php | 3 ++- tests/DataBuilderTest.php | 13 ++++--------- tests/RollbarLoggerTest.php | 3 +-- tests/VerbosityTest.php | 9 +++------ 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/tests/CurlSenderTest.php b/tests/CurlSenderTest.php index 90c01f15..55861cb6 100644 --- a/tests/CurlSenderTest.php +++ b/tests/CurlSenderTest.php @@ -17,7 +17,8 @@ public function testCurlError(): void $response = $logger->log(Level::WARNING, "Testing PHP Notifier", array()); $this->assertContains( - $response->getInfo(), array( + $response->getInfo(), + array( "Couldn't resolve host 'fake-endpointitem'", // hack for PHP 5.3 "Could not resolve host: fake-endpointitem", "Could not resolve: fake-endpointitem (Domain name not found)", diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index 36a797d8..71f429e6 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -7,9 +7,6 @@ class DataBuilderTest extends BaseRollbarTest { - /** - * @var DataBuilder - */ private DataBuilder $dataBuilder; public function setUp(): void @@ -886,8 +883,7 @@ public function testGenerateErrorWrapper(): void public function testCaptureErrorStacktracesException( $captureErrorStacktraces, $expected - ): void - { + ): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), @@ -921,9 +917,9 @@ public function testFramesOrder(): void 'tests/DataBuilderTest.php', $frames[count($frames)-1]->getFilename() ); - // 919 is the line number where the comment "// A" is found + // 915 is the line number where the comment "// A" is found $this->assertEquals( - 919, + 915, $frames[count($frames)-1]->getLineno(), "Possible false negative: did this file change? Check the line number for line with '// A' comment" ); @@ -936,8 +932,7 @@ public function testFramesOrder(): void public function testCaptureErrorStacktracesError( $captureErrorStacktraces, $expected - ): void - { + ): void { $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index 2d3b7cc8..10712863 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -447,8 +447,7 @@ private function scrubTestAssert( string $scrubField = 'sensitive', bool $recursive = true, string $replacement = '*' - ): void - { + ): void { $this->assertEquals( str_repeat($replacement, 8), diff --git a/tests/VerbosityTest.php b/tests/VerbosityTest.php index f1b8a9d2..e727f13c 100644 --- a/tests/VerbosityTest.php +++ b/tests/VerbosityTest.php @@ -1079,8 +1079,7 @@ private function configurableObjectVerbosityTest( callable $verboseExpectations, callable $pre = null, callable $post = null - ): void - { + ): void { $unitTest = $this; // Quiet scenario $this->prepareForLogMocking( @@ -1122,8 +1121,7 @@ private function withTestLambdas( callable $expectations, callable $pre = null, callable $post = null - ): void - { + ): void { if ($pre !== null) { $pre(); } @@ -1158,8 +1156,7 @@ private function rollbarLogTest( string $messageLevel = Level::WARNING, callable $pre = null, callable $post = null - ): void - { + ): void { $rollbarLogger = $this->verboseRollbarLogger($config); $this->configurableObjectVerbosityTest( From 484daa9f1bf1fac15b52122268d9127b6435fdd1 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 24 Oct 2022 16:18:39 -0500 Subject: [PATCH 03/26] Added support for psr/log v3 --- composer.json | 2 +- src/Rollbar.php | 83 ++++++++++++++++++++-------- src/RollbarLogger.php | 67 ++++++++++++++++------- tests/CurlSenderTest.php | 2 +- tests/ReadmeTest.php | 10 ++-- tests/RollbarLoggerTest.php | 87 +++++++++++++++++++----------- tests/RollbarTest.php | 24 +++++---- tests/TestHelpers/ArrayLogger.php | 58 ++++++++++++++++++++ tests/TestHelpers/StdOutLogger.php | 5 +- 9 files changed, 248 insertions(+), 90 deletions(-) create mode 100644 tests/TestHelpers/ArrayLogger.php diff --git a/composer.json b/composer.json index ef5c2dc5..5a0a1f4e 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "require": { "php": ">=8.0.0 <9.0", "ext-curl": "*", - "psr/log": "^1 || ^2", + "psr/log": "^1 || ^2 || ^3", "monolog/monolog": "^2" }, diff --git a/src/Rollbar.php b/src/Rollbar.php index cbe2b0c0..d9ee0841 100644 --- a/src/Rollbar.php +++ b/src/Rollbar.php @@ -2,10 +2,12 @@ namespace Rollbar; +use Psr\Log\InvalidArgumentException; use Rollbar\Payload\Level; use Rollbar\Handlers\FatalHandler; use Rollbar\Handlers\ErrorHandler; use Rollbar\Handlers\ExceptionHandler; +use Stringable; use Throwable; class Rollbar @@ -90,12 +92,49 @@ public static function scope($config) return self::$logger->scope($config); } - public static function log($level, $toLog, $extra = array()) + /** + * Logs a message to the Rollbar service with the specified level. + * + * @param Level|string $level The severity level of the message. + * Must be one of the levels as defined in + * the {@see Level} constants. + * @param string|Stringable $message The log message. + * @param array $context Arbitrary data. + * + * @return void + * + * @throws InvalidArgumentException If $level is not a valid level. + * @throws Throwable Rethrown $message if it is {@see Throwable} and {@see Config::raiseOnError} is true. + */ + public static function log($level, string|Stringable $message, array $context = array()): void + { + if (is_null(self::$logger)) { + return; + } + self::$logger->log($level, $message, $context); + } + + /** + * Creates the {@see Response} object and reports the message to the Rollbar + * service. + * + * @param string|Level $level The severity level to send to Rollbar. + * @param string|Stringable $message The log message. + * @param array $context Any additional context data. + * + * @return Response + * + * @throws InvalidArgumentException If $level is not a valid level. + * @throws Throwable Rethrown $message if it is {@see Throwable} and {@see Config::raiseOnError} is true. + * + * @since 4.0.0 + */ + public static function report($level, string|Stringable $message, array $context = array()): Response { if (is_null(self::$logger)) { return self::getNotInitializedResponse(); } - return self::$logger->log($level, $toLog, (array)$extra); + return self::$logger->report($level, $message, $context); } /** @@ -107,49 +146,49 @@ public static function logUncaught($level, Throwable $toLog, $extra = array()) return self::getNotInitializedResponse(); } $toLog->isUncaught = true; - $result = self::$logger->log($level, $toLog, (array)$extra); + $result = self::$logger->report($level, $toLog, (array)$extra); unset($toLog->isUncaught); return $result; } - public static function debug($toLog, $extra = array()) + public static function debug(string|Stringable $message, array $context = array()): void { - return self::log(Level::DEBUG, $toLog, $extra); + self::log(Level::DEBUG, $message, $context); } - public static function info($toLog, $extra = array()) + public static function info(string|Stringable $message, array $context = array()): void { - return self::log(Level::INFO, $toLog, $extra); + self::log(Level::INFO, $message, $context); } - public static function notice($toLog, $extra = array()) + public static function notice(string|Stringable $message, array $context = array()): void { - return self::log(Level::NOTICE, $toLog, $extra); + self::log(Level::NOTICE, $message, $context); } - public static function warning($toLog, $extra = array()) + public static function warning(string|Stringable $message, array $context = array()): void { - return self::log(Level::WARNING, $toLog, $extra); + self::log(Level::WARNING, $message, $context); } - public static function error($toLog, $extra = array()) + public static function error(string|Stringable $message, array $context = array()): void { - return self::log(Level::ERROR, $toLog, $extra); + self::log(Level::ERROR, $message, $context); } - public static function critical($toLog, $extra = array()) + public static function critical(string|Stringable $message, array $context = array()): void { - return self::log(Level::CRITICAL, $toLog, $extra); + self::log(Level::CRITICAL, $message, $context); } - public static function alert($toLog, $extra = array()) + public static function alert(string|Stringable $message, array $context = array()): void { - return self::log(Level::ALERT, $toLog, $extra); + self::log(Level::ALERT, $message, $context); } - public static function emergency($toLog, $extra = array()) + public static function emergency(string|Stringable $message, array $context = array()): void { - return self::log(Level::EMERGENCY, $toLog, $extra); + self::log(Level::EMERGENCY, $message, $context); } public static function setupExceptionHandling() @@ -170,7 +209,7 @@ public static function setupFatalHandling() self::$fatalHandler->register(); } - private static function getNotInitializedResponse() + private static function getNotInitializedResponse(): Response { return new Response(0, "Rollbar Not Initialized"); } @@ -247,7 +286,7 @@ public static function destroy() public static function report_exception($exc, $extra_data = null, $payload_data = null) { $extra_data = array_merge($extra_data ?? [], $payload_data ?? []); - return self::log(Level::ERROR, $exc, $extra_data)->getUuid(); + return self::report(Level::ERROR, $exc, $extra_data)->getUuid(); } /** @@ -266,7 +305,7 @@ public static function report_message($message, $level = null, $extra_data = nul { $level = $level ?? Level::ERROR; $extra_data = array_merge($extra_data ?? [], $payload_data ?? []); - return self::log($level, $message, $extra_data)->getUuid(); + return self::report($level, $message, $extra_data)->getUuid(); } diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index 3512a9b7..86335a17 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -2,6 +2,8 @@ namespace Rollbar; +use Psr\Log\InvalidArgumentException; +use Stringable; use Throwable; use Psr\Log\AbstractLogger; use Rollbar\Payload\Payload; @@ -85,17 +87,46 @@ public function getCustom() } /** - * @param Level|string $level - * @param mixed $toLog - * @param array $context + * Logs a message to the Rollbar service with the specified level. + * + * @param Level|string $level The severity level of the message. + * Must be one of the levels as defined in + * the {@see Level} constants. + * @param string|Stringable $message The log message. + * @param array $context Arbitrary data. + * + * @return void + * + * @throws InvalidArgumentException If $level is not a valid level. + * @throws Throwable Rethrown $message if it is {@see Throwable} and {@see Config::raiseOnError} is true. + */ + public function log($level, string|Stringable $message, array $context = array()): void + { + $this->report($level, $message, $context); + } + + /** + * Creates the {@see Response} object and reports the message to the Rollbar + * service. + * + * @param string|Level $level The severity level to send to Rollbar. + * @param string|Stringable $message The log message. + * @param array $context Any additional context data. + * + * @return Response + * + * @throws InvalidArgumentException If $level is not a valid level. + * @throws Throwable Rethrown $message if it is {@see Throwable} and {@see Config::raiseOnError} is true. + * + * @since 4.0.0 */ - public function log($level, $toLog, array $context = array()) + public function report($level, string|Stringable $message, array $context = array()): Response { if ($this->disabled()) { $this->verboseLogger()->notice('Rollbar is disabled'); return new Response(0, "Disabled"); } - + // Convert a Level proper into a string proper, as the code paths that // follow have allowed both only by virtue that a Level downcasts to a // string. With strict types, that no longer happens. We should consider @@ -104,23 +135,23 @@ public function log($level, $toLog, array $context = array()) if ($level instanceof Level) { $level = (string)$level; } elseif (!$this->levelFactory->isValidLevel($level)) { - $exception = new \Psr\Log\InvalidArgumentException("Invalid log level '$level'."); + $exception = new InvalidArgumentException("Invalid log level '$level'."); $this->verboseLogger()->error($exception->getMessage()); throw $exception; } - $this->verboseLogger()->info("Attempting to log: [$level] " . $toLog); + $this->verboseLogger()->info("Attempting to log: [$level] " . $message); - if ($this->config->internalCheckIgnored($level, $toLog)) { + if ($this->config->internalCheckIgnored($level, $message)) { $this->verboseLogger()->info('Occurrence ignored'); return new Response(0, "Ignored"); } $accessToken = $this->getAccessToken(); - $payload = $this->getPayload($accessToken, $level, $toLog, $context); - - $isUncaught = $this->isUncaughtLogData($toLog); - if ($this->config->checkIgnored($payload, $accessToken, $toLog, $isUncaught)) { + $payload = $this->getPayload($accessToken, $level, $message, $context); + + $isUncaught = $this->isUncaughtLogData($message); + if ($this->config->checkIgnored($payload, $accessToken, $message, $isUncaught)) { $this->verboseLogger()->info('Occurrence ignored'); $response = new Response(0, "Ignored"); } else { @@ -131,10 +162,10 @@ public function log($level, $toLog, array $context = array()) $encoded = $this->encode($scrubbed); $truncated = $this->truncate($encoded); - + $response = $this->send($truncated, $accessToken); } - + $this->handleResponse($payload, $response); if ($response->getStatus() === 0) { @@ -147,11 +178,11 @@ public function log($level, $toLog, array $context = array()) } else { $this->verboseLogger()->info('Occurrence successfully logged'); } - - if ($toLog instanceof Throwable && $this->config->getRaiseOnError()) { - throw $toLog; + + if ($message instanceof Throwable && $this->config->getRaiseOnError()) { + throw $message; } - + return $response; } diff --git a/tests/CurlSenderTest.php b/tests/CurlSenderTest.php index 55861cb6..0e084309 100644 --- a/tests/CurlSenderTest.php +++ b/tests/CurlSenderTest.php @@ -14,7 +14,7 @@ public function testCurlError(): void "environment" => "testing-php", "endpoint" => "fake-endpoint" )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier", array()); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier", array()); $this->assertContains( $response->getInfo(), diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php index 958162bb..cd41e526 100644 --- a/tests/ReadmeTest.php +++ b/tests/ReadmeTest.php @@ -40,7 +40,7 @@ public function testQuickStart(): void ); // If you want to check if logging with Rollbar was successful - $response = Rollbar::log(Level::INFO, 'testing wasSuccessful()'); + $response = Rollbar::report((new LevelFactory)->fromName(Level::INFO), 'testing wasSuccessful()'); if (!$response->wasSuccessful()) { throw new \Exception('logging with Rollbar failed'); } @@ -98,9 +98,9 @@ public function testBasicUsage(): void try { do_something(); } catch (\Exception $e) { - $result1 = Rollbar::log(Level::ERROR, $e); + $result1 = Rollbar::report(Level::ERROR, $e); // or - $result2 = Rollbar::log(Level::ERROR, $e, array("my" => "extra", "data" => 42)); + $result2 = Rollbar::report(Level::ERROR, $e, array("my" => "extra", "data" => 42)); } $this->assertEquals(200, $result1->getStatus()); @@ -116,8 +116,8 @@ public function testBasicUsage2(): void ) ); - $result1 = Rollbar::log(Level::WARNING, 'could not connect to mysql server'); - $result2 = Rollbar::log( + $result1 = Rollbar::report(Level::WARNING, 'could not connect to mysql server'); + $result2 = Rollbar::report( Level::INFO, 'Here is a message with some additional data', array('x' => 10, 'code' => 'blue') diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index 10712863..5ac48989 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -1,10 +1,9 @@ $this->getTestAccessToken(), - "environment" => "testing-php" - )); - $response = $l->log(Level::WARNING, "Testing PHP Notifier", array()); - $this->assertEquals(200, $response->getStatus()); + // Array logger collects the verbose logs, so we can assert the log was + // successfully sent to the Rollbar service. + $verbose = new ArrayLogger(); + $logger = new RollbarLogger([ + "access_token" => $this->getTestAccessToken(), + "environment" => "testing-php", + "verbose_logger" => $verbose, + ]); + + $this->assertNotContains('[info]Occurrence successfully logged', $verbose->logs); + $logger->log(Level::WARNING, "Testing PHP Notifier", []); +// print_r($array->logs); + $this->assertContains('[info]Attempting to log: [' . Level::WARNING . '] Testing PHP Notifier', $verbose->logs); + $this->assertContains('[info]Occurrence successfully logged', $verbose->logs); } public function testNotLoggingPayload(): void { + // Array logger collects the verbose logs, so we can assert the log was + // successfully sent to the Rollbar service. + $verbose = new ArrayLogger(); $logPayloadLoggerMock = $this->getMockBuilder(LoggerInterface::class)->getMock(); $logPayloadLoggerMock->expects($this->never())->method('debug'); - $logger = new RollbarLogger(array( + $logger = new RollbarLogger([ + "access_token" => $this->getTestAccessToken(), + "environment" => "testing-php", + "log_payload" => false, + "log_payload_logger" => $logPayloadLoggerMock, + "verbose_logger" => $verbose, + ]); + + $this->assertSame(0, $verbose->count(Level::INFO, 'Occurrence successfully logged')); + $logger->log(Level::WARNING, "Testing PHP Notifier", []); + $this->assertSame(1, + $verbose->count(Level::INFO, 'Attempting to log: [' . Level::WARNING . '] Testing PHP Notifier')); + $this->assertSame(1, $verbose->count(Level::INFO, 'Occurrence successfully logged')); + } + + public function testReport(): void + { + $logger = new RollbarLogger([ "access_token" => $this->getTestAccessToken(), - "environment" => "testing-php", - "log_payload" => false, - "log_payload_logger" => $logPayloadLoggerMock - )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier"); - + "environment" => "testing-php", + ]); + + $response = $logger->report(Level::WARNING, "Testing PHP Notifier", []); $this->assertEquals(200, $response->getStatus()); } @@ -211,7 +236,7 @@ public function testEnabled(): void "environment" => "testing-php" )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier", array()); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier", array()); $this->assertEquals(200, $response->getStatus()); $logger = new RollbarLogger(array( @@ -219,7 +244,7 @@ public function testEnabled(): void "environment" => "testing-php", "enabled" => false )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier", array()); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier", array()); $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Disabled", $response->getInfo()); } @@ -230,7 +255,7 @@ public function testTransmit(): void "access_token" => $this->getTestAccessToken(), "environment" => "testing-php" )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier"); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier"); $this->assertEquals(200, $response->getStatus()); $logger = new RollbarLogger(array( @@ -238,7 +263,7 @@ public function testTransmit(): void "environment" => "testing-php", "transmit" => false )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier"); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier"); $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Not transmitting (transmitting disabled in configuration)", $response->getInfo()); } @@ -255,7 +280,7 @@ public function testTransmitBatched(): void "batched" => true, "sender" => $senderMock )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier"); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier"); $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Pending", $response->getInfo()); $logger->flush(); @@ -269,7 +294,7 @@ public function testTransmitBatched(): void 'sender' => $senderMock )); - $response = $logger->log(Level::WARNING, "Testing PHP Notifier"); + $response = $logger->report(Level::WARNING, "Testing PHP Notifier"); $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Pending", $response->getInfo()); $response = $logger->flush(); @@ -285,7 +310,7 @@ public function testLogMalformedPayloadData(): void "transformer" => MalformedPayloadDataTransformer::class )); - $response = $logger->log( + $response = $logger->report( Level::ERROR, "Forced payload's data to false value.", array() @@ -313,7 +338,7 @@ public function testFlush(): void $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Queue empty", $response->getInfo()); - $response = $logger->log(Level::INFO, "Batched message"); + $response = $logger->report(Level::INFO, "Batched message"); $this->assertEquals(0, $response->getStatus()); $this->assertEquals("Pending", $response->getInfo()); @@ -326,7 +351,7 @@ public function testContext(): void "access_token" => $this->getTestAccessToken(), "environment" => "testing-php" )); - $response = $l->log( + $response = $l->report( Level::ERROR, new \Exception("Testing PHP Notifier"), array( @@ -342,7 +367,7 @@ public function testLogStaticLevel(): void "access_token" => $this->getTestAccessToken(), "environment" => "testing-php" )); - $response = $l->log(Level::warning(), "Testing PHP Notifier", array()); + $response = $l->report(Level::warning(), "Testing PHP Notifier", array()); $this->assertEquals(200, $response->getStatus()); } @@ -355,7 +380,7 @@ public function testErrorSampleRates(): void E_ERROR => 0 ) )); - $response = $l->log( + $response = $l->report( Level::ERROR, new ErrorWrapper( E_ERROR, @@ -379,11 +404,11 @@ public function testExceptionSampleRates(): void SilentExceptionSampleRate::class => 0.0 ) )); - $response = $l->log(Level::ERROR, new SilentExceptionSampleRate); + $response = $l->report(Level::ERROR, new SilentExceptionSampleRate); $this->assertEquals(0, $response->getStatus()); - $response = $l->log(Level::ERROR, new \Exception); + $response = $l->report(Level::ERROR, new \Exception); $this->assertEquals(200, $response->getStatus()); } @@ -395,7 +420,7 @@ public function testIncludedErrNo(): void "environment" => "testing-php", "included_errno" => E_ERROR | E_WARNING )); - $response = $l->log( + $response = $l->report( Level::ERROR, new ErrorWrapper( E_USER_ERROR, @@ -713,11 +738,11 @@ public function testMaxItems($maxItemsConfig): void $maxItems = $maxItemsConfig ?? Defaults::get()->maxItems(); for ($i = 0; $i < $maxItems; $i++) { - $response = $logger->log(Level::INFO, 'testing info level'); + $response = $logger->report(Level::INFO, 'testing info level'); $this->assertEquals(200, $response->getStatus()); } - $response = $logger->log(Level::INFO, 'testing info level'); + $response = $logger->report(Level::INFO, 'testing info level'); $this->assertEquals(0, $response->getStatus()); $this->assertEquals( diff --git a/tests/RollbarTest.php b/tests/RollbarTest.php index 7a7cdc20..d30cee00 100644 --- a/tests/RollbarTest.php +++ b/tests/RollbarTest.php @@ -1,9 +1,8 @@ getTestAccessToken(); self::$simpleConfig['environment'] = 'test'; } - private static string|array $simpleConfig = array(); - public static function setUpBeforeClass(): void { Rollbar::destroy(); @@ -82,7 +80,7 @@ public function testLogMessage(): void { Rollbar::init(self::$simpleConfig); - $response = Rollbar::log(Level::INFO, 'testing info level'); + Rollbar::log(Level::INFO, 'testing info level'); $this->assertTrue(true); } @@ -157,11 +155,17 @@ public function testEmergency(): void protected function shortcutMethodTestHelper($level): void { $message = "shortcutMethodTestHelper: $level"; - + + $verbose = new ArrayLogger(); + Rollbar::init(array('verbose_logger' => $verbose)); + $result = Rollbar::$level($message); - $expected = Rollbar::log($level, $message); - - $this->assertEquals($expected, $result); + $this->assertEquals(1, $verbose->count(Level::INFO, "Attempting to log: [$level] " . $message)); + $this->assertEquals(1, $verbose->count(Level::INFO, 'Occurrence successfully logged')); + + $expected = Rollbar::report($level, $message); + $this->assertEquals(2, $verbose->count(Level::INFO, "Attempting to log: [$level] " . $message)); + $this->assertEquals(2, $verbose->count(Level::INFO, 'Occurrence successfully logged')); } /** diff --git a/tests/TestHelpers/ArrayLogger.php b/tests/TestHelpers/ArrayLogger.php new file mode 100644 index 00000000..bfb5c6ec --- /dev/null +++ b/tests/TestHelpers/ArrayLogger.php @@ -0,0 +1,58 @@ +logs[] = self::stringify($level, $message); + } + + /** + * Returns the number of instances of a log in the logs. + * + * @param $level + * @param Stringable|string $message + * + * @return int + */ + public function count($level, Stringable|string $message): int + { + $count = 0; + $str = self::stringify($level, $message); + foreach ($this->logs as $log) { + if ($str === $log) { + $count++; + } + } + return $count; + } +} \ No newline at end of file diff --git a/tests/TestHelpers/StdOutLogger.php b/tests/TestHelpers/StdOutLogger.php index a80ba86b..01324b8c 100644 --- a/tests/TestHelpers/StdOutLogger.php +++ b/tests/TestHelpers/StdOutLogger.php @@ -2,13 +2,14 @@ namespace Rollbar\TestHelpers; +use Stringable; use Rollbar\RollbarLogger; use Psr\Log\LoggerTrait; class StdOutLogger extends RollbarLogger { - public function log($level, $toLog, array $context = array()) + public function log($level, string|Stringable $message, array $context = array()): void { - echo '[' . get_class($this) . ': '. $level . '] ' . $message; + echo '[' . get_class($this) . ': ' . $level . '] ' . $message; } } From c0114cff4019c24608508886c8165f8f4b270a76 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Wed, 26 Oct 2022 06:29:12 -0500 Subject: [PATCH 04/26] Added try finally to ensure dynamic property isUncaught is unset --- src/Rollbar.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Rollbar.php b/src/Rollbar.php index d9ee0841..a4c6c1af 100644 --- a/src/Rollbar.php +++ b/src/Rollbar.php @@ -146,8 +146,11 @@ public static function logUncaught($level, Throwable $toLog, $extra = array()) return self::getNotInitializedResponse(); } $toLog->isUncaught = true; - $result = self::$logger->report($level, $toLog, (array)$extra); - unset($toLog->isUncaught); + try { + $result = self::$logger->report($level, $toLog, (array)$extra); + } finally { + unset($toLog->isUncaught); + } return $result; } From d10139b6e8a141068c74aca574b7fd6043e1822e Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 31 Oct 2022 12:33:41 -0500 Subject: [PATCH 05/26] Removed deprecated log levels and fixed inconsistent use of LevelFactory --- src/Config.php | 20 +---- src/DataBuilder.php | 18 +---- src/LevelFactory.php | 58 ++++++++------ src/Payload/Level.php | 67 +++++++--------- src/RollbarLogger.php | 4 +- tests/ConfigTest.php | 25 +++--- tests/DataBuilderTest.php | 27 +------ tests/DataTest.php | 3 +- tests/LevelFactoryTest.php | 79 ++++++++++++------- tests/LevelTest.php | 26 ------ tests/Payload/LevelTest.php | 41 ++++++++++ tests/ReadmeTest.php | 2 +- tests/RollbarLoggerTest.php | 2 +- .../MalformedPayloadDataTransformer.php | 3 +- tests/VerbosityTest.php | 2 +- 15 files changed, 177 insertions(+), 200 deletions(-) delete mode 100644 tests/LevelTest.php create mode 100644 tests/Payload/LevelTest.php diff --git a/src/Config.php b/src/Config.php index 749e2c8c..768218a3 100644 --- a/src/Config.php +++ b/src/Config.php @@ -143,11 +143,6 @@ class Config private $dataBuilder; private $configArray; - /** - * @var LevelFactory - */ - private $levelFactory; - /** * @var TransformerInterface */ @@ -230,8 +225,6 @@ public function __construct(array $configArray) { $this->includedErrno = Defaults::get()->includedErrno(); - $this->levelFactory = new LevelFactory(); - $this->updateConfig($configArray); $this->errorSampleRates = Defaults::get()->errorSampleRates(); @@ -405,10 +398,6 @@ public function disable(): void private function setDataBuilder(array $config): void { - if (!isset($config['levelFactory'])) { - $config['levelFactory'] = $this->levelFactory; - } - if (!isset($config['utilities'])) { $config['utilities'] = $this->utilities(); } @@ -434,7 +423,7 @@ private function setMinimumLevel(array $config): void if ($override instanceof Level) { $this->minimumLevel = $override->toInt(); } elseif (is_string($override)) { - $level = $this->levelFactory->fromName($override); + $level = LevelFactory::fromName($override); if ($level !== null) { $this->minimumLevel = $level->toInt(); } @@ -731,11 +720,6 @@ public function getDataBuilder() return $this->dataBuilder; } - public function getLevelFactory() - { - return $this->levelFactory; - } - public function getSender() { return $this->sender; @@ -857,7 +841,7 @@ public function internalCheckIgnored(string $level, mixed $toLog): bool return true; } - if ($this->levelTooLow($this->levelFactory->fromName($level))) { + if ($this->levelTooLow(LevelFactory::fromName($level))) { $this->verboseLogger()->debug("Occurrence's level is too low"); return true; } diff --git a/src/DataBuilder.php b/src/DataBuilder.php index 0dfff4c9..d315b4ed 100644 --- a/src/DataBuilder.php +++ b/src/DataBuilder.php @@ -58,11 +58,6 @@ class DataBuilder implements DataBuilderInterface protected $captureEmail; protected $captureUsername; - /** - * @var LevelFactory - */ - protected $levelFactory; - /** * @var Utilities */ @@ -105,7 +100,6 @@ public function __construct($config) $this->setSendMessageTrace($config); $this->setLocalVarsDump($config); $this->setCaptureErrorStacktraces($config); - $this->setLevelFactory($config); $this->setCaptureEmail($config); $this->setCaptureUsername($config); $this->setCaptureIP($config); @@ -331,16 +325,6 @@ protected function setIncludeExcCodeContext($config) $this->includeExcCodeContext = self::$defaults->includeExcCodeContext($fromConfig); } - protected function setLevelFactory($config) - { - $this->levelFactory = $config['levelFactory'] ?? null; - if (!$this->levelFactory) { - throw new \InvalidArgumentException( - 'Missing dependency: LevelFactory not provided to the DataBuilder.' - ); - } - } - protected function setUtilities($config) { $this->utilities = $config['utilities'] ?? null; @@ -557,7 +541,7 @@ protected function getLevel($level, $toLog) $level = $this->psrLevels[$level] ?? null; if ($level !== null) { // this is a well-known PSR level: "error", "notice", "info", etc. - return $this->levelFactory->fromName($level); + return LevelFactory::fromName($level); } } return null; diff --git a/src/LevelFactory.php b/src/LevelFactory.php index fff7d839..2b884fb1 100644 --- a/src/LevelFactory.php +++ b/src/LevelFactory.php @@ -6,49 +6,59 @@ class LevelFactory { - - private static $values; + /** + * Holds the list of log levels as [string => Level]. + * + * @var array|null + */ + private static ?array $levels = null; - private static function init() + /** + * Returns the array of levels as [string => Level]. + * + * @return array + */ + private static function getLevels(): array { - if (is_null(self::$values)) { - self::$values = array( + if (null === self::$levels) { + self::$levels = array( Level::EMERGENCY => new Level("critical", 100000), - Level::ALERT => new Level("critical", 100000), - Level::CRITICAL => new Level("critical", 100000), - Level::ERROR => new Level("error", 10000), - Level::WARNING => new Level("warning", 1000), - Level::NOTICE => new Level("info", 100), - Level::INFO => new Level("info", 100), - Level::DEBUG => new Level("debug", 10), - Level::IGNORED => new Level("ignore", 0), - Level::IGNORE => new Level("ignore", 0) - + Level::ALERT => new Level("critical", 100000), + Level::CRITICAL => new Level("critical", 100000), + Level::ERROR => new Level("error", 10000), + Level::WARNING => new Level("warning", 1000), + Level::NOTICE => new Level("info", 100), + Level::INFO => new Level("info", 100), + Level::DEBUG => new Level("debug", 10), ); } + + return self::$levels; } /** + * Returns the {@see Level} instance for a given log level. If the log level + * is invalid null will be returned. + * * @param string $name level name * - * @return Level + * @return Level|null */ - public function fromName($name) + public static function fromName(string $name): ?Level { - self::init(); $name = strtolower($name); - return self::$values[$name] ?? null; + return self::getLevels()[$name] ?? null; } - + /** - * Check if the provided level is a valid level + * Check if the provided level is a valid level. * * @param string $level * - * @return string + * @return bool */ - public function isValidLevel($level) + public static function isValidLevel(string $level): bool { - return $this->fromName($level) ? true : false; + return self::fromName($level) !== null; } } diff --git a/src/Payload/Level.php b/src/Payload/Level.php index 1dbf35ab..9df0496a 100644 --- a/src/Payload/Level.php +++ b/src/Payload/Level.php @@ -2,68 +2,61 @@ namespace Rollbar\Payload; -use Rollbar\LevelFactory; use Rollbar\SerializerInterface; +/** + * Each constant is a PSR-3 compatible logging level. They are mapped to Rollbar + * service supported levels in {@see LevelFactory::getLevels()}. + */ class Level implements SerializerInterface { - /** - * Those are PSR-3 compatible loggin levels. They are mapped to Rollbar - * service supported levels in Level::init() - */ const EMERGENCY = 'emergency'; - const ALERT = 'alert'; - const CRITICAL = 'critical'; - const ERROR = 'error'; - const WARNING = 'warning'; - const NOTICE = 'notice'; - const INFO = 'info'; - const DEBUG = 'debug'; - - /** - * @deprecated 1.2.0 - */ - const IGNORED = 'ignored'; - /** - * @deprecated 1.2.0 - */ - const IGNORE = 'ignore'; + const ALERT = 'alert'; + const CRITICAL = 'critical'; + const ERROR = 'error'; + const WARNING = 'warning'; + const NOTICE = 'notice'; + const INFO = 'info'; + const DEBUG = 'debug'; /** - * @deprecated 1.2.0 + * Instantiates the level object with the Rollbar service compatible error + * levels. * - * Usage of Level::error(), Level::warning(), Level::info(), Level::notice(), - * Level::debug() is no longer supported. It has been replaced with matching - * class constants, i.e.: Level::ERROR + * @param string $level The Rollbar service error level. + * @param int $val The Rollbar service numeric error level. */ - public static function __callStatic($name, $args) - { - $factory = new LevelFactory(); - $level = $factory->fromName($name); - - if (!$level) { - throw new \Exception("Level '$level' doesn't exist."); - } - - return $level; - } - public function __construct( private string $level, private int $val ) { } + /** + * Returns the Rollbar service error level. + * + * @return string + */ public function __toString() { return $this->level; } + /** + * Returns the Rollbar service numeric error level. + * + * @return int + */ public function toInt(): int { return $this->val; } + /** + * Returns the serialized Rollbar service level. + * + * @return string + */ public function serialize() { return $this->level; diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index 86335a17..696c15f7 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -15,7 +15,6 @@ class RollbarLogger extends AbstractLogger { private $config; - private $levelFactory; private $truncation; private $queue; private $reportCount = 0; @@ -23,7 +22,6 @@ class RollbarLogger extends AbstractLogger public function __construct(array $config) { $this->config = new Config($config); - $this->levelFactory = new LevelFactory(); $this->truncation = new Truncation($this->config); $this->queue = array(); } @@ -134,7 +132,7 @@ public function report($level, string|Stringable $message, array $context = arra // enum here, and work with Level enum through protected level. if ($level instanceof Level) { $level = (string)$level; - } elseif (!$this->levelFactory->isValidLevel($level)) { + } elseif (!LevelFactory::isValidLevel($level)) { $exception = new InvalidArgumentException("Invalid log level '$level'."); $this->verboseLogger()->error($exception->getMessage()); throw $exception; diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index d581436e..98d44f32 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -322,21 +322,21 @@ public function testMinimumLevel(): void 'environment' => $this->env )); - $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(Level::DEBUG())); + $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(LevelFactory::fromName(Level::DEBUG))); - $config->configure(array('minimum_level' => Level::WARNING())); + $config->configure(array('minimum_level' => LevelFactory::fromName(Level::WARNING))); - $this->assertPayloadIgnored($config, $this->prepareMockPayload(Level::DEBUG())); - $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(Level::WARNING())); + $this->assertPayloadIgnored($config, $this->prepareMockPayload(LevelFactory::fromName(Level::DEBUG))); + $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(LevelFactory::fromName(Level::WARNING))); $config = new Config(array( 'access_token' => $this->getTestAccessToken(), 'environment' => $this->env, - 'minimumLevel' => Level::ERROR() + 'minimumLevel' => Level::ERROR )); - $this->assertPayloadIgnored($config, $this->prepareMockPayload(Level::WARNING())); - $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(Level::ERROR())); + $this->assertPayloadIgnored($config, $this->prepareMockPayload(LevelFactory::fromName(Level::WARNING))); + $this->assertPayloadNotIgnored($config, $this->prepareMockPayload(LevelFactory::fromName(Level::ERROR))); } public function assertPayloadIgnored($config, $payload): void @@ -405,7 +405,7 @@ public function testFilter(): void { $d = m::mock(Data::class) ->shouldReceive("getLevel") - ->andReturn(Level::CRITICAL()) + ->andReturn(LevelFactory::fromName(Level::CRITICAL)) ->mock(); $p = m::mock(Payload::class) ->shouldReceive("getData") @@ -744,10 +744,9 @@ public function testCheckIgnore(): void $called = true; } )); - $levelFactory = $config->getLevelFactory(); - + $data = new Data($this->env, new Body(new Message("test"))); - $data->setLevel($levelFactory->fromName(Level::ERROR)); + $data->setLevel(LevelFactory::fromName(Level::ERROR)); $config->checkIgnored( new Payload( @@ -785,10 +784,8 @@ public function testCheckIgnoreParameters(): void } )); - $levelFactory = $config->getLevelFactory(); - $data = new Data($this->env, new Body(new Message("test"))); - $data->setLevel($levelFactory->fromName(Level::ERROR)); + $data->setLevel(LevelFactory::fromName(Level::ERROR)); $config->checkIgnored( new Payload( diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index 71f429e6..317f90bc 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -16,7 +16,6 @@ public function setUp(): void $this->dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); } @@ -345,7 +344,6 @@ public function testBranchKey(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'branch' => 'test-branch', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); @@ -359,7 +357,6 @@ public function testCodeVersion(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'code_version' => '3.4.1', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -372,7 +369,6 @@ public function testHost(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'host' => 'my host', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -384,7 +380,6 @@ public function testGetMessage(): void $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); @@ -399,7 +394,6 @@ public function testGetMessageSendMessageTrace(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'send_message_trace' => true, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); @@ -451,7 +445,6 @@ public function testStackFramesAreUnavailableWhenLocalVarsDumpConfigUnset(): voi $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $exception = $this->exceptionTraceArgsHelper('trace args message'); @@ -474,7 +467,6 @@ public function testStackFramesAreAvailableWhenLocalVarsDumpRequested($valueOfZe 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'local_vars_dump' => true, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $expected = 'trace args message'; @@ -509,7 +501,6 @@ public function testExceptionFramesWithoutContext(): void 'environment' => 'tests', 'include_error_code_context' => true, 'include_exception_code_context' => false, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->getExceptionTrace(new \Exception())->getFrames(); @@ -521,7 +512,6 @@ public function testExceptionFramesWithoutContextDefault(): void $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->getExceptionTrace(new \Exception())->getFrames(); @@ -534,7 +524,6 @@ public function testExceptionFramesWithContext(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'include_exception_code_context' => true, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->getExceptionTrace(new \Exception())->getFrames(); @@ -550,7 +539,6 @@ public function testFramesWithoutContext(): void 'environment' => 'tests', 'include_error_code_context' => false, 'include_exception_code_context' => true, - 'levelFactory' => new LevelFactory, 'utilities' => $utilities )); $testFilePath = __DIR__ . '/DataBuilderTest.php'; @@ -591,7 +579,6 @@ public function testFramesWithContext(): void 'environment' => 'tests', 'include_error_code_context' => true, 'include_exception_code_context' => false, - 'levelFactory' => new LevelFactory, 'utilities' => $utilities )); @@ -656,7 +643,6 @@ public function testFramesWithoutContextDefault(): void $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => $utilities )); @@ -710,7 +696,6 @@ public function testPerson(): void 'username' => 'tester', 'email' => 'test@test.com' ), - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -752,7 +737,6 @@ public function testPersonFunc(): void 'email' => 'test@test.com' ); }, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -769,7 +753,6 @@ public function testPersonIntID(): void 'username' => 'tester', 'email' => 'test@test.com' ), - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -804,7 +787,6 @@ public function testRoot(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'root' => '/var/www/app', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $output = $dataBuilder->makeData(Level::ERROR, "testing", array()); @@ -825,7 +807,6 @@ public function testSetRequestBody(): void $dataBuilder = new DataBuilder(array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities, 'include_raw_request_body' => true, )); @@ -854,7 +835,6 @@ public function testPostDataPutRequest(): void $config = array( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities, 'include_raw_request_body' => true ); @@ -889,7 +869,6 @@ public function testCaptureErrorStacktracesException( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'capture_error_stacktraces' => $captureErrorStacktraces, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); @@ -909,7 +888,6 @@ public function testFramesOrder(): void 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'include_exception_code_context' => true, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); $frames = $dataBuilder->makeFrames(new \Exception(), false); // A @@ -917,9 +895,9 @@ public function testFramesOrder(): void 'tests/DataBuilderTest.php', $frames[count($frames)-1]->getFilename() ); - // 915 is the line number where the comment "// A" is found + // 893 is the line number where the comment "// A" is found $this->assertEquals( - 915, + 893, $frames[count($frames)-1]->getLineno(), "Possible false negative: did this file change? Check the line number for line with '// A' comment" ); @@ -938,7 +916,6 @@ public function testCaptureErrorStacktracesError( 'accessToken' => $this->getTestAccessToken(), 'environment' => 'tests', 'capture_error_stacktraces' => $captureErrorStacktraces, - 'levelFactory' => new LevelFactory, 'utilities' => new Utilities )); diff --git a/tests/DataTest.php b/tests/DataTest.php index bc2a2147..55b4160f 100644 --- a/tests/DataTest.php +++ b/tests/DataTest.php @@ -39,11 +39,10 @@ public function testBody(): void public function testLevel(): void { - $levelFactory = new LevelFactory; $level = Level::ERROR; $this->assertEquals( - $levelFactory->fromName($level), + LevelFactory::fromName($level), $this->data->setLevel($level)->getLevel() ); } diff --git a/tests/LevelFactoryTest.php b/tests/LevelFactoryTest.php index cc8a2373..19d27e41 100644 --- a/tests/LevelFactoryTest.php +++ b/tests/LevelFactoryTest.php @@ -4,58 +4,79 @@ class LevelFactoryTest extends BaseRollbarTest { - private LevelFactory $levelFactory; - - public function setUp(): void - { - $this->levelFactory = new LevelFactory(); - } - /** * @dataProvider isValidLevelProvider */ - public function testIsValidLevelProvider($level, $expected): void + public function testIsValidLevelProvider(string $level, bool $expected): void { - $this->assertEquals( + self::assertSame( $expected, - $this->levelFactory->isValidLevel($level) + LevelFactory::isValidLevel($level) ); } - + public function isValidLevelProvider(): array { $data = $this->fromNameProvider(); foreach ($data as &$testParams) { - $testParams []= true; + $testParams[] = true; } - $data []= array('test-stub', false); + $data[] = ['test-stub', false]; return $data; } - + + public function testFromNameInvalid(): void + { + self::assertNull(LevelFactory::fromName('not a level')); + } + /** * @dataProvider fromNameProvider */ - public function testFromName($level): void + public function testFromName(string $level): void { - $this->assertInstanceOf( + self::assertInstanceOf( Level::class, - $this->levelFactory->fromName($level) + LevelFactory::fromName($level) ); } - + public function fromNameProvider(): array { - return array( - array(Level::EMERGENCY), - array(Level::ALERT), - array(Level::CRITICAL), - array(Level::ERROR), - array(Level::WARNING), - array(Level::NOTICE), - array(Level::INFO), - array(Level::DEBUG), - array(Level::IGNORED), - array(Level::IGNORE), + return [ + [Level::EMERGENCY], + [Level::ALERT], + [Level::CRITICAL], + [Level::ERROR], + [Level::WARNING], + [Level::NOTICE], + [Level::INFO], + [Level::DEBUG], + ]; + } + + /** + * @dataProvider fromNameOrInstanceProvider + */ + public function testFromNameOrInstance(Level|string $level): void + { + self::assertInstanceOf( + Level::class, + LevelFactory::fromName($level) ); } + + public function fromNameOrInstanceProvider(): array + { + return [ + [Level::EMERGENCY], + [Level::ALERT], + [LevelFactory::fromName(Level::CRITICAL)], + [Level::ERROR], + [Level::WARNING], + [LevelFactory::fromName(Level::NOTICE)], + [LevelFactory::fromName(Level::INFO)], + [Level::DEBUG], + ]; + } } diff --git a/tests/LevelTest.php b/tests/LevelTest.php deleted file mode 100644 index c43a516a..00000000 --- a/tests/LevelTest.php +++ /dev/null @@ -1,26 +0,0 @@ -expectException(\Exception::class); - $level = Level::TEST(); - } - - public function testLevel(): void - { - $level = Level::CRITICAL(); - $this->assertNotNull($level); - $this->assertSame(Level::CRITICAL(), $level); - $this->assertSame(Level::critical(), $level); - - $level = Level::Info(); - $this->assertNotNull($level); - $this->assertSame(Level::INFO(), $level); - $this->assertSame('"info"', json_encode($level->serialize())); - } -} diff --git a/tests/Payload/LevelTest.php b/tests/Payload/LevelTest.php new file mode 100644 index 00000000..62858470 --- /dev/null +++ b/tests/Payload/LevelTest.php @@ -0,0 +1,41 @@ +level = (new LevelFactory())->fromName(Level::ERROR); + } + + public function testInvalidLevelThrowsAnException(): void + { + self::expectException(\Error::class); + $level = Level::TEST(); + } + + public function testLevel(): void + { + $level = Level::CRITICAL; + self::assertNotNull($level); + self::assertSame(Level::CRITICAL, $level); + } + + public function testStringable(): void + { + self::assertSame('error', (string)$this->level); + } + + public function testToInt(): void + { + self::assertSame(10000, $this->level->toInt()); + } + + public function testSerialize(): void + { + self::assertSame('error', $this->level->serialize()); + } +} diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php index cd41e526..17865f7d 100644 --- a/tests/ReadmeTest.php +++ b/tests/ReadmeTest.php @@ -40,7 +40,7 @@ public function testQuickStart(): void ); // If you want to check if logging with Rollbar was successful - $response = Rollbar::report((new LevelFactory)->fromName(Level::INFO), 'testing wasSuccessful()'); + $response = Rollbar::report(LevelFactory::fromName(Level::INFO), 'testing wasSuccessful()'); if (!$response->wasSuccessful()) { throw new \Exception('logging with Rollbar failed'); } diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index 5ac48989..6820e07f 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -367,7 +367,7 @@ public function testLogStaticLevel(): void "access_token" => $this->getTestAccessToken(), "environment" => "testing-php" )); - $response = $l->report(Level::warning(), "Testing PHP Notifier", array()); + $response = $l->report(Level::WARNING, "Testing PHP Notifier", array()); $this->assertEquals(200, $response->getStatus()); } diff --git a/tests/TestHelpers/MalformedPayloadDataTransformer.php b/tests/TestHelpers/MalformedPayloadDataTransformer.php index 81df991c..936e38d5 100644 --- a/tests/TestHelpers/MalformedPayloadDataTransformer.php +++ b/tests/TestHelpers/MalformedPayloadDataTransformer.php @@ -14,8 +14,7 @@ public function transform( ): ?Payload { $mock = \Mockery::mock(Data::class)->makePartial(); $mock->shouldReceive("serialize")->andReturn(false); - $levelFactory = new \Rollbar\LevelFactory(); - $mock->setLevel($levelFactory->fromName($level)); + $mock->setLevel(\Rollbar\LevelFactory::fromName($level)); $payload->setData($mock); return $payload; } diff --git a/tests/VerbosityTest.php b/tests/VerbosityTest.php index e727f13c..d7b0f9ab 100644 --- a/tests/VerbosityTest.php +++ b/tests/VerbosityTest.php @@ -605,7 +605,7 @@ function () use ($config, $unitTest) { $dataMock = $unitTest->getMockBuilder(Data::class) ->disableOriginalConstructor() ->getMock(); - $dataMock->method('getLevel')->willReturn(\Rollbar\Payload\Level::INFO()); + $dataMock->method('getLevel')->willReturn(\Rollbar\LevelFactory::fromName(Level::INFO)); $payloadMock = $unitTest->getMockBuilder(Payload::class) ->disableOriginalConstructor() ->getMock(); From 2cbdca3b2ac498f258986ddeaa987f0a38fe3da4 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 31 Oct 2022 14:45:50 -0500 Subject: [PATCH 06/26] Fixed codes style --- tests/RollbarLoggerTest.php | 6 ++++-- tests/TestHelpers/ArrayLogger.php | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index 6820e07f..d4c0e1fa 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -159,8 +159,10 @@ public function testNotLoggingPayload(): void $this->assertSame(0, $verbose->count(Level::INFO, 'Occurrence successfully logged')); $logger->log(Level::WARNING, "Testing PHP Notifier", []); - $this->assertSame(1, - $verbose->count(Level::INFO, 'Attempting to log: [' . Level::WARNING . '] Testing PHP Notifier')); + $this->assertSame( + 1, + $verbose->count(Level::INFO, 'Attempting to log: [' . Level::WARNING . '] Testing PHP Notifier'), + ); $this->assertSame(1, $verbose->count(Level::INFO, 'Occurrence successfully logged')); } diff --git a/tests/TestHelpers/ArrayLogger.php b/tests/TestHelpers/ArrayLogger.php index bfb5c6ec..2d4abfdb 100644 --- a/tests/TestHelpers/ArrayLogger.php +++ b/tests/TestHelpers/ArrayLogger.php @@ -5,7 +5,6 @@ use Psr\Log\AbstractLogger; use Stringable; - /** * Simple logger that saves logs to an array. * @@ -55,4 +54,4 @@ public function count($level, Stringable|string $message): int } return $count; } -} \ No newline at end of file +} From f6bf9330225d8d487be9f3e5dfb4cbfa946a0d1e Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 1 Nov 2022 06:21:12 -0500 Subject: [PATCH 07/26] Removed deprecated reporting methods from Rollbar --- src/Rollbar.php | 69 ------------------------------------------- tests/RollbarTest.php | 37 ----------------------- 2 files changed, 106 deletions(-) diff --git a/src/Rollbar.php b/src/Rollbar.php index a4c6c1af..148728d9 100644 --- a/src/Rollbar.php +++ b/src/Rollbar.php @@ -266,73 +266,4 @@ public static function destroy() { self::$logger = null; } - - // @codingStandardsIgnoreStart - - /** - * Below methods are deprecated and still available only for backwards - * compatibility. If you're still using them in your application, please - * transition to using the ::log method as soon as possible. - */ - - /** - * @param \Exception $exc Exception to be logged - * @param array $extra_data Additional data to be logged with the exception - * @param array $payload_data This is deprecated as of v1.0.0 and remains for - * backwards compatibility. The content fo this array will be merged with - * $extra_data. - * - * @return string uuid - * - * @deprecated 1.0.0 This method has been replaced by ::log - */ - public static function report_exception($exc, $extra_data = null, $payload_data = null) - { - $extra_data = array_merge($extra_data ?? [], $payload_data ?? []); - return self::report(Level::ERROR, $exc, $extra_data)->getUuid(); - } - - /** - * @param string $message Message to be logged - * @param string $level One of the values in \Rollbar\Payload\Level::$values - * @param array $extra_data Additional data to be logged with the exception - * @param array $payload_data This is deprecated as of v1.0.0 and remains for - * backwards compatibility. The content fo this array will be merged with - * $extra_data. - * - * @return string uuid - * - * @deprecated 1.0.0 This method has been replaced by ::log - */ - public static function report_message($message, $level = null, $extra_data = null, $payload_data = null) - { - $level = $level ?? Level::ERROR; - $extra_data = array_merge($extra_data ?? [], $payload_data ?? []); - return self::report($level, $message, $extra_data)->getUuid(); - } - - - /** - * Catch any fatal errors that are causing the shutdown - * - * @deprecated 1.0.0 This method has been replaced by ::fatalHandler - */ - public static function report_fatal_error() - { - self::$fatalHandler->handle(); - } - - - /** - * This function must return false so that the default php error handler runs - * - * @deprecated 1.0.0 This method has been replaced by ::log - */ - public static function report_php_error($errno, $errstr, $errfile, $errline) - { - self::$errorHandler->handle($errno, $errstr, $errfile, $errline); - return false; - } - - // @codingStandardsIgnoreEnd } diff --git a/tests/RollbarTest.php b/tests/RollbarTest.php index d30cee00..7ce8958f 100644 --- a/tests/RollbarTest.php +++ b/tests/RollbarTest.php @@ -168,43 +168,6 @@ protected function shortcutMethodTestHelper($level): void $this->assertEquals(2, $verbose->count(Level::INFO, 'Occurrence successfully logged')); } - /** - * Below are backwards compatibility tests with v0.18.2 - */ - public function testBackwardsSimpleMessageVer(): void - { - Rollbar::init(self::$simpleConfig); - - $uuid = Rollbar::report_message("Hello world"); - $this->assertStringMatchesFormat('%x-%x-%x-%x-%x', $uuid); - } - - public function testBackwardsSimpleError(): void - { - set_error_handler(function () { - }); // disable PHPUnit's error handler - - Rollbar::init(self::$simpleConfig); - - $result = Rollbar::report_php_error(E_ERROR, "Runtime error", "the_file.php", 1); - // always returns false. - $this->assertFalse($result); - } - - public function testBackwardsSimpleException(): void - { - Rollbar::init(self::$simpleConfig); - - $uuid = null; - try { - throw new \Exception("test exception"); - } catch (\Exception $e) { - $uuid = Rollbar::report_exception($e); - } - - $this->assertStringMatchesFormat('%x-%x-%x-%x-%x', $uuid); - } - public function testBackwardsFlush(): void { Rollbar::init(self::$simpleConfig); From b38acb9a3a063e6b34cc6b693ec8c907e7650292 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Wed, 16 Nov 2022 06:25:32 -0600 Subject: [PATCH 08/26] Renamed IStrategy to StrategyInterface and added type annotations and comments --- src/Config.php | 33 ++++++++-- src/Truncation/AbstractStrategy.php | 17 +++-- src/Truncation/FramesStrategy.php | 55 ++++++++++++++--- src/Truncation/IStrategy.php | 20 ------ src/Truncation/MinBodyStrategy.php | 68 +++++++++++--------- src/Truncation/RawStrategy.php | 7 ++- src/Truncation/StrategyInterface.php | 37 +++++++++++ src/Truncation/StringsStrategy.php | 73 +++++++++++++++------- src/Truncation/Truncation.php | 79 ++++++++++++++++-------- tests/Truncation/FramesStrategyTest.php | 10 ++- tests/Truncation/StringsStrategyTest.php | 16 +++-- tests/Truncation/TruncationTest.php | 12 ++-- 12 files changed, 294 insertions(+), 133 deletions(-) delete mode 100644 src/Truncation/IStrategy.php create mode 100644 src/Truncation/StrategyInterface.php diff --git a/src/Config.php b/src/Config.php index 768218a3..449fc898 100644 --- a/src/Config.php +++ b/src/Config.php @@ -202,11 +202,15 @@ class Config private bool $sendMessageTrace = false; /** - * @var string (fully qualified class name) The name of the your custom - * truncation strategy class. The class should inherit from - * Rollbar\Truncation\AbstractStrategy. + * The fully qualified class name of a custom truncation strategy class or null if no custom class is specified. + * The class should implement {@see \Rollbar\Truncation\StrategyInterface}. + * + * @var string|null $customTruncation + * + * @since 1.6.0 + * @since 4.0.0 Added string|null type, and defaults to null. */ - private $customTruncation; + private ?string $customTruncation = null; /** * @var boolean Should the SDK raise an exception after logging an error. @@ -546,12 +550,29 @@ public function getAllowedCircularReferenceTypes() return $this->allowedCircularReferenceTypes; } - public function setCustomTruncation($type) + /** + * Sets the custom truncation strategy class for payloads. + * + * @param string|null $type The fully qualified class name of the custom payload truncation strategy. The class + * must implement {@see \Rollbar\Truncation\StrategyInterface}. If null is given any custom + * strategy will be removed. + * + * @return void + */ + public function setCustomTruncation(?string $type): void { $this->customTruncation = $type; } - public function getCustomTruncation() + /** + * Returns the fully qualified class name of the custom payload truncation strategy. + * + * @return string|null Will return null if a custom truncation strategy was not defined. + * + * @since 1.6.0 + * @since 4.0.0 Added may return null. + */ + public function getCustomTruncation(): ?string { return $this->customTruncation; } diff --git a/src/Truncation/AbstractStrategy.php b/src/Truncation/AbstractStrategy.php index bb69a634..bc32ac7e 100644 --- a/src/Truncation/AbstractStrategy.php +++ b/src/Truncation/AbstractStrategy.php @@ -4,18 +4,23 @@ use Rollbar\Payload\EncodedPayload; -class AbstractStrategy implements IStrategy +/** + * The base for all Rollbar truncation classes. + * + * @since 1.1.0 + */ +abstract class AbstractStrategy implements StrategyInterface { - public function __construct(protected $truncation) + public function __construct(protected Truncation $truncation) { } - - public function execute(EncodedPayload $payload) + + public function execute(EncodedPayload $payload): EncodedPayload { return $payload; } - - public function applies(EncodedPayload $payload) + + public function applies(EncodedPayload $payload): bool { return true; } diff --git a/src/Truncation/FramesStrategy.php b/src/Truncation/FramesStrategy.php index 63fe270f..eed2d577 100644 --- a/src/Truncation/FramesStrategy.php +++ b/src/Truncation/FramesStrategy.php @@ -2,32 +2,60 @@ namespace Rollbar\Truncation; +use Exception; use Rollbar\Payload\EncodedPayload; +/** + * The Frames strategy truncates long trace frame chains by keeping a specific number of frames at the beginning and + * end. The middle frames are removed, if the list of frames is too long. + * + * @since 1.1.0 + */ class FramesStrategy extends AbstractStrategy { - + /** + * The number of frames to keep at the beginning and end of the frames array. + */ const FRAMES_OPTIMIZATION_RANGE = 75; - public function execute(EncodedPayload $payload) + /** + * Truncates the data in the payload by removing excess frames from the middle of the trace chain. + * + * @param EncodedPayload $payload + * + * @return EncodedPayload + * @throws Exception If the payload encoding fails. + */ + public function execute(EncodedPayload $payload): EncodedPayload { $data = $payload->data(); if (isset($data['data']['body']['trace_chain'])) { foreach ($data['data']['body']['trace_chain'] as $offset => $value) { - $data['data']['body']['trace_chain'][$offset]['frames'] = $this->selectFrames($value['frames']); + $data['data']['body']['trace_chain'][$offset]['frames'] = self::selectFrames($value['frames']); } - + $payload->encode($data); } elseif (isset($data['data']['body']['trace']['frames'])) { - $data['data']['body']['trace']['frames'] = $this->selectFrames($data['data']['body']['trace']['frames']); + $data['data']['body']['trace']['frames'] = self::selectFrames($data['data']['body']['trace']['frames']); $payload->encode($data); } return $payload; } - public function selectFrames($frames, $range = self::FRAMES_OPTIMIZATION_RANGE) + /** + * Removes frames from the middle of the stack trace frames. Will keep the number of frames specified by $range at + * the start and end of the array. + * + * This method is also used by {@see MinBodyStrategy}. + * + * @param array $frames The list of stack trace frames. + * @param int $range The number of frames to keep on each end of the frames array. + * + * @return array + */ + public static function selectFrames(array $frames, int $range = self::FRAMES_OPTIMIZATION_RANGE): array { if (count($frames) <= $range * 2) { return $frames; @@ -38,16 +66,23 @@ public function selectFrames($frames, $range = self::FRAMES_OPTIMIZATION_RANGE) array_splice($frames, -$range, $range) ); } - - public function applies(EncodedPayload $payload) + + /** + * Returns true if the payload has a trace chain or trace frames. + * + * @param EncodedPayload $payload + * + * @return bool + */ + public function applies(EncodedPayload $payload): bool { $payload = $payload->data(); - + if (isset($payload['data']['body']['trace_chain']) || isset($payload['data']['body']['trace']['frames'])) { return true; } - + return false; } } diff --git a/src/Truncation/IStrategy.php b/src/Truncation/IStrategy.php deleted file mode 100644 index ac75aff0..00000000 --- a/src/Truncation/IStrategy.php +++ /dev/null @@ -1,20 +0,0 @@ -data(); - - $modified = false; - + $data = $payload->data(); + $modified = false; $traceData = array(); - + if (isset($data['data']['body']['trace'])) { $traceData = &$data['data']['body']['trace']; } elseif (isset($data['data']['body']['trace_chain'])) { $traceData = &$data['data']['body']['trace_chain']; } - + if (isset($traceData['exception'])) { - /** - * Delete exception description - */ + // Delete exception description unset($traceData['exception']['description']); - - /** - * Truncate exception message - */ + + // Truncate exception message $traceData['exception']['message'] = substr( $traceData['exception']['message'], 0, static::EXCEPTION_MESSAGE_LIMIT ); - + $modified = true; } - - /** - * Limit trace frames - */ + + // Limit trace frames if (!empty($traceData['frames'])) { - $framesStrategy = new FramesStrategy($this->truncation); - $traceData['frames'] = $framesStrategy->selectFrames( + $traceData['frames'] = FramesStrategy::selectFrames( $traceData['frames'], static::EXCEPTION_FRAMES_RANGE ); - + $modified = true; } - + if ($modified) { - $payloadClass = get_class($payload); - $payload = new $payloadClass($data); - $payload->encode(); + $payload->encode($data); } - + return $payload; } } diff --git a/src/Truncation/RawStrategy.php b/src/Truncation/RawStrategy.php index 2c5aa6c4..69d32213 100644 --- a/src/Truncation/RawStrategy.php +++ b/src/Truncation/RawStrategy.php @@ -4,9 +4,14 @@ use Rollbar\Payload\EncodedPayload; +/** + * The raw strategy does not truncate the payload at all. + * + * @since 1.1.0 + */ class RawStrategy extends AbstractStrategy { - public function execute(EncodedPayload $payload) + public function execute(EncodedPayload $payload): EncodedPayload { return $payload; } diff --git a/src/Truncation/StrategyInterface.php b/src/Truncation/StrategyInterface.php new file mode 100644 index 00000000..f78aa111 --- /dev/null +++ b/src/Truncation/StrategyInterface.php @@ -0,0 +1,37 @@ +data(); + $data = $payload->data(); $modified = false; - + foreach (static::getThresholds() as $threshold) { - $maxPayloadSize = \Rollbar\Truncation\Truncation::MAX_PAYLOAD_SIZE; - - if (!$this->truncation->needsTruncating($payload, $this)) { + if (!$this->truncation->needsTruncating($payload)) { break; } - + if ($this->traverse($data, $threshold, $payload)) { $modified = true; } } - + if ($modified) { $payload->encode($data); } - + return $payload; } - - protected function traverse(&$data, $threshold, $payload) + + /** + * Traverse recursively reduces the length of each string to the max length of $threshold. The strings in the $data + * array are truncated in place and not returned. + * + * @param array $data An array that may contain strings needing to be truncated. + * @param int $threshold The maximum length string may be before it is truncated. + * @param EncodedPayload $payload The payload that may need to be truncated. + * + * @return bool Returns true if the data was modified. + */ + protected function traverse(array &$data, int $threshold, EncodedPayload $payload): bool { $modified = false; - - foreach ($data as $key => &$value) { + + foreach ($data as &$value) { if (is_array($value)) { if ($this->traverse($value, $threshold, $payload)) { $modified = true; } - } else { - if (is_string($value) && (($strlen = strlen($value)) > $threshold)) { - $value = substr($value, 0, $threshold); - $modified = true; - $payload->decreaseSize($strlen - $threshold); - } + continue; + } + if (is_string($value) && (($strlen = strlen($value)) > $threshold)) { + $value = substr($value, 0, $threshold); + $modified = true; + $payload->decreaseSize($strlen - $threshold); } } - + return $modified; } } diff --git a/src/Truncation/Truncation.php b/src/Truncation/Truncation.php index 2328bbd3..d004fdb1 100644 --- a/src/Truncation/Truncation.php +++ b/src/Truncation/Truncation.php @@ -2,77 +2,104 @@ namespace Rollbar\Truncation; +use Exception; use Rollbar\Payload\EncodedPayload; use Rollbar\Config; -use Rollbar\Truncation\AbstractStrategy; -use Rollbar\Truncation\StringsStrategy; -use Rollbar\Truncation\FramesStrategy; +/** + * The payload truncation manager. + * + * @since 1.2.0 + */ class Truncation { + /** + * If a payload is smaller than this it will not be truncated. + */ const MAX_PAYLOAD_SIZE = 131072; // 128 * 1024 - - protected static $truncationStrategies = array( + + /** + * @var string[] The list of truncation strategies to apply in order. + */ + protected static array $truncationStrategies = array( FramesStrategy::class, - StringsStrategy::class + StringsStrategy::class, ); - + + /** + * Creates the truncation manager class and attempts to register a custom truncation strategy from the configs if + * it exists. + * + * @throws Exception If the strategy class does not implement {@see StrategyInterface}. + */ public function __construct(private Config $config) { if ($custom = $config->getCustomTruncation()) { $this->registerStrategy($custom); } } - - public function registerStrategy($type) + + /** + * Adds a new truncation strategy to the list of strategies used to truncate large payloads before they are sent + * over the wire. A strategy registered with this method will be used before any existing ones are used. It does + * not replace or remove existing strategies. + * + * @param string $type The fully qualified class name of a truncation strategy. The strategy must implement the + * {@see StrategyInterface} interface. + * + * @return void + * @throws Exception If the strategy class does not implement {@see StrategyInterface}. + */ + public function registerStrategy(string $type): void { - if (!class_exists($type) || !is_subclass_of($type, AbstractStrategy::class)) { - throw new \Exception( - "Truncation strategy '$type' doesn't exist or is not a subclass " . - "of Rollbar\Truncation\AbstractStrategy" + if (!class_exists($type)) { + throw new Exception('Truncation strategy "' . $type . '" doesn\'t exist.'); + } + if (!in_array(StrategyInterface::class, class_implements($type))) { + throw new Exception( + 'Truncation strategy "' . $type . '" doesn\'t implement ' . StrategyInterface::class ); } array_unshift(static::$truncationStrategies, $type); } - + /** * Applies truncation strategies in order to keep the payload size under * configured limit. * - * @param \Rollbar\Payload\EncodedPayload $payload - * @param string $strategy + * @param EncodedPayload $payload The payload that may need to be truncated. * - * @return \Rollbar\Payload\EncodedPayload + * @return EncodedPayload */ - public function truncate(EncodedPayload $payload) + public function truncate(EncodedPayload $payload): EncodedPayload { foreach (static::$truncationStrategies as $strategy) { $strategy = new $strategy($this); - + if (!$strategy->applies($payload)) { continue; } - - if (!$this->needsTruncating($payload, $strategy)) { + + if (!$this->needsTruncating($payload)) { break; } $this->config->verboseLogger()->debug('Applying truncation strategy ' . get_class($strategy)); - + $payload = $strategy->execute($payload); } - + return $payload; } - + /** * Check if the payload is too big to be sent * - * @param array $payload + * @param EncodedPayload $payload The payload that may need to be truncated. * * @return boolean */ - public function needsTruncating(EncodedPayload $payload, $strategy) + public function needsTruncating(EncodedPayload $payload): bool { return $payload->size() > self::MAX_PAYLOAD_SIZE; } diff --git a/tests/Truncation/FramesStrategyTest.php b/tests/Truncation/FramesStrategyTest.php index 2e9bb0b1..96ad41b5 100644 --- a/tests/Truncation/FramesStrategyTest.php +++ b/tests/Truncation/FramesStrategyTest.php @@ -11,7 +11,7 @@ class FramesStrategyTest extends BaseRollbarTest /** * @dataProvider executeProvider */ - public function testExecute($data, $expected): void + public function testExecute(array $data, array $expected): void { $config = new Config(array('access_token' => $this->getTestAccessToken())); $truncation = new Truncation($config); @@ -25,7 +25,13 @@ public function testExecute($data, $expected): void $this->assertEquals($expected, $result->data()); } - + + + /** + * Also used by {@see TruncationTest::truncateProvider()}. + * + * @return array + */ public function executeProvider(): array { $data = array( diff --git a/tests/Truncation/StringsStrategyTest.php b/tests/Truncation/StringsStrategyTest.php index c7f769b2..79ceb92a 100644 --- a/tests/Truncation/StringsStrategyTest.php +++ b/tests/Truncation/StringsStrategyTest.php @@ -30,7 +30,12 @@ public function testExecuteTruncateNothing($data, $expected): void $result = $this->execute($data); $this->assertEquals($expected, $result); } - + + /** + * Also used by {@see TruncationTest::truncateProvider()}. + * + * @return array + */ public function executeTruncateNothingProvider(): array { $data = array(); @@ -50,8 +55,6 @@ public function testExecuteArray($data, $expectedThreshold): void { $result = $this->execute($data); - $resultAnalysis = array(); - foreach ($result['data']['body']['message']['body']['value'] as $key => $toTrim) { $this->assertTrue( strlen($toTrim) <= $expectedThreshold, @@ -60,7 +63,12 @@ public function testExecuteArray($data, $expectedThreshold): void ); } } - + + /** + * Also used by {@see TruncationTest::truncateProvider()}. + * + * @return array + */ public function executeArrayProvider(): array { $data = array(); diff --git a/tests/Truncation/TruncationTest.php b/tests/Truncation/TruncationTest.php index 0cb7b816..3eb841db 100644 --- a/tests/Truncation/TruncationTest.php +++ b/tests/Truncation/TruncationTest.php @@ -13,7 +13,7 @@ class TruncationTest extends BaseRollbarTest public function setUp(): void { $config = new Config(array('access_token' => $this->getTestAccessToken())); - $this->truncate = new \Rollbar\Truncation\Truncation($config); + $this->truncate = new Truncation($config); } public function testCustomTruncation(): void @@ -22,7 +22,7 @@ public function testCustomTruncation(): void 'access_token' => $this->getTestAccessToken(), 'custom_truncation' => CustomTruncation::class )); - $this->truncate = new \Rollbar\Truncation\Truncation($config); + $this->truncate = new Truncation($config); $data = new EncodedPayload(array( "data" => array( @@ -39,7 +39,7 @@ public function testCustomTruncation(): void $result = $this->truncate->truncate($data); - $this->assertNotFalse(str_contains($data, 'Custom truncation test string')); + $this->assertStringContainsString('Custom truncation test string', $result); } /** @@ -48,7 +48,7 @@ public function testCustomTruncation(): void public function testTruncateNoPerformance($data): void { - $data = new \Rollbar\Payload\EncodedPayload($data); + $data = new EncodedPayload($data); $data->encode(); $result = $this->truncate->truncate($data); @@ -56,7 +56,7 @@ public function testTruncateNoPerformance($data): void $size = strlen(json_encode($result)); $this->assertTrue( - $size <= \Rollbar\Truncation\Truncation::MAX_PAYLOAD_SIZE, + $size <= Truncation::MAX_PAYLOAD_SIZE, "Truncation failed. Payload size exceeds MAX_PAYLOAD_SIZE." ); } @@ -84,7 +84,7 @@ public function truncateProvider(): array $data = array_merge( $stringsTest->executeTruncateNothingProvider(), - $stringsTest->executearrayProvider(), + $stringsTest->executeArrayProvider(), $framesTestData ); From 743dfd85accde2bf612094348270650485063783 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 28 Nov 2022 16:08:16 -0600 Subject: [PATCH 09/26] Added comments to the EncodedPayload class and payload interfaces --- src/Payload/ContentInterface.php | 8 +++ src/Payload/EncodedPayload.php | 88 +++++++++++++++++++++++++++----- src/SerializerInterface.php | 3 ++ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/src/Payload/ContentInterface.php b/src/Payload/ContentInterface.php index 2805fcff..0e1162d0 100644 --- a/src/Payload/ContentInterface.php +++ b/src/Payload/ContentInterface.php @@ -4,7 +4,15 @@ use Rollbar\SerializerInterface; +/** + * The logic required for the payload body content. + */ interface ContentInterface extends SerializerInterface { + /** + * Returns the key associated with the body content type used in JSON serialization. + * + * @return string + */ public function getKey(): string; } diff --git a/src/Payload/EncodedPayload.php b/src/Payload/EncodedPayload.php index ccd65088..7b187a39 100644 --- a/src/Payload/EncodedPayload.php +++ b/src/Payload/EncodedPayload.php @@ -2,53 +2,113 @@ namespace Rollbar\Payload; +use Exception; +use Rollbar\Truncation\Truncation; + +/** + * This class handles the final stage of data JSON serialization just prior to sending to the Rollbar service. + */ class EncodedPayload { - protected $encoded = null; - protected $size = 0; - + /** + * The encoded data. Null if no data has been encoded yet. + * + * @var string|null + */ + protected ?string $encoded = null; + + /** + * The cached length of the encoded data. + * + * @var int + */ + protected int $size = 0; + + /** + * @param array $data The data to be encoded. + */ public function __construct(protected array $data) { } - + + /** + * Returns the data before it is encoded. + * + * @return array + */ public function data(): array { return $this->data; } - + + /** + * Returns the cached size of the encoded data. + * + * @return int + */ public function size(): int { return $this->size; } - + + /** + * Reduces the cached length of the encoded data by the $amount specified. + * + * Note: this does not reduce size of the data, only the cached size. To reduce the size of the payload data the + * payload must be truncated. See {@see Truncation} for more details. + * + * @param int $amount The amount to decrease the cached data length. + * + * @return void + */ public function decreaseSize(int $amount): void { $this->size -= $amount; } - + + /** + * Updates the payload data and JSON serializes it. The serialized data string is cached and can be access via the + * {@see encoded()} method. + * + * @param array|null $data If an array is given it will overwrite any existing payload data prior to serialization. + * If null (the default value) is given the existing payload data will be serialized. + * + * @return void + * @throws Exception If JSON serialization fails. + */ public function encode(?array $data = null): void { if ($data !== null) { $this->data = $data; } - + $this->encoded = json_encode( $this->data, defined('JSON_PARTIAL_OUTPUT_ON_ERROR') ? JSON_PARTIAL_OUTPUT_ON_ERROR : 0 ); - + if ($this->encoded === false) { - throw new \Exception("Payload data could not be encoded to JSON format."); + throw new Exception("Payload data could not be encoded to JSON format."); } - + $this->size = strlen($this->encoded); } - - public function __toString() + + /** + * Returns the encoded JSON. + * + * @return string + */ + public function __toString(): string { return (string)$this->encoded(); } - + + /** + * Returns the encoded JSON or null if the data to encode was null. + * + * @return string|null + */ public function encoded(): ?string { return $this->encoded; diff --git a/src/SerializerInterface.php b/src/SerializerInterface.php index aea200b2..532bf394 100644 --- a/src/SerializerInterface.php +++ b/src/SerializerInterface.php @@ -2,6 +2,9 @@ namespace Rollbar; +/** + * The base logic required by all internal JSON serializable objects. + */ interface SerializerInterface { /** From 5d325672e70a7bf2c3b688c038caf8e2c847cb9b Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 6 Dec 2022 06:41:46 -0600 Subject: [PATCH 10/26] Fixed #461 Added support for psr/log context exception --- src/DataBuilder.php | 56 ++++++++++++++++++++++++------------ src/DataBuilderInterface.php | 3 +- tests/DataBuilderTest.php | 29 ++++++++++++++++++- tests/FakeDataBuilder.php | 4 +-- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/DataBuilder.php b/src/DataBuilder.php index d315b4ed..f57ef574 100644 --- a/src/DataBuilder.php +++ b/src/DataBuilder.php @@ -15,6 +15,7 @@ use Rollbar\Payload\TraceChain; use Rollbar\Payload\ExceptionInfo; use Rollbar\Rollbar; +use Stringable; use Throwable; class DataBuilder implements DataBuilderInterface @@ -341,14 +342,15 @@ protected function setHost($config) } /** - * @param string $level - * @param Throwable|string $toLog - * @param $context + * @param string $level + * @param Throwable|string|Stringable $toLog + * @param array $context + * * @return Data */ - public function makeData(string $level, Throwable|string $toLog, array $context): Data + public function makeData(string $level, Throwable|string|Stringable $toLog, array $context): Data { - $env = $this->getEnvironment(); + $env = $this->getEnvironment(); $body = $this->getBody($toLog, $context); $data = new Data($env, $body); $data->setLevel($this->getLevel($level, $toLog)) @@ -374,10 +376,19 @@ public function getEnvironment() return $this->environment; } - protected function getBody($toLog, $context) + protected function getBody(Throwable|string|Stringable $toLog, array $context): Body { $baseException = $this->getBaseException(); - if ($toLog instanceof ErrorWrapper) { + + // Get the exception from either the $message or $context['exception']. See + // https://www.php-fig.org/psr/psr-3/#13-context for a description of $context['exception']. + if (isset($context['exception']) && $context['exception'] instanceof $baseException) { + $message = null; + if (!$toLog instanceof Throwable) { + $message = (string) $toLog; + } + $content = $this->getExceptionTrace($context['exception'], $message); + } elseif ($toLog instanceof ErrorWrapper) { $content = $this->getErrorTrace($toLog); } elseif ($toLog instanceof $baseException) { $content = $this->getExceptionTrace($toLog); @@ -393,13 +404,15 @@ public function getErrorTrace(ErrorWrapper $error) } /** - * @param Throwable $exc + * @param Throwable $exc + * @param string|Stringable|null $message + * * @return Trace|TraceChain */ - public function getExceptionTrace(Throwable $exc): Trace|TraceChain + public function getExceptionTrace(Throwable $exc, string|Stringable $message = null): Trace|TraceChain { - $chain = array(); - $chain[] = $this->makeTrace($exc, $this->includeExcCodeContext); + $chain = array(); + $chain[] = $this->makeTrace($exc, $this->includeExcCodeContext, message: $message); $previous = $exc->getPrevious(); @@ -420,22 +433,29 @@ public function getExceptionTrace(Throwable $exc): Trace|TraceChain } /** - * @param Throwable $exception - * @param bool $includeContext whether or not to include context - * @param string|null $classOverride + * @param Throwable $exception + * @param bool $includeContext whether or not to include context + * @param string|null $classOverride + * @param string|Stringable|null $message + * * @return Trace */ - public function makeTrace(Throwable $exception, bool $includeContext, ?string $classOverride = null): Trace - { + public function makeTrace( + Throwable $exception, + bool $includeContext, + ?string $classOverride = null, + string|Stringable $message = null, + ): Trace { if ($this->captureErrorStacktraces) { $frames = $this->makeFrames($exception, $includeContext); } else { $frames = array(); } - + $excInfo = new ExceptionInfo( $classOverride ?: get_class($exception), - $exception->getMessage() + $exception->getMessage(), + $message ); return new Trace($frames, $excInfo); } diff --git a/src/DataBuilderInterface.php b/src/DataBuilderInterface.php index 81d6f46b..f253cb0d 100644 --- a/src/DataBuilderInterface.php +++ b/src/DataBuilderInterface.php @@ -3,9 +3,10 @@ namespace Rollbar; use Rollbar\Payload\Data; +use Stringable; use Throwable; interface DataBuilderInterface { - public function makeData(string $level, Throwable|string $toLog, array $context): Data; + public function makeData(string $level, Throwable|string|Stringable $toLog, array $context): Data; } diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index 317f90bc..61db1bfc 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -2,6 +2,7 @@ namespace Rollbar; +use Exception; use Rollbar\Payload\Level; use Rollbar\TestHelpers\MockPhpStream; @@ -686,6 +687,32 @@ public function testFramesWithoutContextDefault(): void $this->assertNull($output[0]->getContext()); } + public function testExceptionInContext(): void + { + $dataBuilder = new DataBuilder(array( + 'accessToken' => $this->getTestAccessToken(), + 'environment' => 'tests', + 'utilities' => new Utilities(), + )); + + $output = $dataBuilder->makeData( + Level::ERROR, + "testing", + array( + 'exception' => new Exception('testing exception'), + ), + )->serialize(); + + $this->assertSame( + array( + 'class' => 'Exception', + 'message' => 'testing exception', + 'description' => 'testing', + ), + $output['body']['trace']['exception'], + ); + } + public function testPerson(): void { $dataBuilder = new DataBuilder(array( @@ -897,7 +924,7 @@ public function testFramesOrder(): void ); // 893 is the line number where the comment "// A" is found $this->assertEquals( - 893, + 920, $frames[count($frames)-1]->getLineno(), "Possible false negative: did this file change? Check the line number for line with '// A' comment" ); diff --git a/tests/FakeDataBuilder.php b/tests/FakeDataBuilder.php index 51d70b5f..2193ab06 100644 --- a/tests/FakeDataBuilder.php +++ b/tests/FakeDataBuilder.php @@ -1,9 +1,9 @@ Date: Tue, 6 Dec 2022 09:02:33 -0600 Subject: [PATCH 11/26] Removed the line number from the comment --- tests/DataBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index 61db1bfc..6c87c48c 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -922,7 +922,7 @@ public function testFramesOrder(): void 'tests/DataBuilderTest.php', $frames[count($frames)-1]->getFilename() ); - // 893 is the line number where the comment "// A" is found + // The line number where the comment "// A" is found should be the expeced value. $this->assertEquals( 920, $frames[count($frames)-1]->getLineno(), From 850611819524c7dbd87536169f1ffe097275976f Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 6 Dec 2022 09:05:53 -0600 Subject: [PATCH 12/26] Fixed spelling --- tests/DataBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/DataBuilderTest.php b/tests/DataBuilderTest.php index 6c87c48c..75a6a60e 100644 --- a/tests/DataBuilderTest.php +++ b/tests/DataBuilderTest.php @@ -922,7 +922,7 @@ public function testFramesOrder(): void 'tests/DataBuilderTest.php', $frames[count($frames)-1]->getFilename() ); - // The line number where the comment "// A" is found should be the expeced value. + // The line number where the comment "// A" is found should be the expected value. $this->assertEquals( 920, $frames[count($frames)-1]->getLineno(), From 37d1b0de33ed2cc25b2e2e1aa02ce77681c1af9a Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 12 Dec 2022 15:52:15 -0600 Subject: [PATCH 13/26] Fixed call of method name changed in 8fac418 --- src/Config.php | 7 ++++++- src/RollbarLogger.php | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Config.php b/src/Config.php index 449fc898..6784a505 100644 --- a/src/Config.php +++ b/src/Config.php @@ -721,7 +721,12 @@ protected function setupWithOptions( } } - public function logPayloadLogger() + /** + * Returns the logger responsible for logging request payload and response dumps, if enabled. + * + * @return LoggerInterface + */ + public function logPayloadLogger(): LoggerInterface { return $this->logPayloadLogger; } diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index 696c15f7..330685cf 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -3,6 +3,7 @@ namespace Rollbar; use Psr\Log\InvalidArgumentException; +use Psr\Log\LoggerInterface; use Stringable; use Throwable; use Psr\Log\AbstractLogger; @@ -256,9 +257,14 @@ public function getDataBuilder() return $this->config->getDataBuilder(); } - public function outputLogger() + /** + * Returns the logger responsible for logging request payload and response dumps, if enabled. + * + * @return LoggerInterface + */ + public function logPayloadLogger(): LoggerInterface { - return $this->config->outputLogger(); + return $this->config->logPayloadLogger(); } public function verboseLogger() From 0b358a5f5c4c40beccc7120cea1ebfd3e1a88de2 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Thu, 15 Dec 2022 06:36:21 -0600 Subject: [PATCH 14/26] Added types and method docs to Rollbar and RollbarLogger classes --- src/Rollbar.php | 358 +++++++++++++++++++++++++++++++++++------- src/RollbarLogger.php | 261 ++++++++++++++++++++++++------ 2 files changed, 515 insertions(+), 104 deletions(-) diff --git a/src/Rollbar.php b/src/Rollbar.php index 148728d9..ecb3ef2a 100644 --- a/src/Rollbar.php +++ b/src/Rollbar.php @@ -2,6 +2,7 @@ namespace Rollbar; +use Exception; use Psr\Log\InvalidArgumentException; use Rollbar\Payload\Level; use Rollbar\Handlers\FatalHandler; @@ -13,19 +14,68 @@ class Rollbar { /** - * @var RollbarLogger + * The instance of the logger. This is null if Rollbar has not been initialized or {@see Rollbar::destroy()} has + * been called. + * + * @var RollbarLogger|null + */ + private static ?RollbarLogger $logger = null; + + /** + * The fatal error handler instance or null if it was disabled or Rollbar has not been initialized. + * + * @var FatalHandler|null */ - private static $logger = null; - private static $fatalHandler = null; - private static $errorHandler = null; - private static $exceptionHandler = null; + private static ?FatalHandler $fatalHandler = null; + /** + * The error handler instance or null if it was disabled or Rollbar has not been initialized. + * + * @var ErrorHandler|null + */ + private static ?ErrorHandler $errorHandler = null; + + /** + * The exception handler instance or null if it was disabled or Rollbar has not been initialized. + * + * @var ExceptionHandler|null + */ + private static ?ExceptionHandler $exceptionHandler = null; + + /** + * Sets up Rollbar monitoring and logging. + * + * This method may be called more than once to update or extend the configs. To do this pass an array as the + * $configOrLogger argument. Any config values in the array will update or replace existing configs. + * + * Note: this and the following two parameters are only used the first time the logger is created. This prevents + * multiple error monitors from reporting the same error more than once. To change these values you must call + * {@see Rollbar::destroy()} first. + * + * Example: + * + * // Turn off the fatal error handler + * $configs = Rollbar::logger()->getConfig(); + * Rollbar::destroy(); + * Rollbar::init($configs, handleFatal: false); + * + * @param RollbarLogger|array $configOrLogger This can be either an array of config options or an already + * configured {@see RollbarLogger} instance. + * @param bool $handleException If set to false Rollbar will not monitor exceptions. + * @param bool $handleError If set to false Rollbar will not monitor errors. + * @param bool $handleFatal If set to false Rollbar will not monitor fatal errors. + * + * @return void + * @throws Exception If the $configOrLogger argument is an array that has invalid configs. + * + * @link https://docs.rollbar.com/docs/basic-php-installation-setup + */ public static function init( - $configOrLogger, - $handleException = true, - $handleError = true, - $handleFatal = true - ) { + RollbarLogger|array $configOrLogger, + bool $handleException = true, + bool $handleError = true, + bool $handleFatal = true + ): void { $setupHandlers = is_null(self::$logger); self::setLogger($configOrLogger); @@ -44,47 +94,92 @@ public static function init( } } - private static function setLogger($configOrLogger) + /** + * Creates or configures the RollbarLogger instance. + * + * @param RollbarLogger|array $configOrLogger The configs array or a new {@see RollbarLogger} to use or replace the + * current one with, if one already exists. If a logger already exists + * and this is an array the current logger's configs will be extended + * configs from the array. + * + * @return void + * @throws Exception If the $configOrLogger argument is an array that has invalid configs. + */ + private static function setLogger(RollbarLogger|array $configOrLogger): void { if ($configOrLogger instanceof RollbarLogger) { - $logger = $configOrLogger; + self::$logger = $configOrLogger; + return; } // Replacing the logger rather than configuring the existing logger breaks BC - if (self::$logger && !isset($logger)) { + if (self::$logger !== null) { self::$logger->configure($configOrLogger); return; } - self::$logger = $logger ?? new RollbarLogger($configOrLogger); + self::$logger = new RollbarLogger($configOrLogger); } - - public static function enable() + + /** + * Enables logging of errors to Rollbar. + * + * @return void + */ + public static function enable(): void { - return self::logger()->enable(); + self::logger()->enable(); } - - public static function disable() + + /** + * Disables logging of errors to Rollbar. + * + * @return void + */ + public static function disable(): void { - return self::logger()->disable(); + self::logger()->disable(); } - - public static function enabled() + + /** + * Returns true if the Rollbar logger is enabled. + * + * @return bool + */ + public static function enabled(): bool { return self::logger()->enabled(); } - - public static function disabled() + + /** + * Returns true if the Rollbar logger is disabled. + * + * @return bool + */ + public static function disabled(): bool { return self::logger()->disabled(); } - public static function logger() + /** + * Returns the current logger instance, or null if it has not been initialized or has been destroyed. + * + * @return RollbarLogger|null + */ + public static function logger(): ?RollbarLogger { return self::$logger; } - public static function scope($config) + /** + * Creates and returns a new {@see RollbarLogger} instance. + * + * @param array $config The configs extend the configs of the current logger instance, if it exists. + * + * @return RollbarLogger + * @throws Exception If the $config argument is an array that has invalid configs. + */ + public static function scope(array $config): RollbarLogger { if (is_null(self::$logger)) { return new RollbarLogger($config); @@ -138,91 +233,202 @@ public static function report($level, string|Stringable $message, array $context } /** + * Attempts to log a {@see Throwable} as an uncaught exception. + * + * @param string|Level $level The log level severity to use. + * @param Throwable $toLog The exception to log. + * @param array $context The array of additional data to pass with the stack trace. + * + * @return Response + * @throws Throwable The rethrown $toLog. + * * @since 3.0.0 */ - public static function logUncaught($level, Throwable $toLog, $extra = array()) + public static function logUncaught(string|Level $level, Throwable $toLog, array $context = array()): Response { if (is_null(self::$logger)) { return self::getNotInitializedResponse(); } $toLog->isUncaught = true; try { - $result = self::$logger->report($level, $toLog, (array)$extra); + $result = self::$logger->report($level, $toLog, $context); } finally { unset($toLog->isUncaught); } return $result; } - + + /** + * Logs a message with the {@see Level::DEBUG} log level. + * + * @param string|Stringable $message The debug message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function debug(string|Stringable $message, array $context = array()): void { self::log(Level::DEBUG, $message, $context); } - + + /** + * Logs a message with the {@see Level::INFO} log level. + * + * @param string|Stringable $message The info message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function info(string|Stringable $message, array $context = array()): void { self::log(Level::INFO, $message, $context); } - + + /** + * Logs a message with the {@see Level::NOTICE} log level. + * + * @param string|Stringable $message The notice message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function notice(string|Stringable $message, array $context = array()): void { self::log(Level::NOTICE, $message, $context); } - + + /** + * Logs a message with the {@see Level::WARNING} log level. + * + * @param string|Stringable $message The warning message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function warning(string|Stringable $message, array $context = array()): void { self::log(Level::WARNING, $message, $context); } - + + /** + * Logs a message with the {@see Level::ERROR} log level. + * + * @param string|Stringable $message The error message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function error(string|Stringable $message, array $context = array()): void { self::log(Level::ERROR, $message, $context); } - + + /** + * Logs a message with the {@see Level::CRITICAL} log level. + * + * @param string|Stringable $message The critical message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function critical(string|Stringable $message, array $context = array()): void { self::log(Level::CRITICAL, $message, $context); } - + + /** + * Logs a message with the {@see Level::ALERT} log level. + * + * @param string|Stringable $message The alert message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function alert(string|Stringable $message, array $context = array()): void { self::log(Level::ALERT, $message, $context); } - + + /** + * Logs a message with the {@see Level::EMERGENCY} log level. + * + * @param string|Stringable $message The emergency message to log. + * @param array $context The additional data to send with the message. + * + * @return void + * @throws Throwable + */ public static function emergency(string|Stringable $message, array $context = array()): void { self::log(Level::EMERGENCY, $message, $context); } - public static function setupExceptionHandling() + /** + * Creates a listener that monitors for exceptions. + * + * @return void + */ + public static function setupExceptionHandling(): void { self::$exceptionHandler = new ExceptionHandler(self::$logger); self::$exceptionHandler->register(); } - - public static function setupErrorHandling() + + /** + * Creates a listener that monitors for errors. + * + * @return void + */ + public static function setupErrorHandling(): void { self::$errorHandler = new ErrorHandler(self::$logger); self::$errorHandler->register(); } - public static function setupFatalHandling() + /** + * Creates a listener that monitors for fatal errors that cause the program to shut down. + * + * @return void + */ + public static function setupFatalHandling(): void { self::$fatalHandler = new FatalHandler(self::$logger); self::$fatalHandler->register(); } + /** + * Creates and returns a {@see Response} to use if Rollbar is attempted to be used prior to being initialized. + * + * @return Response + */ private static function getNotInitializedResponse(): Response { return new Response(0, "Rollbar Not Initialized"); } - - public static function setupBatchHandling() + + /** + * This method makes sure the queue of logs stored in memory are sent to Rollbar prior to shut down. + * + * @return void + */ + public static function setupBatchHandling(): void { register_shutdown_function('Rollbar\Rollbar::flushAndWait'); } - public static function flush() + /** + * Sends all the queued logs to Rollbar. + * + * @return void + */ + public static function flush(): void { if (is_null(self::$logger)) { return; @@ -230,39 +436,75 @@ public static function flush() self::$logger->flush(); } - public static function flushAndWait() + /** + * Sends all the queued logs to Rollbar and waits for the response. + * + * @return void + */ + public static function flushAndWait(): void { if (is_null(self::$logger)) { return; } self::$logger->flushAndWait(); } - - public static function addCustom($key, $value) + + /** + * Adds a new key / value pair that will be sent with the payload to Rollbar. If the key already exists in the + * custom data array the existing value will be overwritten. + * + * @param string $key The key to store this value in the custom array. + * @param mixed $data The value that is going to be stored. Must be a primitive or JSON serializable. + * + * @return void + */ + public static function addCustom(string $key, mixed $data): void { - self::$logger->addCustom($key, $value); + self::$logger->addCustom($key, $data); } - - public static function removeCustom($key) + + /** + * Removes a key from the custom data array that is sent with the payload to Rollbar. + * + * @param string $key The key to remove. + * + * @return void + */ + public static function removeCustom(string $key): void { self::$logger->removeCustom($key); } - - public static function getCustom() + + /** + * Returns the array of key / value pairs that will be sent with the payload to Rollbar. + * + * @return array|null + */ + public static function getCustom(): ?array { - self::$logger->getCustom(); + return self::$logger->getCustom(); } - - public static function configure($config) + + /** + * Configures the existing {@see RollbarLogger} instance. + * + * @param array $config The array of configs. This does not need to be complete as it extends the existing + * configuration. Any existing values present in the new configs will be overwritten. + * + * @return void + */ + public static function configure(array $config): void { self::$logger->configure($config); } - + /** - * Destroys the currently stored $logger allowing for a fresh configuration. - * This is especially used in testing scenarios. + * Destroys the currently stored $logger allowing for a fresh configuration. This is especially used in testing + * scenarios. + * + * @return void */ - public static function destroy() + public static function destroy(): void { self::$logger = null; } diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index 330685cf..c241a834 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -2,6 +2,7 @@ namespace Rollbar; +use Exception; use Psr\Log\InvalidArgumentException; use Psr\Log\LoggerInterface; use Stringable; @@ -10,77 +11,168 @@ use Rollbar\Payload\Payload; use Rollbar\Payload\Level; use Rollbar\Truncation\Truncation; -use Monolog\Logger as MonologLogger; use Rollbar\Payload\EncodedPayload; class RollbarLogger extends AbstractLogger { - private $config; - private $truncation; - private $queue; - private $reportCount = 0; + /** + * @var Config $config The logger configuration instance. + */ + private Config $config; + + /** + * @var Truncation The payload truncation manager for the logger. + */ + private Truncation $truncation; + + /** + * @var array $queue The queue for sending payloads in batched mode. + */ + private array $queue; + /** + * @var int $reportCount The number of reports already sent or queued. + */ + private int $reportCount = 0; + + /** + * Creates a new instance of the RollbarLogger. + * + * @param array $config The array of configs to use for the logger. + * + * @throws Exception If a custom truncation strategy class does not implement {@see StrategyInterface}. + */ public function __construct(array $config) { - $this->config = new Config($config); + $this->config = new Config($config); $this->truncation = new Truncation($this->config); - $this->queue = array(); + $this->queue = array(); } /** + * Returns the configs object. + * + * @return Config + * * @since 3.0 */ - public function getConfig() + public function getConfig(): Config { return $this->config; } - - public function enable() + + /** + * Enables logging of errors to Rollbar. + * + * @return void + */ + public function enable(): void { - return $this->config->enable(); + $this->config->enable(); } - - public function disable() + + /** + * Disables logging of errors to Rollbar. + * + * @return void + */ + public function disable(): void { - return $this->config->disable(); + $this->config->disable(); } - - public function enabled() + + /** + * Returns true if the Rollbar logger is enabled. + * + * @return bool + */ + public function enabled(): bool { return $this->config->enabled(); } - - public function disabled() + + /** + * Returns true if the Rollbar logger is disabled. + * + * @return bool + */ + public function disabled(): bool { return $this->config->disabled(); } - public function configure(array $config) + /** + * Updates the existing configurations. All existing configurations will be kept unless explicitly updated in the + * $config array. + * + * @param array $config The new configurations to add or overwrite the existing configurations. + * + * @return void + */ + public function configure(array $config): void { $this->config->configure($config); } - public function scope(array $config) + /** + * Returns a new {@see RollbarLogger} instance with a combination of the configs from the current logger updated + * with the extra $configs array. + * + * @param array $config Additional configurations to update or overwrite the existing configurations. + * + * @return RollbarLogger + * @throws Exception + */ + public function scope(array $config): RollbarLogger { return new RollbarLogger($this->extend($config)); } - public function extend(array $config) + /** + * Deeply combines the provided $config array and the existing configurations and returns the combined array of + * configs. + * + * @param array $config The new configs to update or overwrite the existing configurations. + * + * @return array + */ + public function extend(array $config): array { return $this->config->extend($config); } - - public function addCustom($key, $data) + + /** + * Adds a new key / value pair that will be sent with the payload to Rollbar. If the key already exists in the + * custom data array the existing value will be overwritten. + * + * @param string $key The key to store this value in the custom array. + * @param mixed $data The value that is going to be stored. Must be a primitive or JSON serializable. + * + * @return void + */ + public function addCustom(string $key, mixed $data): void { $this->config->addCustom($key, $data); } - - public function removeCustom($key) + + /** + * Removes a key from the custom data array that is sent with the payload to Rollbar. + * + * @param string $key The key to remove. + * + * @return void + */ + public function removeCustom(string $key): void { $this->config->removeCustom($key); } - - public function getCustom() + + /** + * Returns the array of key / value pairs that will be sent with the payload to Rollbar. + * + * @return array|null + */ + public function getCustom(): mixed { return $this->config->getCustom(); } @@ -185,10 +277,15 @@ public function report($level, string|Stringable $message, array $context = arra return $response; } + /** + * Sends and flushes the batch payload queue. + * + * @return Response|null + */ public function flush(): ?Response { if ($this->getQueueSize() > 0) { - $batch = $this->queue; + $batch = $this->queue; $this->queue = array(); return $this->config->sendBatch($batch, $this->getAccessToken()); } @@ -196,22 +293,47 @@ public function flush(): ?Response return new Response(0, "Queue empty"); } + /** + * Sends and flushes the batch payload queue, and waits for the requests to be sent. + * + * @return void + */ public function flushAndWait(): void { $this->flush(); $this->config->wait($this->getAccessToken()); } - public function shouldIgnoreError($errno) + /** + * Returns true if the error level should be ignored because of error level or sampling rates. + * + * @param int $errno The PHP error level bitmask. + * + * @return bool + */ + public function shouldIgnoreError(int $errno): bool { return $this->config->shouldIgnoreError($errno); } + /** + * Returns the number of report payloads currently in batch queue. + * + * @return int + */ public function getQueueSize(): int { return count($this->queue); } + /** + * Sends a report to the Rollbar service. + * + * @param EncodedPayload $payload The prepared payload to send. + * @param string $accessToken The API access token. + * + * @return Response + */ protected function send(EncodedPayload $payload, string $accessToken): Response { if ($this->reportCount >= $this->config->getMaxItems()) { @@ -236,23 +358,47 @@ protected function send(EncodedPayload $payload, string $accessToken): Response $this->verboseLogger()->debug("Added payload to the queue (running in `batched` mode)."); return $response; } - + return $this->config->send($payload, $accessToken); } - protected function getPayload(string $accessToken, $level, $toLog, $context) - { - $data = $this->config->getRollbarData($level, $toLog, $context); + /** + * Creates a payload from a log level and message or error. + * + * @param string $accessToken The API access token. + * @param string $level The log level. Should be one of the {@see Level} constants. + * @param string|Stringable $toLog The message or error to be sent to Rollbar. + * @param array $context Additional data to send with the message. + * + * @return Payload|null + */ + protected function getPayload( + string $accessToken, + string $level, + string|Stringable $toLog, + array $context, + ): ?Payload { + $data = $this->config->getRollbarData($level, $toLog, $context); $payload = new Payload($data, $accessToken); return $this->config->transform($payload, $level, $toLog, $context); } + /** + * Returns the access token for the logger instance. + * + * @return string + */ protected function getAccessToken(): string { return $this->config->getAccessToken(); } - - public function getDataBuilder() + + /** + * Returns the configured DataBuilder instance. + * + * @return DataBuilder + */ + public function getDataBuilder(): DataBuilder { return $this->config->getDataBuilder(); } @@ -267,18 +413,34 @@ public function logPayloadLogger(): LoggerInterface return $this->config->logPayloadLogger(); } - public function verboseLogger() + /** + * Returns the verbose logger instance. + * + * @return LoggerInterface + */ + public function verboseLogger(): LoggerInterface { return $this->config->verboseLogger(); } + /** + * Calls the custom 'responseHandler', config if it exists. + * + * @param Payload $payload The payload that was sent. + * @param mixed $response The response from the Rollbar service. + * + * @return void + */ protected function handleResponse(Payload $payload, mixed $response): void { $this->config->handleResponse($payload, $response); } - + /** - * @param array $serializedPayload + * Tries to remove sensitive data from the payload before it is sent. + * + * @param array $serializedPayload The multidimensional array of data to be sent. + * * @return array */ protected function scrub(array &$serializedPayload): array @@ -286,21 +448,28 @@ protected function scrub(array &$serializedPayload): array $serializedPayload['data'] = $this->config->getScrubber()->scrub($serializedPayload['data']); return $serializedPayload; } - + /** - * @param \Rollbar\Payload\EncodedPayload $payload - * @return \Rollbar\Payload\EncodedPayload + * Reduces the size of the data, so it does not exceed size limits. + * + * @param EncodedPayload $payload The payload to possibly truncate. + * + * @return EncodedPayload */ - protected function truncate(\Rollbar\Payload\EncodedPayload &$payload) + protected function truncate(EncodedPayload $payload): EncodedPayload { return $this->truncation->truncate($payload); } - + /** - * @param array &$payload - * @return \Rollbar\Payload\EncodedPayload + * JSON serializes the payload. + * + * @param array $payload The data payload to serialize. + * + * @return EncodedPayload + * @throws Exception If JSON serialization fails. */ - protected function encode(array &$payload) + protected function encode(array $payload): EncodedPayload { $encoded = new EncodedPayload($payload); $encoded->encode(); From 28da38a987c816da56d389aa3af8b4db39eb58df Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Thu, 15 Dec 2022 06:37:20 -0600 Subject: [PATCH 15/26] Updated some Config comments and fixed return type --- src/Config.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Config.php b/src/Config.php index 6784a505..21d43d93 100644 --- a/src/Config.php +++ b/src/Config.php @@ -193,6 +193,10 @@ class Config private $mtRandmax; private $includedErrno; + + /** + * @var bool Sets whether to respect current {@see error_reporting()} level or not. + */ private bool $useErrorReporting = false; /** @@ -884,10 +888,10 @@ public function internalCheckIgnored(string $level, mixed $toLog): bool } /** - * Check if the error should be ignored due to `included_errno` config, - * `use_error_reporting` config or `error_sample_rates` config. + * Check if the error should be ignored due to `includedErrno` config, `useErrorReporting` config or + * `errorSampleRates` config. * - * @param errno + * @param int $errno The PHP error level bitmask. * * @return bool */ @@ -1058,7 +1062,8 @@ public function send(EncodedPayload $payload, string $accessToken): ?Response public function sendBatch(array $batch, string $accessToken): ?Response { if ($this->transmitting()) { - return $this->sender->sendBatch($batch, $accessToken); + $this->sender->sendBatch($batch, $accessToken); + return null; } else { $response = new Response(0, "Not transmitting (transmitting disabled in configuration)"); $this->verboseLogger()->warning($response->getInfo()); From 88f99faf75240ae425b25fb1596c32d377b09aac Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 19 Dec 2022 17:38:07 -0500 Subject: [PATCH 16/26] Added required public methods to the DataBuilderInterface --- src/DataBuilder.php | 85 ++++++++++++++++++++++++------------ src/DataBuilderInterface.php | 74 +++++++++++++++++++++++++++++++ src/ErrorWrapper.php | 20 ++++++--- tests/ErrorWrapperTest.php | 4 +- tests/FakeDataBuilder.php | 20 ++++++++- 5 files changed, 168 insertions(+), 35 deletions(-) diff --git a/src/DataBuilder.php b/src/DataBuilder.php index f57ef574..291f6426 100644 --- a/src/DataBuilder.php +++ b/src/DataBuilder.php @@ -64,7 +64,12 @@ class DataBuilder implements DataBuilderInterface */ protected $utilities; - public function __construct($config) + /** + * Initializes the data builder from the Rollbar configs. + * + * @param array $config The configuration array. + */ + public function __construct(array $config) { self::$defaults = Defaults::get(); @@ -281,7 +286,15 @@ protected function setServerExtras($config) $this->serverExtras = $config['serverExtras'] ?? null; } - public function setCustom($config) + /** + * Stores the 'custom' key from the $config array. The 'custom' key should hold an array of key / value pairs to be + * sent to Rollbar with each request. + * + * @param array $config The configuration array. + * + * @return void + */ + public function setCustom(array $config): void { $this->custom = $config['custom'] ?? \Rollbar\Defaults::get()->custom(); } @@ -342,9 +355,12 @@ protected function setHost($config) } /** - * @param string $level - * @param Throwable|string|Stringable $toLog - * @param array $context + * Creates the {@see Data} object from an exception or log message. This method respects the PSR-3 standard on + * handling exceptions in the context https://www.php-fig.org/psr/psr-3/#13-context. + * + * @param string $level The severity log level for the item being logged. + * @param Throwable|string|Stringable $toLog The exception or message to be logged. + * @param array $context Any additional context data. * * @return Data */ @@ -961,8 +977,13 @@ protected function getServerExtras() { return $this->serverExtras; } - - public function getCustom() + + /** + * Returns the array of key / value pairs that will be sent with the payload to Rollbar. + * + * @return array|null + */ + public function getCustom(): ?array { return $this->custom; } @@ -1043,22 +1064,32 @@ protected function resolveCustomContent(mixed $custom): array return ['message' => $custom]; } - public function addCustom($key, $data) + /** + * Adds a new key / value pair that will be sent with the payload to Rollbar. If the key already exists in the + * custom data array the existing value will be overwritten. + * + * @param string $key The key to store this value in the custom array. + * @param mixed $data The value that is going to be stored. Must be a primitive or JSON serializable. + * + * @return void + */ + public function addCustom(string $key, mixed $data): void { - if ($this->custom === null) { - $this->custom = array(); - } - if (!is_array($this->custom)) { - throw new \Exception( - "Custom data configured in Rollbar::init() is not an array." - ); + $this->custom = array(); } $this->custom[$key] = $data; } - - public function removeCustom($key) + + /** + * Removes a key from the custom data array that is sent with the payload to Rollbar. + * + * @param string $key The key to remove. + * + * @return void + */ + public function removeCustom(string $key): void { unset($this->custom[$key]); } @@ -1114,18 +1145,18 @@ private function getSourceLines($filename) return $source; } - + /** - * Wrap a PHP error in an ErrorWrapper class and add backtrace information + * Wrap a PHP error in the {@see ErrorWrapper} class and add stacktrace information. * - * @param string $errno - * @param string $errstr - * @param string $errfile - * @param string $errline + * @param int $errno The level of the error raised. + * @param string $errstr The error message. + * @param string|null $errfile The filename that the error was raised in. + * @param int|null $errline The line number where the error was raised. * * @return ErrorWrapper */ - public function generateErrorWrapper($errno, $errstr, $errfile, $errline) + public function generateErrorWrapper(int $errno, string $errstr, ?string $errfile, ?int $errline): ErrorWrapper { return new ErrorWrapper( $errno, @@ -1140,12 +1171,12 @@ public function generateErrorWrapper($errno, $errstr, $errfile, $errline) /** * Fetches the stack trace for fatal and regular errors. * - * @var string $errfile - * @var string $errline + * @param string|null $errfile The filename that the error was raised in. + * @param int|null $errline The line number where the error was raised. * * @return array */ - protected function buildErrorTrace($errfile, $errline) + protected function buildErrorTrace(?string $errfile, ?int $errline): array { if ($this->captureErrorStacktraces) { $backTrace = $this->fetchErrorTrace(); diff --git a/src/DataBuilderInterface.php b/src/DataBuilderInterface.php index f253cb0d..a612571a 100644 --- a/src/DataBuilderInterface.php +++ b/src/DataBuilderInterface.php @@ -6,7 +6,81 @@ use Stringable; use Throwable; +/** + * A data builder is used to normalize, parse, and prepare errors, exceptions, and messages to Rollbar. + */ interface DataBuilderInterface { + /** + * Initializes the data builder from the Rollbar configs. + * + * @param array $config The configuration array. + */ + public function __construct(array $config); + + /** + * Creates the {@see Data} object from an exception or log message. This method needs to respect the PSR-3 standard + * on handling exceptions in the context https://www.php-fig.org/psr/psr-3/#13-context. + * + * @param string $level The severity log level for the item being logged. + * @param Throwable|string|Stringable $toLog The exception or message to be logged. + * @param array $context Any additional context data. This method should respect exceptions + * in the 'exception' key according PSR-3 logging standard. + * + * @return Data + */ public function makeData(string $level, Throwable|string|Stringable $toLog, array $context): Data; + + /** + * Stores the 'custom' key from the $config array. The 'custom' key should hold an array of key / value pairs to be + * sent to Rollbar with each request. + * + * @param array $config The configuration array. + * + * @return void + */ + public function setCustom(array $config): void; + + /** + * Adds a new key / value pair that will be sent with the payload to Rollbar. + * + * @param string $key The key to store this value in the custom array. + * @param mixed $data The value that is going to be stored. Must be a primitive or JSON serializable. + * + * @return void + */ + public function addCustom(string $key, mixed $data): void; + + /** + * Removes a key from the custom data array that is sent with the payload to Rollbar. + * + * @param string $key The key to remove. + * + * @return void + */ + public function removeCustom(string $key): void; + + /** + * Returns the array of key / value pairs that will be sent with the payload to Rollbar. + * + * @return array|null + */ + public function getCustom(): ?array; + + /** + * Wrap a PHP error in the {@see ErrorWrapper} class and add stacktrace information. + * + * @param int $errno The level of the error raised. + * @param string $errstr The error message. + * @param string|null $errfile The filename that the error was raised in. + * @param int|null $errline The line number where the error was raised. + * + * @return ErrorWrapper + */ + public function generateErrorWrapper( + int $errno, + string $errstr, + ?string $errfile, + ?int $errline + ): ErrorWrapper; } diff --git a/src/ErrorWrapper.php b/src/ErrorWrapper.php index cbeca008..fe3867f3 100644 --- a/src/ErrorWrapper.php +++ b/src/ErrorWrapper.php @@ -32,12 +32,22 @@ private static function getConstName($const) return self::$constName[$const] ?? null; } + /** + * Creates the instance from the error data. + * + * @param int $errorLevel The level of the error raised. + * @param string $errorMessage The error message. + * @param string|null $errorFile The filename that the error was raised in. + * @param int|null $errorLine The line number where the error was raised. + * @param array|null $backTrace The stack trace for the error. + * @param Utilities $utilities The configured utilities class. + */ public function __construct( - public $errorLevel, - public $errorMessage, - public $errorFile, - public $errorLine, - public $backTrace, + public int $errorLevel, + public string $errorMessage, + public ?string $errorFile, + public ?int $errorLine, + public ?array $backTrace, $utilities ) { parent::__construct($this->errorMessage, $this->errorLevel); diff --git a/tests/ErrorWrapperTest.php b/tests/ErrorWrapperTest.php index 678c6bc4..cbea7885 100644 --- a/tests/ErrorWrapperTest.php +++ b/tests/ErrorWrapperTest.php @@ -11,10 +11,10 @@ public function testBacktrace(): void "", null, null, - "FAKE BACKTRACE", + ['fake' => 'FAKE BACKTRACE'], new Utilities ); - $this->assertEquals("FAKE BACKTRACE", $errWrapper->getBacktrace()); + $this->assertEquals(['fake' => 'FAKE BACKTRACE'], $errWrapper->getBacktrace()); } public function testGetClassName(): void diff --git a/tests/FakeDataBuilder.php b/tests/FakeDataBuilder.php index 2193ab06..2f4467b3 100644 --- a/tests/FakeDataBuilder.php +++ b/tests/FakeDataBuilder.php @@ -23,7 +23,25 @@ public function makeData(string $level, Throwable|string|Stringable $toLog, arra return new Data('test', new Body(new Message('test'))); } - public function setCustom(): void + public function setCustom(array $config): void { } + + public function addCustom(string $key, mixed $data): void + { + } + + public function removeCustom(string $key): void + { + } + + public function getCustom(): ?array + { + return null; + } + + public function generateErrorWrapper(int $errno, string $errstr, ?string $errfile, ?int $errline): ErrorWrapper + { + return new ErrorWrapper($errno, $errstr, $errfile, $errline, [], new Utilities()); + } } From fc36f14f941c313a0bae4bf042e3c08b550518a4 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 19 Dec 2022 17:38:42 -0500 Subject: [PATCH 17/26] Removed tests for a custom type other than array --- tests/ConfigTest.php | 145 ------------------------------------------- 1 file changed, 145 deletions(-) diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 98d44f32..a80557e5 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -478,151 +478,6 @@ public function testCustom(): void $this->assertSame($expectedCustom, $actualCustom); } - public function testCustomPrimitive(): void - { - $config = new Config(array( - "access_token" => $this->getTestAccessToken(), - "environment" => $this->env, - "custom" => true, - )); - - $result = $config->getDataBuilder()->makeData( - Level::INFO, - "Test message with custom data added dynamically.", - array(), - ); - - $custom = $result->getCustom(); - - $this->assertSame(array('message' => true), $custom); - } - - public function testCustomPrimitiveFalsy(): void - { - $config = new Config(array( - "access_token" => $this->getTestAccessToken(), - "environment" => $this->env, - "custom" => 0.0, - )); - - $result = $config->getDataBuilder()->makeData( - Level::INFO, - "Test message with custom data added dynamically.", - array(), - ); - - $custom = $result->getCustom(); - - $this->assertSame(array(), $custom); - } - - public function testCustomObject(): void - { - $expectedCustom = array( - "foo" => "bar", - "fuzz" => "buzz" - ); - $config = new Config(array( - "access_token" => $this->getTestAccessToken(), - "environment" => $this->env, - "custom" => (object) $expectedCustom, - )); - - // New error handler to make sure we get the deprecated notice - set_error_handler(function ( - int $errno, - string $errstr, - ) : bool { - $this->assertStringContainsString("deprecated", $errstr); - return true; - }, E_USER_DEPRECATED); - - $result = $config->getDataBuilder()->makeData( - Level::INFO, - "Test message with custom data added dynamically.", - array(), - ); - - // Clear the handler, so it does not mess with other tests. - restore_error_handler(); - - $actualCustom = $result->getCustom(); - - $this->assertSame($expectedCustom, $actualCustom); - } - - public function testDeprecatedSerializable(): void - { - $expectedCustom = array( - "foo" => "bar", - "fuzz" => "buzz" - ); - $config = new Config(array( - "access_token" => $this->getTestAccessToken(), - "environment" => $this->env, - "custom" => new DeprecatedSerializable($expectedCustom), - )); - - // New error handler to make sure we get the deprecated notice - set_error_handler(function ( - int $errno, - string $errstr, - ) : bool { - $this->assertStringContainsString("Serializable", $errstr); - $this->assertStringContainsString("deprecated", $errstr); - return true; - }, E_USER_DEPRECATED); - - $result = $config->getDataBuilder()->makeData( - Level::INFO, - "Test message with custom data added dynamically.", - array(), - ); - - // Clear the handler, so it does not mess with other tests. - restore_error_handler(); - - $actualCustom = $result->getCustom(); - - $this->assertSame($expectedCustom, $actualCustom); - } - - public function testCustomSerializable() - { - $expectedCustom = array( - "foo" => "bar", - "fuzz" => "buzz" - ); - $config = new Config(array( - "access_token" => $this->getTestAccessToken(), - "environment" => $this->env, - "custom" => new CustomSerializable($expectedCustom), - )); - - // Make sure the deprecation notice is not sent if the object implements __serializable as it should - set_error_handler(function ( - int $errno, - string $errstr, - ) : bool { - $this->assertStringNotContainsString("Serializable", $errstr); - $this->assertStringNotContainsString("deprecated", $errstr); - return true; - }, E_USER_DEPRECATED); - - $result = $config->getDataBuilder()->makeData( - Level::INFO, - "Test message with custom data added dynamically.", - array(), - ); - - // Clear the handler, so it does not mess with other tests. - restore_error_handler(); - - $actualCustom = $result->getCustom(); - - $this->assertSame($expectedCustom, $actualCustom); - } - public function testMaxItems(): void { $config = new Config(array( From 806ec2f6bce3f3d14b8c9f23888d30a7b2e3bc53 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 20 Dec 2022 09:04:28 -0500 Subject: [PATCH 18/26] Added typing / comments to the FilterInterface and removed the token argument --- src/Config.php | 4 ++-- src/FilterInterface.php | 14 +++++++++++++- src/RollbarLogger.php | 2 +- tests/ConfigTest.php | 10 ++++------ tests/VerbosityTest.php | 7 +++---- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/Config.php b/src/Config.php index 21d43d93..fa318082 100644 --- a/src/Config.php +++ b/src/Config.php @@ -833,7 +833,7 @@ public function getSendMessageTrace() return $this->sendMessageTrace; } - public function checkIgnored($payload, string $accessToken, $toLog, bool $isUncaught) + public function checkIgnored($payload, $toLog, bool $isUncaught) { if (isset($this->checkIgnore)) { try { @@ -856,7 +856,7 @@ public function checkIgnored($payload, string $accessToken, $toLog, bool $isUnca } if (!is_null($this->filter)) { - $filter = $this->filter->shouldSend($payload, $accessToken); + $filter = $this->filter->shouldSend($payload); $this->verboseLogger()->debug("Custom filter result: " . var_export($filter, true)); return $filter; } diff --git a/src/FilterInterface.php b/src/FilterInterface.php index ee1a98c0..2591f9ff 100644 --- a/src/FilterInterface.php +++ b/src/FilterInterface.php @@ -4,7 +4,19 @@ use Rollbar\Payload\Payload; +/** + * The FilterInterface allows a custom payload filter to be used. It should be passed to the configs with the 'filter' + * key. A custom filter should implement this interface. + */ interface FilterInterface { - public function shouldSend(Payload $payload, string $accessToken); + /** + * Method called to determine if a payload should be sent to the Rollbar service. If true is returned the payload + * will not be sent. + * + * @param Payload $payload The payload instance that may be sent. + * + * @return bool + */ + public function shouldSend(Payload $payload): bool; } diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index c241a834..4608b0bd 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -242,7 +242,7 @@ public function report($level, string|Stringable $message, array $context = arra $payload = $this->getPayload($accessToken, $level, $message, $context); $isUncaught = $this->isUncaughtLogData($message); - if ($this->config->checkIgnored($payload, $accessToken, $message, $isUncaught)) { + if ($this->config->checkIgnored($payload, $message, $isUncaught)) { $this->verboseLogger()->info('Occurrence ignored'); $response = new Response(0, "Ignored"); } else { diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index a80557e5..f71bf7b4 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -341,12 +341,12 @@ public function testMinimumLevel(): void public function assertPayloadIgnored($config, $payload): void { - $this->assertTrue($config->checkIgnored($payload, 'access-token', $this->error, false)); + $this->assertTrue($config->checkIgnored($payload, $this->error, false)); } public function assertPayloadNotIgnored($config, $payload): void { - $this->assertFalse($config->checkIgnored($payload, 'access-token', $this->error, false)); + $this->assertFalse($config->checkIgnored($payload, $this->error, false)); } private function prepareMockPayload($level): Payload @@ -421,8 +421,8 @@ public function testFilter(): void "environment" => $this->env, "filter" => $filter )); - $this->assertTrue($c->checkIgnored($p, "fake_access_token", $this->error, false)); - $this->assertFalse($c->checkIgnored($p, "fake_access_token", $this->error, false)); + $this->assertTrue($c->checkIgnored($p, $this->error, false)); + $this->assertFalse($c->checkIgnored($p, $this->error, false)); } public function testSender(): void @@ -608,7 +608,6 @@ public function testCheckIgnore(): void $data, $config->getAccessToken() ), - $this->getTestAccessToken(), $this->error, false ); @@ -647,7 +646,6 @@ public function testCheckIgnoreParameters(): void $data, $config->getAccessToken() ), - $this->getTestAccessToken(), $this->error, true ); diff --git a/tests/VerbosityTest.php b/tests/VerbosityTest.php index d7b0f9ab..e825eec9 100644 --- a/tests/VerbosityTest.php +++ b/tests/VerbosityTest.php @@ -612,7 +612,6 @@ function () use ($config, $unitTest) { $payloadMock->method('getData')->willReturn($dataMock); $config->checkIgnored( $payloadMock, - $unitTest->getTestAccessToken(), $payloadMock, false ); @@ -651,7 +650,7 @@ function () use ($config, $unitTest) { // logic under test $data = $config->getRollbarData(\Rollbar\Payload\Level::INFO, 'some message', array()); $payload = new \Rollbar\Payload\Payload($data, $unitTest->getTestAccessToken()); - $config->checkIgnored($payload, $unitTest->getTestAccessToken(), 'some message', false); + $config->checkIgnored($payload, 'some message', false); }, function () use ($unitTest) { // verbosity expectations @@ -685,7 +684,7 @@ function () use ($config, $unitTest) { // logic under test $data = $config->getRollbarData(\Rollbar\Payload\Level::INFO, 'some message', array()); $payload = new \Rollbar\Payload\Payload($data, $unitTest->getTestAccessToken()); - $config->checkIgnored($payload, $unitTest->getTestAccessToken(), 'some message', false); + $config->checkIgnored($payload, 'some message', false); }, function () use ($unitTest) { // verbosity expectations @@ -722,7 +721,7 @@ function () use ($config, $unitTest) { // logic under test $data = $config->getRollbarData(\Rollbar\Payload\Level::INFO, 'some message', array()); $payload = new \Rollbar\Payload\Payload($data, $unitTest->getTestAccessToken()); - $config->checkIgnored($payload, $unitTest->getTestAccessToken(), 'some message', false); + $config->checkIgnored($payload, 'some message', false); }, function () use ($unitTest) { // verbosity expectations From 039f54aa7e20fc4f00c83c49b59f180c76aa3c40 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 20 Dec 2022 10:52:21 -0500 Subject: [PATCH 19/26] Updated the typing and comments for the ResponseHandlerInterface --- src/Config.php | 2 +- src/ResponseHandlerInterface.php | 17 ++++++++++++++++- src/RollbarLogger.php | 6 +++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Config.php b/src/Config.php index 21d43d93..f9539d0f 100644 --- a/src/Config.php +++ b/src/Config.php @@ -1077,7 +1077,7 @@ public function wait(string $accessToken, $max = 0): void $this->sender->wait($accessToken, $max); } - public function handleResponse(Payload $payload, mixed $response): void + public function handleResponse(Payload $payload, Response $response): void { if (!is_null($this->responseHandler)) { $this->verboseLogger()->debug( diff --git a/src/ResponseHandlerInterface.php b/src/ResponseHandlerInterface.php index 540c8160..e731763e 100644 --- a/src/ResponseHandlerInterface.php +++ b/src/ResponseHandlerInterface.php @@ -4,7 +4,22 @@ use Rollbar\Payload\Payload; +/** + * The response handler interface allows the processing of responses from the Rollbar service after a log message or + * error report has been sent to Rollbar. A custom response handler FQCN may be passed in the config array with the key + * "responseHandler". The custom handler class constructor may be a single argument by including it in the config array + * with the "responseHandlerOptions" key. If the "responseHandlerOptions" key does not exist an empty array will be + * passed to the constructor. + */ interface ResponseHandlerInterface { - public function handleResponse(Payload $payload, mixed $response): void; + /** + * The handleResponse method is called with the response from the Rollbar service after an error or log message has + * been sent. + * + * @param Payload $payload The payload object that was sent to Rollbar. + * @param Response $response The response that was returned. If the response status code is 0, it likely represents + * an ignored error that was never sent. + */ + public function handleResponse(Payload $payload, Response $response): void; } diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index c241a834..82555ab1 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -426,12 +426,12 @@ public function verboseLogger(): LoggerInterface /** * Calls the custom 'responseHandler', config if it exists. * - * @param Payload $payload The payload that was sent. - * @param mixed $response The response from the Rollbar service. + * @param Payload $payload The payload that was sent. + * @param Response $response The response from the Rollbar service. * * @return void */ - protected function handleResponse(Payload $payload, mixed $response): void + protected function handleResponse(Payload $payload, Response $response): void { $this->config->handleResponse($payload, $response); } From 734c7a3f1c2fc5e4689b65480dfab7a5eefe0ebd Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 3 Jan 2023 15:49:17 -0600 Subject: [PATCH 20/26] Added typing / comments to the ScrubberInterface and Scrubber --- src/Config.php | 2 +- src/Payload/Payload.php | 2 +- src/Scrubber.php | 128 ++++++++++++++---- src/ScrubberInterface.php | 15 +- tests/RollbarLoggerTest.php | 2 +- tests/ScrubberTest.php | 88 ++++++------ .../MalformedPayloadDataTransformer.php | 2 +- 7 files changed, 168 insertions(+), 71 deletions(-) diff --git a/src/Config.php b/src/Config.php index 21d43d93..17f0d473 100644 --- a/src/Config.php +++ b/src/Config.php @@ -833,7 +833,7 @@ public function getSendMessageTrace() return $this->sendMessageTrace; } - public function checkIgnored($payload, string $accessToken, $toLog, bool $isUncaught) + public function checkIgnored(Payload $payload, string $accessToken, $toLog, bool $isUncaught) { if (isset($this->checkIgnore)) { try { diff --git a/src/Payload/Payload.php b/src/Payload/Payload.php index 44d2cc69..251f9033 100644 --- a/src/Payload/Payload.php +++ b/src/Payload/Payload.php @@ -40,7 +40,7 @@ public function setAccessToken(string $accessToken): self return $this; } - public function serialize($maxDepth = -1) + public function serialize($maxDepth = -1): array { $objectHashes = array(); $result = array( diff --git a/src/Scrubber.php b/src/Scrubber.php index 89faaf14..7df84c6d 100644 --- a/src/Scrubber.php +++ b/src/Scrubber.php @@ -2,33 +2,70 @@ namespace Rollbar; +/** + * The Scrubber class removes protected or sensitive data and PII from the payload before it is sent over the wire to + * the Rollbar Service. It can be configured with the 'scrub_fields' and 'scrub_safelist' configs. + */ class Scrubber implements ScrubberInterface { - protected static $defaults; - protected $scrubFields; - protected $safelist; + /** + * A list of field names to scrub data from. + * + * @var string[] + */ + protected array $scrubFields; - public function __construct($config) + /** + * A list of fields to NOT scrub data from. Each field should be a '.' delimited list of nested keys. + * + * @var string[] + */ + protected array $safelist; + + /** + * Sets up and configures the Scrubber from the array of configs. + * + * @param array $config + */ + public function __construct(array $config) { - self::$defaults = Defaults::get(); $this->setScrubFields($config); $this->setSafelist($config); } - protected function setScrubFields($config) + /** + * Sets the fields to scrub from the configs array. + * + * @param array $config The configs. + * + * @return void + */ + protected function setScrubFields(array $config): void { $fromConfig = $config['scrubFields'] ?? null; if (!isset($fromConfig)) { $fromConfig = $config['scrub_fields'] ?? null; } - $this->scrubFields = self::$defaults->scrubFields($fromConfig); + $this->scrubFields = Defaults::get()->scrubFields($fromConfig); } + /** + * Returns the list of keys to scrub data from. + * + * @return string[] + */ public function getScrubFields() { return $this->scrubFields; } + /** + * Sets the list of keys to not scrub data from. + * + * @param $config + * + * @return void + */ protected function setSafelist($config) { $fromConfig = $config['scrubSafelist'] ?? null; @@ -38,6 +75,11 @@ protected function setSafelist($config) $this->safelist = $fromConfig ?: array(); } + /** + * Returns the list of keys that data will not be scrubbed from. + * + * @return string[] + */ public function getSafelist() { return $this->safelist; @@ -46,12 +88,13 @@ public function getSafelist() /** * Scrub a data structure including arrays and query strings. * - * @param mixed $data Data to be scrubbed. - * @param array $fields Sequence of field names to scrub. + * @param array $data Data to be scrubbed. * @param string $replacement Character used for scrubbing. - * @param string $path Path of traversal in the array + * @param string $path Path of traversal in the array + * + * @return mixed */ - public function scrub(&$data, $replacement = '********', $path = '') + public function scrub(array &$data, string $replacement = '********', string $path = ''): array { $fields = $this->getScrubFields(); @@ -59,19 +102,31 @@ public function scrub(&$data, $replacement = '********', $path = '') return $data; } - // Scrub fields is case insensitive, so force all fields to lowercase + // Scrub fields is case-insensitive, so force all fields to lowercase $fields = array_change_key_case(array_flip($fields), CASE_LOWER); return $this->internalScrub($data, $fields, $replacement, $path); } - public function internalScrub(&$data, $fields, $replacement, $path) + /** + * This method does most of the heavy lifting of scrubbing sensitive data from the serialized paylaod. It executes + * recursively over arrays and attempts to parse key / value pairs from strings. + * + * @param mixed $data the data to be scrubbed. + * @param array $fields The keys to private data that should be scrubbed. + * @param string $replacement The text to replace sensitive data with. + * @param string $path The path to the current field delimited with '.'. It may be several fields long, if + * the current field is deeply nested. + * + * @return mixed + */ + public function internalScrub(mixed &$data, array $fields, string $replacement, string $path): mixed { if (is_array($data)) { -// scrub arrays + // scrub arrays $data = $this->scrubArray($data, $fields, $replacement, $path); } elseif (is_string($data)) { -// scrub URLs and query strings + // scrub URLs and query strings $query = parse_url($data, PHP_URL_QUERY); if ($query) { $data = str_replace( @@ -90,25 +145,38 @@ public function internalScrub(&$data, $fields, $replacement, $path) return $data; } - protected function scrubArray(&$arr, $fields, $replacement = '********', $path = '') - { + /** + * Scrubs sensitive data from an array. This will call {@see self::internalScrub()} and can execute recursively. + * + * @param array $arr The array of values to scrub. + * @param array $fields The keys to scrub from the data. + * @param string $replacement The text to replace scrubbed data with. + * @param string $path The path to the current array of values. This will be an empty string if it is the + * top level array. Otherwise, it will be '.' delimited list of field names. + * + * @return array The scrubbed data. + */ + protected function scrubArray( + array &$arr, + array $fields, + string $replacement = '********', + string $path = '' + ): array { if (!$fields || !$arr) { return $arr; } - $scrubber = $this; + $scrubber = $this; $scrubberFn = function ( &$val, $key ) use ( $fields, $replacement, - &$scrubberFn, $scrubber, &$path ) { - $parent = $path; - $current = !$path ? $key : $path . '.' . $key; + $current = !$path ? (string)$key : $path . '.' . $key; if (in_array($current, $scrubber->getSafelist())) { return; @@ -118,19 +186,27 @@ protected function scrubArray(&$arr, $fields, $replacement = '********', $path = // backtraces -- coerce to string to satisfy strict types if (isset($fields[strtolower((string)$key)])) { $val = $replacement; - } else { - $val = $scrubber->internalScrub($val, $fields, $replacement, $current); + return; } - - $current = $parent; + $val = $scrubber->internalScrub($val, $fields, $replacement, $current); }; + // We use array_walk() recursively, instead of array_walk_recursive() so we can build the nested path. array_walk($arr, $scrubberFn); return $arr; } - protected function scrubQueryString($query, $fields, $replacement = 'xxxxxxxx') + /** + * Scrubs sensitive data from a query string formatted string. + * + * @param string $query The string to scrub data from. + * @param array $fields The keys to scrub data from. + * @param string $replacement the text to replace scrubbed data. + * + * @return string + */ + protected function scrubQueryString(string $query, array $fields, string $replacement = 'xxxxxxxx'): string { // PHP reports warning if parse_str() detects more than max_input_vars items. @parse_str($query, $parsed); diff --git a/src/ScrubberInterface.php b/src/ScrubberInterface.php index c864562b..d3d36a59 100644 --- a/src/ScrubberInterface.php +++ b/src/ScrubberInterface.php @@ -2,7 +2,20 @@ namespace Rollbar; +/** + * The scrubber interface allows a custom scrubber to be created that removes sensitive data and PII from the payload + * before it is sent to the Rollbar service. Optionally, the class implementing the interface may include a constructor + * that accepts a single argument for the configs array. + */ interface ScrubberInterface { - public function scrub(&$data, $replacement); + /** + * The scrub method is called to clean PII from the exception or the log message payload. + * + * @param array $data The array serialized data to be scrubbed. + * @param string $replacement The replacement value to use for anything that is deemed sensitive. + * + * @return array + */ + public function scrub(array &$data, string $replacement): array; } diff --git a/tests/RollbarLoggerTest.php b/tests/RollbarLoggerTest.php index d4c0e1fa..773a7728 100644 --- a/tests/RollbarLoggerTest.php +++ b/tests/RollbarLoggerTest.php @@ -318,7 +318,7 @@ public function testLogMalformedPayloadData(): void array() ); - $this->assertEquals(400, $response->getStatus()); + $this->assertEquals(422, $response->getStatus()); } public function testFlush(): void diff --git a/tests/ScrubberTest.php b/tests/ScrubberTest.php index 469b46ae..5d19e617 100644 --- a/tests/ScrubberTest.php +++ b/tests/ScrubberTest.php @@ -11,14 +11,14 @@ public function scrubUrlDataProvider(): array { return array( 'nothing to scrub' => array( - 'https://rollbar.com', // $testData + array('https://rollbar.com'), // $testData array(), // $scrubfields - 'https://rollbar.com' // $expected + array('https://rollbar.com'), // $expected ), 'mix of scrub and no scrub' => array( - 'https://rollbar.com?arg1=val1&arg2=val2&arg3=val3', // $testData + array('https://rollbar.com?arg1=val1&arg2=val2&arg3=val3'), // $testData array('arg2'), // $scrubFields - 'https://rollbar.com?arg1=val1&arg2=xxxxxxxx&arg3=val3' // $expected + array('https://rollbar.com?arg1=val1&arg2=xxxxxxxx&arg3=val3'), // $expected ), ); } @@ -87,12 +87,12 @@ public function scrubSafelistProvider(): array /** * @dataProvider scrubDataProvider */ - public function testScrub($testData, $scrubFields, $expected): void + public function testScrub(array $testData, array $scrubFields, array $expected): void { $scrubber = new Scrubber(array( - 'scrubFields' => $scrubFields + 'scrubFields' => $scrubFields, )); - $result = $scrubber->scrub($testData); + $result = $scrubber->scrub($testData); $this->assertEquals($expected, $result, "Looks like some fields did not get scrubbed correctly."); } @@ -116,18 +116,18 @@ private function scrubJSONNumbersProvider(): array { return array( 'plain array' => array( - '[1023,1924]', + array('[1023,1924]'), array( 'sensitive' ), - '[1023,1924]' + array('[1023,1924]') ), 'param equals array' => array( - 'b=[1023,1924]', + array('b=[1023,1924]'), array( 'sensitive' ), - 'b=[1023,1924]' + array('b=[1023,1924]') ) ); } @@ -200,23 +200,27 @@ private function scrubFlatStringDataProvider(): array { return array( // $testData - '?' . http_build_query( - array( - 'arg1' => 'val 1', - 'sensitive' => 'scrubit', - 'arg2' => 'val 3' - ) + array( + '?' . http_build_query( + array( + 'arg1' => 'val 1', + 'sensitive' => 'scrubit', + 'arg2' => 'val 3', + ) + ), ), array( // $scrubFields 'sensitive' ), // $expected - '?' . http_build_query( - array( - 'arg1' => 'val 1', - 'sensitive' => 'xxxxxxxx', - 'arg2' => 'val 3' - ) + array( + '?' . http_build_query( + array( + 'arg1' => 'val 1', + 'sensitive' => 'xxxxxxxx', + 'arg2' => 'val 3', + ) + ), ), ); } @@ -225,29 +229,33 @@ private function scrubRecursiveStringDataProvider(): array { return array( // $testData - '?' . http_build_query( - array( - 'arg1' => 'val 1', - 'sensitive' => 'scrubit', - 'arg2' => array( - 'arg3' => 'val 3', - 'sensitive' => 'scrubit' + array( + '?' . http_build_query( + array( + 'arg1' => 'val 1', + 'sensitive' => 'scrubit', + 'arg2' => array( + 'arg3' => 'val 3', + 'sensitive' => 'scrubit', + ), ) - ) + ), ), array( // $scrubFields - 'sensitive' + 'sensitive', ), // $expected - '?' . http_build_query( - array( - 'arg1' => 'val 1', - 'sensitive' => 'xxxxxxxx', - 'arg2' => array( - 'arg3' => 'val 3', - 'sensitive' => 'xxxxxxxx' + array( + '?' . http_build_query( + array( + 'arg1' => 'val 1', + 'sensitive' => 'xxxxxxxx', + 'arg2' => array( + 'arg3' => 'val 3', + 'sensitive' => 'xxxxxxxx', + ), ) - ) + ), ), ); } diff --git a/tests/TestHelpers/MalformedPayloadDataTransformer.php b/tests/TestHelpers/MalformedPayloadDataTransformer.php index 936e38d5..7975b2ae 100644 --- a/tests/TestHelpers/MalformedPayloadDataTransformer.php +++ b/tests/TestHelpers/MalformedPayloadDataTransformer.php @@ -13,7 +13,7 @@ public function transform( array $context = array() ): ?Payload { $mock = \Mockery::mock(Data::class)->makePartial(); - $mock->shouldReceive("serialize")->andReturn(false); + $mock->shouldReceive("serialize")->andReturn(array()); $mock->setLevel(\Rollbar\LevelFactory::fromName($level)); $payload->setData($mock); return $payload; From 743e0abe4cfb3bf6e1a2089e6e543f10f0e1903a Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 9 Jan 2023 17:18:48 -0600 Subject: [PATCH 21/26] Added typing / comments to the SenderInterface --- src/Senders/AgentSender.php | 7 +----- src/Senders/CurlSender.php | 7 +----- src/Senders/FluentSender.php | 8 +------ src/Senders/SenderInterface.php | 41 +++++++++++++++++++++++++++++---- tests/ConfigTest.php | 2 +- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/Senders/AgentSender.php b/src/Senders/AgentSender.php index 82468f74..06ef775d 100644 --- a/src/Senders/AgentSender.php +++ b/src/Senders/AgentSender.php @@ -55,7 +55,7 @@ public function sendBatch(array $batch, string $accessToken): void /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function wait(string $accessToken, int $max) + public function wait(string $accessToken, int $max): void { return; } @@ -65,9 +65,4 @@ private function loadAgentFile() $filename = $this->agentLogLocation . '/rollbar-relay.' . getmypid() . '.' . microtime(true) . '.rollbar'; $this->agentLog = fopen($filename, 'a'); } - - public function toString() - { - return "agent log: " . $this->agentLogLocation; - } } diff --git a/src/Senders/CurlSender.php b/src/Senders/CurlSender.php index 9d4dd73c..0df74309 100644 --- a/src/Senders/CurlSender.php +++ b/src/Senders/CurlSender.php @@ -96,7 +96,7 @@ public function sendBatch(array $batch, string $accessToken): void $this->checkForCompletedRequests($accessToken); } - public function wait(string $accessToken, int $max = 0) + public function wait(string $accessToken, int $max = 0): void { if (count($this->inflightRequests) <= $max) { return; @@ -187,9 +187,4 @@ private function removeFinishedRequests(string $accessToken) } $this->maybeSendMoreBatchRequests($accessToken); } - - public function toString() - { - return "Rollbar API endpoint: " . $this->getEndpoint(); - } } diff --git a/src/Senders/FluentSender.php b/src/Senders/FluentSender.php index f9e53192..ddae224c 100644 --- a/src/Senders/FluentSender.php +++ b/src/Senders/FluentSender.php @@ -96,7 +96,7 @@ public function sendBatch(array $batch, string $accessToken, &$responses = array /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function wait(string $accessToken, int $max) + public function wait(string $accessToken, int $max): void { return; } @@ -108,10 +108,4 @@ protected function loadFluentLogger() { $this->fluentLogger = new FluentLogger($this->fluentHost, $this->fluentPort); } - - public function toString() - { - return "fluentd " . $this->fluentHost . ":" . $this->fluentPort . - " tag: " . $this->fluentTag; - } } diff --git a/src/Senders/SenderInterface.php b/src/Senders/SenderInterface.php index 720c3b4d..a705633f 100644 --- a/src/Senders/SenderInterface.php +++ b/src/Senders/SenderInterface.php @@ -2,13 +2,46 @@ namespace Rollbar\Senders; -use Rollbar\Payload\Payload; use Rollbar\Payload\EncodedPayload; +use Rollbar\Payload\Payload; +use Rollbar\Response; +/** + * The sender interface is used to define how an error report sender should transport payloads to Rollbar Service. + * + * An optional constructor can be included in the implementing class. If the constructor is present a single argument + * with the value of the `senderOptions` config option will be passed to the constructor. + */ interface SenderInterface { - public function send(EncodedPayload $payload, string $accessToken); + /** + * Sends the payload to the Rollbar service and returns the response. + * + * @param EncodedPayload $payload The payload to deliver to the Rollbar service. + * @param string $accessToken The project access token. + * + * @return Response + */ + public function send(EncodedPayload $payload, string $accessToken): Response; + + /** + * Sends an array of payloads to the Rollbar service. + * + * @param Payload[] $batch The array of {@see Payload} instances. + * @param string $accessToken The project access token. + * + * @return void + */ public function sendBatch(array $batch, string $accessToken): void; - public function wait(string $accessToken, int $max); - public function toString(); + + /** + * Method used to keep the batch send process alive until all or $max number of Payloads are sent, which ever comes + * first. + * + * @param string $accessToken The project access token. + * @param int $max The maximum payloads to send before stopping the batch send process. + * + * @return void + */ + public function wait(string $accessToken, int $max): void; } diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index a80557e5..95ad7f10 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -124,7 +124,7 @@ public function testLoggingPayload(): void ); $senderMock = $this->getMockBuilder(SenderInterface::class) ->getMock(); - $senderMock->method('send')->willReturn(null); + $senderMock->method('send')->willReturn(new Response(200, 'Test')); $payload = new \Rollbar\Payload\EncodedPayload(array('data'=>array())); $payload->encode(); From 575fbdca312020931003bbed2813f989b6467c70 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 9 Jan 2023 18:03:03 -0600 Subject: [PATCH 22/26] Added the `$isUncaught` argument to `FilterInterface::shouldSend` --- src/Config.php | 2 +- src/FilterInterface.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Config.php b/src/Config.php index fa318082..e165e733 100644 --- a/src/Config.php +++ b/src/Config.php @@ -856,7 +856,7 @@ public function checkIgnored($payload, $toLog, bool $isUncaught) } if (!is_null($this->filter)) { - $filter = $this->filter->shouldSend($payload); + $filter = $this->filter->shouldSend($payload, $isUncaught); $this->verboseLogger()->debug("Custom filter result: " . var_export($filter, true)); return $filter; } diff --git a/src/FilterInterface.php b/src/FilterInterface.php index 2591f9ff..ff446de9 100644 --- a/src/FilterInterface.php +++ b/src/FilterInterface.php @@ -14,9 +14,11 @@ interface FilterInterface * Method called to determine if a payload should be sent to the Rollbar service. If true is returned the payload * will not be sent. * - * @param Payload $payload The payload instance that may be sent. + * @param Payload $payload The payload instance that may be sent. + * @param bool $isUncaught True if the payload represents an error that was caught by one of the Rollbar + * exception or error handlers. * * @return bool */ - public function shouldSend(Payload $payload): bool; + public function shouldSend(Payload $payload, bool $isUncaught): bool; } From 1be308cc2b4b26a33b1923922b222ce7171d7123 Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 10 Jan 2023 06:39:15 -0600 Subject: [PATCH 23/26] Removed null return type from TransformerInterface::transform() --- src/Config.php | 2 +- src/RollbarLogger.php | 4 ++-- src/TransformerInterface.php | 4 ++-- tests/TestHelpers/MalformedPayloadDataTransformer.php | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Config.php b/src/Config.php index 6b9289f6..db58dc3b 100644 --- a/src/Config.php +++ b/src/Config.php @@ -795,7 +795,7 @@ public function transform( Level|string $level, mixed $toLog, array $context = array () - ): ?Payload { + ): Payload { if (count($this->custom) > 0) { $this->verboseLogger()->debug("Adding custom data to the payload."); $data = $payload->getData(); diff --git a/src/RollbarLogger.php b/src/RollbarLogger.php index 82555ab1..d8493334 100644 --- a/src/RollbarLogger.php +++ b/src/RollbarLogger.php @@ -370,14 +370,14 @@ protected function send(EncodedPayload $payload, string $accessToken): Response * @param string|Stringable $toLog The message or error to be sent to Rollbar. * @param array $context Additional data to send with the message. * - * @return Payload|null + * @return Payload */ protected function getPayload( string $accessToken, string $level, string|Stringable $toLog, array $context, - ): ?Payload { + ): Payload { $data = $this->config->getRollbarData($level, $toLog, $context); $payload = new Payload($data, $accessToken); return $this->config->transform($payload, $level, $toLog, $context); diff --git a/src/TransformerInterface.php b/src/TransformerInterface.php index c988cb01..2ae54dc6 100644 --- a/src/TransformerInterface.php +++ b/src/TransformerInterface.php @@ -12,6 +12,6 @@ public function transform( Payload $payload, Level|string $level, mixed $toLog, - array $context = array () - ): ?Payload; + array $context = array() + ): Payload; } diff --git a/tests/TestHelpers/MalformedPayloadDataTransformer.php b/tests/TestHelpers/MalformedPayloadDataTransformer.php index 7975b2ae..e6c07c19 100644 --- a/tests/TestHelpers/MalformedPayloadDataTransformer.php +++ b/tests/TestHelpers/MalformedPayloadDataTransformer.php @@ -3,15 +3,16 @@ use Rollbar\Payload\Level; use Rollbar\Payload\Payload; use Rollbar\Payload\Data; +use Rollbar\TransformerInterface; -class MalformedPayloadDataTransformer implements \Rollbar\TransformerInterface +class MalformedPayloadDataTransformer implements TransformerInterface { public function transform( Payload $payload, Level|string $level, mixed $toLog, array $context = array() - ): ?Payload { + ): Payload { $mock = \Mockery::mock(Data::class)->makePartial(); $mock->shouldReceive("serialize")->andReturn(array()); $mock->setLevel(\Rollbar\LevelFactory::fromName($level)); From f928f1d47d516d6bd564748e318ce7fc2db2f86b Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Tue, 10 Jan 2023 06:39:29 -0600 Subject: [PATCH 24/26] Added typing / comments to the TransformerInterface --- src/TransformerInterface.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/TransformerInterface.php b/src/TransformerInterface.php index 2ae54dc6..f9cd330f 100644 --- a/src/TransformerInterface.php +++ b/src/TransformerInterface.php @@ -4,10 +4,33 @@ use Rollbar\Payload\Level; use Rollbar\Payload\Payload; -use Throwable; +/** + * The scrubber interface allows changes to be made to the error or log {@see Payload} before it is checked to see if + * it will be ignored, is serialized, scrubbed of PII or many other processes. The transform method is executed + * directly after the payload is created. + * + * Note: transforms are only applied to payloads that were created through calling one of the {@see Rollbar} or + * {@see RollbarLogger} logging methods or for errors and exceptions that where caught by Rollbar. + * + * An optional constructor can be included in the implementing class. The constructor should accept a single array + * argument. The value of the argument will be the value of `transformerOptions` from the configs array, or an empty + * array if `transformerOptions` does not exist. + */ interface TransformerInterface { + /** + * The transform method allows changes to be made to a {@see Payload} just after it is created and before it is + * passed to anything else in the standard logging and error catching process. + * + * @param Payload $payload The payload that has just been created. + * @param Level|string $level The severity of the log message or error. + * @param mixed $toLog The error or message that is being logged. + * @param array $context Additional context data that may be sent with the message. In accordance with + * PSR-3 an exception may be in $context['exception'] not $toLog. + * + * @return Payload + */ public function transform( Payload $payload, Level|string $level, From 8e800ccede881a495be36693847d922ac976981e Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Mon, 16 Jan 2023 09:11:38 -0600 Subject: [PATCH 25/26] Fixed #469 Added requireAccessToken() method to senders --- src/Config.php | 13 ++++++++++--- src/Senders/AgentSender.php | 16 +++++++++++++++- src/Senders/CurlSender.php | 12 ++++++++++++ src/Senders/FluentSender.php | 12 ++++++++++++ src/Senders/SenderInterface.php | 9 +++++++++ tests/ConfigTest.php | 7 +++++-- tests/FluentTest.php | 2 +- 7 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/Config.php b/src/Config.php index 25474b5a..e79a0a2f 100644 --- a/src/Config.php +++ b/src/Config.php @@ -291,13 +291,14 @@ protected function updateConfig(array $config): void $this->setLogPayloadLogger($config); $this->setVerbose($config); $this->setVerboseLogger($config); + // The sender must be set before the access token, so we know if it is required. + $this->setSender($config); $this->setAccessToken($config); $this->setDataBuilder($config); $this->setTransformer($config); $this->setMinimumLevel($config); $this->setReportSuppressed($config); $this->setFilters($config); - $this->setSender($config); $this->setScrubber($config); $this->setBatched($config); $this->setBatchSize($config); @@ -337,8 +338,14 @@ private function setAccessToken(array $config): void if (isset($_ENV['ROLLBAR_ACCESS_TOKEN']) && !isset($config['access_token'])) { $config['access_token'] = $_ENV['ROLLBAR_ACCESS_TOKEN']; } - $this->utilities()->validateString($config['access_token'], "config['access_token']", 32, false); - $this->accessToken = $config['access_token']; + + $this->utilities()->validateString( + $config['access_token'], + "config['access_token']", + 32, + !$this->sender->requireAccessToken(), + ); + $this->accessToken = $config['access_token'] ?? ''; } private function setEnabled(array $config): void diff --git a/src/Senders/AgentSender.php b/src/Senders/AgentSender.php index 06ef775d..285c742b 100644 --- a/src/Senders/AgentSender.php +++ b/src/Senders/AgentSender.php @@ -60,9 +60,23 @@ public function wait(string $accessToken, int $max): void return; } + /** + * Returns true if the access token is required by the sender to send the payload. The agent can be configured to + * provide its own access token. But may not have its own, so we are requiring it for now. See + * {@link https://github.com/rollbar/rollbar-php/issues/405} for more details. + * + * @since 4.0.0 + * + * @return bool + */ + public function requireAccessToken(): bool + { + return true; + } + private function loadAgentFile() { - $filename = $this->agentLogLocation . '/rollbar-relay.' . getmypid() . '.' . microtime(true) . '.rollbar'; + $filename = $this->agentLogLocation . '/rollbar-relay.' . getmypid() . '.' . microtime(true) . '.rollbar'; $this->agentLog = fopen($filename, 'a'); } } diff --git a/src/Senders/CurlSender.php b/src/Senders/CurlSender.php index 0df74309..4994827a 100644 --- a/src/Senders/CurlSender.php +++ b/src/Senders/CurlSender.php @@ -110,6 +110,18 @@ public function wait(string $accessToken, int $max = 0): void } } + /** + * Returns true if the access token is required by the sender to send the payload. The curl sender requires the + * access token since it is sending directly to the Rollbar service. + * + * @return bool + * @since 4.0.0 + */ + public function requireAccessToken(): bool + { + return false; + } + private function maybeSendMoreBatchRequests(string $accessToken) { $max = $this->maxBatchRequests - count($this->inflightRequests); diff --git a/src/Senders/FluentSender.php b/src/Senders/FluentSender.php index ddae224c..11f9612c 100644 --- a/src/Senders/FluentSender.php +++ b/src/Senders/FluentSender.php @@ -101,6 +101,18 @@ public function wait(string $accessToken, int $max): void return; } + /** + * Returns true if the access token is required by the sender to send the payload. The Fluentd service can provide + * its own access token. + * + * @return bool + * @since 4.0.0 + */ + public function requireAccessToken(): bool + { + return false; + } + /** * Loads the fluent logger */ diff --git a/src/Senders/SenderInterface.php b/src/Senders/SenderInterface.php index a705633f..395ffc60 100644 --- a/src/Senders/SenderInterface.php +++ b/src/Senders/SenderInterface.php @@ -44,4 +44,13 @@ public function sendBatch(array $batch, string $accessToken): void; * @return void */ public function wait(string $accessToken, int $max): void; + + /** + * Returns true if the access token is required by the sender to send the payload. In cases where an intermediary + * sender is being used like Fluentd. + * + * @return bool + * @since 4.0.0 + */ + public function requireAccessToken(): bool; } diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index b7b8e0b5..3e158286 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -428,11 +428,14 @@ public function testFilter(): void public function testSender(): void { $p = m::mock(EncodedPayload::class); - $sender = m::mock(SenderInterface::class) - ->shouldReceive("send") + $sender = m::mock(SenderInterface::class); + $sender->shouldReceive("send") ->with($p, $this->getTestAccessToken()) ->once() ->mock(); + $sender->shouldReceive('requireAccessToken') + ->once() + ->mock(); $c = new Config(array( "access_token" => $this->getTestAccessToken(), "environment" => $this->env, diff --git a/tests/FluentTest.php b/tests/FluentTest.php index 8438ca35..7272ac33 100644 --- a/tests/FluentTest.php +++ b/tests/FluentTest.php @@ -28,7 +28,7 @@ public function testFluent(): void 'fluent_port' => $port, 'handler' => 'fluent' )); - $this->assertEquals(200, $logger->log(Level::INFO, 'this is a test', array())->getStatus()); + $this->assertEquals(200, $logger->report(Level::INFO, 'this is a test', array())->getStatus()); socket_close($socket); } From c5fd934dc26e4c3f85471817edd63a6d00a7717a Mon Sep 17 00:00:00 2001 From: Daniel Morell Date: Wed, 18 Jan 2023 06:38:56 -0600 Subject: [PATCH 26/26] Updated CHANGELOG, README, and version for v4.0.0-beta --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++ README.md | 15 ++++++----- src/Payload/Notifier.php | 2 +- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 070393ea..435a3960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [4.0.0-beta] +### Added +* PHP 8 language level mitigations, add typehints by @Chris8934 in #569. +* Added support for `psr/log` v3 by @danielmorell in #577. +* Added comments and type annotations to the `EncodedPayload` class and payload + interfaces by @danielmorell in #581. +* Added typing / comments to `Rollbar` and `RollbarLogger` classes by + @danielmorell in #585. +* Added required public methods to the `DataBuilderInterface` by @danielmorell + in #586. +* Added typing / comments to the `ResponseHandlerInterface` by @danielmorell in + #588. +* Added typing / comments to the `ScrubberInterface` and `Scrubber` class by + @danielmorell in #591. +* Added typing / comments to the `FilterInterface` by @danielmorell in #587. +* Added typing / comments to the `SenderInterface` by @danielmorell in #592. +### Changed +* Renamed `IStrategy` to `StrategyInterface` updated `Truncation` and changed + custom truncation strategy from requiring class extend the `AbstractStrategy` + to now require it implement `StrategyInterface` by @danielmorell in #580. +* Replaced the `FilterInterface::shouldSend()` `$accessĪ¤oken` argument with + `$isUncaught` making it close to `check_ignore` usage @danielmorell in #587. +### Removed +* Removed deprecated log levels and fixed inconsistent use of + `Rollbar/LevelFactory` by @danielmorell in #578. +* Removed previously deprecated reporting methods from `Rollbar` by @danielmorell + in #579. +* Removed the `null` return type from `TransformerInterface::getPayload()` + by @danielmorell in #593. +### Fixed +* Fixed call of method name changed in 8fac418 by @danielmorell in #583. +* Fixed #461 Added support for `psr/log` context exception by @danielmorell in + #582. +* Fixed #469 Added `requireAccessToken()` method to `SenderInterface` by + @danielmorell in #595. + +## [3.1.4] - 2022-11-18 +This version adds a catch during the serialization process to stop serializaiton +errors from causing reports not to be sent to rollbar. +### Added +* Error catching error during serialization by @stephpy in #576 + +## [3.1.3] - 2022-05-23 +This release patches several bugs. +### Added +* Added Safer `parse_str()` usage by @tanakahisateru in #566 +### Fixed +* Fixed comment line number in tests by @matt-h in #563 +* Fixed rollbar/rollbar-php-laravel#136 try using `__serialize` when obj + implements `\Serializable` by @pcoutinho in #567. +* Fixed error suppressor context detection for PHP 8 by @tanakahisateru in #565 +* Fixed #571 added `null` check on `$filename` by @danielmorell in #572 +* Fixed bug in tests on local machine (mac m1) by @Chris53897 in #568 + ## [3.1.2] - 2022-03-30 This release is a patch to fix a regression in functionality that was introduced in v3.0.0. diff --git a/README.md b/README.md index 1db9d0e9..da4f2dfc 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,12 @@ From the Settings > Project Access Token menu, click Create New Access Token. Copy the `post_client_item` value and paste it into the code below. ```php -require 'vendor/autoload.php'; // composer require rollbar/rollbar:^2 +require 'vendor/autoload.php'; // composer require rollbar/rollbar -\Rollbar\Rollbar::init( - [ 'access_token' => '***', 'environment' => 'development' ] -); +\Rollbar\Rollbar::init([ + 'access_token' => '***', + 'environment' => 'development', +]); ``` For detailed usage instructions and configuration reference, refer to our @@ -63,7 +64,7 @@ For detailed usage instructions and configuration reference, refer to our Major releases of this library support major versions of PHP, as follows: -* For PHP 8, choose the `master` branch. +* For PHP 8, choose the `4.x` or `3.x` branch. * For PHP 7, choose a `2.x` release. * For PHP 5, choose a `1.x` release. @@ -72,7 +73,9 @@ composer: ```sh # for PHP 8 compatibility -$ composer require rollbar/rollbar:dev-master +$ composer require rollbar/rollbar:^4 +# or +$ composer require rollbar/rollbar:^3 # for PHP 7 compatibility $ composer require rollbar/rollbar:^2 diff --git a/src/Payload/Notifier.php b/src/Payload/Notifier.php index 59715013..aa8fd5bd 100644 --- a/src/Payload/Notifier.php +++ b/src/Payload/Notifier.php @@ -8,7 +8,7 @@ class Notifier implements SerializerInterface { const NAME = "rollbar-php"; - const VERSION = "3.1.2"; + const VERSION = "4.0.0-beta"; use UtilitiesTrait;