|
| 1 | +<?php |
| 2 | +/** |
| 3 | +* 2007-2010 PrestaShop |
| 4 | +* |
| 5 | +* NOTICE OF LICENSE |
| 6 | +* |
| 7 | +* This source file is subject to the Open Software License (OSL 3.0) |
| 8 | +* that is bundled with this package in the file LICENSE.txt. |
| 9 | +* It is also available through the world-wide-web at this URL: |
| 10 | +* http://opensource.org/licenses/osl-3.0.php |
| 11 | +* If you did not receive a copy of the license and are unable to |
| 12 | +* obtain it through the world-wide-web, please send an email |
| 13 | +* to [email protected] so we can send you a copy immediately. |
| 14 | +* |
| 15 | +* DISCLAIMER |
| 16 | +* |
| 17 | +* Do not edit or add to this file if you wish to upgrade PrestaShop to newer |
| 18 | +* versions in the future. If you wish to customize PrestaShop for your |
| 19 | +* needs please refer to http://www.prestashop.com for more information. |
| 20 | +* Page-level DocBlock |
| 21 | +* @author Prestashop SA <[email protected]> |
| 22 | +* @copyright 2007-2010 Prestashop SA : 6 rue lacepede, 75005 PARIS |
| 23 | +* @version Release: $Revision: 1.4 $ |
| 24 | +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
| 25 | +* International Registred Trademark & Property of PrestaShop SA |
| 26 | + * PrestaShop Webservice Library |
| 27 | + * @package PrestaShopWebservice |
| 28 | + */ |
| 29 | + |
| 30 | +/** |
| 31 | + * @package PrestaShopWebservice |
| 32 | + */ |
| 33 | +class PrestaShopWebservice |
| 34 | +{ |
| 35 | + |
| 36 | + /** @var string Shop URL */ |
| 37 | + protected $url; |
| 38 | + |
| 39 | + /** @var string Authentification key */ |
| 40 | + protected $key; |
| 41 | + |
| 42 | + /** @var boolean is debug activated */ |
| 43 | + protected $debug; |
| 44 | + |
| 45 | + /** @var array compatible versions of PrestaShop Webservice */ |
| 46 | + const psCompatibleVersionsMin = '1.4.0.17'; |
| 47 | + const psCompatibleVersionsMax = '1.4.7.5'; |
| 48 | + |
| 49 | + /** |
| 50 | + * PrestaShopWebservice constructor. Throw an exception when CURL is not installed/activated |
| 51 | + * <code> |
| 52 | + * <?php |
| 53 | + * require_once('./PrestaShopWebservice.php'); |
| 54 | + * try |
| 55 | + * { |
| 56 | + * $ws = new PrestaShopWebservice('http://mystore.com/', 'ZQ88PRJX5VWQHCWE4EE7SQ7HPNX00RAJ', false); |
| 57 | + * // Now we have a webservice object to play with |
| 58 | + * } |
| 59 | + * catch (PrestaShopWebserviceException $ex) |
| 60 | + * { |
| 61 | + * echo 'Error : '.$ex->getMessage(); |
| 62 | + * } |
| 63 | + * ?> |
| 64 | + * </code> |
| 65 | + * @param string $url Root URL for the shop |
| 66 | + * @param string $key Authentification key |
| 67 | + * @param mixed $debug Debug mode Activated (true) or deactivated (false) |
| 68 | + */ |
| 69 | + function __construct($url, $key, $debug = true) { |
| 70 | + if (!extension_loaded('curl')) |
| 71 | + throw new PrestaShopWebserviceException('Please activate the PHP extension \'curl\' to allow use of PrestaShop webservice library'); |
| 72 | + $this->url = $url; |
| 73 | + $this->key = $key; |
| 74 | + $this->debug = $debug; |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * Take the status code and throw an exception if the server didn't return 200 or 201 code |
| 79 | + * @param int $status_code Status code of an HTTP return |
| 80 | + */ |
| 81 | + protected function checkStatusCode($status_code) |
| 82 | + { |
| 83 | + $error_label = 'This call to PrestaShop Web Services failed and returned an HTTP status of %d. That means: %s.'; |
| 84 | + switch($status_code) |
| 85 | + { |
| 86 | + case 200: case 201: break; |
| 87 | + case 204: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'No content'));break; |
| 88 | + case 400: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'Bad Request'));break; |
| 89 | + case 401: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'Unauthorized'));break; |
| 90 | + case 404: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'Not Found'));break; |
| 91 | + case 405: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'Method Not Allowed'));break; |
| 92 | + case 500: throw new PrestaShopWebserviceException(sprintf($error_label, $status_code, 'Internal Server Error'));break; |
| 93 | + default: throw new PrestaShopWebserviceException('This call to PrestaShop Web Services returned an unexpected HTTP status of:' . $status_code); |
| 94 | + } |
| 95 | + } |
| 96 | + /** |
| 97 | + * Handles a CURL request to PrestaShop Webservice. Can throw exception. |
| 98 | + * @param string $url Resource name |
| 99 | + * @param mixed $curl_params CURL parameters (sent to curl_set_opt) |
| 100 | + * @return array status_code, response |
| 101 | + */ |
| 102 | + protected function executeRequest($url, $curl_params = array()) |
| 103 | + { |
| 104 | + $defaultParams = array( |
| 105 | + CURLOPT_HEADER => TRUE, |
| 106 | + CURLOPT_RETURNTRANSFER => TRUE, |
| 107 | + CURLINFO_HEADER_OUT => TRUE, |
| 108 | + CURLOPT_HTTPAUTH => CURLAUTH_BASIC, |
| 109 | + CURLOPT_USERPWD => $this->key.':', |
| 110 | + CURLOPT_HTTPHEADER => array( 'Expect:' ) |
| 111 | + ); |
| 112 | + |
| 113 | + $session = curl_init($url); |
| 114 | + |
| 115 | + $curl_options = array(); |
| 116 | + foreach ($defaultParams as $defkey => $defval) |
| 117 | + { |
| 118 | + if (isset($curl_params[$defkey])) |
| 119 | + $curl_options[$defkey] = $curl_params[$defkey]; |
| 120 | + else |
| 121 | + $curl_options[$defkey] = $defaultParams[$defkey]; |
| 122 | + } |
| 123 | + foreach ($curl_params as $defkey => $defval) |
| 124 | + if (!isset($curl_options[$defkey])) |
| 125 | + $curl_options[$defkey] = $curl_params[$defkey]; |
| 126 | + |
| 127 | + curl_setopt_array($session, $curl_options); |
| 128 | + $response = curl_exec($session); |
| 129 | + |
| 130 | + $index = strpos($response, "\r\n\r\n"); |
| 131 | + if ($index === false && $curl_params[CURLOPT_CUSTOMREQUEST] != 'HEAD') |
| 132 | + throw new PrestaShopWebserviceException('Bad HTTP response'); |
| 133 | + |
| 134 | + $header = substr($response, 0, $index); |
| 135 | + $body = substr($response, $index + 4); |
| 136 | + |
| 137 | + $headerArrayTmp = explode("\n", $header); |
| 138 | + |
| 139 | + $headerArray = array(); |
| 140 | + foreach ($headerArrayTmp as &$headerItem) |
| 141 | + { |
| 142 | + $tmp = explode(':', $headerItem); |
| 143 | + $tmp = array_map('trim', $tmp); |
| 144 | + if (count($tmp) == 2) |
| 145 | + $headerArray[$tmp[0]] = $tmp[1]; |
| 146 | + } |
| 147 | + |
| 148 | + if (array_key_exists('PSWS-Version', $headerArray)) |
| 149 | + { |
| 150 | + if ( |
| 151 | + version_compare(PrestaShopWebservice::psCompatibleVersionsMin, $headerArray['PSWS-Version']) == 1 || |
| 152 | + version_compare(PrestaShopWebservice::psCompatibleVersionsMax, $headerArray['PSWS-Version']) == -1 |
| 153 | + ) |
| 154 | + throw new PrestaShopWebserviceException('This library is not compatible with this version of PrestaShop. Please upgrade/downgrade this library'); |
| 155 | + } |
| 156 | + |
| 157 | + if ($this->debug) |
| 158 | + { |
| 159 | + $this->printDebug('HTTP REQUEST HEADER', curl_getinfo($session, CURLINFO_HEADER_OUT)); |
| 160 | + $this->printDebug('HTTP RESPONSE HEADER', $header); |
| 161 | + |
| 162 | + } |
| 163 | + $status_code = curl_getinfo($session, CURLINFO_HTTP_CODE); |
| 164 | + if ($status_code === 0) |
| 165 | + throw new PrestaShopWebserviceException('CURL Error: '.curl_error($session)); |
| 166 | + curl_close($session); |
| 167 | + if ($this->debug) |
| 168 | + { |
| 169 | + if ($curl_params[CURLOPT_CUSTOMREQUEST] == 'PUT' || $curl_params[CURLOPT_CUSTOMREQUEST] == 'POST') |
| 170 | + $this->printDebug('XML SENT', $curl_params[CURLOPT_POSTFIELDS]); |
| 171 | + if ($curl_params[CURLOPT_CUSTOMREQUEST] != 'DELETE' && $curl_params[CURLOPT_CUSTOMREQUEST] != 'HEAD') |
| 172 | + $this->printDebug('RETURN HTTP BODY', $body); |
| 173 | + } |
| 174 | + return array('status_code' => $status_code, 'response' => $body, 'header' => $header); |
| 175 | + } |
| 176 | + public function printDebug($title, $content) |
| 177 | + { |
| 178 | + echo '<div style="display:table;background:#CCC;font-size:8pt;padding:7px"><h6 style="font-size:9pt;margin:0">'.$title.'</h6><pre>'.htmlentities($content).'</pre></div>'; |
| 179 | + } |
| 180 | + /** |
| 181 | + * Load XML from string. Can throw exception |
| 182 | + * @param string $response String from a CURL response |
| 183 | + * @return SimpleXMLElement status_code, response |
| 184 | + */ |
| 185 | + protected function parseXML($response) |
| 186 | + { |
| 187 | + if ($response != '') |
| 188 | + { |
| 189 | + libxml_use_internal_errors(true); |
| 190 | + $xml = simplexml_load_string($response); |
| 191 | + if (libxml_get_errors()) |
| 192 | + throw new PrestaShopWebserviceException('HTTP XML response is not parsable : '.var_export(libxml_get_errors(), true)); |
| 193 | + return $xml; |
| 194 | + } |
| 195 | + else |
| 196 | + throw new PrestaShopWebserviceException('HTTP response is empty'); |
| 197 | + } |
| 198 | + |
| 199 | + /** |
| 200 | + * Add (POST) a resource |
| 201 | + * <p>Unique parameter must take : <br><br> |
| 202 | + * 'resource' => Resource name<br> |
| 203 | + * 'postXml' => Full XML string to add resource<br><br> |
| 204 | + * Examples are given in the tutorial</p> |
| 205 | + * @param array $options |
| 206 | + * @return SimpleXMLElement status_code, response |
| 207 | + */ |
| 208 | + public function add($options) |
| 209 | + { |
| 210 | + $xml = ''; |
| 211 | + |
| 212 | + if (isset($options['resource'], $options['postXml']) || isset($options['url'], $options['postXml'])) |
| 213 | + { |
| 214 | + $url = (isset($options['resource']) ? $this->url.'/api/'.$options['resource'] : $options['url']); |
| 215 | + $xml = $options['postXml']; |
| 216 | + } |
| 217 | + else |
| 218 | + throw new PrestaShopWebserviceException('Bad parameters given'); |
| 219 | + $request = self::executeRequest($url, array(CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => 'xml='.$xml)); |
| 220 | + |
| 221 | + self::checkStatusCode($request['status_code']); |
| 222 | + return self::parseXML($request['response']); |
| 223 | + } |
| 224 | + |
| 225 | + /** |
| 226 | + * Retrieve (GET) a resource |
| 227 | + * <p>Unique parameter must take : <br><br> |
| 228 | + * 'url' => Full URL for a GET request of Webservice (ex: http://mystore.com/api/customers/1/)<br> |
| 229 | + * OR<br> |
| 230 | + * 'resource' => Resource name,<br> |
| 231 | + * 'id' => ID of a resource you want to get<br><br> |
| 232 | + * </p> |
| 233 | + * <code> |
| 234 | + * <?php |
| 235 | + * require_once('./PrestaShopWebservice.php'); |
| 236 | + * try |
| 237 | + * { |
| 238 | + * $ws = new PrestaShopWebservice('http://mystore.com/', 'ZQ88PRJX5VWQHCWE4EE7SQ7HPNX00RAJ', false); |
| 239 | + * $xml = $ws->get(array('resource' => 'orders', 'id' => 1)); |
| 240 | + * // Here in $xml, a SimpleXMLElement object you can parse |
| 241 | + * foreach ($xml->children()->children() as $attName => $attValue) |
| 242 | + * echo $attName.' = '.$attValue.'<br />'; |
| 243 | + * } |
| 244 | + * catch (PrestaShopWebserviceException $ex) |
| 245 | + * { |
| 246 | + * echo 'Error : '.$ex->getMessage(); |
| 247 | + * } |
| 248 | + * ?> |
| 249 | + * </code> |
| 250 | + * @param array $options Array representing resource to get. |
| 251 | + * @return SimpleXMLElement status_code, response |
| 252 | + */ |
| 253 | + public function get($options) |
| 254 | + { |
| 255 | + if (isset($options['url'])) |
| 256 | + $url = $options['url']; |
| 257 | + elseif (isset($options['resource'])) |
| 258 | + { |
| 259 | + $url = $this->url.'/api/'.$options['resource']; |
| 260 | + $url_params = array(); |
| 261 | + if (isset($options['id'])) |
| 262 | + $url .= '/'.$options['id']; |
| 263 | + |
| 264 | + $params = array('filter', 'display', 'sort', 'limit'); |
| 265 | + foreach ($params as $p) |
| 266 | + foreach ($options as $k => $o) |
| 267 | + if (strpos($k, $p) !== false) |
| 268 | + $url_params[$k] = $options[$k]; |
| 269 | + if (count($url_params) > 0) |
| 270 | + $url .= '?'.http_build_query($url_params); |
| 271 | + } |
| 272 | + else |
| 273 | + throw new PrestaShopWebserviceException('Bad parameters given'); |
| 274 | + |
| 275 | + $request = self::executeRequest($url, array(CURLOPT_CUSTOMREQUEST => 'GET')); |
| 276 | + |
| 277 | + self::checkStatusCode($request['status_code']);// check the response validity |
| 278 | + return self::parseXML($request['response']); |
| 279 | + } |
| 280 | + |
| 281 | + /** |
| 282 | + * Head method (HEAD) a resource |
| 283 | + * |
| 284 | + * @param array $options Array representing resource for head request. |
| 285 | + * @return SimpleXMLElement status_code, response |
| 286 | + */ |
| 287 | + public function head($options) |
| 288 | + { |
| 289 | + if (isset($options['url'])) |
| 290 | + $url = $options['url']; |
| 291 | + elseif (isset($options['resource'])) |
| 292 | + { |
| 293 | + $url = $this->url.'/api/'.$options['resource']; |
| 294 | + $url_params = array(); |
| 295 | + if (isset($options['id'])) |
| 296 | + $url .= '/'.$options['id']; |
| 297 | + |
| 298 | + $params = array('filter', 'display', 'sort', 'limit'); |
| 299 | + foreach ($params as $p) |
| 300 | + foreach ($options as $k => $o) |
| 301 | + if (strpos($k, $p) !== false) |
| 302 | + $url_params[$k] = $options[$k]; |
| 303 | + if (count($url_params) > 0) |
| 304 | + $url .= '?'.http_build_query($url_params); |
| 305 | + } |
| 306 | + else |
| 307 | + throw new PrestaShopWebserviceException('Bad parameters given'); |
| 308 | + $request = self::executeRequest($url, array(CURLOPT_CUSTOMREQUEST => 'HEAD', CURLOPT_NOBODY => true)); |
| 309 | + self::checkStatusCode($request['status_code']);// check the response validity |
| 310 | + return $request['header']; |
| 311 | + } |
| 312 | + /** |
| 313 | + * Edit (PUT) a resource |
| 314 | + * <p>Unique parameter must take : <br><br> |
| 315 | + * 'resource' => Resource name ,<br> |
| 316 | + * 'id' => ID of a resource you want to edit,<br> |
| 317 | + * 'putXml' => Modified XML string of a resource<br><br> |
| 318 | + * Examples are given in the tutorial</p> |
| 319 | + * @param array $options Array representing resource to edit. |
| 320 | + */ |
| 321 | + public function edit($options) |
| 322 | + { |
| 323 | + $xml = ''; |
| 324 | + if (isset($options['url'])) |
| 325 | + $url = $options['url']; |
| 326 | + elseif ((isset($options['resource'], $options['id']) || isset($options['url'])) && $options['putXml']) |
| 327 | + { |
| 328 | + $url = (isset($options['url']) ? $options['url'] : $this->url.'/api/'.$options['resource'].'/'.$options['id']); |
| 329 | + $xml = $options['putXml']; |
| 330 | + } |
| 331 | + else |
| 332 | + throw new PrestaShopWebserviceException('Bad parameters given'); |
| 333 | + |
| 334 | + $request = self::executeRequest($url, array(CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => $xml)); |
| 335 | + self::checkStatusCode($request['status_code']);// check the response validity |
| 336 | + return self::parseXML($request['response']); |
| 337 | + } |
| 338 | + |
| 339 | + /** |
| 340 | + * Delete (DELETE) a resource. |
| 341 | + * Unique parameter must take : <br><br> |
| 342 | + * 'resource' => Resource name<br> |
| 343 | + * 'id' => ID or array which contains IDs of a resource(s) you want to delete<br><br> |
| 344 | + * <code> |
| 345 | + * <?php |
| 346 | + * require_once('./PrestaShopWebservice.php'); |
| 347 | + * try |
| 348 | + * { |
| 349 | + * $ws = new PrestaShopWebservice('http://mystore.com/', 'ZQ88PRJX5VWQHCWE4EE7SQ7HPNX00RAJ', false); |
| 350 | + * $xml = $ws->delete(array('resource' => 'orders', 'id' => 1)); |
| 351 | + * // Following code will not be executed if an exception is thrown. |
| 352 | + * echo 'Successfully deleted.'; |
| 353 | + * } |
| 354 | + * catch (PrestaShopWebserviceException $ex) |
| 355 | + * { |
| 356 | + * echo 'Error : '.$ex->getMessage(); |
| 357 | + * } |
| 358 | + * ?> |
| 359 | + * </code> |
| 360 | + * @param array $options Array representing resource to delete. |
| 361 | + */ |
| 362 | + public function delete($options) |
| 363 | + { |
| 364 | + if (isset($options['url'])) |
| 365 | + $url = $options['url']; |
| 366 | + elseif (isset($options['resource']) && isset($options['id'])) |
| 367 | + if (is_array($options['id'])) |
| 368 | + $url = $this->url.'/api/'.$options['resource'].'/?id=['.implode(',', $options['id']).']'; |
| 369 | + else |
| 370 | + $url = $this->url.'/api/'.$options['resource'].'/'.$options['id']; |
| 371 | + $request = self::executeRequest($url, array(CURLOPT_CUSTOMREQUEST => 'DELETE')); |
| 372 | + self::checkStatusCode($request['status_code']);// check the response validity |
| 373 | + return true; |
| 374 | + } |
| 375 | + |
| 376 | + |
| 377 | +} |
| 378 | + |
| 379 | +/** |
| 380 | + * @package PrestaShopWebservice |
| 381 | + */ |
| 382 | +class PrestaShopWebserviceException extends Exception { } |
| 383 | + |
0 commit comments