baseURL = $base; $this->cache_expire = $expiry; } /** * Sets the Query string parameters to send a request. * @param array $params An array passed with necessary parameters. */ function setQueryString($params=NULL){ $this->queryString = http_build_query($params,'','&'); } /** * Set basic authentication */ function basicAuth($username, $password) { $this->authUsername = $username; $this->authPassword = $password; } /** * Set a custom HTTP header */ function httpHeader($header) { $this->customHeaders[] = $header; } protected function constructURL(){ return "$this->baseURL" . ($this->queryString ? "?$this->queryString" : ""); } /** * Connects to the RESTful service and gets its response. * @deprecated Use {@link request()} instead. */ public function connect($subURL = ""){ // url for the request $url = $this->constructURL() . $subURL; // set the cache directory $cachedir=TEMP_FOLDER; // default silverstrip-cache $cache_file = md5($url); //encoded name of cache file $cache_path = $cachedir."/$cache_file"; // check for file exists in cache if( !isset($_GET['flush']) && ( @file_exists("$cache_path") && ((@filemtime($cache_path) + $this->cache_expire) > ( time() )))) { $this->rawXML = file_get_contents($cache_path); return $this->rawXML; } else { // not available in cache fetch from server $statusOK = false; $ch = curl_init(); $timeout = 5; $useragent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, $useragent); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); if($this->customHeaders) curl_setopt($ch, CURLOPT_HTTPHEADER, $this->customHeaders); if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword"); $this->rawXML = curl_exec($ch); if($this->rawXML === false) { user_error("Curl Error:" . curl_error($ch), E_USER_WARNING); return NULL; } $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // Success if($statusCode >= 200 && $statusCode < 300) { // fill output with xml and continue $statusOK = true; } else { // Failure: throw error and return NULL switch($statusCode) { case 401: user_error("Bad username/password given to RestfulService, url $url", E_USER_WARNING); return NULL; default: user_error("Error code $statusCode from url $url", E_USER_WARNING); return NULL; } } // Try using file_get_contents if cURL is not installed in your system. // $this->rawXML = file_get_contents($url); // results returned - from cache / live if($statusOK && $this->rawXML != "") { //save the response in cache $fp = @fopen($cache_path,"w+"); @fwrite($fp,$this->rawXML); @fclose($fp); if($this->checkErrors == true) { return $this->errorCatch($this->rawXML); } else { return $this->rawXML; } // I think this following else can actually be removed :P } else { user_error("Invalid Response (maybe your calling to wrong URL or server unavailable)", E_USER_WARNING); return NULL; } } } /** * Makes a request to the RESTful server, and return a {@link RestfulService_Response} object for parsing of the result. * @todo Better POST, PUT, DELETE, and HEAD support * @todo Caching of requests - probably only GET and HEAD requestst * @todo JSON support in RestfulService_Response * @todo Pass the response headers to RestfulService_Response * * This is a replacement of {@link connect()}. */ public function request($subURL, $method = "GET", $data = null, $headers = null) { $url = $this->baseURL . $subURL; //url for the request $method = strtoupper($method); assert(in_array($method, array('GET','POST','PUT','DELETE','HEAD','OPTIONS'))); //check for file exists in cache //set the cache directory /* we've disabled caching until we can figure out how to deal with storing responses $cachedir=TEMP_FOLDER; //default silverstrip-cache $cache_file = md5($url); //encoded name of cache file $cache_path = $cachedir."/$cache_file"; if( !isset($_GET['flush']) && ( @file_exists("$cache_path") && ((@filemtime($cache_path) + $this->cache_expire) > ( time() )))){ $this->rawXML = file_get_contents($cache_path); } else {//not available in cache fetch from server */ $ch = curl_init(); $timeout = 5; $useragent = "SilverStripe/2.2"; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, $useragent); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); if($this->customHeaders) { $headers = array_merge((array)$this->customHeaders, (array)$headers); } if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword"); $responseBody = curl_exec($ch); if($responseBody === false) { $curlError = curl_error($ch); // Problem verifying the server SSL certificate; just ignore it as it's not mandatory if(strpos($curlError,'14090086') !== false) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $responseBody = curl_exec($ch); $curlError = curl_error($ch); } if($respnoseBody === false) { user_error("Curl Error:" . $curlError, E_USER_WARNING); return; } } $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = new RestfulService_Response($responseBody, curl_getinfo($ch, CURLINFO_HTTP_CODE)); curl_close($ch); return $response; } /** * Gets attributes as an array, of a particular type of element. * Example : * returns id, owner,secret and sever attribute values of all such photo elements. * @param string $xml The source xml to parse, this could be the original response received. * @param string $collection The name of parent node which wraps the elements, if available * @param string $element The element we need to extract the attributes. */ public function getAttributes($xml, $collection=NULL, $element=NULL){ $xml = new SimpleXMLElement($xml); $output = new DataObjectSet(); if($collection) $childElements = $xml->{$collection}; if($element) $childElements = $xml->{$collection}->{$element}; if($childElements){ foreach($childElements as $child){ $data = array(); foreach($child->attributes() as $key => $value){ $data["$key"] = Convert::raw2xml($value); } $output->push(new ArrayData($data)); } } return $output; } /** * Gets an attribute of a particular element. * @param string $xml The source xml to parse, this could be the original response received. * @param string $collection The name of the parent node which wraps the element, if available * @param string $element The element we need to extract the attribute * @param string $attr The name of the attribute */ public function getAttribute($xml, $collection=NULL, $element=NULL, $attr){ $xml = new SimpleXMLElement($xml); $attr_value = ""; if($collection) $childElements = $xml->{$collection}; if($element) $childElements = $xml->{$collection}->{$element}; if($childElements) $attr_value = (string) $childElements[$attr]; return Convert::raw2xml($attr_value); } /** * Gets set of node values as an array. * When you get to the depth in the hierachchy use node_child_subchild syntax to get the value. * @param string $xml The the source xml to parse, this could be the original response received. * @param string $collection The name of parent node which wraps the elements, if available * @param string $element The element we need to extract the node values. */ public function getValues($xml, $collection=NULL, $element=NULL){ $xml = new SimpleXMLElement($xml); $output = new DataObjectSet(); $childElements = $xml; if($collection) $childElements = $xml->{$collection}; if($element) $childElements = $xml->{$collection}->{$element}; if($childElements){ foreach($childElements as $child){ $data = array(); $this->getRecurseValues($child,$data); $output->push(new ArrayData($data)); } } return $output; } protected function getRecurseValues($xml,&$data,$parent=""){ $conv_value = ""; $child_count = 0; foreach($xml as $key=>$value) { $child_count++; $k = ($parent == "") ? (string)$key : $parent . "_" . (string)$key; if($this->getRecurseValues($value,$data,$k) == 0){ // no childern, aka "leaf node" $conv_value = Convert::raw2xml($value); } //Review the fix for similar node names overriding it's predecessor if(array_key_exists($k, $data) == true) { $data[$k] = $data[$k] . ",". $conv_value; } else { $data[$k] = $conv_value; } } return $child_count; } /** * Gets a single node value. * @param string $xml The source xml to parse, this could be the original response received. * @param string $collection The name of parent node which wraps the elements, if available * @param string $element The element we need to extract the node value. */ function getValue($xml, $collection=NULL, $element=NULL){ $xml = new SimpleXMLElement($xml); if($collection) $childElements = $xml->{$collection}; if($element) $childElements = $xml->{$collection}->{$element}; if($childElements) return Convert::raw2xml($childElements); } /** * Searches for a node in document tree and returns it value. * @param string $xml source xml to parse, this could be the original response received. * @param string $node Node to search for */ function searchValue($xml, $node=NULL){ $xml = new SimpleXMLElement($xml); $childElements = $xml->xpath($node); if($childElements) return Convert::raw2xml($childElements[0]); } /** * Searches for a node in document tree and returns its attributes. * @param string $xml the source xml to parse, this could be the original response received. * @param string $node Node to search for */ function searchAttributes($xml, $node=NULL){ $xml = new SimpleXMLElement($xml); $output = new DataObjectSet(); $childElements = $xml->xpath($node); if($childElements) foreach($childElements as $child){ $data = array(); foreach($child->attributes() as $key => $value){ $data["$key"] = Convert::raw2xml($value); } $output->push(new ArrayData($data)); } return $output; } } class RestfulService_Response extends HTTPResponse { protected $simpleXML; function __construct($body, $statusCode = 200, $headers = null) { $this->setbody($body); $this->setStatusCode($statusCode); $this->headers = $headers; } function simpleXML() { if(!$this->simpleXML) $this->simpleXML = new SimpleXMLElement($this->body); return $this->simpleXML; } /** * Return an array of xpath matches */ function xpath($xpath) { return $this->simpleXML()->xpath($xpath); } /** * Return the first xpath match */ function xpath_one($xpath) { $items = $this->xpath($xpath); return $items[0]; } } ?>