Skip to content

Commit

Permalink
Improved exceptions and added handler.
Browse files Browse the repository at this point in the history
  • Loading branch information
denpamusic committed Oct 11, 2018
1 parent 47b9ae2 commit 81df483
Show file tree
Hide file tree
Showing 20 changed files with 870 additions and 167 deletions.
1 change: 0 additions & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ plugins:
enabled: true
exclude_patterns:
- "tests/"
- "src/Exceptions/ClientException.php" # empty exception
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
"psr-4" : {
"Denpa\\Bitcoin\\": "src"
},
"classmap" : [
"tests"
],
"files" : [
"src/functions.php"
]
},
"autoload-dev": {
"psr-4" : {
"Denpa\\Bitcoin\\Tests\\": "tests"
}
}
}
137 changes: 64 additions & 73 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

namespace Denpa\Bitcoin;

use Denpa\Bitcoin\Exceptions\BadConfigurationException;
use Denpa\Bitcoin\Exceptions\BadRemoteCallException;
use Exception;
use GuzzleHttp\Client as GuzzleHttp;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Promise;
Expand Down Expand Up @@ -57,7 +59,7 @@ class Client
public function __construct($config = [])
{
// init defaults
$this->config = $this->defaultConfig($this->parseUrl($config));
$this->config = $this->mergeDefaultConfig($this->parseUrl($config));

// construct client
$this->client = new GuzzleHttp([
Expand Down Expand Up @@ -149,12 +151,12 @@ public function request($method, ...$params)

if ($response->hasError()) {
// throw exception on error
throw new Exceptions\BitcoindException($response->error());
throw new BadRemoteCallException($response);
}

return $response;
} catch (RequestException $exception) {
throw $this->handleException($exception);
} catch (Exception $exception) {
throw exception()->handle($exception);
}
}

Expand Down Expand Up @@ -208,22 +210,65 @@ public function __call($method, array $params = [])
}

/**
* Set default config values.
* Handles async request success.
*
* @param array $config
* @param \Psr\Http\Message\ResponseInterface $response
* @param callable|null $callback
*
* @return void
*/
protected function onSuccess(ResponseInterface $response, callable $callback = null)
{
if (!is_null($callback)) {
$callback($response);
}
}

/**
* Handles async request failure.
*
* @param \Exception $exception
* @param callable|null $callback
*
* @return void
*/
protected function onError(Exception $exception, callable $callback = null)
{
if (!is_null($callback)) {
try {
exception()->handle($exception);
} catch (Exception $exception) {
$callback($exception);
}
}
}

/**
* Gets default configuration.
*
* @return array
*/
protected function defaultConfig(array $config = [])
protected function getDefaultConfig()
{
$defaults = [
'scheme' => 'http',
'host' => '127.0.0.1',
'port' => 8332,
'user' => '',
'password' => '',
return [
'scheme' => 'http',
'host' => '127.0.0.1',
'port' => 8332,
'user' => '',
'password' => '',
'ca' => null,
];
}

/**
* Merge config with default values.
*
* @param array $config
*
* @return array
*/
protected function mergeDefaultConfig(array $config = [])
{
// use same var name as laravel-bitcoinrpc
if (
!array_key_exists('password', $config) &&
Expand All @@ -233,7 +278,7 @@ protected function defaultConfig(array $config = [])
unset($config['pass']);
}

return array_merge($defaults, $config);
return array_merge($this->getDefaultConfig(), $config);
}

/**
Expand Down Expand Up @@ -323,7 +368,10 @@ protected function parseUrl($config)
$parts = array_intersect_key($parts, array_flip($allowed));

if (!$parts || empty($parts)) {
throw new Exceptions\ClientException('Invalid url');
throw new BadConfigurationException(
['url' => $config],
'Invalid url'
);
}

return $parts;
Expand All @@ -350,61 +398,4 @@ protected function makeJson($method, $params = [])
],
];
}

/**
* Handles async request success.
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param callable|null $callback
*
* @return void
*/
protected function onSuccess(ResponseInterface $response, callable $callback = null)
{
if (!is_null($callback)) {
if ($response->hasError()) {
$response = new Exceptions\BitcoindException($response->error());
}

$callback($response);
}
}

/**
* Handles async request failure.
*
* @param \GuzzleHttp\Exception\RequestException $exception
* @param callable|null $callback
*
* @return void
*/
protected function onError(RequestException $exception, callable $callback = null)
{
if (!is_null($callback)) {
$callback($this->handleException($exception));
}
}

/**
* Handles exceptions.
*
* @param \Exception $exception
*
* @return \Exception
*/
protected function handleException($exception)
{
if ($exception->hasResponse()) {
$response = $exception->getResponse();

if ($response->hasError()) {
return new Exceptions\BitcoindException($response->error());
}
}

return new Exceptions\ClientException(
$exception->getMessage(),
$exception->getCode()
);
}
}
52 changes: 52 additions & 0 deletions src/Exceptions/BadConfigurationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Denpa\Bitcoin\Exceptions;

class BadConfigurationException extends ClientException
{
/**
* Configuration container.
*
* @var array
*/
protected $config;

/**
* Constructs new bad configuration exception.
*
* @param array $config
* @param mixed $args,...
*
* @return void
*/
public function __construct(array $config, ...$args)
{
$this->config = $config;

parent::__construct(...$args);
}

/**
* Gets config data.
*
* @return array
*/
public function getConfig()
{
return $this->config;
}

/**
* Returns array of parameters.
*
* @return array
*/
protected function getConstructorParameters()
{
return [
$this->getConfig(),
$this->getMessage(),
$this->getCode(),
];
}
}
52 changes: 52 additions & 0 deletions src/Exceptions/BadRemoteCallException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Denpa\Bitcoin\Exceptions;

use Denpa\Bitcoin\Responses\Response;

class BadRemoteCallException extends ClientException
{
/**
* Response object.
*
* @var \Denpa\Bitcoin\Responses\Response
*/
protected $response;

/**
* Constructs new bad remote call exception.
*
* @param \Denpa\Bitcoin\Responses\Response $response
*
* @return void
*/
public function __construct(Response $response)
{
$this->response = $response;

$error = $response->error();
parent::__construct($error['message'], $error['code']);
}

/**
* Gets response object.
*
* @return \Denpa\Bitcoin\Responses\Response
*/
public function getResponse()
{
return $this->response;
}

/**
* Returns array of parameters.
*
* @return array
*/
protected function getConstructorParameters()
{
return [
$this->getResponse(),
];
}
}
20 changes: 0 additions & 20 deletions src/Exceptions/BitcoindException.php

This file was deleted.

42 changes: 40 additions & 2 deletions src/Exceptions/ClientException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,46 @@

namespace Denpa\Bitcoin\Exceptions;

use RuntimeException;
use Exception;

class ClientException extends RuntimeException
abstract class ClientException extends Exception
{
/**
* Returns class name in provided namespace.
*
* @param string $namespace
*
* @return \Exception
*/
public function withNamespace($namespace)
{
$classname = $this->getClassName();

$class = $namespace."\\$classname";

if (class_exists($class)) {
return new $class(...$this->getConstructorParameters());
}

return $this;
}

/**
* Gets exception class name.
*
* @return string
*/
protected function getClassName()
{
$pos = ($pos = strrpos(static::class, '\\')) !== false ? $pos + 1 : 0;

return substr(static::class, $pos);
}

/**
* Returns array of parameters.
*
* @return array
*/
abstract protected function getConstructorParameters();
}
Loading

0 comments on commit 81df483

Please sign in to comment.