Skip to content

Commit f388b5c

Browse files
committed
Fix compat with PHP 7
1 parent 5b90ca5 commit f388b5c

4 files changed

Lines changed: 97 additions & 14 deletions

File tree

src/Logs/LogsAggregator.php

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Sentry\State\HubInterface;
1313
use Sentry\State\Scope;
1414
use Sentry\Util\Arr;
15+
use Sentry\Util\Str;
1516

1617
/**
1718
* @internal
@@ -57,21 +58,18 @@ public function add(
5758
return;
5859
}
5960

60-
$formattedMessage = $message;
61+
$formattedMessage = Str::vsprintfOrNull($message, $values);
6162

62-
if (!empty($values)) {
63-
try {
64-
$formattedMessage = vsprintf($message, $values);
65-
} catch (\ValueError $e) {
66-
// If formatting fails we don't format the message and log the error
67-
if ($sdkLogger !== null) {
68-
$sdkLogger->warning('Failed to format log message with values.', [
69-
'message' => $message,
70-
'values' => $values,
71-
'exception' => $e,
72-
]);
73-
}
63+
if ($formattedMessage === null) {
64+
// If formatting fails we don't format the message and log the error
65+
if ($sdkLogger !== null) {
66+
$sdkLogger->warning('Failed to format log message with values.', [
67+
'message' => $message,
68+
'values' => $values,
69+
]);
7470
}
71+
72+
$formattedMessage = $message;
7573
}
7674

7775
$log = (new Log($timestamp, $this->getTraceId($hub), $level, $formattedMessage))

src/Serializer/EnvelopItems/EventItem.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Sentry\Serializer\Traits\BreadcrumbSeralizerTrait;
1010
use Sentry\Serializer\Traits\StacktraceFrameSeralizerTrait;
1111
use Sentry\Util\JSON;
12+
use Sentry\Util\Str;
1213

1314
/**
1415
* @internal
@@ -124,7 +125,7 @@ public static function toEnvelopeItem(Event $event): string
124125
$payload['message'] = [
125126
'message' => $event->getMessage(),
126127
'params' => $event->getMessageParams(),
127-
'formatted' => $event->getMessageFormatted() ?? vsprintf($event->getMessage(), $event->getMessageParams()),
128+
'formatted' => $event->getMessageFormatted() ?? Str::vsprintfOrNull($event->getMessage(), $event->getMessageParams()) ?? $event->getMessage(),
128129
];
129130
}
130131
}

src/Util/Str.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Util;
6+
7+
/**
8+
* This class provides some utility methods to work with strings.
9+
*
10+
* @internal
11+
*/
12+
class Str
13+
{
14+
/**
15+
* Safe way of running `vsprintf` without throwing an exception.
16+
*
17+
* If the string could not be formatted, it returns `null`.
18+
*
19+
* @see https://www.php.net/manual/en/function.vsprintf.php
20+
*
21+
* @param array<bool|float|int|string|null> $values
22+
*/
23+
public static function vsprintfOrNull(string $message, array $values): ?string
24+
{
25+
if (empty($values)) {
26+
return $message;
27+
}
28+
29+
try {
30+
$result = @vsprintf($message, $values);
31+
32+
// @phpstan-ignore-next-line on PHP 7 `vsprintf` does not throw an exception but can return `false`
33+
return $result === false ? null : $result;
34+
} catch (\Error $e) { // This is technically a `ValueError` in PHP 8.0+ but this works in PHP 7 as well
35+
return null;
36+
}
37+
}
38+
}

tests/Util/StrTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Tests\Util;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Sentry\Util\Str;
9+
10+
final class StrTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider vsprintfOrNullDataProvider
14+
*/
15+
public function testVsprintfOrNull(string $message, array $values, ?string $expected): void
16+
{
17+
$this->assertSame($expected, Str::vsprintfOrNull($message, $values));
18+
}
19+
20+
public static function vsprintfOrNullDataProvider(): \Generator
21+
{
22+
yield [
23+
'Simple message without values',
24+
[],
25+
'Simple message without values',
26+
];
27+
28+
yield [
29+
'Message with a value: %s',
30+
['value'],
31+
'Message with a value: value',
32+
];
33+
34+
yield [
35+
'Message with placeholders but no values: %s',
36+
[],
37+
'Message with placeholders but no values: %s',
38+
];
39+
40+
yield [
41+
'Message with placeholders but incorrect number of values: %s, %s',
42+
['value'],
43+
null,
44+
];
45+
}
46+
}

0 commit comments

Comments
 (0)