Completed
Push — master ( f7f813...50031e )
by Denis
02:29
created

Client::getResponseParser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace PhpJsonRpc;
4
5
use PhpJsonRpc\Client\IdGenerator;
6
use PhpJsonRpc\Client\IdGeneratorInterface;
7
use PhpJsonRpc\Core\Result\ResultError;
8
use PhpJsonRpc\Error\InvalidResponseException;
9
use PhpJsonRpc\Client\HttpTransport;
10
use PhpJsonRpc\Client\AbstractTransport;
11
use PhpJsonRpc\Client\RequestBuilder;
12
use PhpJsonRpc\Client\ResponseParser;
13
use PhpJsonRpc\Core\Call\AbstractCall;
14
use PhpJsonRpc\Core\Call\CallNotification;
15
use PhpJsonRpc\Core\Call\CallUnit;
16
use PhpJsonRpc\Core\CallSpecifier;
17
use PhpJsonRpc\Core\Result\ResultUnit;
18
use PhpJsonRpc\Core\ResultSpecifier;
19
20
class Client
21
{
22
    /**
23
     * @var AbstractCall[]
24
     */
25
    private $units = [];
26
27
    /**
28
     * @var bool
29
     */
30
    private $isSingleRequest = true;
31
32
    /**
33
     * @var RequestBuilder
34
     */
35
    private $requestBuilder;
36
37
    /**
38
     * @var AbstractTransport
39
     */
40
    private $transport;
41
42
    /**
43
     * @var ResponseParser
44
     */
45
    private $responseParser;
46
47
    /**
48
     * @var IdGeneratorInterface
49
     */
50
    private $generatorId;
51
52
    /**
53
     * Client constructor.
54
     *
55
     * @param string $url
56
     */
57
    public function __construct(string $url)
58
    {
59
        $this->requestBuilder = new RequestBuilder();
60
        $this->transport      = new HttpTransport($url);
61
        $this->responseParser = new ResponseParser();
62
        $this->generatorId    = new IdGenerator();
63
    }
64
65
    /**
66
     * @return AbstractTransport
67
     */
68
    public function getTransport(): AbstractTransport
69
    {
70
        return $this->transport;
71
    }
72
73
    /**
74
     * Set transport engine
75
     *
76
     * @param AbstractTransport $transport
77
     */
78
    public function setTransport(AbstractTransport $transport)
79
    {
80
        $this->transport = $transport;
81
    }
82
83
    /**
84
     * @return ResponseParser
85
     */
86
    public function getResponseParser()
87
    {
88
        return $this->responseParser;
89
    }
90
91
    /**
92
     * @param ResponseParser $responseParser
93
     */
94
    public function setResponseParser($responseParser)
95
    {
96
        $this->responseParser = $responseParser;
97
    }
98
99
    /**
100
     * @return IdGeneratorInterface
101
     */
102
    public function getGeneratorId(): IdGeneratorInterface
103
    {
104
        return $this->generatorId;
105
    }
106
107
    /**
108
     * @param IdGeneratorInterface $idGenerator
109
     */
110
    public function setIdGenerator(IdGeneratorInterface $idGenerator)
111
    {
112
        $this->generatorId = $idGenerator;
113
    }
114
115
    /**
116
     * Make request
117
     *
118
     * @param string $method
119
     * @param array  $parameters
120
     *
121
     * @return $this|mixed
122
     */
123
    public function call(string $method, array $parameters)
124
    {
125
        $this->units[] = new CallUnit($this->generatorId->get(), $method, $parameters);
126
127
        if ($this->isSingleRequest) {
128
            $resultSpecifier = $this->execute(new CallSpecifier($this->units, true));
129
130
            if (!$resultSpecifier->isSingleResult()) {
131
                throw new InvalidResponseException();
132
            }
133
134
            list($result) = $resultSpecifier->getResults();
135
136
            if ($result instanceof ResultUnit) {
137
                /** @var ResultUnit $result */
138
                return $result->getResult();
139
            }
140
141
            return null;
142
        }
143
144
        return $this;
145
    }
146
147
    /**
148
     * Make notification request
149
     *
150
     * @param string $method
151
     * @param array  $parameters
152
     *
153
     * @return $this|null
154
     */
155
    public function notification(string $method, array $parameters)
156
    {
157
        $this->units[] = new CallNotification($method, $parameters);
158
159
        if ($this->isSingleRequest) {
160
            $this->execute(new CallSpecifier($this->units, true));
161
            return null;
162
        }
163
164
        return $this;
165
    }
166
167
    /**
168
     * Start batch request
169
     *
170
     * @return $this
171
     */
172
    public function batch()
173
    {
174
        $this->isSingleRequest = false;
175
        return $this;
176
    }
177
178
    /**
179
     * Execute batch request
180
     *
181
     * @return array
182
     */
183
    public function batchExecute()
184
    {
185
        $results = $this->execute(new CallSpecifier($this->units, false))->getResults();
186
187
        // Make right order in sequence of results. It's required operation, because JSON-RPC2
188
        // specification define: "The Response objects being returned from a batch call MAY be returned
189
        // in any order within the Array. The Client SHOULD match contexts between the set of Request objects and the
190
        // resulting set of Response objects based on the id member within each Object."
191
192
        $callMap = [];
193
        foreach ($this->units as $index => $unit) {
194
            /** @var CallUnit $unit */
195
            $callMap[$unit->getRawId()] = $index;
196
        }
197
198
        if (count($results) !== count($this->units)) {
199
            throw new InvalidResponseException();
200
        }
201
202
        $resultSequence = [];
203
        foreach ($results as $result) {
204
            if ($result instanceof ResultUnit) {
205
                /** @var ResultUnit $result */
206
                $resultSequence[ $callMap[$result->getId()] ] = $result->getResult();
207
            } elseif ($result instanceof ResultError) {
208
                /** @var ResultError $result */
209
                $resultSequence[ $callMap[$result->getId()] ] = null;
210
            }
211
        }
212
        ksort($resultSequence);
213
214
        return $resultSequence;
215
    }
216
217
    /**
218
     * @param CallSpecifier $call
219
     *
220
     * @return ResultSpecifier
221
     */
222
    private function execute(CallSpecifier $call): ResultSpecifier
223
    {
224
        $request  = $this->requestBuilder->build($call);
225
        $response = $this->transport->request($request);
226
227
        return $this->responseParser->parse($response);
228
    }
229
}
230