Skip to content

Commit

Permalink
Merge pull request #639 from bugsnag/support-enums-in-metadata
Browse files Browse the repository at this point in the history
Support enums in metadata
  • Loading branch information
imjoehaines authored Feb 3, 2022
2 parents 5a092e1 + ada4d46 commit d810ec3
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 1 deletion.
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

0 comments on commit d810ec3

Please sign in to comment.