-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enhanced decoding flexibility and mapping capability
Introduced iterable as the return type for decoders to allow for more flexible data structures, moving away from strict arrays. This allows the use of generators for on-demand data processing. Added a `MapperInterface` for transforming responses into objects, facilitating object-oriented handling of response data. Streamlined the creation of default decoders by defining `ChainDecoder::default` to reduce redundancy and ensure consistency across usage. A new `GenericMapper` allows custom mapping functions, providing clients with customizable response handling strategies. Additionally, `Response` now implements `JsonSerializable`, offering a standardized way to convert response data to JSON.
- Loading branch information
Showing
13 changed files
with
240 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fansipan\Contracts; | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
|
||
interface MapperInterface extends DecoderInterface | ||
{ | ||
/** | ||
* Map the response to an object. | ||
*/ | ||
public function map(ResponseInterface $response): ?object; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fansipan\Mapper; | ||
|
||
use Fansipan\Contracts\DecoderInterface; | ||
use Fansipan\Contracts\MapperInterface; | ||
use Fansipan\Decoder\ChainDecoder; | ||
use Psr\Http\Message\ResponseInterface; | ||
|
||
final class GenericMapper implements MapperInterface | ||
{ | ||
/** | ||
* @var callable(iterable): ?object | ||
*/ | ||
private $onSuccess; | ||
|
||
/** | ||
* @var callable(iterable): ?object | ||
*/ | ||
private $onFailure; | ||
|
||
/** | ||
* @var DecoderInterface | ||
*/ | ||
private $decoder; | ||
|
||
/** | ||
* @param callable(iterable): ?object $onSuccess | ||
* @param callable(iterable): ?object $onFailure | ||
*/ | ||
public function __construct( | ||
callable $onSuccess, | ||
callable $onFailure, | ||
?DecoderInterface $decoder = null | ||
) { | ||
$this->onSuccess = $onSuccess; | ||
$this->onFailure = $onFailure; | ||
$this->decoder = $decoder ?? ChainDecoder::default(); | ||
} | ||
|
||
public function map(ResponseInterface $response): ?object | ||
{ | ||
$status = $response->getStatusCode(); | ||
$decoded = $this->decoder->decode($response); | ||
|
||
if ($status >= 200 && $status < 300) { | ||
return ($this->onSuccess)($decoded); | ||
} else { | ||
return ($this->onFailure)($decoded); | ||
} | ||
} | ||
|
||
public function decode(ResponseInterface $response): iterable | ||
{ | ||
return $this->decoder->decode($response); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fansipan\Tests; | ||
|
||
use Fansipan\GenericConnector; | ||
use Fansipan\Mock\MockClient; | ||
use Fansipan\Mock\MockResponse; | ||
use Fansipan\Tests\Services\JsonPlaceholder\GetUserRequest; | ||
use Fansipan\Tests\Services\JsonPlaceholder\User; | ||
|
||
final class MapperTest extends TestCase | ||
{ | ||
public function test_mapper(): void | ||
{ | ||
$client = new MockClient([ | ||
MockResponse::fixture(__DIR__.'/fixtures/user.json'), | ||
]); | ||
|
||
$connector = (new GenericConnector())->withClient($client); | ||
$response = $connector->send(new GetUserRequest(1)); | ||
|
||
$user = $response->object(); | ||
|
||
$this->assertInstanceOf(User::class, $user); | ||
$this->assertSame(1, $user->id); | ||
$this->assertSame('Leanne Graham', $user->name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fansipan\Tests\Services\JsonPlaceholder; | ||
|
||
use Fansipan\Contracts\DecoderInterface; | ||
use Fansipan\Mapper\GenericMapper; | ||
use Fansipan\Request; | ||
use Fansipan\Util; | ||
|
||
final class GetUserRequest extends Request | ||
{ | ||
private $id; | ||
|
||
public function __construct(int $id) | ||
{ | ||
$this->id = $id; | ||
} | ||
|
||
public function endpoint(): string | ||
{ | ||
return 'https://jsonplaceholder.typicode.com/users/'.$this->id; | ||
} | ||
|
||
public function decoder(): DecoderInterface | ||
{ | ||
return new GenericMapper( | ||
static function (iterable $data) { | ||
return User::fromArray(Util::iteratorToArray($data)); | ||
}, | ||
static function (iterable $data) { | ||
return User::fromArray(Util::iteratorToArray($data)); | ||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Fansipan\Tests\Services\JsonPlaceholder; | ||
|
||
final class User | ||
{ | ||
/** | ||
* @var int | ||
*/ | ||
public $id; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $name; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $email; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $phone; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
public $website; | ||
|
||
public static function fromArray(array $data): self | ||
{ | ||
$self = new self(); | ||
|
||
$self->id = $data['id'] ?? 0; | ||
$self->name = $data['name'] ?? ''; | ||
$self->email = $data['email'] ?? ''; | ||
$self->phone = $data['phone'] ?? ''; | ||
$self->website = $data['website'] ?? ''; | ||
|
||
return $self; | ||
} | ||
} |