1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace AdrianMejias\FactomApi; |
4
|
|
|
|
5
|
|
|
use GuzzleHttp\Client; |
6
|
|
|
use GuzzleHttp\Exception\RequestException; |
7
|
|
|
use GuzzleHttp\Psr7\Request; |
8
|
|
|
|
9
|
|
|
use AdrianMejias\FactomApi\Exceptions\InvalidFactomApiConfig; |
10
|
|
|
|
11
|
|
|
class FactomConnector |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* The JSON RPC spec that the API uses. |
15
|
|
|
* |
16
|
|
|
* @var string |
17
|
|
|
*/ |
18
|
|
|
const JSON_RPC = '2.0'; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* The "ID" param provided in all requests to the API. |
22
|
|
|
* |
23
|
|
|
* @var integer |
24
|
|
|
*/ |
25
|
|
|
const REQUEST_ID = 0; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* The header content type in all requests to the API. |
29
|
|
|
* |
30
|
|
|
* @var string |
31
|
|
|
*/ |
32
|
|
|
const HEADER_CONTENT_TYPE = 'text/plain'; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* The header accept in all requests to the API. |
36
|
|
|
* |
37
|
|
|
* @var string |
38
|
|
|
*/ |
39
|
|
|
const HEADER_ACCEPT = 'application/json'; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* The generic error if cannot load server properly. |
43
|
|
|
* |
44
|
|
|
* @var string |
45
|
|
|
*/ |
46
|
|
|
const BLANK_PAGE_ERROR = 'Page not found'; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* The client instance. |
50
|
|
|
* |
51
|
|
|
* @var null|GuzzleHttp\Client |
52
|
|
|
*/ |
53
|
|
|
protected $client = null; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* The URL for all API requests. |
57
|
|
|
* |
58
|
|
|
* @var null|string |
59
|
|
|
*/ |
60
|
|
|
protected $url = 'http://localhost:8088/v2'; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Make secure URL requests. |
64
|
|
|
* |
65
|
|
|
* @var null|bool |
66
|
|
|
*/ |
67
|
|
|
protected $ssl = false; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Path to the certificate file for using factomd over TLS. |
71
|
|
|
* |
72
|
|
|
* @var null |
73
|
|
|
*/ |
74
|
|
|
protected $certifcate = null; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* The provided username for interacting with factomd |
78
|
|
|
* Optional. |
79
|
|
|
* |
80
|
|
|
* @var null |
81
|
|
|
*/ |
82
|
|
|
protected $username = null; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* The provided password for interacting with factomd |
86
|
|
|
* Optional. |
87
|
|
|
* |
88
|
|
|
* @var null |
89
|
|
|
*/ |
90
|
|
|
protected $password = null; |
91
|
|
|
|
92
|
|
|
public function __construct(string $url, bool $ssl = false, string $certificate = null, string $username = null, string $password = null) |
93
|
|
|
{ |
94
|
|
|
$this->url = $url; |
95
|
|
|
$this->ssl = $ssl; |
96
|
|
|
$this->certificate = $certificate; |
|
|
|
|
97
|
|
|
$this->username = $username; |
|
|
|
|
98
|
|
|
$this->password = $password; |
|
|
|
|
99
|
|
|
|
100
|
|
|
if (! function_exists('curl_init')) { |
101
|
|
|
throw InvalidFactomApiConfig::noCurlFound(); |
102
|
|
|
} elseif (empty($this->url)) { |
103
|
|
|
throw InvalidFactomApiConfig::noUrlDefined(); |
104
|
|
|
} elseif (empty($this->certificate) && $this->ssl) { |
|
|
|
|
105
|
|
|
throw InvalidFactomApiConfig::noCertificateDefined(); |
106
|
|
|
} elseif (! empty($this->certificate) && $this->ssl) { |
|
|
|
|
107
|
|
|
if (preg_match('/^(https:\/\/)/i', $this->url)) { |
108
|
|
|
throw InvalidFactomApiConfig::noSecureUrlDefined(); |
109
|
|
|
} elseif (! file_exists($this->certificate)) { |
|
|
|
|
110
|
|
|
throw InvalidFactomApiConfig::noCertificateExists(); |
111
|
|
|
} |
112
|
|
|
} elseif (! empty($this->username) && empty($this->password)) { |
113
|
|
|
throw InvalidFactomApiConfig::noUsernameDefined(); |
114
|
|
|
} elseif (empty($this->username) && ! empty($this->password)) { |
115
|
|
|
throw InvalidFactomApiConfig::noPasswordDefined(); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
if (! $this->ssl) { |
119
|
|
|
$this->certificate = null; |
|
|
|
|
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
$this->client = new Client([ |
|
|
|
|
123
|
|
|
'base_uri' => rtrim($this->url, '/').'/', |
124
|
|
|
'timeout' => 10, |
125
|
|
|
'http_errors' => false, |
126
|
|
|
'debug' => false, |
127
|
|
|
]); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* Call the requested endpoint. |
132
|
|
|
* |
133
|
|
|
* @param string $actionName |
|
|
|
|
134
|
|
|
* @param array $params |
135
|
|
|
* @param array $extraOptions |
136
|
|
|
* |
137
|
|
|
* @return object|string |
138
|
|
|
* |
139
|
|
|
* @throws Exception When a Guzzle error occurs |
140
|
|
|
*/ |
141
|
|
|
public function callEndpoint(string $action, string $method, array $params = [], array $extraOptions = []) |
142
|
|
|
{ |
143
|
|
|
// Check our method... |
144
|
|
|
if (! in_array(strtoupper($method), ['GET', 'POST'])) { |
145
|
|
|
throw InvalidFactomApiConfig::invalidMethodCalled(); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$options = [ |
149
|
|
|
'headers' => [ |
150
|
|
|
'Content-Type' => self::HEADER_CONTENT_TYPE, |
151
|
|
|
'Accept' => self::HEADER_ACCEPT, |
152
|
|
|
], |
153
|
|
|
// 'verify' => false, |
|
|
|
|
154
|
|
|
'json' => [ |
155
|
|
|
'jsonrpc' => self::JSON_RPC, |
156
|
|
|
'id' => self::REQUEST_ID, |
157
|
|
|
'method' => strtolower($action), |
158
|
|
|
'params' => $params, |
159
|
|
|
], |
160
|
|
|
] + $extraOptions; |
161
|
|
|
|
162
|
|
|
// Append certificate verification |
163
|
|
|
// if ($this->ssl) { |
|
|
|
|
164
|
|
|
// $options['verify'] = $this->certificate; |
|
|
|
|
165
|
|
|
// $options['cert'] = [ |
|
|
|
|
166
|
|
|
// 'cert' => [ |
|
|
|
|
167
|
|
|
// $this->certificate, |
168
|
|
|
// $this->password |
169
|
|
|
// ], |
170
|
|
|
// ]; |
171
|
|
|
// } |
172
|
|
|
|
173
|
|
|
// Append authentication to params |
174
|
|
|
if (! empty($this->username) && ! empty($this->password)) { |
175
|
|
|
$options['auth'] = [ |
176
|
|
|
'username' => $this->username, |
177
|
|
|
'password' => $this->password, |
178
|
|
|
]; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$response = null; |
182
|
|
|
$error = null; |
183
|
|
|
|
184
|
|
|
// Make the call to factom server |
185
|
|
|
try { |
186
|
|
|
$response = $this->client->{strtolower($method)}($this->url, $options); |
187
|
|
|
} catch(RequestException $e) { |
188
|
|
|
$error = $e->getMessage(); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
if (!empty($error)) { |
192
|
|
|
throw InvalidFactomApiConfig::invalidApiResponse($error, $action); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$status_code = $response->getStatusCode(); |
196
|
|
|
$reason_phrase = $response->getReasonPhrase(); |
197
|
|
|
$body = (string) $response->getBody()->getContents(); |
198
|
|
|
|
199
|
|
|
// Check for empty body |
200
|
|
|
if (empty($body)) { |
201
|
|
|
throw InvalidFactomApiConfig::emptyApiResponse($action); |
202
|
|
|
} elseif ($status_code != 200) { |
203
|
|
|
throw InvalidFactomApiConfig::invalidApiResponse($reason_phrase, $action); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
// return Json |
207
|
|
|
if ($json_body = json_decode($body)) { |
208
|
|
|
// Check for empty result |
209
|
|
|
if (empty($json_body->result)) { |
210
|
|
|
throw InvalidFactomApiConfig::emptyApiResponse($action); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
return $json_body->result; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
// return Response |
217
|
|
|
return $body; |
218
|
|
|
} |
219
|
|
|
} |
220
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.