Code

< 40 %
40-60 %
> 60 %
1
<?php
2
3
namespace Bankiru\Api\BrowserKit;
4
5
use ScayTrase\Api\JsonRpc\Exception\JsonRpcProtocolException;
6
use ScayTrase\Api\JsonRpc\Exception\ResponseParseException;
7
use ScayTrase\Api\JsonRpc\JsonRpcNotificationResponse;
8
use ScayTrase\Api\JsonRpc\JsonRpcResponseInterface;
9
use ScayTrase\Api\JsonRpc\RequestTransformation;
10
use ScayTrase\Api\JsonRpc\SyncResponse;
11
use ScayTrase\Api\Rpc\Exception\RemoteCallFailedException;
12
use ScayTrase\Api\Rpc\ResponseCollectionInterface;
13
use ScayTrase\Api\Rpc\RpcRequestInterface;
14
use Symfony\Component\BrowserKit\Response;
15
16
final class JsonRpcResponseCollection implements \IteratorAggregate, ResponseCollectionInterface
17
{
18
    /** @var JsonRpcResponseInterface[] */
19
    protected $hashedResponses = [];
20
    /** @var  Response */
21
    private $response;
22
    /** @var  RequestTransformation[] */
23
    private $transformations;
24
    /** @var  JsonRpcResponseInterface[] */
25
    private $responses = [];
26
27
    /**
28
     * JsonRpcResponseCollection constructor.
29
     *
30
     * @param Response                $response
31
     * @param RequestTransformation[] $transformations
32
     */
33
    public function __construct(Response $response, array $transformations)
34
    {
35
        $this->response        = $response;
36
        $this->transformations = $transformations;
37
        $this->sync();
38
    }
39
40
    /** {@inheritdoc} */
41
    public function getIterator()
42
    {
43
        return new \ArrayIterator($this->responses);
44
    }
45
46
    /** {@inheritdoc} */
47
    public function getResponse(RpcRequestInterface $request)
48
    {
49
        if (array_key_exists(spl_object_hash($request), $this->hashedResponses)) {
50
            return $this->hashedResponses[spl_object_hash($request)];
51
        }
52
53
        $storedRequest = null;
54
        foreach ($this->transformations as $transformation) {
55
            if ($transformation->getOriginalCall() === $request) {
56
                $storedRequest = $transformation->getTransformedCall();
57
                break;
58
            }
59
        }
60
61
        if (null === $storedRequest) {
62
            throw new \OutOfBoundsException('Given request was not invoked for this collection');
63
        }
64
65
        if ($storedRequest->isNotification()) {
66
            $this->hashedResponses[spl_object_hash($request)] = new JsonRpcNotificationResponse();
67
68
            return $this->hashedResponses[spl_object_hash($request)];
69
        }
70
71
        if (!array_key_exists($storedRequest->getId(), $this->responses)) {
72
            throw JsonRpcProtocolException::requestSendButNotResponded($storedRequest);
73
        }
74
75
        $this->hashedResponses[spl_object_hash($request)] = $this->responses[$storedRequest->getId()];
76
77
        return $this->hashedResponses[spl_object_hash($request)];
78
    }
79
80
    private function sync()
81
    {
82
        if (200 !== $this->response->getStatus()) {
83
            throw new RemoteCallFailedException('Remote response was not successful');
84
        }
85
86
        $data = (string)$this->response->getContent();
87
88
        // Null (empty response) is expected if only notifications were sent
89
        $rawResponses = [];
90
91
        if ('' !== $data) {
92
            $rawResponses = json_decode($data, false);
93
            if (json_last_error() !== JSON_ERROR_NONE) {
94
                throw ResponseParseException::notAJsonResponse();
95
            }
96
        }
97
98
        if (!is_array($rawResponses) && $rawResponses instanceof \stdClass) {
99
            $rawResponses = [$rawResponses];
100
        }
101
102
        $this->responses = [];
103
        foreach ((array)$rawResponses as $rawResponse) {
104
            try {
105
                $response = new SyncResponse($rawResponse);
106
            } catch (ResponseParseException $exception) {
107
                continue;
108
            }
109
110
            $this->responses[$response->getId()] = $response;
111
        }
112
    }
113
}
114