Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support enums in metadata #639

Merged
merged 2 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ Changelog

## TBD

### Enhancements

* Improve serialisation of backed enums. Previously a backed enum would JSON encode to their backing value, but will now include the enum name like `EnumName::CaseName (value)`
[#639](https://github.com/bugsnag/bugsnag-php/pull/639)

### Fixes

* A number of errors in docblocks have been corrected
[xPaw](https://github.com/xPaw)
[#633](https://github.com/bugsnag/bugsnag-php/pull/633)
[#637](https://github.com/bugsnag/bugsnag-php/pull/637)
* Handle serialising pure enums when added as metadata. Previously a pure enum would be JSON encoded as `null`, but will now be converted to a string like `EnumName::CaseName`
[#639](https://github.com/bugsnag/bugsnag-php/pull/639)

## 3.26.1 (2021-09-09)

Expand Down
7 changes: 6 additions & 1 deletion phpstan/baseline-less-than-8.1.neon
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
parameters:
ignoreErrors: []
ignoreErrors:
- '#Class UnitEnum not found\.#'
- '#.*invalid type UnitEnum\.#'
- '#.*unknown class UnitEnum\.#'
- '#Class BackedEnum not found\.#'
- '#.*unknown class BackedEnum\.#'
26 changes: 26 additions & 0 deletions src/Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

namespace Bugsnag;

use BackedEnum;
use Bugsnag\Breadcrumbs\Breadcrumb;
use Bugsnag\DateTime\Date;
use Exception;
use InvalidArgumentException;
use Throwable;
use UnitEnum;

class Report
{
Expand Down Expand Up @@ -777,6 +779,10 @@ protected function cleanupObj($obj, $isMetaData)
}

if (is_object($obj)) {
if ($obj instanceof UnitEnum) {
return $this->enumToString($obj);
}

return $this->cleanupObj(json_decode(json_encode($obj), true), $isMetaData);
}

Expand Down Expand Up @@ -833,4 +839,24 @@ protected function removeNullElements($array)

return $array;
}

/**
* Convert the given enum to a string.
*
* @param UnitEnum $enum
*
* @return string
*/
private function enumToString(UnitEnum $enum)
{
// e.g. My\Enum::SomeCase
$string = sprintf('%s::%s', get_class($enum), $enum->name);

// add the value, if there is one
if ($enum instanceof BackedEnum) {
$string .= sprintf(' (%s)', $enum->value);
}

return $string;
}
}
73 changes: 73 additions & 0 deletions tests/phpt/php8.1/backed_enums_can_be_added_as_metadata.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
--TEST--
Backed enums can be added as metadata
--FILE--
<?php
namespace Some\Namespace;

enum StringBackedEnum: string {
case Admin = 'admin';
case User = 'user';
}

enum IntBackedEnum: int {
case Square = 1;
case Circle = 2;
}

$client = require __DIR__ . '/../_prelude.php';

$client->setMetaData([
'data' => [
'admin' => StringBackedEnum::Admin,
'user' => StringBackedEnum::User,
'square' => IntBackedEnum::Square,
'circle' => IntBackedEnum::Circle,
],
]);

echo "Backed enums should be stored as objects\n";
var_dump($client->getMetaData()['data']);
echo "\n";

$client->notifyException(new \Exception('hello'), function (\Bugsnag\Report $report): void {
echo "Backed enums should be converted to string representation when serialised\n";
var_dump($report->toArray()['metaData']['data']);
echo "\n";
});
?>
--SKIPIF--
<?php
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
echo 'SKIP — this test requires PHP 8.1+ for enum support';
}
?>
--EXPECTF--
Backed enums should be stored as objects
array(4) {
["admin"]=>
enum(Some\Namespace\StringBackedEnum::Admin)
["user"]=>
enum(Some\Namespace\StringBackedEnum::User)
["square"]=>
enum(Some\Namespace\IntBackedEnum::Square)
["circle"]=>
enum(Some\Namespace\IntBackedEnum::Circle)
}

Backed enums should be converted to string representation when serialised
array(4) {
["admin"]=>
string(46) "Some\Namespace\StringBackedEnum::Admin (admin)"
["user"]=>
string(44) "Some\Namespace\StringBackedEnum::User (user)"
["square"]=>
string(40) "Some\Namespace\IntBackedEnum::Square (1)"
["circle"]=>
string(40) "Some\Namespace\IntBackedEnum::Circle (2)"
}

Guzzle request made (1 event)!
* Method: 'POST'
* URI: 'http://localhost/notify'
* Events:
- hello
86 changes: 86 additions & 0 deletions tests/phpt/php8.1/pure_enums_can_be_added_as_metadata.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
--TEST--
Pure enums can be added as metadata
--FILE--
<?php
namespace Some\Namespace;

enum MyPureEnum {
case TheFirstCase;
case SecondCase;
case CaseNumberThree;
}

namespace Another\Namespace;

enum AnotherPureEnum {
case One;
case Two;
}

$client = require __DIR__ . '/../_prelude.php';

$client->setMetaData([
'data' => [
'first case' => \Some\Namespace\MyPureEnum::TheFirstCase,
'second case' => \Some\Namespace\MyPureEnum::SecondCase,
'third case' => \Some\Namespace\MyPureEnum::CaseNumberThree,
'unrelated thing' => 'yes',
'case one' => \Another\Namespace\AnotherPureEnum::One,
'case two' => \Another\Namespace\AnotherPureEnum::Two,
],
]);

echo "Pure enums should be stored as objects\n";
var_dump($client->getMetaData()['data']);
echo "\n";

$client->notifyException(new \Exception('hello'), function (\Bugsnag\Report $report): void {
echo "Pure enums should be converted to a string representation when serialised\n";
var_dump($report->toArray()['metaData']['data']);
echo "\n";
});
?>
--SKIPIF--
<?php
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
echo 'SKIP — this test requires PHP 8.1+ for enum support';
}
?>
--EXPECTF--
Pure enums should be stored as objects
array(6) {
["first case"]=>
enum(Some\Namespace\MyPureEnum::TheFirstCase)
["second case"]=>
enum(Some\Namespace\MyPureEnum::SecondCase)
["third case"]=>
enum(Some\Namespace\MyPureEnum::CaseNumberThree)
["unrelated thing"]=>
string(3) "yes"
["case one"]=>
enum(Another\Namespace\AnotherPureEnum::One)
["case two"]=>
enum(Another\Namespace\AnotherPureEnum::Two)
}

Pure enums should be converted to a string representation when serialised
array(6) {
["first case"]=>
string(39) "Some\Namespace\MyPureEnum::TheFirstCase"
["second case"]=>
string(37) "Some\Namespace\MyPureEnum::SecondCase"
["third case"]=>
string(42) "Some\Namespace\MyPureEnum::CaseNumberThree"
["unrelated thing"]=>
string(3) "yes"
["case one"]=>
string(38) "Another\Namespace\AnotherPureEnum::One"
["case two"]=>
string(38) "Another\Namespace\AnotherPureEnum::Two"
}

Guzzle request made (1 event)!
* Method: 'POST'
* URI: 'http://localhost/notify'
* Events:
- hello