1 <?php
2 3 4 5 6 7 8 9
10 class RestfulService extends ViewableData {
11 protected $baseURL;
12 protected $queryString;
13 protected $errorTag;
14 protected $checkErrors;
15 protected $cache_expire;
16 protected $authUsername, $authPassword;
17 protected = array();
18 protected $proxy;
19 protected static $default_proxy;
20
21 22 23 24 25 26 27 28 29
30 static function set_default_proxy($proxy, $port = 80, $user = "", $password = "", $socks = false) {
31 self::$default_proxy = array(
32 CURLOPT_PROXY => $proxy,
33 CURLOPT_PROXYUSERPWD => "{$user}:{$password}",
34 CURLOPT_PROXYPORT => $port,
35 CURLOPT_PROXYTYPE => ($socks ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP)
36 );
37 }
38
39 40 41 42 43
44 function __construct($base, $expiry=3600){
45 $this->baseURL = $base;
46 $this->cache_expire = $expiry;
47 $this->proxy = self::$default_proxy;
48 parent::__construct();
49 }
50
51 52 53 54
55 function setQueryString($params=NULL){
56 $this->queryString = http_build_query($params,'','&');
57 }
58
59 60 61 62 63 64 65 66 67
68 function setProxy($proxy, $port = 80, $user = "", $password = "", $socks = false) {
69 $this->proxy = array(
70 CURLOPT_PROXY => $proxy,
71 CURLOPT_PROXYUSERPWD => "{$user}:{$password}",
72 CURLOPT_PROXYPORT => $port,
73 CURLOPT_PROXYTYPE => ($socks ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP)
74 );
75 }
76
77 78 79
80 function basicAuth($username, $password) {
81 $this->authUsername = $username;
82 $this->authPassword = $password;
83 }
84
85 86 87
88 function ($header) {
89 $this->customHeaders[] = $header;
90 }
91
92 protected function constructURL(){
93 return "$this->baseURL" . ($this->queryString ? "?$this->queryString" : "");
94 }
95
96 97 98
99 public function connect($subURL = '') {
100 user_error("RestfulService::connect is deprecated; use RestfulService::request", E_USER_NOTICE);
101 return $this->request($subURL)->getBody();
102 }
103
104 105 106 107 108 109 110 111 112
113 public function request($subURL = '', $method = "GET", $data = null, $headers = null, $curlOptions = array()) {
114 $url = $this->getAbsoluteRequestURL($subURL);
115
116 $method = strtoupper($method);
117
118 assert(in_array($method, array('GET','POST','PUT','DELETE','HEAD','OPTIONS')));
119
120 $cachedir = TEMP_FOLDER;
121 $cache_file = md5($url);
122 $cache_path = $cachedir."/xmlresponse_$cache_file";
123
124
125 if(!isset($_GET['flush']) && @file_exists($cache_path) && @filemtime($cache_path) + $this->cache_expire > time()) {
126 $store = file_get_contents($cache_path);
127 $response = unserialize($store);
128
129 } else {
130 $ch = curl_init();
131 $timeout = 5;
132 $useragent = "SilverStripe/" . SapphireInfo::Version();
133 @curl_setopt($ch, CURLOPT_URL, $url);
134 @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
135 @curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
136 @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
137 @curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
138 @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
139
140
141 if($this->customHeaders) {
142 $headers = array_merge((array)$this->customHeaders, (array)$headers);
143 }
144
145 if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
146
147
148 if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword");
149
150
151 if($method == 'POST') {
152 curl_setopt($ch, CURLOPT_POST, 1);
153 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
154 }
155
156
157 if(is_array($this->proxy)) {
158 curl_setopt_array($ch, $this->proxy);
159 }
160
161
162 curl_setopt_array($ch, $curlOptions);
163
164
165 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
166 $responseBody = curl_exec($ch);
167 $curlError = curl_error($ch);
168
169
170 if(strpos($curlError,'14090086') !== false) {
171 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
172 $responseBody = curl_exec($ch);
173 $curlError = curl_error($ch);
174 }
175
176 if($responseBody === false) {
177 user_error("Curl Error:" . $curlError, E_USER_WARNING);
178 return;
179 }
180
181 $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
182 $response = new RestfulService_Response($responseBody, curl_getinfo($ch, CURLINFO_HTTP_CODE));
183
184 curl_close($ch);
185
186
187 $store = serialize($response);
188 file_put_contents($cache_path,$store);
189 }
190
191 return $response;
192 }
193
194 195 196 197
198 function getAbsoluteRequestURL($subURL) {
199 $url = $this->baseURL . $subURL;
200 if($this->queryString) {
201 if(strpos($url, '?') !== false) {
202 $url .= '&' . $this->queryString;
203 } else {
204 $url .= '?' . $this->queryString;
205 }
206 }
207
208 return str_replace(' ', '%20', $url);
209 }
210
211 212 213 214 215 216 217 218
219
220 public function getAttributes($xml, $collection=NULL, $element=NULL){
221 $xml = new SimpleXMLElement($xml);
222 $output = new DataObjectSet();
223
224 if($collection)
225 $childElements = $xml->{$collection};
226 if($element)
227 $childElements = $xml->{$collection}->{$element};
228
229 if($childElements){
230 foreach($childElements as $child){
231 $data = array();
232 foreach($child->attributes() as $key => $value){
233 $data["$key"] = Convert::raw2xml($value);
234 }
235 $output->push(new ArrayData($data));
236 }
237 }
238 return $output;
239
240 }
241
242 243 244 245 246 247 248
249
250 public function getAttribute($xml, $collection=NULL, $element=NULL, $attr){
251 $xml = new SimpleXMLElement($xml);
252 $attr_value = "";
253
254 if($collection)
255 $childElements = $xml->{$collection};
256 if($element)
257 $childElements = $xml->{$collection}->{$element};
258
259 if($childElements)
260 $attr_value = (string) $childElements[$attr];
261
262 return Convert::raw2xml($attr_value);
263
264 }
265
266
267 268 269 270 271 272 273
274
275 public function getValues($xml, $collection=NULL, $element=NULL){
276 $xml = new SimpleXMLElement($xml);
277 $output = new DataObjectSet();
278
279 $childElements = $xml;
280 if($collection)
281 $childElements = $xml->{$collection};
282 if($element)
283 $childElements = $xml->{$collection}->{$element};
284
285 if($childElements){
286 foreach($childElements as $child){
287 $data = array();
288 $this->getRecurseValues($child,$data);
289 $output->push(new ArrayData($data));
290 }
291 }
292 return $output;
293 }
294
295 protected function getRecurseValues($xml,&$data,$parent=""){
296 $conv_value = "";
297 $child_count = 0;
298 foreach($xml as $key=>$value)
299 {
300 $child_count++;
301 $k = ($parent == "") ? (string)$key : $parent . "_" . (string)$key;
302 if($this->getRecurseValues($value,$data,$k) == 0){
303 $conv_value = Convert::raw2xml($value);
304 }
305
306 if(array_key_exists($k, $data) == true) {
307 $data[$k] = $data[$k] . ",". $conv_value;
308 }
309 else {
310 $data[$k] = $conv_value;
311 }
312
313
314 }
315 return $child_count;
316
317 }
318
319 320 321 322 323 324
325
326 function getValue($xml, $collection=NULL, $element=NULL){
327 $xml = new SimpleXMLElement($xml);
328
329 if($collection)
330 $childElements = $xml->{$collection};
331 if($element)
332 $childElements = $xml->{$collection}->{$element};
333
334 if($childElements)
335 return Convert::raw2xml($childElements);
336 }
337
338 339 340 341 342
343 function searchValue($xml, $node=NULL){
344 $xml = new SimpleXMLElement($xml);
345 $childElements = $xml->xpath($node);
346
347 if($childElements)
348 return Convert::raw2xml($childElements[0]);
349 }
350
351 352 353 354 355
356 function searchAttributes($xml, $node=NULL){
357 $xml = new SimpleXMLElement($xml);
358 $output = new DataObjectSet();
359
360 $childElements = $xml->xpath($node);
361
362 if($childElements)
363 foreach($childElements as $child){
364 $data = array();
365 foreach($child->attributes() as $key => $value){
366 $data["$key"] = Convert::raw2xml($value);
367 }
368
369 $output->push(new ArrayData($data));
370 }
371
372 return $output;
373 }
374 }
375
376 377 378 379
380 class RestfulService_Response extends SS_HTTPResponse {
381 protected $simpleXML;
382
383 function __construct($body, $statusCode = 200, $headers = null) {
384 $this->setbody($body);
385 $this->setStatusCode($statusCode);
386 $this->headers = $headers;
387 }
388
389 function simpleXML() {
390 if(!$this->simpleXML) {
391 try {
392 $this->simpleXML = new SimpleXMLElement($this->body);
393 }
394 catch(Exception $e) {
395 user_error("String could not be parsed as XML. " . $e, E_USER_WARNING);
396 }
397 }
398 return $this->simpleXML;
399 }
400
401 402 403
404 function xpath($xpath) {
405 return $this->simpleXML()->xpath($xpath);
406 }
407
408 409 410
411 function xpath_one($xpath) {
412 $items = $this->xpath($xpath);
413 return $items[0];
414 }
415 }
416
417 ?>
418
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-