diff --git a/.github/workflows/php-integration-tests.yml b/.github/workflows/php-integration-tests.yml index 338cf1f..6b8f656 100644 --- a/.github/workflows/php-integration-tests.yml +++ b/.github/workflows/php-integration-tests.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - php-service: [ '72', '73', '74', '80', '81', '82' ] + php-service: [ '74', '80', '81', '82' ] steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/php-static-analysis.yml b/.github/workflows/php-static-analysis.yml index dedcd5b..52daf10 100644 --- a/.github/workflows/php-static-analysis.yml +++ b/.github/workflows/php-static-analysis.yml @@ -31,12 +31,19 @@ jobs: uses: inpsyde/reusable-workflows/.github/workflows/lint-php.yml@main if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run lint only')) }} with: - PHP_MATRIX: '["7.2", "7.3", "7.4", "8.0", "8.1", "8.2"]' + PHP_MATRIX: '["7.4", "8.0", "8.1", "8.2"]' coding-standards-analysis-php: if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run PHPCS only')) }} uses: inpsyde/reusable-workflows/.github/workflows/coding-standards-php.yml@main + with: + PHP_VERSION: '8.0' static-code-analysis-php: if: ${{ (github.event_name != 'workflow_dispatch') || ((github.event.inputs.jobs == 'Run all') || (github.event.inputs.jobs == 'Run Psalm only')) }} uses: inpsyde/reusable-workflows/.github/workflows/static-analysis-php.yml@main + strategy: + matrix: + php-version: [ '7.4', '8.0', '8.1', '8.2' ] + with: + PHP_VERSION: ${{ matrix.php-version }} diff --git a/.github/workflows/php-unit-tests.yml b/.github/workflows/php-unit-tests.yml index 1953aff..b3ad1a9 100644 --- a/.github/workflows/php-unit-tests.yml +++ b/.github/workflows/php-unit-tests.yml @@ -25,35 +25,26 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2' ] + php-versions: [ '7.4', '8.0', '8.1', '8.2' ] + dependency-versions: ['highest', 'lowest'] steps: - name: Checkout uses: actions/checkout@v3 - - name: Use coverage? - if: ${{ matrix.php-versions == '7.4' }} - run: echo "USE_COVERAGE=yes" >> $GITHUB_ENV - - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} ini-values: zend.assertions=1, error_reporting=E_ALL, display_errors=On - coverage: ${{ ((env.USE_COVERAGE == 'yes') && 'xdebug') || 'none' }} + coverage: ${{ env.USE_COVERAGE == 'yes' && 'xdebug' || 'none' }} - name: Install Composer dependencies uses: ramsey/composer-install@v2 + with: + dependency-versions: ${{ matrix.dependency-versions }} - name: Run unit tests - run: composer tests:unit:${{ ((env.USE_COVERAGE == 'yes') && 'codecov') || 'no-cov' }} + run: composer tests:unit:no-cov - - name: Update coverage - if: ${{ env.USE_COVERAGE == 'yes' }} - uses: codecov/codecov-action@v3 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: ./coverage.xml - flags: unittests - verbose: true diff --git a/.gitignore b/.gitignore index a57a787..6c97b07 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,10 @@ # Docker .github/workflows/docker/php*/*.sh + +# Adding a folder to put things temporarily +temp/ + +# IDE +.idea/ + diff --git a/composer.json b/composer.json index 4a5c981..80599d6 100644 --- a/composer.json +++ b/composer.json @@ -37,22 +37,22 @@ } ], "require": { - "php": ">=7.2 < 8.3", - "psr/log": "^1.1.4", + "php": "^7.4||>=8.0 < 8.3", + "psr/log": ">=1.0.1 <2.0||^2.0||^3.0", "wecodemore/wordpress-early-hook": "^1.1.0", - "monolog/monolog": "^2.3.5" + "monolog/monolog": ">=2.0.1 <3" }, "require-dev": { - "phpunit/phpunit": "^8.5.33", "brain/monkey": "^2.6.1", "mockery/mockery": "^1.3.6", "mikey179/vfsstream": "~v1.6.11", "inpsyde/php-coding-standards": "^1", - "vimeo/psalm": "^4.30.0", "inpsyde/wp-stubs-versions": "dev-latest", "roots/wordpress-no-content": ">=6.1.1", "symfony/process": "^v4.4.44", - "globalis/wp-cli-bin": "^2.7.1" + "globalis/wp-cli-bin": "^2.7.1", + "vimeo/psalm": "^5.15", + "phpunit/phpunit": "^9.6" }, "provide": { "psr/log-implementation": "1.0.0" @@ -88,6 +88,7 @@ }, "scripts": { "cs": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs", + "cs:fix": "@php ./vendor/bin/phpcbf", "psalm": "@php ./vendor/vimeo/psalm/psalm --no-suggestions --find-unused-psalm-suppress --no-diff --no-cache --no-file-cache", "tests:unit": "@php ./vendor/phpunit/phpunit/phpunit --testsuite=unit", "tests:unit:no-cov": "@php ./vendor/phpunit/phpunit/phpunit --testsuite=unit --no-coverage", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d2d7421..85875ac 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,34 +1,30 @@ - - - - - - - - - tests/unit - - - tests/integration - - - - - - src - - + + + + src + + + + + + + + tests/unit + + + tests/integration + + diff --git a/src/Data/FailedLogin.php b/src/Data/FailedLogin.php index 8daec23..101b4e6 100644 --- a/src/Data/FailedLogin.php +++ b/src/Data/FailedLogin.php @@ -107,15 +107,25 @@ private function countAttempts(int $ttl = 300): void || !isset($attempts[$userIp]['count']) || !isset($attempts[$userIp]['last_logged']) ) { - $attempts[$userIp] = ['count' => 0, 'last_logged' => 0]; + /** + * @var array $data + */ + $data = ['count' => 0, 'last_logged' => 0]; + $attempts[$userIp] = $data; } /** @psalm-suppress MixedOperand */ $attempts[$userIp]['count']++; - /** @psalm-suppress PropertyTypeCoercion */ + /** @psalm-suppress InvalidPropertyAssignmentValue */ $this->attemptsData = $attempts; + /** + * Psalm warns us about count and last_logged possibly being bool to int converted + * We assume the value retrieved when calling get_site_transient is an integer on both + * @psalm-suppress RiskyCast + */ $count = (int)$attempts[$userIp]['count']; + /** @psalm-suppress RiskyCast */ $lastLogged = (int)$attempts[$userIp]['last_logged']; /** diff --git a/src/DefaultHandler/LogsFolder.php b/src/DefaultHandler/LogsFolder.php index ef4736b..0954531 100644 --- a/src/DefaultHandler/LogsFolder.php +++ b/src/DefaultHandler/LogsFolder.php @@ -35,7 +35,11 @@ public static function determineFolder(?string $customFolder = null): ?string * them, and package could be fully functional even if failures happen. * Silence looks like best option here. * + * Also for some reason __return_true seems not to be a valid argument? + * I found this related issue https://github.com/vimeo/psalm/issues/3571 + * * phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler + * @psalm-suppress PossiblyInvalidArgument */ set_error_handler('__return_true'); diff --git a/src/HookListener/CronDebugListener.php b/src/HookListener/CronDebugListener.php index 7e3d43c..1e17b78 100644 --- a/src/HookListener/CronDebugListener.php +++ b/src/HookListener/CronDebugListener.php @@ -83,7 +83,7 @@ private function registerEventListener(LogActionUpdater $updater): void } $cronArray = _get_cron_array(); - /** @psalm-suppress DocblockTypeContradiction */ + /** @psalm-suppress TypeDoesNotContainType,DocblockTypeContradiction */ if (!$cronArray || !is_array($cronArray)) { return; } diff --git a/src/PsrBridge.php b/src/PsrBridge.php index d2eaf65..182a7fc 100644 --- a/src/PsrBridge.php +++ b/src/PsrBridge.php @@ -72,7 +72,7 @@ public function withDefaultChannel(string $defaultChannel): PsrBridge * * phpcs:disable Generic.Metrics.CyclomaticComplexity */ - public function log($level, $message, array $context = []) + public function log($level, $message, array $context = []): void { // phpcs:enable Generic.Metrics.CyclomaticComplexity $throwable = null; diff --git a/tests/src/TestLogger/AbstractLoggerV1.php b/tests/src/TestLogger/AbstractLoggerV1.php new file mode 100644 index 0000000..c293393 --- /dev/null +++ b/tests/src/TestLogger/AbstractLoggerV1.php @@ -0,0 +1,139 @@ + + * @license GPLv2+ + * @link https://www.inpsyde.com + */ + +namespace Inpsyde\Wonolog\Tests\TestLogger; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +abstract class AbstractLoggerV1 implements LoggerInterface +{ + /** + * System is unusable. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function emergency($message, array $context = []) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function alert($message, array $context = []) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function critical($message, array $context = []) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function error($message, array $context = []) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function warning($message, array $context = []) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function notice($message, array $context = []) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function info($message, array $context = []) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param mixed[] $context + * + * @return void + */ + public function debug($message, array $context = []) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/tests/src/TestLogger/TestLoggerV1.php b/tests/src/TestLogger/TestLoggerV1.php new file mode 100644 index 0000000..3b80870 --- /dev/null +++ b/tests/src/TestLogger/TestLoggerV1.php @@ -0,0 +1,174 @@ + + * @license GPLv2+ + * @link https://www.inpsyde.com + */ + +namespace Inpsyde\Wonolog\Tests\TestLogger; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @method bool hasEmergency($record) + * @method bool hasAlert($record) + * @method bool hasCritical($record) + * @method bool hasError($record) + * @method bool hasWarning($record) + * @method bool hasNotice($record) + * @method bool hasInfo($record) + * @method bool hasDebug($record) + * + * @method bool hasEmergencyRecords() + * @method bool hasAlertRecords() + * @method bool hasCriticalRecords() + * @method bool hasErrorRecords() + * @method bool hasWarningRecords() + * @method bool hasNoticeRecords() + * @method bool hasInfoRecords() + * @method bool hasDebugRecords() + * + * @method bool hasEmergencyThatContains($message) + * @method bool hasAlertThatContains($message) + * @method bool hasCriticalThatContains($message) + * @method bool hasErrorThatContains($message) + * @method bool hasWarningThatContains($message) + * @method bool hasNoticeThatContains($message) + * @method bool hasInfoThatContains($message) + * @method bool hasDebugThatContains($message) + * + * @method bool hasEmergencyThatMatches($message) + * @method bool hasAlertThatMatches($message) + * @method bool hasCriticalThatMatches($message) + * @method bool hasErrorThatMatches($message) + * @method bool hasWarningThatMatches($message) + * @method bool hasNoticeThatMatches($message) + * @method bool hasInfoThatMatches($message) + * @method bool hasDebugThatMatches($message) + * + * @method bool hasEmergencyThatPasses($message) + * @method bool hasAlertThatPasses($message) + * @method bool hasCriticalThatPasses($message) + * @method bool hasErrorThatPasses($message) + * @method bool hasWarningThatPasses($message) + * @method bool hasNoticeThatPasses($message) + * @method bool hasInfoThatPasses($message) + * @method bool hasDebugThatPasses($message) + */ +class TestLoggerV1 extends AbstractLoggerV1 +{ + /** + * @var array + */ + // phpcs:ignore Inpsyde.CodeQuality.ForbiddenPublicProperty.Found + public $records = []; + + // phpcs:ignore Inpsyde.CodeQuality.ForbiddenPublicProperty.Found + public $recordsByLevel = []; + + /** + * @inheritdoc + */ + public function log($level, $message, array $context = []) + { + $record = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(static function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(static function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(static function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + // phpcs:ignore NeutronStandard.Functions.DisallowCallUserFunc.CallUserFunc + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if ( + preg_match( + '/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', + $method, + $matches + ) > 0 + ) { + $genericMethod = $matches[1] + . ('Records' !== $matches[3] ? 'Record' : '') + . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + // phpcs:ignore NeutronStandard.Functions.DisallowCallUserFunc.CallUserFunc + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException( + 'Call to undefined method ' . get_class($this) . '::' . $method . '()' + ); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/tests/src/TestLogger/TestLoggerV2V3.php b/tests/src/TestLogger/TestLoggerV2V3.php new file mode 100644 index 0000000..046124e --- /dev/null +++ b/tests/src/TestLogger/TestLoggerV2V3.php @@ -0,0 +1,368 @@ + + * @license GPLv2+ + * @link https://www.inpsyde.com + */ + +namespace Inpsyde\Wonolog\Tests\TestLogger; + +use Psr\Log\LoggerInterface; +use Psr\Log\LoggerTrait; + +class TestLoggerV2V3 implements LoggerInterface +{ + use LoggerTrait; + + // phpcs:ignore Inpsyde.CodeQuality.ForbiddenPublicProperty.Found, PHPCompatibility.Classes.NewTypedProperties.Found + public array $records = []; + + // phpcs:ignore Inpsyde.CodeQuality.ForbiddenPublicProperty.Found, PHPCompatibility.Classes.NewTypedProperties.Found + public array $recordsByLevel = []; + + /** + * @inheritdoc + */ + public function log($level, $message, array $context = []): void + { + $record = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + /** + * @param string $level + * @return bool + */ + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + /** + * @param array $record + * @param string $level + * @return bool + */ + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + + return $this->hasRecordThatPasses(static function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + /** + * @param string $message + * @param string $level + * @return bool + */ + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses( + fn ($rec) => str_contains($rec['message'], $message), + $level + ); + } + + /** + * @param string $regex + * @param string $level + * @return bool + */ + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses( + fn ($rec) => preg_match($regex, $rec['message']) > 0, + $level + ); + } + + /** + * @param callable $predicate + * @param string $level + * @return bool + */ + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if ($predicate($rec, $i)) { + return true; + } + } + + return false; + } + + /** + * @deprecated Since psr/log-util 1.1 + */ + public function __call($method, $args) + { + // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged + @trigger_error( + sprintf( + // phpcs:ignore Inpsyde.CodeQuality.LineLength.TooLong + 'Since psr/log-util 1.1: Method "%s" is deprecated and should not be called. Use method "%s" instead.', + __FUNCTION__, + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $method + ), + \E_USER_DEPRECATED + ); + + if ( + preg_match( + '/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', + $method, + $matches + ) > 0 + ) { + $genericMethod = $matches[1] + . ('Records' !== $matches[3] ? 'Record' : '') + . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + // phpcs:ignore NeutronStandard.Functions.DisallowCallUserFunc.CallUserFunc + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException( + 'Call to undefined method ' . get_class($this) . '::' . $method . '()' + ); + } + + public function hasEmergency($record): bool + { + return $this->hasRecord($record, 'emergency'); + } + + public function hasAlert($record): bool + { + return $this->hasRecord($record, 'alert'); + } + + public function hasCritical($record): bool + { + return $this->hasRecord($record, 'critical'); + } + + public function hasError($record): bool + { + return $this->hasRecord($record, 'error'); + } + + public function hasWarning($record): bool + { + return $this->hasRecord($record, 'warning'); + } + + public function hasNotice($record): bool + { + return $this->hasRecord($record, 'notice'); + } + + public function hasInfo($record): bool + { + return $this->hasRecord($record, 'info'); + } + + public function hasDebug($record): bool + { + return $this->hasRecord($record, 'debug'); + } + + public function hasEmergencyRecords(): bool + { + return $this->hasRecords('emergency'); + } + + public function hasAlertRecords(): bool + { + return $this->hasRecords('alert'); + } + + public function hasCriticalRecords(): bool + { + return $this->hasRecords('critical'); + } + + public function hasErrorRecords(): bool + { + return $this->hasRecords('error'); + } + + public function hasWarningRecords(): bool + { + return $this->hasRecords('warning'); + } + + public function hasNoticeRecords(): bool + { + return $this->hasRecords('notice'); + } + + public function hasInfoRecords(): bool + { + return $this->hasRecords('info'); + } + + public function hasDebugRecords(): bool + { + return $this->hasRecords('debug'); + } + + public function hasEmergencyThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'emergency'); + } + + public function hasAlertThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'alert'); + } + + public function hasCriticalThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'critical'); + } + + public function hasErrorThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'error'); + } + + public function hasWarningThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'warning'); + } + + public function hasNoticeThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'notice'); + } + + public function hasInfoThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'info'); + } + + public function hasDebugThatContains($message): bool + { + return $this->hasRecordThatContains($message, 'debug'); + } + + public function hasEmergencyThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'emergency'); + } + + public function hasAlertThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'alert'); + } + + public function hasCriticalThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'critical'); + } + + public function hasErrorThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'error'); + } + + public function hasWarningThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'warning'); + } + + public function hasNoticeThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'notice'); + } + + public function hasInfoThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'info'); + } + + public function hasDebugThatMatches(string $regex): bool + { + return $this->hasRecordThatMatches($regex, 'debug'); + } + + public function hasEmergencyThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'emergency'); + } + + public function hasAlertThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'alert'); + } + + public function hasCriticalThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'critical'); + } + + public function hasErrorThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'error'); + } + + public function hasWarningThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'warning'); + } + + public function hasNoticeThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'notice'); + } + + public function hasInfoThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'info'); + } + + public function hasDebugThatPasses(callable $predicate): bool + { + return $this->hasRecordThatPasses($predicate, 'debug'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/tests/unit/HookListener/CronDebugListenerTest.php b/tests/unit/HookListener/CronDebugListenerTest.php index ae5eebf..0df22a5 100644 --- a/tests/unit/HookListener/CronDebugListenerTest.php +++ b/tests/unit/HookListener/CronDebugListenerTest.php @@ -109,8 +109,8 @@ static function (LogData $log) use (&$logs): void { $regxp = '~^Cron action "%s" performed\. Duration: [0|1]\.[0-9]+ seconds\.$~'; - static::assertRegExp(sprintf($regxp, 'wp_scheduled_delete'), $logs[0]); - static::assertRegExp(sprintf($regxp, 'wp_update_plugins'), $logs[1]); - static::assertRegExp(sprintf($regxp, 'wp_version_check'), $logs[2]); + static::assertMatchesRegularExpression(sprintf($regxp, 'wp_scheduled_delete'), $logs[0]); + static::assertMatchesRegularExpression(sprintf($regxp, 'wp_update_plugins'), $logs[1]); + static::assertMatchesRegularExpression(sprintf($regxp, 'wp_version_check'), $logs[2]); } } diff --git a/tests/unit/LogActionUpdaterTest.php b/tests/unit/LogActionUpdaterTest.php index 21b86a5..9248f83 100644 --- a/tests/unit/LogActionUpdaterTest.php +++ b/tests/unit/LogActionUpdaterTest.php @@ -10,6 +10,8 @@ use Inpsyde\Wonolog\Data\Log; use Inpsyde\Wonolog\LogActionUpdater; use Inpsyde\Wonolog\LogLevel as WonologLogLevel; +use Inpsyde\Wonolog\Tests\TestLogger\TestLoggerV1; +use Inpsyde\Wonolog\Tests\TestLogger\TestLoggerV2V3; use Inpsyde\Wonolog\Tests\UnitTestCase; use Monolog\Logger; use Psr\Log\LogLevel; @@ -94,7 +96,8 @@ public function testUpdateLogsUsingPsrLogger(): void $log = new Log('Test me', Logger::EMERGENCY, Channels::SECURITY, ['foo' => 'bar']); - $logger = new TestLogger(); + + $logger = $this->buildLogger(); $channels = \Mockery::mock(Channels::class); $channels->expects('isIgnored')->with($log)->andReturn(false); @@ -145,7 +148,7 @@ public function testUpdateLogsUsingPsrLoggerWithMaskedInput(): void $log = new Log('Test me', Logger::EMERGENCY, Channels::SECURITY, $context); - $logger = new TestLogger(); + $logger = $this->buildLogger(); $channels = \Mockery::mock(Channels::class); $channels->expects('isIgnored')->with($log)->andReturn(false); @@ -160,4 +163,9 @@ public function testUpdateLogsUsingPsrLoggerWithMaskedInput(): void static::assertSame(LogLevel::EMERGENCY, $record['level']); static::assertSame($contextExpected, $record['context']); } + + private function buildLogger() + { + return version_compare(phpversion(), '8.0', '>=') ? new TestLoggerV2V3() : new TestLoggerV1(); + } }