diff --git a/CHANGELOG.md b/CHANGELOG.md index bee5391..84024b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +- Fix TypeError when exceptions with string error codes are thrown ## [0.7.3] - 2021-06-29 diff --git a/example/generated/Twitch/Twirp/Example/TwirpError.php b/example/generated/Twitch/Twirp/Example/TwirpError.php index aaff79c..32fdaf0 100644 --- a/example/generated/Twitch/Twirp/Example/TwirpError.php +++ b/example/generated/Twitch/Twirp/Example/TwirpError.php @@ -91,8 +91,9 @@ public static function newError(string $code, string $msg): self public static function errorFrom(\Throwable $e, string $msg = ''): self { $msg = empty($msg) ? $e->getMessage() : $msg; + $code = is_int($e->getCode()) ? $e->getCode() : 0; - $err = new self(ErrorCode::Internal, $msg, $e->getCode(), $e); + $err = new self(ErrorCode::Internal, $msg, $code, $e); $err->setMeta('cause', $e->getMessage()); return $err; diff --git a/example/tests/TwirpErrorTest.php b/example/tests/TwirpErrorTest.php index 73aea86..54d3eb9 100644 --- a/example/tests/TwirpErrorTest.php +++ b/example/tests/TwirpErrorTest.php @@ -102,4 +102,30 @@ public function it_creates_an_error_from_an_exception_with_a_custom_message(): v $this->assertEquals('custom msg', $error->getMessage()); $this->assertEquals('msg', $error->getMeta('cause')); } + + /** + * Exception->getCode is not guaranteed to return an int, even though the method has a type hint. + * See: https://www.php.net/manual/en/exception.getcode.php + * > Returns the exception code as int in Exception but possibly as other + * > type in Exception descendants (for example as string in PDOException). + * + * @test + */ + public function it_works_with_string_codes(): void + { + $exception = new class('msg', 'code') extends \PDOException + { + public function __construct(string $msg, string $code) + { + parent::__construct($msg); + $this->code = $code; + } + }; + $error = TwirpError::errorFrom($exception); + + $this->assertEquals(ErrorCode::Internal, $error->getErrorCode()); + $this->assertEquals('msg', $error->getMessage()); + $this->assertEquals('msg', $error->getMeta('cause')); + $this->assertEquals(0, $error->getCode()); + } } diff --git a/protoc-gen-twirp_php/templates/global/TwirpError.php.tmpl b/protoc-gen-twirp_php/templates/global/TwirpError.php.tmpl index 4cff887..b525239 100644 --- a/protoc-gen-twirp_php/templates/global/TwirpError.php.tmpl +++ b/protoc-gen-twirp_php/templates/global/TwirpError.php.tmpl @@ -91,8 +91,10 @@ final class TwirpError extends \Exception implements Error public static function errorFrom(\Throwable $e, string $msg = ''): self { $msg = empty($msg) ? $e->getMessage() : $msg; + // Exception->getCode is not guaranteed to return an int, see https://www.php.net/manual/en/exception.getcode.php + $code = is_int($e->getCode()) ? $e->getCode() : 0; - $err = new self(ErrorCode::Internal, $msg, $e->getCode(), $e); + $err = new self(ErrorCode::Internal, $msg, $code, $e); $err->setMeta('cause', $e->getMessage()); return $err;