diff --git a/README.md b/README.md index 766654b..e93754d 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@ composer require phpclassic/php-shopify ``` ### Requirements -PHPShopify uses curl extension for handling http calls. So you need to have the curl extension installed and enabled with PHP. ->However if you prefer to use any other available package library for handling HTTP calls, you can easily do so by modifying 1 line in each of the `get()`, `post()`, `put()`, `delete()` methods in `PHPShopify\HttpRequestJson` class. +PHPShopify relies on the `cURL` extension to perform HTTP requests. Make sure the `cURL` extension is installed and enabled in your PHP environment. Alternatively, you can provide your own HTTP client by implementing the `PHPShopify\HttpClient` interface. You can pass additional curl configuration to `ShopifySDK` ```php @@ -26,6 +25,19 @@ $config = array( ) ); +PHPShopify\ShopifySDK::config($config); +``` +## Guzzle or Custom HTTP Client +If you prefer to use a different HTTP library, you can create a custom adapter by implementing the `PHPShopify\HttpClient` interface and passing it via the `HttpClient` configuration option. + +For example, using Guzzle is straightforward with the provided adapter: +```php +$client = new GuzzleHttp\Client(); +$config = array( + // ... + 'HttpClient' => new PHPShopify\GuzzleAdapter($client) +); + PHPShopify\ShopifySDK::config($config); ``` ## Usage diff --git a/lib/AuthHelper.php b/lib/AuthHelper.php index 101f903..f861107 100644 --- a/lib/AuthHelper.php +++ b/lib/AuthHelper.php @@ -173,7 +173,7 @@ public static function getAccessToken() $response = HttpRequestJson::post($config['AdminUrl'] . 'oauth/access_token', $data); - if (CurlRequest::$lastHttpCode >= 400) { + if (ShopifySDK::getClient()->getLastResponseCode() >= 400) { throw new SdkException("The shop is invalid or the authorization code has already been used."); } diff --git a/lib/CurlAdapter.php b/lib/CurlAdapter.php new file mode 100644 index 0000000..1abef61 --- /dev/null +++ b/lib/CurlAdapter.php @@ -0,0 +1,68 @@ +client = $client; + } + + /** + * @param $url + * @param $headers + * + * @return string + */ + public function get($url, $headers = array()) + { + $this->lastResponse = $this->client->get($url, [ + 'headers' => $headers, + ]); + + return $this->getContents(); + } + + /** + * @param string $url + * @param array $data + * @param array $headers + * + * @return string + */ + public function post($url, $data = array(), $headers = array()) + { + $options = [ + 'headers' => $headers, + ]; + + if (!empty($data)) { + $options['json'] = $data; + } + + $this->lastResponse = $this->client->post($url, $options); + + return $this->getContents(); + } + + /** + * @param string $url + * @param array $data + * @param array $headers + * + * @return string + */ + public function put($url, $data = array(), $headers = array()) + { + $options = [ + 'headers' => $headers, + ]; + + if (!empty($data)) { + $options['json'] = $data; + } + + $this->lastResponse = $this->client->put($url, $options); + + return $this->getContents(); + } + + /** + * @param $url + * @param $headers + * + * @return string + */ + public function delete($url, $headers = array()) + { + $this->lastResponse = $this->client->delete($url, [ + 'headers' => $headers, + ]); + + return $this->getContents(); + } + + /** + * @return mixed + */ + public function getLastResponse() + { + return $this->lastResponse; + } + + /** + * @return int + */ + public function getLastResponseCode() + { + if (empty($this->lastResponse)) { + return 0; + } + + return $this->lastResponse->getStatusCode(); + } + + /** + * @return array + */ + public function getLastResponseHeaders() + { + if (empty($this->lastResponse)) { + return array(); + } + + $result = array(); + + foreach ($this->lastResponse->getHeaders() as $name => $value) { + $result[strtolower($name)] = $value[0]; + } + + return $result; + } + + /** + * @return string + */ + protected function getContents() + { + $contents = ''; + $body = $this->lastResponse->getBody(); + + if ($body) { + $contents = $body->getContents(); + $body->rewind(); + } + + return $contents; + } +} \ No newline at end of file diff --git a/lib/HttpClient.php b/lib/HttpClient.php new file mode 100644 index 0000000..2d32b81 --- /dev/null +++ b/lib/HttpClient.php @@ -0,0 +1,50 @@ + $data, 'variables' => $variables]; self::$postDataGraphQL = json_encode(['query' => $data, 'variables' => $variables]); } else { + self::$postData = ['query' => $data]; self::$postDataGraphQL = json_encode(['query' => $data]); } } diff --git a/lib/HttpRequestJson.php b/lib/HttpRequestJson.php index c325b74..ca213da 100644 --- a/lib/HttpRequestJson.php +++ b/lib/HttpRequestJson.php @@ -26,6 +26,11 @@ class HttpRequestJson */ protected static $httpHeaders; + /** + * @var array + */ + protected static $postData = array(); + /** * Prepared JSON string to be posted with request * @@ -44,7 +49,7 @@ class HttpRequestJson */ protected static function prepareRequest($httpHeaders = array(), $dataArray = array()) { - + self::$postData = $dataArray; self::$postDataJSON = json_encode($dataArray); self::$httpHeaders = $httpHeaders; @@ -128,6 +133,7 @@ public static function delete($url, $httpHeaders = array()) * @return array */ public static function processRequest($method, $url) { + $client = ShopifySDK::getClient(); $retry = 0; $raw = null; @@ -135,16 +141,16 @@ public static function processRequest($method, $url) { try { switch($method) { case 'GET': - $raw = CurlRequest::get($url, self::$httpHeaders); + $raw = $client->get($url, self::$httpHeaders); break; case 'POST': - $raw = CurlRequest::post($url, self::$postDataJSON, self::$httpHeaders); + $raw = $client->post($url, self::$postData, self::$httpHeaders); break; case 'PUT': - $raw = CurlRequest::put($url, self::$postDataJSON, self::$httpHeaders); + $raw = $client->put($url, self::$postData, self::$httpHeaders); break; case 'DELETE': - $raw = CurlRequest::delete($url, self::$httpHeaders); + $raw = $client->delete($url, self::$httpHeaders); break; default: throw new \Exception("unexpected request method '$method'"); @@ -187,6 +193,7 @@ public static function shouldRetry($response, $error, $retry) { */ protected static function processResponse($response) { + $client = ShopifySDK::getClient(); $responseArray = json_decode($response, true); if ($responseArray === null) { @@ -196,10 +203,8 @@ protected static function processResponse($response) $httpDeleted = 204; //Delete Successful $httpOther = 303; //See other (headers). - $lastHttpResponseHeaders = CurlRequest::$lastHttpResponseHeaders; - - //should be null if any other library used for http calls - $httpCode = CurlRequest::$lastHttpCode; + $lastHttpResponseHeaders = $client->getLastResponseHeaders(); + $httpCode = $client->getLastResponseCode(); if ($httpCode == $httpOther && array_key_exists('location', $lastHttpResponseHeaders)) { return ['location' => $lastHttpResponseHeaders['location']]; diff --git a/lib/ShopifyResource.php b/lib/ShopifyResource.php index dd3b2cb..a153346 100644 --- a/lib/ShopifyResource.php +++ b/lib/ShopifyResource.php @@ -524,10 +524,11 @@ protected function castString($array) */ public function processResponse($responseArray, $dataKey = null) { - self::$lastHttpResponseHeaders = CurlRequest::$lastHttpResponseHeaders; + $client = ShopifySDK::getClient(); - $lastResponseHeaders = CurlRequest::$lastHttpResponseHeaders; - $this->getLinks($lastResponseHeaders); + self::$lastHttpResponseHeaders = $client->getLastResponseHeaders(); + + $this->getLinks(self::$lastHttpResponseHeaders); if (isset($responseArray['errors'])) { $message = $this->castString($responseArray['errors']); @@ -537,7 +538,7 @@ public function processResponse($responseArray, $dataKey = null) return array('account_activation_url'=>false); } - throw new ApiException($message, CurlRequest::$lastHttpCode); + throw new ApiException($message, $client->getLastResponseCode()); } if ($dataKey && isset($responseArray[$dataKey])) { diff --git a/lib/ShopifySDK.php b/lib/ShopifySDK.php index de31d00..4037add 100644 --- a/lib/ShopifySDK.php +++ b/lib/ShopifySDK.php @@ -373,6 +373,14 @@ public static function config($config) CurlRequest::config($config['Curl']); } + if (isset($config['HttpClient'])) { + if (!$config['HttpClient'] instanceof HttpClient) { + throw new \Exception('HttpClient must be an instance of PHPShopify\HttpClient.'); + } + } else { + self::$config['HttpClient'] = new CurlAdapter(); + } + return new ShopifySDK; } @@ -475,4 +483,12 @@ public static function checkApiCallLimit($firstCallWait = false) static::$microtimeOfLastApiCall = microtime(true); } + + /** + * @return HttpClient + */ + public static function getClient() + { + return self::$config['HttpClient']; + } }