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

Feature/exception factory #50

Merged
merged 20 commits into from
Oct 10, 2017
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,7 @@ Please do not forget to set the `_API_KEY` constant in

Information regarding the test cases can be found in the [README.md](./tests/README.md)
located in [test](/tests).

## Exceptions
The SDK can throw multiple exceptions. For an overview of these exceptions please
take a look at [EXCEPTIONS.md](./src/Exception/EXCEPTION.md)
27 changes: 26 additions & 1 deletion src/Exception/ApiException.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
<?php
namespace bunq\Exception;

use Exception;

/**
*/
class ApiException extends BunqException
class ApiException extends Exception
{
/**
* @var int
*/
private $responseCode;

/**
* @param string $message
* @param int $responseCode
*/
public function __construct(string $message, int $responseCode)
{
$this->responseCode = $responseCode;

parent::__construct($message);
}

/**
* @return int
*/
public function getResponseCode(): int
{
return $this->responseCode;
}
}
9 changes: 9 additions & 0 deletions src/Exception/BadRequestException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class BadRequestException extends ApiException
{

}
84 changes: 84 additions & 0 deletions src/Exception/EXCEPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## Exceptions
When you make a request via the SDK, there is a chance of request failing
due to various reasons. When such a failure happens, an exception
corresponding to the error occurred is thrown.


----
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these ---- ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a it more beautiful :P Its like a paragraph separator. View it as an actual markdown and you shall see 😁

#### Possible Exceptions
* `BadRequestException` If the request returns with status code `400`
* `UnauthorizedException` If the request returns with status code `401`
* `ForbiddenException` If the request returns with status code `403`
* `NotFoundException` If the request returns with status code `404`
* `MethodNotAllowedException` If the request returns with status code `405`
* `TooManyRequestsException` If the request returns with status code `429`
* `PleaseContactBunqException` If the request returns with status code `500`.
If you get this exception, please contact us preferably via the support chat in the bunq app.
* `UnknownApiErrorException` If none of the above mentioned exceptions are thrown,
this exception will be thrown instead.

For more information regarding these errors, please take a look on the documentation
page here: https://doc.bunq.com/api/1/page/errors

---
#### Base exception
All the exceptions have the same base exception which looks like this:
```php
<?php
class ApiException extends Exception
{
/**
* @var int
*/
private $responseCode;

/**
* @param string $message
* @param int $responseCode
*/
public function __construct(string $message, int $responseCode)
{
//Some hidden code
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after // please! :)

}

/**
* @return int
*/
public function getResponseCode(): int
{
return $this->responseCode;
}
}
```
The `Exception` class which is being extended has an `getMessage()` method which is `final` and therefore cannot be
overridden.

This means that each exception will have a response code and an error message
related to the specific error returned by API.

---
#### Exception handling
Since each API error has a distinct SDK exception type corresponding to it,
you can catch the exact exceptions you expect 👏.

```php
<?php
use bunq\Context\ApiContext;
use bunq\Util\BunqEnumApiEnvironmentType;
use bunq\Exception\BadRequestException;


const API_KEY = 'Some invalid API key ';
const DEVICE_DESCRIPTION = 'This will cause BadRequestException to be thrown.';

try{
//Make a call that might fail
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after // please! :)

$apiContext = ApiContext::create(BunqEnumApiEnvironmentType::SANDBOX(), API_KEY, DEVICE_DESCRIPTION);
} catch (BadRequestException $error){
// Do something if exception is thrown.
echo $error->getResponseCode() . PHP_EOL;
echo $error->getMessage() . PHP_EOL;
}


```
83 changes: 83 additions & 0 deletions src/Exception/ExceptionFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
namespace bunq\Exception;

/**
*/
class ExceptionFactory
{
/**
* HTTP error response codes constants.
*/
const HTTP_RESPONSE_CODE_BAD_REQUEST = 400;
const HTTP_RESPONSE_CODE_UNAUTHORIZED = 401;
const HTTP_RESPONSE_CODE_FORBIDDEN = 403;
const HTTP_RESPONSE_CODE_NOT_FOUND = 404;
const HTTP_RESPONSE_CODE_METHOD_NOT_ALLOWED = 405;
const HTTP_RESPONSE_CODE_TOO_MANY_REQUESTS = 429;
const HTTP_RESPONSE_CODE_INTERNAL_SERVER_ERROR = 500;

/**
* Formatting constants
*/
const FORMAT_RESPONSE_CODE_LINE = 'HTTP Response Code: %s';
const GLUE_ERROR_MESSAGES = "\n";

/**
* The first item index in an array.
*/
const INDEX_FIRST = 0;

/**
* @param string[] $messages
* @param int $responseCode
*
* @return ApiException
*/
public static function createExceptionForResponse(array $messages, int $responseCode): ApiException
{
$errorMessage = static::generateErrorMessage($responseCode, $messages);

switch ($responseCode)
{
case self::HTTP_RESPONSE_CODE_BAD_REQUEST:
return new BadRequestException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_UNAUTHORIZED:
return new UnauthorizedException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_FORBIDDEN:
return new ForbiddenException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_NOT_FOUND:
return new NotFoundException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_METHOD_NOT_ALLOWED:
return new MethodNotAllowedException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_TOO_MANY_REQUESTS:
return new TooManyRequestsException($errorMessage, $responseCode);
case self::HTTP_RESPONSE_CODE_INTERNAL_SERVER_ERROR:
return new PleaseContactBunqException($errorMessage, $responseCode);
default:
return new UnknownApiErrorException($errorMessage, $responseCode);
}
}

/**
* @param int $responseCode
* @param string[] $messages
*
* @return string
*/
private static function generateErrorMessage(int $responseCode, array $messages): string
{
$lineResponseCode = sprintf(self::FORMAT_RESPONSE_CODE_LINE, $responseCode);

return static::glueMessages(array_merge([$lineResponseCode], $messages));
}

/**
* @param string[] $messages
*
* @return string
*/
private static function glueMessages(array $messages): string
{
return implode(self::GLUE_ERROR_MESSAGES, $messages);
}
}
9 changes: 9 additions & 0 deletions src/Exception/ForbiddenException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class ForbiddenException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/MethodNotAllowedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class MethodNotAllowedException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/NotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class NotFoundException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/PleaseContactBunqException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class PleaseContactBunqException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/TooManyRequestsException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class TooManyRequestsException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/UnauthorizedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class UnauthorizedException extends ApiException
{

}
9 changes: 9 additions & 0 deletions src/Exception/UnknownApiErrorException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace bunq\Exception;

/**
*/
class UnknownApiErrorException extends ApiException
{

}
Loading