Client   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 51
c 1
b 0
f 0
dl 0
loc 144
rs 10
wmc 16

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A query() 0 20 1
A notify() 0 9 1
B send() 0 20 9
A getHeaders() 0 7 1
A sendData() 0 14 1
A setResponsesError() 0 4 2
1
<?php
2
3
namespace veejay\jsonrpc;
4
5
use veejay\jsonrpc\batch\Request;
6
use veejay\jsonrpc\batch\Response;
7
8
class Client
9
{
10
    /**
11
     * @var string
12
     */
13
    protected $uri;
14
15
    /**
16
     * List of requests.
17
     * @var Request[]
18
     */
19
    protected $requests = [];
20
21
    /**
22
     * List of responses.
23
     * Key - response ID
24
     * @var Response[]
25
     */
26
    protected $responses = [];
27
28
    /**
29
     * @param string $uri
30
     */
31
    public function __construct(string $uri)
32
    {
33
        $this->uri = $uri;
34
    }
35
36
    /**
37
     * Add query.
38
     * @param string $method
39
     * @param array $params
40
     * @return Response
41
     */
42
    public function query(string $method, array $params = []): Response
43
    {
44
        $id = count($this->requests);
45
46
        // Create Request
47
        $this->requests[] = (new Request)->setProperties([
48
            'jsonrpc' => Request::VERSION,
49
            'method' => $method,
50
            'params' => $params,
51
            'id' => $id,
52
        ]);
53
54
        // Create Response
55
        $response = $this->responses[$id] = new Response;
56
        $response->setProperties([
57
            'jsonrpc' => Request::VERSION,
58
            'id' => $id,
59
        ]);
60
        $response->setError(Response::PARSE_ERROR);
61
        return $response;
62
    }
63
64
    /**
65
     * Add notification.
66
     * @param string $method
67
     * @param array $params
68
     * @return void
69
     */
70
    public function notify(string $method, array $params = [])
71
    {
72
        $request = new Request;
73
        $request->setProperties([
74
            'jsonrpc' => Request::VERSION,
75
            'method' => $method,
76
            'params' => $params,
77
        ]);
78
        $this->requests[] = $request;
79
    }
80
81
    /**
82
     * @return void
83
     */
84
    public function send()
85
    {
86
        $data = $this->sendData();
87
        if ($data === null) return;
88
        
89
        if (isset($data->error->code)) {
90
            $this->setResponsesError($data->error->code, (string)$data->error->message);
91
            return;
92
        }
93
94
        if (is_object($data)) {
95
            $data = [$data];
96
        }
97
98
        foreach ($data as $datum) {
99
            if (!is_object($datum) || !property_exists($datum, 'id')) continue;
100
            $response = array_key_exists($datum->id, $this->responses) ? $this->responses[$datum->id] : null;
101
            if (!$response) continue;
102
            $response->resetError();
103
            $response->setProperties($datum);
104
        }
105
    }
106
107
    /**
108
     * Set errors for all responses.
109
     * @param int $code
110
     * @param string $message
111
     * @return void
112
     */
113
    protected function setResponsesError(int $code, string $message = '')
114
    {
115
        foreach ($this->responses as $response) {
116
            $response->setError($code, $message);
117
        }
118
    }
119
120
    /**
121
     * Send data on server and receive the response.
122
     * @return array|object|null - NULL if error occurred
123
     */
124
    protected function sendData()
125
    {
126
        $content = json_encode($this->requests);
127
128
        $context = stream_context_create([
129
            'http' => [
130
                'method' => 'POST',
131
                'header' => implode("\r\n", $this->getHeaders($content)),
132
                'content' => $content,
133
            ],
134
        ]);
135
136
        $content = file_get_contents($this->uri, false, $context);
137
        return json_decode($content);
138
    }
139
140
    /**
141
     * Get headers for request.
142
     * @param string $content
143
     * @return array
144
     */
145
    private function getHeaders(string $content): array
146
    {
147
        return [
148
            'Accept: application/json',
149
            'Content-Type: application/json',
150
            'Connection: close',
151
            'Content-Length: ' . strlen($content),
152
        ];
153
    }
154
}
155