diff --git a/.gitignore b/.gitignore index 432b975..e4aa829 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -vendor +/vendor/ /nbproject/private/ -.idea/ \ No newline at end of file +.idea/ diff --git a/.travis.yml b/.travis.yml index d8af61b..04812b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php php: - - 7.1 + - 7.3 before_script: composer install diff --git a/LICENSE b/LICENSE index 8dada3e..04b10a7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,9 @@ +/** + * This license applies to all files within this code base. + * This license must be attached if files are moved out of this codebase. + * @copyright Tareq Mahmood + */ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/README.md b/README.md index db54033..9f88fdd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/phpclassic/php-shopify.svg?branch=master)](https://travis-ci.org/phpclassic/php-shopify) [![Monthly Downloads](https://poser.pugx.org/phpclassic/php-shopify/d/monthly)](https://packagist.org/packages/phpclassic/php-shopify) [![Total Downloads](https://poser.pugx.org/phpclassic/php-shopify/downloads)](https://packagist.org/packages/phpclassic/php-shopify) [![Latest Stable Version](https://poser.pugx.org/phpclassic/php-shopify/v/stable)](https://packagist.org/packages/phpclassic/php-shopify) [![Latest Unstable Version](https://poser.pugx.org/phpclassic/php-shopify/v/unstable)](https://packagist.org/packages/phpclassic/php-shopify) [![License](https://poser.pugx.org/phpclassic/php-shopify/license)](https://packagist.org/packages/phpclassic/php-shopify) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ME9N6M2B87XT4¤cy_code=USD&source=url) -PHPShopify is a simple SDK implementation of Shopify API. It helps accessing the API in an object oriented way. +PHPShopify is a minimal SDK for using the Shopify API. ## Installation Install with Composer @@ -11,8 +11,8 @@ 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 uses curl extension for handling http calls. So you need to have the PHP curl extension installed and enabled. ## Usage @@ -22,24 +22,24 @@ You can use PHPShopify in a pretty simple object oriented way. If you are using your own private API, provide the ApiKey and Password. ```php -$config = array( +$config = [ 'ShopUrl' => 'yourshop.myshopify.com', 'ApiKey' => '***YOUR-PRIVATE-API-KEY***', - 'Password' => '***YOUR-PRIVATE-API-PASSWORD***', -); + 'Password' => '***YOUR-PRIVATE-API-PASSWORD***' +]; -PHPShopify\ShopifySDK::config($config); +$shopify = new PHPShopify\ShopifySDK($config); ``` For Third party apps, use the permanent access token. ```php -$config = array( +$config = [ 'ShopUrl' => 'yourshop.myshopify.com', - 'AccessToken' => '***ACCESS-TOKEN-FOR-THIRD-PARTY-APP***', -); + 'AccessToken' => '***ACCESS-TOKEN-FOR-THIRD-PARTY-APP***' +]; -PHPShopify\ShopifySDK::config($config); +$shopify = new PHPShopify\ShopifySDK($config); ``` ##### How to get the permanent access token for a shop? There is a AuthHelper class to help you getting the permanent access token from the shop using oAuth. @@ -47,13 +47,13 @@ There is a AuthHelper class to help you getting the permanent access token from 1) First, you need to configure the SDK with additional parameter SharedSecret ```php -$config = array( +$config = [ 'ShopUrl' => 'yourshop.myshopify.com', 'ApiKey' => '***YOUR-PRIVATE-API-KEY***', - 'SharedSecret' => '***YOUR-SHARED-SECRET***', -); + 'SharedSecret' => '***YOUR-SHARED-SECRET***' +]; -PHPShopify\ShopifySDK::config($config); +$shopify = new PHPShopify\ShopifySDK($config); ``` 2) Create the authentication request @@ -67,21 +67,15 @@ $scopes = 'read_products,write_products,read_script_tags,write_script_tags'; //$scopes = array('read_products','write_products','read_script_tags', 'write_script_tags'); $redirectUrl = 'https://yourappurl.com/your_redirect_url.php'; -\PHPShopify\AuthHelper::createAuthRequest($scopes, $redirectUrl); -``` - -> If you want the function to return the authentication url instead of auto-redirecting, you can set the argument `$return` (5th argument) to `true`. - -```php -\PHPShopify\AuthHelper::createAuthRequest($scopes, $redirectUrl, null, null, true); +$url = $shopify->createAuthHelper()->createAuthRequest($scopes, $redirectUrl); ``` 3) Get the access token when redirected back to the `$redirectUrl` after app authorization. ```php //your_redirect_url.php -PHPShopify\ShopifySDK::config($config); -$accessToken = \PHPShopify\AuthHelper::getAccessToken(); +$shopify = new PHPShopify\ShopifySDK($config); +$accessToken = $shopifyClient->createAuthHelper()->getAccessToken($_GET); //Now store it in database or somewhere else ``` @@ -96,12 +90,6 @@ $accessToken = \PHPShopify\AuthHelper::createAuthRequest($scopes); #### Get the ShopifySDK Object -```php -$shopify = new PHPShopify\ShopifySDK; -``` - -You can provide the configuration as a parameter while instantiating the object (if you didn't configure already by calling `config()` method) - ```php $shopify = new PHPShopify\ShopifySDK($config); ``` @@ -118,8 +106,8 @@ $products = $shopify->Product->get(); - Get any specific product with ID (GET request) ```php -$productID = 23564666666; -$product = $shopify->Product($productID)->get(); +$productId = 23564666666; +$product = $shopify->Product($productId)->get(); ``` You can also filter the results by using the url parameters (as specified by Shopify API Reference for each specific resource). @@ -127,11 +115,11 @@ You can also filter the results by using the url parameters (as specified by Sho - For example get the list of cancelled orders after a specified date and time (and `fields` specifies the data columns for each row to be rendered) : ```php -$params = array( +$params = [ 'status' => 'cancelled', 'created_at_min' => '2016-06-25T16:15:47-04:00', 'fields' => 'id,line_items,name,total_price' -); +]; $orders = $shopify->Order->get($params); ``` @@ -139,7 +127,7 @@ $orders = $shopify->Order->get($params); - Create a new order (POST Request) ```php -$order = array ( +$order = [ "email" => "foo@example.com", "fulfillment_status" => "unfulfilled", "line_items" => [ @@ -148,7 +136,7 @@ $order = array ( "quantity" => 5 ] ] -); +]; $shopify->Order->post($order); ``` @@ -159,19 +147,19 @@ $shopify->Order->post($order); - Update an order (PUT Request) ```php -$updateInfo = array ( +$updateInfo = [ "fulfillment_status" => "fulfilled", -); +]; -$shopify->Order($orderID)->put($updateInfo); +$shopify->Order($orderId)->put($updateInfo); ``` - Remove a Webhook (DELETE request) ```php -$webHookID = 453487303; +$webHookId = 453487303; -$shopify->Webhook($webHookID)->delete()); +$shopify->Webhook($webHookId)->delete()); ``` @@ -181,14 +169,14 @@ $shopify->Webhook($webHookID)->delete()); - For example, get the images of a product (GET request) ```php -$productID = 23564666666; -$productImages = $shopify->Product($productID)->Image->get(); +$productId = 23564666666; +$productImages = $shopify->Product($productId)->Image->get(); ``` - Add a new address for a customer (POST Request) ```php -$address = array( +$address = [ "address1" => "129 Oak St", "city" => "Ottawa", "province" => "ON", @@ -197,41 +185,41 @@ $address = array( "last_name" => "Lastnameson", "first_name" => "Mother", "country" => "CA", -); +]; -$customerID = 4425749127; +$customerId = 4425749127; -$shopify->Customer($customerID)->Address->post($address); +$shopify->Customer($customerId)->Address->post($address); ``` - Create a fulfillment event (POST request) ```php -$fulfillmentEvent = array( +$fulfillmentEvent = [ "status" => "in_transit" -); +]; -$shopify->Order($orderID)->Fulfillment($fulfillmentID)->Event->post($fulfillmentEvent); +$shopify->Order($orderId)->Fulfillment($fulfillmentId)->Event->post($fulfillmentEvent); ``` - Update a Blog article (PUT request) ```php -$blogID = 23564666666; -$articleID = 125336666; -$updateArtilceInfo = array( +$blogId = 23564666666; +$articleId = 125336666; +$updateArticleInfo = [ "title" => "My new Title", "author" => "Your name", "tags" => "Tags, Will Be, Updated", "body_html" => "

Look, I can even update through a web service.<\/p>", -); -$shopify->Blog($blogID)->Article($articleID)->put($updateArtilceInfo); +]; +$shopify->Blog($blogId)->Article($articleId)->put($updateArticleInfo); ``` - Delete any specific article from a specific blog (DELETE request) ```php -$blogArticle = $shopify->Blog($blogID)->Article($articleID)->delete(); +$blogArticle = $shopify->Blog($blogId)->Article($articleId)->delete(); ``` ### GraphQL *v1.1* @@ -259,7 +247,6 @@ $data = $shopify->GraphQL->post($graphQL); ##### GraphQL Builder This SDK only accepts a GraphQL string as input. You can build your GraphQL from [Shopify GraphQL Builder](https://help.shopify.com/en/api/graphql-admin-api/graphiql-builder) - ### Resource Mapping Some resources are available directly, some resources are only available through parent resources and a few resources can be accessed both ways. It is recommended that you see the details in the related Shopify API Reference page about each resource. Each resource name here is linked to related Shopify API Reference page. > Use the resources only by listed resource map. Trying to get a resource directly which is only available through parent resource may end up with errors. @@ -345,7 +332,7 @@ $productCount = $shopify->Product->count(); - Make an address default for the customer. ```php -$shopify->Customer($customerID)->Address($addressID)->makeDefault(); +$shopify->Customer($customerId)->Address($addressId)->makeDefault(); ``` - Search for customers with keyword "Bob" living in country "United States". diff --git a/composer.json b/composer.json index 6fdced1..564ef1e 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "homepage": "https://github.com/phpclassic/php-shopify", "type": "library", "require": { - "php": ">=5.6", + "php": ">=7.3", "ext-curl": "*", "ext-json": "*" }, diff --git a/composer.lock b/composer.lock index 8a526e6..89af88e 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8624cace8c373f5a022e66c876da9f1f", + "content-hash": "2960f8805c6360d7e5e677e8141b46d0", "packages": [], "packages-dev": [ { @@ -65,16 +65,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.9.3", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", "shasum": "" }, "require": { @@ -109,7 +109,7 @@ "object", "object graph" ], - "time": "2019-08-09T12:45:53+00:00" + "time": "2020-01-17T21:11:47+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -165,40 +165,38 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.2", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -209,33 +207,36 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-09-12T14:27:41+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.2", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" + "ext-tokenizer": "^7.2", + "mockery/mockery": "~1" }, "type": "library", "extra": { @@ -259,37 +260,37 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" + "time": "2020-02-18T18:59:58+00:00" }, { "name": "phpspec/prophecy", - "version": "1.9.0", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", + "phpspec/phpspec": "^2.5 || ^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { @@ -322,7 +323,7 @@ "spy", "stub" ], - "time": "2019-10-03T11:07:50+00:00" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1230,16 +1231,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.13.1", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", + "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", "shasum": "" }, "require": { @@ -1251,7 +1252,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-master": "1.14-dev" } }, "autoload": { @@ -1284,20 +1285,20 @@ "polyfill", "portable" ], - "time": "2019-11-27T13:56:44+00:00" + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/yaml", - "version": "v4.4.1", + "version": "v4.4.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "76de473358fe802578a415d5bb43c296cf09d211" + "reference": "94d005c176db2080e98825d98e01e8b311a97a88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/76de473358fe802578a415d5bb43c296cf09d211", - "reference": "76de473358fe802578a415d5bb43c296cf09d211", + "url": "https://api.github.com/repos/symfony/yaml/zipball/94d005c176db2080e98825d98e01e8b311a97a88", + "reference": "94d005c176db2080e98825d98e01e8b311a97a88", "shasum": "" }, "require": { @@ -1343,20 +1344,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-11-12T14:51:11+00:00" + "time": "2020-02-03T10:46:43+00:00" }, { "name": "webmozart/assert", - "version": "1.6.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", - "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "shasum": "" }, "require": { @@ -1391,7 +1392,7 @@ "check", "validate" ], - "time": "2019-11-24T13:36:37+00:00" + "time": "2020-02-14T12:15:55+00:00" } ], "aliases": [], @@ -1400,7 +1401,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6", + "php": ">=7.3", "ext-curl": "*", "ext-json": "*" }, diff --git a/lib/AbandonedCheckout.php b/lib/AbandonedCheckout.php deleted file mode 100644 index 15686cc..0000000 --- a/lib/AbandonedCheckout.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/18/16 9:50 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/abandoned_checkouts Shopify API Reference for Abandoned checkouts - */ - -namespace PHPShopify; - - -class AbandonedCheckout extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'checkout'; -} \ No newline at end of file diff --git a/lib/ApplicationCharge.php b/lib/ApplicationCharge.php deleted file mode 100644 index b557911..0000000 --- a/lib/ApplicationCharge.php +++ /dev/null @@ -1,29 +0,0 @@ - - * Created at 8/18/16 9:50 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/applicationcharge Shopify API Reference for ApplicationCharge - */ - -namespace PHPShopify; - - -class ApplicationCharge extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'application_charge'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - // To activate ApplicationCharge - protected $customPostActions = array( - 'activate', - ); -} diff --git a/lib/Article.php b/lib/Article.php deleted file mode 100644 index e1fb53c..0000000 --- a/lib/Article.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Created at 8/18/16 3:18 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/article Shopify API Reference for Article - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Article -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * @property-read Metafield $Metafield - * - * @method Event Event(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * - */ -class Article extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'article'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Event', - 'Metafield', - ); -} \ No newline at end of file diff --git a/lib/Asset.php b/lib/Asset.php deleted file mode 100644 index 56a1007..0000000 --- a/lib/Asset.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/18/16 3:39 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/asset Shopify API Reference for Asset - */ - -namespace PHPShopify; - - -class Asset extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'asset'; -} \ No newline at end of file diff --git a/lib/AuthHelper.php b/lib/AuthHelper.php index e879964..90ccf37 100644 --- a/lib/AuthHelper.php +++ b/lib/AuthHelper.php @@ -1,178 +1,133 @@ - * Created at: 8/27/16 10:58 AM UTC+06:00 - */ namespace PHPShopify; - use PHPShopify\Exception\SdkException; +use PHPShopify\Http\HttpRequestJson; class AuthHelper { - /** - * Get the url of the current page - * - * @return string - */ - public static function getCurrentUrl() - { - if (isset($_SERVER['HTTPS']) && - ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || - isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && - $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { - $protocol = 'https'; - } - else { - $protocol = 'http'; + /** @var array */ + protected $config; + /** @var HttpRequestJson */ + protected $httpRequestJson; + + public function __construct(array $config, ?HttpRequestJson $httpRequestJson = null) { + $this->config = $config; + + if ($httpRequestJson === null) { + $httpRequestJson = new HttpRequestJson(); } - return "$protocol://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; + $this->httpRequestJson = $httpRequestJson; } - /** - * Build a query string from a data array - * This is a replacement for http_build_query because that returns an url-encoded string. - * - * @param array $data Data array - * - * @return array - */ - public static function buildQueryString($data) - { - $paramStrings = []; - foreach ($data as $key => $value) { - $paramStrings[] = "$key=$value"; + public static function getCurrentUrl(): string { + if ( + in_array($_SERVER['HTTPS'] ?? null, ['on', 1]) + && + ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? null) === 'https' + ) { + $protocol = 'https'; + } else { + $protocol = 'http'; } - return join('&', $paramStrings); + + return "{$protocol}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; } /** * Verify if the request is made from shopify using hmac hash value * + * @inheritDoc + * @see https://ecommerce.shopify.com/c/shopify-apis-and-technology/t/hmac-calculation-vs-ids-arrays-320575 * @throws SdkException if SharedSecret is not provided or hmac is not found in the url parameters - * - * @return bool */ - public static function verifyShopifyRequest() - { - $data = $_GET; + public function verifyShopifyRequest(array $data): bool { + $sharedSecret = $this->config['SharedSecret']; - if(!isset(ShopifySDK::$config['SharedSecret'])) { - throw new SdkException("Please provide SharedSecret while configuring the SDK client."); + if (!isset($data['hmac']) || !is_string($data['hmac'])) { + throw new SdkException("HMAC value not found in url parameters."); } - $sharedSecret = ShopifySDK::$config['SharedSecret']; + $hashItems = []; - //Get the hmac and remove it from array - if (isset($data['hmac'])) { - $hmac = $data['hmac']; - unset($data['hmac']); - } else { - throw new SdkException("HMAC value not found in url parameters."); - } - //signature validation is deprecated - if (isset($data['signature'])) { - unset($data['signature']); - } - //Create data string for the remaining url parameters - $dataString = self::buildQueryString($data); + foreach ($data as $key => $value) { + if (in_array($key, ['hmac', 'signature'], true)) { + continue; + } - $realHmac = hash_hmac('sha256', $dataString, $sharedSecret); + if (is_array($value)) { + $value = '["' . implode('", "', $value) . '"]'; + } - //hash the values before comparing (to prevent time attack) - if(md5($realHmac) === md5($hmac)) { - return true; - } else { - return false; + $hashItems[$key] = "{$key}={$value}"; } + + ksort($hashItems); + $hashString = implode('&', $hashItems); + + return hash_hmac('sha256', $hashString, $sharedSecret) === $data['hmac']; } /** - * Redirect the user to the authorization page to allow the app access to the shop + * Get the URL to redirected the user to authorize app access to the shop. * * @see https://help.shopify.com/api/guides/authentication/oauth#scopes For allowed scopes - * - * @param string|string[] $scopes Scopes required by app - * @param string $redirectUrl - * @param string $state - * @param string[] $options - * @param bool $return If true, will return the authentical url instead of auto-redirecting to the page. - * @throws SdkException if required configuration is not provided in $config - * - * @return void|string + * @inheritDoc + * @param string|string[] $scope Scopes required by app + * @param string[] $grantOptions */ - public static function createAuthRequest($scopes, $redirectUrl = null, $state = null, $options = null, $return = false) - { - $config = ShopifySDK::$config; - - if(!isset($config['ShopUrl']) || !isset($config['ApiKey'])) { - throw new SdkException("ShopUrl and ApiKey are required for authentication request. Please check SDK configuration!"); + public function createAuthUrl( + ?array $scope, + ?string $redirectUrl, + ?string $state = null, + ?array $grantOptions = null + ): ?string { + assert(is_string($scope) || is_array($scope)); + + if ($redirectUrl === null) { + $redirectUrl = static::getCurrentUrl(); } - if (!$redirectUrl) { - if(!isset($config['SharedSecret'])) { - throw new SdkException("SharedSecret is required for getting access token. Please check SDK configuration!"); - } + $parameters = [ + 'client_id' => $this->config['ApiKey'], + 'redirect_uri' => $redirectUrl + ]; - //If redirect url is the same as this url, then need to check for access token when redirected back from shopify - if(isset($_GET['code'])) { - return self::getAccessToken($config); - } else { - $redirectUrl = self::getCurrentUrl(); - } + if ($scope !== null) { + $parameters['scope'] = implode(',', $scope); } - if (is_array($scopes)) { - $scopes = join(',', $scopes); - } - if(!empty($state)) { - $state = '&state=' . $state; + if ($state !== null) { + $parameters['state'] = $state; } - if(!empty($options)) { - $options = '&grant_options[]=' . join(',', $options); - } - // Official call structure - // https://{shop}.myshopify.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}&state={nonce}&grant_options[]={option} - $authUrl = $config['AdminUrl'] . 'oauth/authorize?client_id=' . $config['ApiKey'] . '&redirect_uri=' . $redirectUrl . "&scope=$scopes" . $state . $options; - if ($return) { - return $authUrl; + if ($grantOptions !== null) { + $parameters['grant_options[]'] = implode(',', $grantOptions); } - header("Location: $authUrl"); + $parameters = http_build_query($parameters); + return "{$this->config['AdminUrl']}oauth/authorize?{$parameters}"; } /** * Get Access token for the API * Call this when being redirected from shopify page ( to the $redirectUrl) after authentication - * - * @throws SdkException if SharedSecret or ApiKey is missing in SDK configuration or request is not valid - * - * @return string */ - public static function getAccessToken() - { - $config = ShopifySDK::$config; + public function getAccessToken(array $data): ?string { + if($this->verifyShopifyRequest($data)) { + $data = [ + 'client_id' => $this->config['ApiKey'], + 'client_secret' => $this->config['SharedSecret'], + 'code' => $data['code'], + ]; - if(!isset($config['SharedSecret']) || !isset($config['ApiKey'])) { - throw new SdkException("SharedSecret and ApiKey are required for getting access token. Please check SDK configuration!"); - } - - if(self::verifyShopifyRequest()) { - $data = array( - 'client_id' => $config['ApiKey'], - 'client_secret' => $config['SharedSecret'], - 'code' => $_GET['code'], - ); - - $response = HttpRequestJson::post($config['AdminUrl'] . 'oauth/access_token', $data); + $response = $this->httpRequestJson->post("{$this->config['AdminUrl']}oauth/access_token", $data); - return isset($response['access_token']) ? $response['access_token'] : null; - } else { - throw new SdkException("This request is not initiated from a valid shopify shop!"); + return $response['access_token'] ?? null; } + + throw new SdkException("This request is not initiated from a valid shopify shop!"); } } diff --git a/lib/Blog.php b/lib/Blog.php deleted file mode 100644 index 83d0370..0000000 --- a/lib/Blog.php +++ /dev/null @@ -1,40 +0,0 @@ - - * Created at 8/18/16 10:46 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/blog Shopify API Reference for Blog - */ - -namespace PHPShopify; - -/** - * -------------------------------------------------------------------------- - * Blog -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Article $Article - * @property-read Event $Event - * @property-read Metafield $Metafield - * - * @method Article Article(integer $id = null) - * @method Event Event(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * - */ -class Blog extends ShopifyResource -{ - /** - * @inheritDoc - */ - public $resourceKey = 'blog'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Article', - 'Event', - 'Metafield', - ); -} \ No newline at end of file diff --git a/lib/CarrierService.php b/lib/CarrierService.php deleted file mode 100644 index edb5e29..0000000 --- a/lib/CarrierService.php +++ /dev/null @@ -1,24 +0,0 @@ - - * Created at 8/19/16 10:49 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/carrierservice Shopify API Reference for CarrierService - */ - -namespace PHPShopify; - - -class CarrierService extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'carrier_service'; - - /** - * @inheritDoc - */ - public $countEnabled = false; -} \ No newline at end of file diff --git a/lib/Collect.php b/lib/Collect.php deleted file mode 100644 index 99e8c13..0000000 --- a/lib/Collect.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 10:54 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/collect Shopify API Reference for Collect - */ - -namespace PHPShopify; - - -class Collect extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'collect'; -} \ No newline at end of file diff --git a/lib/Collection.php b/lib/Collection.php deleted file mode 100644 index 1d2c84a..0000000 --- a/lib/Collection.php +++ /dev/null @@ -1,35 +0,0 @@ - Child Resources - * -------------------------------------------------------------------------- - * - * @property-read Product $Product - * - * @method Product Product(integer $id = null) - * - * @see https://shopify.dev/docs/admin-api/rest/reference/products/collection - * - */ -class Collection extends ShopifyResource -{ - /** - * @inheritDoc - */ - public $readOnly = false; - - /** - * @inheritDoc - */ - protected $resourceKey = 'collection'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Product', - ); -} \ No newline at end of file diff --git a/lib/Comment.php b/lib/Comment.php deleted file mode 100644 index ca749bc..0000000 --- a/lib/Comment.php +++ /dev/null @@ -1,56 +0,0 @@ - - * Created at 8/19/16 10:58 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/comment Shopify API Reference for Comment - */ - -namespace PHPShopify; - - -/** - * - * -------------------------------------------------------------------------- - * Comment -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * - * @method Event Event(integer $id = null) - * - * -------------------------------------------------------------------------- - * Comment -> Custom actions - * -------------------------------------------------------------------------- - * @method array markSpam() Mark a Comment as spam - * @method array markNotSpam() Mark a Comment as not spam - * @method array approve() Approve a Comment - * @method array remove() Remove a Comment - * @method array restore() Restore a Comment - * - */ -class Comment extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'comment'; - - /** - * @inheritDoc - */ - protected $childResource = array ( - 'Event', - ); - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'spam' => 'markSpam', - 'not_spam' => 'markNotSpam', - 'approve', - 'remove', - 'restore', - ); -} \ No newline at end of file diff --git a/lib/Country.php b/lib/Country.php deleted file mode 100644 index 158fd5d..0000000 --- a/lib/Country.php +++ /dev/null @@ -1,43 +0,0 @@ - - * Created at 8/19/16 11:44 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/country Shopify API Reference for Country - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Country -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Province $Province - * - * @method Province Province(integer $id = null) - * - */ -class Country extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'country'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Province', - ); - - /** - * @inheritDoc - */ - protected function pluralizeKey() - { - return 'countries'; - } -} \ No newline at end of file diff --git a/lib/CurlRequest.php b/lib/CurlRequest.php deleted file mode 100644 index 73567e1..0000000 --- a/lib/CurlRequest.php +++ /dev/null @@ -1,184 +0,0 @@ - - * Created at 8/17/16 2:50 PM UTC+06:00 - */ - -namespace PHPShopify; - - -use PHPShopify\Exception\CurlException; -use PHPShopify\Exception\ResourceRateLimitException; - -/* -|-------------------------------------------------------------------------- -| CurlRequest -|-------------------------------------------------------------------------- -| -| This class handles get, post, put, delete HTTP requests -| -*/ -class CurlRequest -{ - /** - * HTTP Code of the last executed request - * - * @var integer - */ - public static $lastHttpCode; - - /** - * HTTP response headers of last executed request - * - * @var array - */ - public static $lastHttpResponseHeaders = array(); - - /** - * Initialize the curl resource - * - * @param string $url - * @param array $httpHeaders - * - * @return resource - */ - protected static function init($url, $httpHeaders = array()) - { - // Create Curl resource - $ch = curl_init(); - - // Set URL - curl_setopt($ch, CURLOPT_URL, $url); - - //Return the transfer as a string - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - - curl_setopt($ch, CURLOPT_HEADER, true); - curl_setopt($ch, CURLOPT_USERAGENT, 'PHPClassic/PHPShopify'); - - $headers = array(); - foreach ($httpHeaders as $key => $value) { - $headers[] = "$key: $value"; - } - //Set HTTP Headers - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - - return $ch; - - } - - /** - * Implement a GET request and return output - * - * @param string $url - * @param array $httpHeaders - * - * @return string - */ - public static function get($url, $httpHeaders = array()) - { - //Initialize the Curl resource - $ch = self::init($url, $httpHeaders); - - return self::processRequest($ch); - } - - /** - * Implement a POST request and return output - * - * @param string $url - * @param array $data - * @param array $httpHeaders - * - * @return string - */ - public static function post($url, $data, $httpHeaders = array()) - { - $ch = self::init($url, $httpHeaders); - //Set the request type - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - - return self::processRequest($ch); - } - - /** - * Implement a PUT request and return output - * - * @param string $url - * @param array $data - * @param array $httpHeaders - * - * @return string - */ - public static function put($url, $data, $httpHeaders = array()) - { - $ch = self::init($url, $httpHeaders); - //set the request type - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - - return self::processRequest($ch); - } - - /** - * Implement a DELETE request and return output - * - * @param string $url - * @param array $httpHeaders - * - * @return string - */ - public static function delete($url, $httpHeaders = array()) - { - $ch = self::init($url, $httpHeaders); - //set the request type - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); - - return self::processRequest($ch); - } - - /** - * Execute a request, release the resource and return output - * - * @param resource $ch - * - * @throws CurlException if curl request is failed with error - * - * @return string - */ - protected static function processRequest($ch) - { - # Check for 429 leaky bucket error - while (1) { - $output = curl_exec($ch); - $response = new CurlResponse($output); - - self::$lastHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if (self::$lastHttpCode != 429) { - break; - } - - $limitHeader = explode('/', $response->getHeader('X-Shopify-Shop-Api-Call-Limit'), 2); - - if (isset($limitHeader[1]) && $limitHeader[0] < $limitHeader[1]) { - throw new ResourceRateLimitException($response->getBody()); - } - - usleep(500000); - } - - if (curl_errno($ch)) { - throw new Exception\CurlException(curl_errno($ch) . ' : ' . curl_error($ch)); - } - - // close curl resource to free up system resources - curl_close($ch); - - self::$lastHttpResponseHeaders = $response->getHeaders(); - - return $response->getBody(); - } - -} diff --git a/lib/CurlResponse.php b/lib/CurlResponse.php deleted file mode 100644 index 02a9eec..0000000 --- a/lib/CurlResponse.php +++ /dev/null @@ -1,74 +0,0 @@ -parse($response); - } - - /** - * @param string $response - */ - private function parse($response) - { - $response = \explode("\r\n\r\n", $response); - if (\count($response) > 1) { - // We want the last two parts - $response = \array_slice($response, -2, 2); - list($headers, $body) = $response; - foreach (\explode("\r\n", $headers) as $header) { - $pair = \explode(': ', $header, 2); - if (isset($pair[1])) { - $headerKey = strtolower($pair[0]); - $this->headers[$headerKey] = $pair[1]; - } - } - } else { - $body = $response[0]; - } - - $this->body = $body; - } - - /** - * @return array - */ - public function getHeaders() - { - return $this->headers; - } - - /** - * @param string $key - * - * @return string - */ - public function getHeader($key) - { - return isset($this->headers[$key]) ? $this->headers[$key] : null; - } - - /** - * @return string - */ - public function getBody() - { - return $this->body; - } - - public function __toString() - { - $body = $this->getBody(); - $body = $body ? : ''; - - return $body; - } -} diff --git a/lib/Currency.php b/lib/Currency.php deleted file mode 100644 index a93a68b..0000000 --- a/lib/Currency.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Created at 8/19/16 11:46 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/customcollection Shopify API Reference for CustomCollection - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * CustomCollection -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * @property-read Metafield $Metafield - * - * @method Event Event(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * - */ -class CustomCollection extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'custom_collection'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Event', - 'Metafield', - ); -} \ No newline at end of file diff --git a/lib/Customer.php b/lib/Customer.php deleted file mode 100644 index a058624..0000000 --- a/lib/Customer.php +++ /dev/null @@ -1,63 +0,0 @@ - - * Created at 8/19/16 11:47 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/customer Shopify API Reference for Customer - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Customer -> Child Resources - * -------------------------------------------------------------------------- - * @property-read CustomerAddress $Address - * @property-read Metafield $Metafield - * - * @method CustomerAddress Address(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * -------------------------------------------------------------------------- - * Customer -> Custom actions - * -------------------------------------------------------------------------- - * @method array search() Search for customers matching supplied query - */ -class Customer extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey ='customer'; - - /** - * @inheritDoc - */ - public $searchEnabled = true; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'CustomerAddress' => 'Address', - 'Metafield', - 'Order' - ); - - /** - * Sends an account invite to a customer. - * - * @param array $customer_invite Customized invite data - * - * @return array - */ - public function send_invite($customer_invite = array()) - { - if (empty ( $customer_invite ) ) $customer_invite = new \stdClass(); - $url = $this->generateUrl(array(), 'send_invite'); - $dataArray = $this->wrapData($customer_invite, 'customer_invite'); - - return $this->post($dataArray, $url, false); - } -} \ No newline at end of file diff --git a/lib/CustomerAddress.php b/lib/CustomerAddress.php deleted file mode 100644 index 32c60c1..0000000 --- a/lib/CustomerAddress.php +++ /dev/null @@ -1,57 +0,0 @@ - - * Created at 8/19/16 12:07 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/customeraddress Shopify API Reference for CustomerAddress - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * CustomerAddress -> Custom actions - * -------------------------------------------------------------------------- - * @method array makeDefault() Sets the address as default for the customer - * - */ -class CustomerAddress extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'address'; - - /** - * @inheritDoc - */ - protected $customPutActions = array( - 'default' => 'makeDefault', - ); - - /** - * @inheritDoc - */ - protected function pluralizeKey() - { - return 'addresses'; - } - - - /** - * Perform bulk operations against a number of addresses - * - * @param array $params - * - * @return array - */ - //TODO Issue (Getting Error from API) : Internal server error - public function set($params) - { - $url = $this->generateUrl($params, 'set'); - - return $this->put(array(), $url); - } -} \ No newline at end of file diff --git a/lib/CustomerSavedSearch.php b/lib/CustomerSavedSearch.php deleted file mode 100644 index 3cec785..0000000 --- a/lib/CustomerSavedSearch.php +++ /dev/null @@ -1,43 +0,0 @@ - - * Created at 8/19/16 2:07 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/customersavedsearch Shopify API Reference for CustomerSavedSearch - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * CustomerSavedSearch -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Customer $Customer - * - * @method Customer Customer(integer $id = null) - * - */ -class CustomerSavedSearch extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'customer_saved_search'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Customer', - ); - - /** - * @inheritDoc - */ - protected function pluralizeKey() - { - return 'customer_saved_searches'; - } -} \ No newline at end of file diff --git a/lib/Discount.php b/lib/Discount.php deleted file mode 100644 index f2779aa..0000000 --- a/lib/Discount.php +++ /dev/null @@ -1,35 +0,0 @@ - - * Created at 8/19/16 2:28 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/discount Shopify API Reference for Discount - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Discount -> Custom actions - * -------------------------------------------------------------------------- - * @method array enable() Enable a discount - * @method array disable() Disable a discount - * - */ -class Discount extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'discount'; - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'enable', - 'disable', - ); -} \ No newline at end of file diff --git a/lib/DiscountCode.php b/lib/DiscountCode.php deleted file mode 100644 index e13889e..0000000 --- a/lib/DiscountCode.php +++ /dev/null @@ -1,34 +0,0 @@ - - * Created at 5/06/19 2:09 AM UTC+03:00 - * - * @see https://help.shopify.com/api/reference/discounts/discountcode Shopify API Reference for PriceRule - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * DiscountCode -> Custom actions - * -------------------------------------------------------------------------- - * @method array lookup() Retrieves the location of a discount code. - * - */ - -class DiscountCode extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'discount_code'; - - /** - * @inheritDoc - */ - protected $customGetActions = array( - 'lookup', - ); -} \ No newline at end of file diff --git a/lib/DraftOrder.php b/lib/DraftOrder.php deleted file mode 100644 index 902cee5..0000000 --- a/lib/DraftOrder.php +++ /dev/null @@ -1,42 +0,0 @@ - - * Created at 8/14/19 18:28 PM UTC+02:00 - * - * @see https://help.shopify.com/api/reference/draftorder Shopify API Reference for DraftOrder - */ - -namespace PHPShopify; - - - -/** - * -------------------------------------------------------------------------- - * DraftOrder -> Custom actions - * -------------------------------------------------------------------------- - * @method array send_invoice() Send the invoice for a DraftOrder - * @method array complete() Complete a DraftOrder - * - */ -class DraftOrder extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'draft_order'; - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'send_invoice', - ); - - /** - * @inheritDoc - */ - protected $customPutActions = array( - 'complete', - ); -} \ No newline at end of file diff --git a/lib/Event.php b/lib/Event.php deleted file mode 100644 index 830c540..0000000 --- a/lib/Event.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at: 8/21/16 8:39 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/event/ Shopify API Reference for Event - */ - -namespace PHPShopify; - - -class Event extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'event'; -} \ No newline at end of file diff --git a/lib/Exception/ApiException.php b/lib/Exception/ApiException.php index 9acf168..cfb5b27 100644 --- a/lib/Exception/ApiException.php +++ b/lib/Exception/ApiException.php @@ -1,14 +1,17 @@ - * Created at 8/19/16 10:28 AM UTC+06:00 - */ namespace PHPShopify\Exception; +class ApiException extends SdkException { + public static function factory(string $message, int $status): void { + if ($message === 'Unavailable Shop') { + throw new ShopUnavailableException($message, $status); + } -class ApiException extends \Exception -{ + if (preg_match('/Exceeded (\d+) calls per second for api client\. Reduce request rates to resume uninterrupted service\./', $message)) { + throw new ResourceRateLimitException($message, $status); + } -} \ No newline at end of file + throw new self($message, $status); + } +} diff --git a/lib/Exception/CurlException.php b/lib/Exception/CurlException.php index 21f2b40..b40d91a 100644 --- a/lib/Exception/CurlException.php +++ b/lib/Exception/CurlException.php @@ -1,14 +1,6 @@ - * Created at 8/19/16 10:26 AM UTC+06:00 - */ namespace PHPShopify\Exception; - -class CurlException extends \Exception -{ - -} \ No newline at end of file +class CurlException extends SdkException { +} diff --git a/lib/Exception/ResourceRateLimitException.php b/lib/Exception/ResourceRateLimitException.php index 1e7843d..99b51dd 100644 --- a/lib/Exception/ResourceRateLimitException.php +++ b/lib/Exception/ResourceRateLimitException.php @@ -2,7 +2,5 @@ namespace PHPShopify\Exception; -class ResourceRateLimitException extends ApiException -{ - +class ResourceRateLimitException extends ApiException { } diff --git a/lib/Exception/SdkException.php b/lib/Exception/SdkException.php index b0cdf93..9d7e08e 100644 --- a/lib/Exception/SdkException.php +++ b/lib/Exception/SdkException.php @@ -1,14 +1,6 @@ - * Created at 8/19/16 10:29 AM UTC+06:00 - */ namespace PHPShopify\Exception; - -class SdkException extends \Exception -{ - -} \ No newline at end of file +class SdkException extends \Exception { +} diff --git a/lib/Exception/ShopUnavailableException.php b/lib/Exception/ShopUnavailableException.php new file mode 100644 index 0000000..db529c5 --- /dev/null +++ b/lib/Exception/ShopUnavailableException.php @@ -0,0 +1,6 @@ + - * Created at 8/19/16 3:04 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/fulfillment Shopify API Reference for Fulfillment - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Fulfillment -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * - * @method Event Event(integer $id = null) - * - * -------------------------------------------------------------------------- - * Fulfillment -> Custom actions - * -------------------------------------------------------------------------- - * @method array complete() Complete a fulfillment - * @method array open() Open a pending fulfillment - * @method array cancel() Cancel a fulfillment - * - */ -class Fulfillment extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'fulfillment'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'FulfillmentEvent' => 'Event', - ); - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'complete', - 'open', - 'cancel', - ); -} \ No newline at end of file diff --git a/lib/FulfillmentEvent.php b/lib/FulfillmentEvent.php deleted file mode 100644 index cc44f83..0000000 --- a/lib/FulfillmentEvent.php +++ /dev/null @@ -1,35 +0,0 @@ - - * Created at 8/19/16 4:49 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/fulfillmentevent Shopify API Reference for FulfillmentEvent - */ - -namespace PHPShopify; - - -class FulfillmentEvent extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'fulfillment_event'; - - /** - * @inheritDoc - */ - public function getResourcePath() - { - return 'events'; - } - - /** - * @inheritDoc - */ - public function getResourcePostKey() - { - return 'event'; - } -} \ No newline at end of file diff --git a/lib/FulfillmentService.php b/lib/FulfillmentService.php deleted file mode 100644 index a4b1612..0000000 --- a/lib/FulfillmentService.php +++ /dev/null @@ -1,24 +0,0 @@ - - * Created at 8/19/16 5:28 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/fulfillmentservice Shopify API Reference for FulfillmentService - */ - -namespace PHPShopify; - - -class FulfillmentService extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'fulfillment_service'; - - /** - * @inheritDoc - */ - public $countEnabled = false; -} \ No newline at end of file diff --git a/lib/GiftCard.php b/lib/GiftCard.php deleted file mode 100644 index 2391064..0000000 --- a/lib/GiftCard.php +++ /dev/null @@ -1,48 +0,0 @@ - - * Created at 8/19/16 5:35 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/gift_card Shopify API Reference for GiftCard - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * GiftCard -> Custom actions - * -------------------------------------------------------------------------- - * @method array search() Search for gift cards matching supplied query - * - */ -class GiftCard extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'gift_card'; - - /** - * @inheritDoc - */ - public $searchEnabled = true; - - /** - * Disable a gift card. - * Disabling a gift card is permanent and cannot be undone. - * - * @return array - */ - public function disable() - { - $url = $this->generateUrl(array(), 'disable'); - - $dataArray = array( - 'id' => $this->id, - ); - - return $this->post($dataArray, $url); - } -} \ No newline at end of file diff --git a/lib/GraphQL.php b/lib/GraphQL.php deleted file mode 100644 index 185593b..0000000 --- a/lib/GraphQL.php +++ /dev/null @@ -1,78 +0,0 @@ -generateUrl(); - - $response = HttpRequestGraphQL::post($url, $graphQL, $this->httpHeaders, $variables); - - return $this->processResponse($response); - } - - /** - * @inheritdoc - * @throws SdkException - */ - public function get($urlParams = array(), $url = null, $dataKey = null) - { - throw new SdkException("Only POST method is allowed for GraphQL!"); - } - - /** - * @inheritdoc - * @throws SdkException - */ - public function put($dataArray, $url = null, $wrapData = true) - { - throw new SdkException("Only POST method is allowed for GraphQL!"); - } - - /** - * @inheritdoc - * @throws SdkException - */ - public function delete($urlParams = array(), $url = null) - { - throw new SdkException("Only POST method is allowed for GraphQL!"); - } -} \ No newline at end of file diff --git a/lib/Http/CurlRequest.php b/lib/Http/CurlRequest.php new file mode 100644 index 0000000..b703ddb --- /dev/null +++ b/lib/Http/CurlRequest.php @@ -0,0 +1,181 @@ + $value) { + $headers[] = "{$key}: {$value}"; + } + + curl_setopt(self::$ch, CURLOPT_HTTPHEADER, $headers); + + return self::$ch; + } + + public function destroy(): void { + if (self::$ch !== null) { + $ch = self::$ch; + self::$ch = null; + curl_close($ch); + } + } + + public function get(string $url, array $httpHeaders = []): CurlResponse { + return static::processRequest(static::init('GET', $url, $httpHeaders)); + } + + /** + * @inheritDoc + * @param string|array $data + */ + public function post(string $url, $data, array $httpHeaders = []): CurlResponse { + return static::processRequest(static::init('POST', $url, $httpHeaders, $data)); + } + + public function put($url, $data, array $httpHeaders = []): CurlResponse { + return static::processRequest(static::init('PUT', $url, $httpHeaders, $data)); + } + + public function delete(string $url, array $httpHeaders = []): CurlResponse { + return static::processRequest(static::init('DELETE', $url, $httpHeaders)); + } + + /** + * @inheritDoc + * @param resource $ch + * @throws CurlException if curl request is failed with error + */ + protected function processRequest($ch): CurlResponse { + $start = microtime(true); + $tries = 0; + # Check for 429 leaky bucket error + while (true) { + $output = curl_exec($ch); + + if (curl_errno($ch)) { + throw new CurlException(curl_errno($ch) . ' : ' . curl_error($ch)); + } + + assert(is_string($output)); + + $parsedResponse = static::parseResponse($output); + // Note: Missing error handling here. + $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); + $response = new CurlResponse($status, $parsedResponse['headers'], $parsedResponse['body']); + + if ($response->getStatus() != 429) { + break; + } + + $limitHeader = explode('/', $response->getHeader('X-Shopify-Shop-Api-Call-Limit'), 2); + $tries++; + $took = (microtime(true) - $start) + (static::RATE_LIMIT_RETRY_DELAY / 1000000); + + /** + * This makes no sense. It can likely ignore this header and use Retry-After if set otherwise throw an + * exception. + */ + if ((isset($limitHeader[1]) && $limitHeader[0] < $limitHeader[1]) || + $tries > static::RATE_LIMIT_RETRIES || $took > static::RATE_LIMIT_TIMEOUT) { + throw new ResourceRateLimitException($response->getBody()); + } + + usleep(static::RATE_LIMIT_RETRY_DELAY); + } + + return $response; + } + + protected function parseResponse(string $response): array { + $response = explode("\r\n\r\n", $response, 2); + + assert(count($response) === 2); + $headers = []; + [$headerString, $bodyString] = $response; + + foreach (explode("\r\n", $headerString) as $header) { + $pair = explode(': ', $header, 2); + [$key, $value] = $pair + [1 => null]; + $key = strtolower($key); + + if (!array_key_exists($key, $headers)) { + $headers[$key] = []; + } + + $headers[$key][] = $value; + } + + $body = static::parseBody($bodyString); + + return compact('headers', 'body'); + } + + protected function serializeData($data): string { + return http_build_query($data); + } + + protected function parseBody(string $body) { + return $body; + } +} diff --git a/lib/Http/CurlResponse.php b/lib/Http/CurlResponse.php new file mode 100644 index 0000000..fc2ce8a --- /dev/null +++ b/lib/Http/CurlResponse.php @@ -0,0 +1,36 @@ +status = $status; + $this->headers = $headers; + $this->body = $body; + } + + public function getHeader(string $key): ?string { + return $this->headers[$key][0] ?? null; + } + + public function getBody() { + return $this->body; + } + + public function getStatus(): int { + return $this->status; + } + + public function __toString() { + $body = $this->getBody(); + $body = $body ? : ''; + + return $body; + } +} diff --git a/lib/Http/HttpRequestJson.php b/lib/Http/HttpRequestJson.php new file mode 100644 index 0000000..b913a98 --- /dev/null +++ b/lib/Http/HttpRequestJson.php @@ -0,0 +1,26 @@ + $data, 'variables' => $variables]); - self::$httpHeaders['Content-type'] = 'application/json'; - } else { - self::$httpHeaders['Content-type'] = 'application/graphql'; - } - } - - /** - * Implement a POST request and return json decoded output - * - * @param string $url - * @param mixed $data - * @param array $httpHeaders - * @param array|null $variables - * - * @return string - */ - public static function post($url, $data, $httpHeaders = array(), $variables = null) - { - self::prepareRequest($httpHeaders, $data, $variables); - - $response = CurlRequest::post($url, self::$postDataGraphQL, self::$httpHeaders); - - return self::processResponse($response); - } -} \ No newline at end of file diff --git a/lib/HttpRequestJson.php b/lib/HttpRequestJson.php deleted file mode 100644 index ceab78f..0000000 --- a/lib/HttpRequestJson.php +++ /dev/null @@ -1,142 +0,0 @@ - - * Created at: 8/24/16 9:03 AM UTC+06:00 - */ - -namespace PHPShopify; - -/** - * Class HttpRequestJson - * - * Prepare the data / headers for JSON requests, make the call and decode the response - * Accepts data in array format returns data in array format - * - * @uses CurlRequest - * - * @package PHPShopify - */ -class HttpRequestJson -{ - - /** - * HTTP request headers - * - * @var array - */ - protected static $httpHeaders; - - /** - * Prepared JSON string to be posted with request - * - * @var string - */ - private static $postDataJSON; - - - /** - * Prepare the data and request headers before making the call - * - * @param array $httpHeaders - * @param array $dataArray - * - * @return void - */ - protected static function prepareRequest($httpHeaders = array(), $dataArray = array()) - { - - self::$postDataJSON = json_encode($dataArray); - - self::$httpHeaders = $httpHeaders; - - if (!empty($dataArray)) { - self::$httpHeaders['Content-type'] = 'application/json'; - self::$httpHeaders['Content-Length'] = strlen(self::$postDataJSON); - } - } - - /** - * Implement a GET request and return json decoded output - * - * @param string $url - * @param array $httpHeaders - * - * @return array - */ - public static function get($url, $httpHeaders = array()) - { - self::prepareRequest($httpHeaders); - - $response = CurlRequest::get($url, self::$httpHeaders); - - return self::processResponse($response); - } - - /** - * Implement a POST request and return json decoded output - * - * @param string $url - * @param array $dataArray - * @param array $httpHeaders - * - * @return array - */ - public static function post($url, $dataArray, $httpHeaders = array()) - { - self::prepareRequest($httpHeaders, $dataArray); - - $response = CurlRequest::post($url, self::$postDataJSON, self::$httpHeaders); - - return self::processResponse($response); - } - - /** - * Implement a PUT request and return json decoded output - * - * @param string $url - * @param array $dataArray - * @param array $httpHeaders - * - * @return array - */ - public static function put($url, $dataArray, $httpHeaders = array()) - { - self::prepareRequest($httpHeaders, $dataArray); - - $response = CurlRequest::put($url, self::$postDataJSON, self::$httpHeaders); - - return self::processResponse($response); - } - - /** - * Implement a DELETE request and return json decoded output - * - * @param string $url - * @param array $httpHeaders - * - * @return array - */ - public static function delete($url, $httpHeaders = array()) - { - self::prepareRequest($httpHeaders); - - $response = CurlRequest::delete($url, self::$httpHeaders); - - return self::processResponse($response); - } - - /** - * Decode JSON response - * - * @param string $response - * - * @return array - */ - protected static function processResponse($response) - { - - return json_decode($response, true); - } - -} \ No newline at end of file diff --git a/lib/InventoryItem.php b/lib/InventoryItem.php deleted file mode 100644 index 7f55df9..0000000 --- a/lib/InventoryItem.php +++ /dev/null @@ -1,15 +0,0 @@ - - * Created at 04/15/18 02:25 PM UTC+03:00 - * - * @see https://help.shopify.com/api/reference/inventoryitem - */ - -namespace PHPShopify; - -class InventoryItem extends ShopifyResource -{ - /** @inheritDoc */ - protected $resourceKey = 'inventory_item'; -} diff --git a/lib/Location.php b/lib/Location.php deleted file mode 100644 index f4a589a..0000000 --- a/lib/Location.php +++ /dev/null @@ -1,36 +0,0 @@ - - * Created at 8/19/16 5:47 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/location Shopify API Reference for Location - */ - -namespace PHPShopify; - - -class Location extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'location'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - public $readOnly = true; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'InventoryLevel', - ); -} \ No newline at end of file diff --git a/lib/Metafield.php b/lib/Metafield.php deleted file mode 100644 index 95d0853..0000000 --- a/lib/Metafield.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 5:51 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/metafield Shopify API Reference for Metafield - */ - -namespace PHPShopify; - - -class Metafield extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'metafield'; -} \ No newline at end of file diff --git a/lib/Multipass.php b/lib/Multipass.php deleted file mode 100644 index 51e542d..0000000 --- a/lib/Multipass.php +++ /dev/null @@ -1,29 +0,0 @@ - - * Created at 8/19/16 6:05 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/multipass Shopify API Reference for Multipass - */ - -namespace PHPShopify; - - -use PHPShopify\Exception\ApiException; - -class Multipass extends ShopifyResource -{ - - /** - * Multipass constructor. - * - * @param integer $id - * - * @throws ApiException - */ - public function __construct($id = null) - { - throw new ApiException("Multipass API is not available yet!"); - } -} \ No newline at end of file diff --git a/lib/Order.php b/lib/Order.php deleted file mode 100644 index 98efd2a..0000000 --- a/lib/Order.php +++ /dev/null @@ -1,67 +0,0 @@ - - * Created at 8/19/16 2:59 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/order Shopify API Reference for Order - */ - -namespace PHPShopify; - - - -/** - * -------------------------------------------------------------------------- - * Order -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Fulfillment $Fulfillment - * @property-read OrderRisk $Risk - * @property-read Refund $Refund - * @property-read Transaction $Transaction - * @property-read Event $Event - * @property-read Metafield $Metafield - * - * @method Fulfillment Fulfillment(integer $id = null) - * @method OrderRisk Risk(integer $id = null) - * @method Refund Refund(integer $id = null) - * @method Transaction Transaction(integer $id = null) - * @method Event Event(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * - * -------------------------------------------------------------------------- - * Order -> Custom actions - * -------------------------------------------------------------------------- - * @method array close() Close an Order - * @method array open() Re-open a closed Order - * @method array cancel(array $data) Cancel an Order - * - */ -class Order extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'order'; - - /** - * @inheritDoc - */ - protected $childResource = array ( - 'Fulfillment', - 'OrderRisk' => 'Risk', - 'Refund', - 'Transaction', - 'Event', - 'Metafield', - ); - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'close', - 'open', - 'cancel', - ); -} \ No newline at end of file diff --git a/lib/OrderRisk.php b/lib/OrderRisk.php deleted file mode 100644 index 9281b7b..0000000 --- a/lib/OrderRisk.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 6:10 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/order_risks Shopify API Reference for Order Risks - */ - -namespace PHPShopify; - - -class OrderRisk extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'risk'; -} \ No newline at end of file diff --git a/lib/Page.php b/lib/Page.php deleted file mode 100644 index 7b01ca0..0000000 --- a/lib/Page.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Created at 8/17/16 10:39 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/page Shopify API Reference for Page - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Page -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * @property-read Metafield $Metafield - * - * @method Event Event(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * - */ -class Page extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'page'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Event', - 'Metafield', - ); -} \ No newline at end of file diff --git a/lib/Policy.php b/lib/Policy.php deleted file mode 100644 index 53598c8..0000000 --- a/lib/Policy.php +++ /dev/null @@ -1,37 +0,0 @@ - - * Created at 8/19/16 6:22 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/policy Shopify API Reference for Policy - */ - -namespace PHPShopify; - - -class Policy extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'policy'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - public $readOnly = true; - - /** - * @inheritDoc - */ - public function pluralizeKey() - { - return 'policies'; - } -} \ No newline at end of file diff --git a/lib/PriceRule.php b/lib/PriceRule.php deleted file mode 100644 index de08014..0000000 --- a/lib/PriceRule.php +++ /dev/null @@ -1,40 +0,0 @@ - - * Created at 5/06/19 2:06 AM UTC+03:00 - * - * @see https://help.shopify.com/api/reference/discounts/pricerule Shopify API Reference for PriceRule - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * PriceRule -> Child Resources - * -------------------------------------------------------------------------- - * @property-read ShopifyResource $DiscountCode - * - * @method ShopifyResource DiscountCode(integer $id = null) - * - */ -class PriceRule extends ShopifyResource -{ - /** - * @inheritDoc - */ - public $resourceKey = 'price_rule'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'DiscountCode' - ); -} \ No newline at end of file diff --git a/lib/Product.php b/lib/Product.php deleted file mode 100644 index f866d32..0000000 --- a/lib/Product.php +++ /dev/null @@ -1,44 +0,0 @@ - - * Created at 8/18/16 10:46 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/product Shopify API Reference for Product - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Product -> Child Resources - * -------------------------------------------------------------------------- - * @property-read ProductImage $Image - * @property-read ProductVariant $Variant - * @property-read Metafield $Metafield - * @property-read Event $Event - * - * @method ProductImage Image(integer $id = null) - * @method ProductVariant Variant(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * @method Event Event(integer $id = null) - * - */ -class Product extends ShopifyResource -{ - /** - * @inheritDoc - */ - public $resourceKey = 'product'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'ProductImage' => 'Image', - 'ProductVariant' => 'Variant', - 'Metafield', - 'Event' - ); -} \ No newline at end of file diff --git a/lib/ProductImage.php b/lib/ProductImage.php deleted file mode 100644 index 5ba26cd..0000000 --- a/lib/ProductImage.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/18/16 1:35 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/product_image Shopify API Reference for Product Image - */ - -namespace PHPShopify; - - -class ProductImage extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'image'; -} \ No newline at end of file diff --git a/lib/ProductListing.php b/lib/ProductListing.php deleted file mode 100644 index 912a25f..0000000 --- a/lib/ProductListing.php +++ /dev/null @@ -1,26 +0,0 @@ - - * Created at: 6/2/18 1:38 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/sales_channels/productlisting Shopify API Reference for Shipping Zone - */ - -namespace PHPShopify; - - -class ProductListing extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'product_listing'; - - /** - * @inheritDoc - */ - protected $customGetActions = array ( - 'product_ids' => 'productIds', - ); -} \ No newline at end of file diff --git a/lib/ProductVariant.php b/lib/ProductVariant.php deleted file mode 100644 index fd34066..0000000 --- a/lib/ProductVariant.php +++ /dev/null @@ -1,40 +0,0 @@ - - * Created at 8/18/16 1:50 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/product_variant Shopify API Reference for Product Variant - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * ProductVariant -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Metafield $Metafield - * - * @method Metafield Metafield(integer $id = null) - * - */ -class ProductVariant extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'variant'; - - /** - * @inheritDoc - */ - public $searchEnabled = true; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Metafield', - ); -} \ No newline at end of file diff --git a/lib/Province.php b/lib/Province.php deleted file mode 100644 index efc0cf2..0000000 --- a/lib/Province.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 6:25 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/province Shopify API Reference for Province - */ - -namespace PHPShopify; - - -class Province extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'province'; -} \ No newline at end of file diff --git a/lib/RecurringApplicationCharge.php b/lib/RecurringApplicationCharge.php deleted file mode 100644 index 4ec74a9..0000000 --- a/lib/RecurringApplicationCharge.php +++ /dev/null @@ -1,69 +0,0 @@ - - * Created at 8/19/16 6:30 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/recurringapplicationcharge Shopify API Reference for RecurringApplicationCharge - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * RecurringApplicationCharge -> Child Resources - * -------------------------------------------------------------------------- - * @property-read UsageCharge $UsageCharge - * - * @method UsageCharge UsageCharge(integer $id = null) - * - * -------------------------------------------------------------------------- - * RecurringApplicationCharge -> Custom actions - * -------------------------------------------------------------------------- - * @method array activate() Activate a recurring application charge - * - */ -class RecurringApplicationCharge extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'recurring_application_charge'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'UsageCharge', - ); - - /** - * @inheritDoc - */ - protected $customPostActions = array( - 'activate', - ); - - /* - * Customize a recurring application charge - * - * @param array $data - * - * @return array - * - */ - public function customize($dataArray) - { - $dataArray = $this->wrapData($dataArray); - - $url = $this->generateUrl($dataArray, 'customize'); - - return $this->put(array(), $url); - } -} \ No newline at end of file diff --git a/lib/Redirect.php b/lib/Redirect.php deleted file mode 100644 index 85cc643..0000000 --- a/lib/Redirect.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 7:13 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/redirect Shopify API Reference for Redirect - */ - -namespace PHPShopify; - - -class Redirect extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'redirect'; -} \ No newline at end of file diff --git a/lib/Refund.php b/lib/Refund.php deleted file mode 100644 index c91edbe..0000000 --- a/lib/Refund.php +++ /dev/null @@ -1,33 +0,0 @@ - - * Created at 8/19/16 7:19 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/refund Shopify API Reference for Refund - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Refund -> Custom actions - * -------------------------------------------------------------------------- - * @method array calculate() Calculate a Refund. - * - */ -class Refund extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'refund'; - - /** - * @inheritDoc - */ - protected $customPostActions = array ( - 'calculate', - ); -} \ No newline at end of file diff --git a/lib/Report.php b/lib/Report.php deleted file mode 100644 index 8a646cc..0000000 --- a/lib/Report.php +++ /dev/null @@ -1,16 +0,0 @@ - - * Created at 8/17/16 4:46 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/scripttag Shopify API Reference for ScriptTag - */ - -namespace PHPShopify; - - -class ScriptTag extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'script_tag'; -} \ No newline at end of file diff --git a/lib/ShippingZone.php b/lib/ShippingZone.php deleted file mode 100644 index 5f9cc76..0000000 --- a/lib/ShippingZone.php +++ /dev/null @@ -1,29 +0,0 @@ - - * Created at 8/19/16 7:36 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/shipping_zone Shopify API Reference for Shipping Zone - */ - -namespace PHPShopify; - - -class ShippingZone extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'shipping_zone'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - public $readOnly = true; -} \ No newline at end of file diff --git a/lib/Shop.php b/lib/Shop.php deleted file mode 100644 index 58a86df..0000000 --- a/lib/Shop.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Created at 8/19/16 10:42 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/shop Shopify API Reference for Shop - */ - -namespace PHPShopify; - - -class Shop extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'shop'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - public $readOnly = true; - - /** - * @inheritDoc - */ - public function pluralizeKey() - { - //Only one shop object for each store. So no pluralize - return 'shop'; - } -} \ No newline at end of file diff --git a/lib/ShopifyResource.php b/lib/ShopifyResource.php index f9940be..b2cfda1 100644 --- a/lib/ShopifyResource.php +++ b/lib/ShopifyResource.php @@ -1,9 +1,5 @@ - * Created at 8/17/16 3:14 PM UTC+06:00 - * * @see https://help.shopify.com/api/reference Shopify API Reference */ @@ -12,31 +8,16 @@ use PHPShopify\Exception\ApiException; use PHPShopify\Exception\SdkException; use PHPShopify\Exception\CurlException; -use Psr\Http\Message\ResponseInterface; - -/* -|-------------------------------------------------------------------------- -| Shopify API SDK Base Class -|-------------------------------------------------------------------------- -| -| This class handles get, post, put, delete and any other custom actions for the API -| -*/ -abstract class ShopifyResource -{ - /** - * HTTP request headers - * - * @var array - */ - protected $httpHeaders = array(); +use PHPShopify\Http\HttpRequestJson; +use PHPShopify\Http\CurlResponse; +abstract class ShopifyResource { /** - * HTTP response headers of last executed request + * HTTP request headers * * @var array */ - public static $lastHttpResponseHeaders = array(); + protected $httpHeaders = []; /** * The base URL of the API Resource (excluding the '.json' extension). @@ -62,7 +43,7 @@ abstract class ShopifyResource * * @var array */ - protected $childResource = array(); + protected $childResource = []; /** * If search is enabled for the resource @@ -99,10 +80,10 @@ abstract class ShopifyResource * @var array $customPutActions * @var array $customDeleteActions */ - protected $customGetActions = array(); - protected $customPostActions = array(); - protected $customPutActions = array(); - protected $customDeleteActions = array(); + protected $customGetActions = []; + protected $customPostActions = []; + protected $customPutActions = []; + protected $customDeleteActions = []; /** * The ID of the resource @@ -122,25 +103,13 @@ abstract class ShopifyResource * @throws SdkException if Either AccessToken or ApiKey+Password Combination is not found in configuration */ - /** - * Response Header Link, used for pagination - * @see: https://help.shopify.com/en/api/guides/paginated-rest-results?utm_source=exacttarget&utm_medium=email&utm_campaign=api_deprecation_notice_1908 - * @var string $nextLink - */ - private $nextLink = null; - - /** - * Response Header Link, used for pagination - * @see: https://help.shopify.com/en/api/guides/paginated-rest-results?utm_source=exacttarget&utm_medium=email&utm_campaign=api_deprecation_notice_1908 - * @var string $prevLink - */ - private $prevLink = null; + /** @var ShopifySDK */ + protected $sdk; - public function __construct($id = null, $parentResourceUrl = '') - { + public function __construct(ShopifySdk $sdk, $id = null, $parentResourceUrl = '') { $this->id = $id; - - $config = ShopifySDK::$config; + $this->sdk = $sdk; + $config = $sdk->getConfig(); $this->resourceUrl = ($parentResourceUrl ? $parentResourceUrl . '/' : $config['ApiUrl']) . $this->getResourcePath() . ($this->id ? '/' . $this->id : ''); @@ -161,8 +130,7 @@ public function __construct($id = null, $parentResourceUrl = '') * * @return ShopifyResource */ - public function __get($childName) - { + public function __get($childName) { return $this->$childName(); } @@ -182,64 +150,44 @@ public function __get($childName) * * @return mixed / ShopifyResource */ - public function __call($name, $arguments) - { - //If the $name starts with an uppercase letter, it's considered as a child class - //Otherwise it's a custom action + public function __call($name, $arguments) { if (ctype_upper($name[0])) { - //Get the array key of the childResource in the childResource array - $childKey = array_search($name, $this->childResource); + $childKey = array_search($name, $this->childResource, true); if ($childKey === false) { throw new SdkException("Child Resource $name is not available for " . $this->getResourceName()); } - //If any associative key is given to the childname, then it will be considered as the class name, - //otherwise the childname will be the class name $childClassName = !is_numeric($childKey) ? $childKey : $name; - $childClass = __NAMESPACE__ . "\\" . $childClassName; - - //If first argument is provided, it will be considered as the ID of the resource. - $resourceID = !empty($arguments) ? $arguments[0] : null; + return $this->sdk->createResource($childClassName, $arguments, $this->resourceUrl); + } else { + $actionMaps = [ + 'post' => $this->customPostActions, + 'put' => $this->customPutActions, + 'get' => $this->customGetActions, + 'delete'=> $this->customDeleteActions, + ]; + $actionKey = false; - $api = new $childClass($resourceID, $this->resourceUrl); + foreach ($actionMaps as $httpMethod => $actions) { + $actionKey = array_search($name, $actions, true); - return $api; - } else { - $actionMaps = array( - 'post' => 'customPostActions', - 'put' => 'customPutActions', - 'get' => 'customGetActions', - 'delete'=> 'customDeleteActions', - ); - - //Get the array key for the action in the actions array - foreach ($actionMaps as $httpMethod => $actionArrayKey) { - $actionKey = array_search($name, $this->$actionArrayKey); - if ($actionKey !== false) break; + if ($actionKey !== false) { + break; + } } if ($actionKey === false) { throw new SdkException("No action named $name is defined for " . $this->getResourceName()); } - //If any associative key is given to the action, then it will be considered as the method name, - //otherwise the action name will be the method name $customAction = !is_numeric($actionKey) ? $actionKey : $name; + $methodArgument = !empty($arguments) ? $arguments[0] : []; + $urlParams = $dataArray = []; - //Get the first argument if provided with the method call - $methodArgument = !empty($arguments) ? $arguments[0] : array(); - - //Url parameters - $urlParams = array(); - //Data body - $dataArray = array(); - - //Consider the argument as url parameters for get and delete request - //and data array for post and put request if ($httpMethod == 'post' || $httpMethod == 'put') { $dataArray = $methodArgument; } else { @@ -250,19 +198,16 @@ public function __call($name, $arguments) if ($httpMethod == 'post' || $httpMethod == 'put') { return $this->$httpMethod($dataArray, $url, false); - } else { - return $this->$httpMethod($dataArray, $url); } + + return $this->$httpMethod($dataArray, $url); } } /** * Get the resource name (or the class name) - * - * @return string */ - public function getResourceName() - { + public function getResourceName(): string { return substr(get_called_class(), strrpos(get_called_class(), '\\') + 1); } @@ -270,11 +215,8 @@ public function getResourceName() * Get the resource key to be used for while sending data to the API * * Normally its the same as $resourceKey, when it's different, the specific resource class will override this function - * - * @return string */ - public function getResourcePostKey() - { + public function getResourcePostKey(): string { return $this->resourceKey; } @@ -282,11 +224,8 @@ public function getResourcePostKey() * Get the pluralized version of the resource key * * Normally its the same as $resourceKey appended with 's', when it's different, the specific resource class will override this function - * - * @return string */ - protected function pluralizeKey() - { + protected function pluralizeKey(): string { return $this->resourceKey . 's'; } @@ -295,317 +234,204 @@ protected function pluralizeKey() * * Normally its the same as the pluralized version of the resource key, * when it's different, the specific resource class will override this function - * - * @return string */ - protected function getResourcePath() - { + protected function getResourcePath(): string { return $this->pluralizeKey(); } /** * Generate the custom url for api request based on the params and custom action (if any) - * - * @param array $urlParams - * @param string $customAction - * - * @return string */ - public function generateUrl($urlParams = array(), $customAction = null) - { - return $this->resourceUrl . ($customAction ? "/$customAction" : '') . '.json' . (!empty($urlParams) ? '?' . http_build_query($urlParams) : ''); + public function generateUrl(array $urlParams = [], ?string $customAction = null): string { + return $this->resourceUrl . ($customAction ? "/{$customAction}" : '') . '.json' . (!empty($urlParams) ? '?' . http_build_query($urlParams) : ''); } - /** - * Generate a HTTP GET request and return results as an array - * - * @param array $urlParams Check Shopify API reference of the specific resource for the list of URL parameters - * @param string $url - * @param string $dataKey Keyname to fetch data from response array - * - * @uses HttpRequestJson::get() to send the HTTP request - * - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return array - */ - public function get($urlParams = array(), $url = null, $dataKey = null) - { - if (!$url) $url = $this->generateUrl($urlParams); + public function get(array $urlParams = [], ?string $url = null, $dataKey = null) { + if (!$url) { + $url = $this->generateUrl($urlParams); + } - $response = HttpRequestJson::get($url, $this->httpHeaders); + $response = $this->sdk->getHttpRequestJson()->get($url, $this->httpHeaders); - if (!$dataKey) $dataKey = $this->id ? $this->resourceKey : $this->pluralizeKey(); + if (!$dataKey) { + $dataKey = $this->id ? $this->resourceKey : $this->pluralizeKey(); + } return $this->processResponse($response, $dataKey); + } + + public function each(array $urlParams = [], ?string $url = null, $dataKey = null): \Generator { + if (!$url) { + $url = $this->generateUrl($urlParams); + } + + if (!$dataKey) { + $dataKey = $this->id ? $this->resourceKey : $this->pluralizeKey(); + } + + while ($url !== null) { + $response = $this->sdk->getHttpRequestJson()->get($url, $this->httpHeaders); + + $data = $response->getBody(); + + if ($data === null || !count($data)) { + break; + } + + yield $this->processResponse($response, $dataKey); + $url = self::getLinks($response)['next'] ?? null; + } } - /** - * Get count for the number of resources available - * - * @param array $urlParams Check Shopify API reference of the specific resource for the list of URL parameters - * - * @throws SdkException - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return integer - */ - public function count($urlParams = array()) - { + public function count($urlParams = []) { if (!$this->countEnabled) { throw new SdkException("Count is not available for " . $this->getResourceName()); } $url = $this->generateUrl($urlParams, 'count'); - return $this->get(array(), $url, 'count'); + return $this->get([], $url, 'count'); } - /** - * Search within the resouce - * - * @param mixed $query - * - * @throws SdkException if search is not enabled for the resouce - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return array - */ - public function search($query) - { + public function search($query) { if (!$this->searchEnabled) { throw new SdkException("Search is not available for " . $this->getResourceName()); } - if (!is_array($query)) $query = array('query' => $query); + if (!is_array($query)) { + $query = ['query' => $query]; + } $url = $this->generateUrl($query, 'search'); - return $this->get(array(), $url); + return $this->get([], $url); } - /** - * Call POST method to create a new resource - * - * @param array $dataArray Check Shopify API reference of the specific resource for the list of required and optional data elements to be provided - * @param string $url - * @param bool $wrapData - * - * @uses HttpRequestJson::post() to send the HTTP request - * - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return array - */ - public function post($dataArray, $url = null, $wrapData = true) - { - if (!$url) $url = $this->generateUrl(); + public function post(?array $dataArray, ?string $url = null, bool $wrapData = true) { + if (!$url) { + $url = $this->generateUrl(); + } - if ($wrapData && !empty($dataArray)) $dataArray = $this->wrapData($dataArray); + if ($wrapData && $dataArray !== null) { + $dataArray = $this->wrapData($dataArray); + } - $response = HttpRequestJson::post($url, $dataArray, $this->httpHeaders); + $response = $this->sdk->getHttpRequestJson()->post($url, $dataArray, $this->httpHeaders); return $this->processResponse($response, $this->resourceKey); } - /** - * Call PUT method to update an existing resource - * - * @param array $dataArray Check Shopify API reference of the specific resource for the list of required and optional data elements to be provided - * @param string $url - * @param bool $wrapData - * - * @uses HttpRequestJson::put() to send the HTTP request - * - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return array - */ - public function put($dataArray, $url = null, $wrapData = true) - { - - if (!$url) $url = $this->generateUrl(); + public function put(array $dataArray, ?string $url = null, bool $wrapData = true): array { + if (!$url) { + $url = $this->generateUrl(); + } - if ($wrapData && !empty($dataArray)) $dataArray = $this->wrapData($dataArray); + if ($wrapData && !empty($dataArray)) { + $dataArray = $this->wrapData($dataArray); + } - $response = HttpRequestJson::put($url, $dataArray, $this->httpHeaders); + $response = $this->sdk->getHttpRequestJson()->put($url, $dataArray, $this->httpHeaders); return $this->processResponse($response, $this->resourceKey); } - /** - * Call DELETE method to delete an existing resource - * - * @param array $urlParams Check Shopify API reference of the specific resource for the list of URL parameters - * @param string $url - * - * @uses HttpRequestJson::delete() to send the HTTP request - * - * @throws ApiException if the response has an error specified - * @throws CurlException if response received with unexpected HTTP code. - * - * @return array an empty array will be returned if the request is successfully completed - */ - public function delete($urlParams = array(), $url = null) - { - if (!$url) $url = $this->generateUrl($urlParams); + public function delete(array $urlParams = [], ?string $url = null): void { + if (!$url) { + $url = $this->generateUrl($urlParams); + } - $response = HttpRequestJson::delete($url, $this->httpHeaders); + $response = $this->sdk->getHttpRequestJson()->delete($url, $this->httpHeaders); + $response = $this->processResponse($response); - return $this->processResponse($response); + if ($response !== null) { + throw new SdkException('Unexpected API response on delete: ' . HttpRequestJson::encode($response)); + } } - /** - * Wrap data array with resource key - * - * @param array $dataArray - * @param string $dataKey - * - * @return array - */ - protected function wrapData($dataArray, $dataKey = null) - { - if (!$dataKey) $dataKey = $this->getResourcePostKey(); + protected function wrapData(array $dataArray, $dataKey = null): array { + if (!$dataKey) { + $dataKey = $this->getResourcePostKey(); + } - return array($dataKey => $dataArray); + return [$dataKey => $dataArray]; } - /** - * Convert an array to string - * - * @param array $array - * - * @internal - * - * @return string - */ - protected function castString($array) - { - if ( ! is_array($array)) return (string) $array; + protected static function castString($array): string { + if (!is_array($array)) { + return (string)$array; + } $string = ''; $i = 0; + foreach ($array as $key => $val) { - //Add values separated by comma - //prepend the key string, if it's an associative key - //Check if the value itself is another array to be converted to string - $string .= ($i === $key ? '' : "$key - ") . $this->castString($val) . ', '; + $string .= ($i === $key ? '' : "$key - ") . self::castString($val) . ', '; $i++; } - //Remove trailing comma and space $string = rtrim($string, ', '); return $string; } /** - * Process the request response - * - * @param array $responseArray Request response in array format - * @param string $dataKey Keyname to fetch data from response array - * + * @inheritDoc * @throws ApiException if the response has an error specified * @throws CurlException if response received with unexpected HTTP code. - * - * @return array */ - public function processResponse($responseArray, $dataKey = null) - { - self::$lastHttpResponseHeaders = CurlRequest::$lastHttpResponseHeaders; + protected static function validateResponse(CurlResponse $response) { + $body = $response->getBody(); - if ($responseArray === null) { - //Something went wrong, Checking HTTP Codes - $httpOK = 200; //Request Successful, OK. - $httpCreated = 201; //Create Successful. + if ($body === null) { + $httpOK = 200; + $httpCreated = 201; + $httpCode = $response->getStatus(); - //should be null if any other library used for http calls - $httpCode = CurlRequest::$lastHttpCode; - - if ($httpCode != null && $httpCode != $httpOK && $httpCode != $httpCreated) { + if ($httpCode !== $httpOK && $httpCode !== $httpCreated) { throw new Exception\CurlException("Request failed with HTTP Code $httpCode."); } } - $lastResponseHeaders = CurlRequest::$lastHttpResponseHeaders; - $this->getLinks($lastResponseHeaders); - - if (isset($responseArray['errors'])) { - $message = $this->castString($responseArray['errors']); + if (isset($body['errors'])) { + $message = self::castString($body['errors']); - throw new ApiException($message, CurlRequest::$lastHttpCode); + ApiException::factory($message, $response->getStatus()); } - if ($dataKey && isset($responseArray[$dataKey])) { - return $responseArray[$dataKey]; - } else { - return $responseArray; - } + return $body; } - public function getLinks($responseHeaders){ - $this->nextLink = $this->getLink($responseHeaders,'next'); - $this->prevLink = $this->getLink($responseHeaders,'previous'); + protected function processResponse(CurlResponse $response, $dataKey = null) { + $body = self::validateResponse($response); + + if ($dataKey !== null) { + return $body[$dataKey] ?? null; + } + + return $body; } - public function getLink($responseHeaders, $type='next'){ + protected static function getLinks(CurlResponse $response): ?array { + $linkHeader = $response->getHeader('link'); - if(array_key_exists('x-shopify-api-version', $responseHeaders) - && $responseHeaders['x-shopify-api-version'] < '2019-07'){ + if ($linkHeader === null) { return null; } - if(!empty($responseHeaders['link'])) { - if (stristr($responseHeaders['link'], '; rel="'.$type.'"') > -1) { - $headerLinks = explode(',', $responseHeaders['link']); - foreach ($headerLinks as $headerLink) { - if (stristr($headerLink, '; rel="'.$type.'"') === -1) { - continue; - } - - $pattern = '#<(.*?)>; rel="'.$type.'"#m'; - preg_match($pattern, $headerLink, $linkResponseHeaders); - if ($linkResponseHeaders) { - return $linkResponseHeaders[1]; - } - } - } - } - - return null; - } + $links = []; - public function getPrevLink(){ - return $this->prevLink; - } - - public function getNextLink(){ - return $this->nextLink; - } + foreach (explode(', ', $linkHeader) as $headerLink) { + if (preg_match('/^<(.*?)>; rel="([^"]+)"/D', $headerLink, $matches)) { + $type = $matches[2]; + assert(in_array($type, ['next', 'previous'], true)); + assert(!array_key_exists($type, $links[$type])); + $links[$type] = $matches[1]; + } - public function getUrlParams($url) { - if ($url) { - $parts = parse_url($url); - return $parts['query']; + assert(false); } - return ''; - } - - public function getNextPageParams(){ - $nextPageParams = []; - parse_str($this->getUrlParams($this->getNextLink()), $nextPageParams); - return $nextPageParams; - } - public function getPrevPageParams(){ - $nextPageParams = []; - parse_str($this->getUrlParams($this->getPrevLink()), $nextPageParams); - return $nextPageParams; + return count($links) ? $links : null; } } diff --git a/lib/ShopifyResource/AbandonedCheckout.php b/lib/ShopifyResource/AbandonedCheckout.php new file mode 100644 index 0000000..b2f3837 --- /dev/null +++ b/lib/ShopifyResource/AbandonedCheckout.php @@ -0,0 +1,12 @@ + 'markSpam', + 'not_spam' => 'markNotSpam', + 'approve', + 'remove', + 'restore' + ]; +} diff --git a/lib/ShopifyResource/Country.php b/lib/ShopifyResource/Country.php new file mode 100644 index 0000000..b80f8d1 --- /dev/null +++ b/lib/ShopifyResource/Country.php @@ -0,0 +1,23 @@ + 'Address', + 'Metafield', + 'Order' + ]; + + public function send_invite(array $customer_invite = []): array { + if (empty ( $customer_invite ) ) $customer_invite = new \stdClass(); + $url = $this->generateUrl([], 'send_invite'); + $dataArray = $this->wrapData($customer_invite, 'customer_invite'); + + return $this->post($dataArray, $url, false); + } +} diff --git a/lib/ShopifyResource/CustomerAddress.php b/lib/ShopifyResource/CustomerAddress.php new file mode 100644 index 0000000..8421d83 --- /dev/null +++ b/lib/ShopifyResource/CustomerAddress.php @@ -0,0 +1,34 @@ + 'makeDefault' + ]; + + protected function pluralizeKey(): string { + return 'addresses'; + } + + /** + * Perform bulk operations against a number of addresses + * Issue (Getting Error from API) : Internal server error + * @param array $params + * @return array + */ + public function set(array $params): array { + $url = $this->generateUrl($params, 'set'); + + return $this->put([], $url); + } +} diff --git a/lib/ShopifyResource/CustomerSavedSearch.php b/lib/ShopifyResource/CustomerSavedSearch.php new file mode 100644 index 0000000..57366ad --- /dev/null +++ b/lib/ShopifyResource/CustomerSavedSearch.php @@ -0,0 +1,23 @@ + 'Event' + ]; + protected $customPostActions = [ + 'complete', + 'open', + 'cancel' + ]; +} diff --git a/lib/ShopifyResource/FulfillmentEvent.php b/lib/ShopifyResource/FulfillmentEvent.php new file mode 100644 index 0000000..3050b5f --- /dev/null +++ b/lib/ShopifyResource/FulfillmentEvent.php @@ -0,0 +1,19 @@ +generateUrl([], 'disable'); + + $dataArray = [ + 'id' => $this->id + ]; + + return $this->post($dataArray, $url); + } +} diff --git a/lib/ShopifyResource/GraphQL.php b/lib/ShopifyResource/GraphQL.php new file mode 100644 index 0000000..28172ca --- /dev/null +++ b/lib/ShopifyResource/GraphQL.php @@ -0,0 +1,73 @@ +generateUrl(); + } + + $httpHeaders = $this->httpHeaders; + + if (!isset($httpHeaders['X-Shopify-Access-Token'])) { + throw new SdkException("The GraphQL Admin API requires an access token for making authenticated requests!"); + } + + if (is_array($variables)) { + $httpHeaders['Content-type'] = 'application/json'; + $data = json_encode(['query' => $graphQL, 'variables' => $variables]); + } else { + $httpHeaders['Content-type'] = 'application/graphql'; + $data = $graphQL; + } + + return $this->processResponse($this->sdk->getHttpRequestJson()->post($url, $data, $this->httpHeaders)); + } + + /** + * @inheritdoc + * @throws SdkException + */ + public function get(array $urlParams = [], ?string $url = null, $dataKey = null) { + throw new SdkException("Only POST method is allowed for GraphQL!"); + } + + /** + * @inheritdoc + * @throws SdkException + */ + public function put(array $dataArray, ?string $url = null, bool $wrapData = true): array { + throw new SdkException("Only POST method is allowed for GraphQL!"); + } + + /** + * @inheritdoc + * @throws SdkException + */ + public function delete(array $urlParams = [], ?string $url = null): void { + throw new SdkException("Only POST method is allowed for GraphQL!"); + } +} diff --git a/lib/ShopifyResource/InventoryItem.php b/lib/ShopifyResource/InventoryItem.php new file mode 100644 index 0000000..abf87e2 --- /dev/null +++ b/lib/ShopifyResource/InventoryItem.php @@ -0,0 +1,12 @@ + - * Created at 04/15/18 02:31 PM UTC+03:00 - * * @see https://help.shopify.com/api/reference/inventorylevel */ -namespace PHPShopify; +namespace PHPShopify\ShopifyResource; + +use PHPShopify\ShopifyResource; /** - * Class InventoryLevel - * * @method array adjust($data) Adjust inventory level. * @method array connect($data) Connect an inventory item to a location. * @method array set($data) Sets an inventory level for a single inventory item within a location. */ -class InventoryLevel extends ShopifyResource -{ - /** @inheritDoc */ +class InventoryLevel extends ShopifyResource { protected $resourceKey = 'inventory_level'; - - /** @inheritDoc */ protected $customPostActions = [ 'adjust', 'connect', - 'set', + 'set' ]; } diff --git a/lib/ShopifyResource/Location.php b/lib/ShopifyResource/Location.php new file mode 100644 index 0000000..857f0a7 --- /dev/null +++ b/lib/ShopifyResource/Location.php @@ -0,0 +1,17 @@ + 'Risk', + 'Refund', + 'Transaction', + 'Event', + 'Metafield' + ]; + protected $customPostActions = [ + 'close', + 'open', + 'cancel' + ]; +} diff --git a/lib/ShopifyResource/OrderRisk.php b/lib/ShopifyResource/OrderRisk.php new file mode 100644 index 0000000..83f1267 --- /dev/null +++ b/lib/ShopifyResource/OrderRisk.php @@ -0,0 +1,12 @@ + 'Image', + 'ProductVariant' => 'Variant', + 'Metafield', + 'Event' + ]; +} diff --git a/lib/ShopifyResource/ProductImage.php b/lib/ShopifyResource/ProductImage.php new file mode 100644 index 0000000..1ce0050 --- /dev/null +++ b/lib/ShopifyResource/ProductImage.php @@ -0,0 +1,12 @@ + 'productIds' + ]; +} diff --git a/lib/ShopifyResource/ProductVariant.php b/lib/ShopifyResource/ProductVariant.php new file mode 100644 index 0000000..e0b081d --- /dev/null +++ b/lib/ShopifyResource/ProductVariant.php @@ -0,0 +1,21 @@ +wrapData($dataArray); + + $url = $this->generateUrl($dataArray, 'customize'); + + return $this->put([], $url); + } +} diff --git a/lib/ShopifyResource/Redirect.php b/lib/ShopifyResource/Redirect.php new file mode 100644 index 0000000..e3ace6f --- /dev/null +++ b/lib/ShopifyResource/Redirect.php @@ -0,0 +1,12 @@ +generateUrl($params, 'order'); + + return $this->put([], $url); + } +} diff --git a/lib/ShopifyResource/Theme.php b/lib/ShopifyResource/Theme.php new file mode 100644 index 0000000..0d5093d --- /dev/null +++ b/lib/ShopifyResource/Theme.php @@ -0,0 +1,20 @@ + - * Created at 8/16/16 10:42 AM UTC+06:00 - * * @see https://help.shopify.com/api/reference/ Shopify API Reference */ namespace PHPShopify; - /* |-------------------------------------------------------------------------- | Shopify API SDK Client Class @@ -64,97 +59,97 @@ | $data = $shopify->GraphQL->post($graphQL); | */ + use PHPShopify\Exception\SdkException; +use PHPShopify\Http\HttpRequestJson; /** - * @property-read AbandonedCheckout $AbandonedCheckout - * @property-read Blog $Blog - * @property-read CarrierService $CarrierService - * @property-read Collect $Collect - * @property-read Collection $Collection - * @property-read Comment $Comment - * @property-read Country $Country - * @property-read Currency $Currency - * @property-read CustomCollection $CustomCollection - * @property-read Customer $Customer - * @property-read CustomerSavedSearch $CustomerSavedSearch - * @property-read Discount $Discount - * @property-read DiscountCode $DiscountCode - * @property-read DraftOrder $DraftOrder - * @property-read PriceRule $PriceRule - * @property-read Event $Event - * @property-read FulfillmentService $FulfillmentService - * @property-read GiftCard $GiftCard - * @property-read InventoryItem $InventoryItem - * @property-read InventoryLevel $InventoryLevel - * @property-read Location $Location - * @property-read Metafield $Metafield - * @property-read Multipass $Multipass - * @property-read Order $Order - * @property-read Page $Page - * @property-read Policy $Policy - * @property-read Product $Product - * @property-read ProductListing $ProductListing - * @property-read ProductVariant $ProductVariant - * @property-read RecurringApplicationCharge $RecurringApplicationCharge - * @property-read Redirect $Redirect - * @property-read ScriptTag $ScriptTag - * @property-read ShippingZone $ShippingZone - * @property-read Shop $Shop - * @property-read SmartCollection $SmartCollection - * @property-read Theme $Theme - * @property-read User $User - * @property-read Webhook $Webhook - * @property-read GraphQL $GraphQL - * - * @method AbandonedCheckout AbandonedCheckout(integer $id = null) - * @method Blog Blog(integer $id = null) - * @method CarrierService CarrierService(integer $id = null) - * @method Collect Collect(integer $id = null) - * @method Collection Collection(integer $id = null) - * @method Comment Comment(integer $id = null) - * @method Country Country(integer $id = null) - * @method Currency Currency(integer $id = null) - * @method CustomCollection CustomCollection(integer $id = null) - * @method Customer Customer(integer $id = null) - * @method CustomerSavedSearch CustomerSavedSearch(integer $id = null) - * @method Discount Discount(integer $id = null) - * @method DraftOrder DraftOrder(integer $id = null) - * @method DiscountCode DiscountCode(integer $id = null) - * @method PriceRule PriceRule(integer $id = null) - * @method Event Event(integer $id = null) - * @method FulfillmentService FulfillmentService(integer $id = null) - * @method GiftCard GiftCard(integer $id = null) - * @method InventoryItem InventoryItem(integer $id = null) - * @method InventoryLevel InventoryLevel(integer $id = null) - * @method Location Location(integer $id = null) - * @method Metafield Metafield(integer $id = null) - * @method Multipass Multipass(integer $id = null) - * @method Order Order(integer $id = null) - * @method Page Page(integer $id = null) - * @method Policy Policy(integer $id = null) - * @method Product Product(integer $id = null) - * @method ProductListing ProductListing(integer $id = null) - * @method ProductVariant ProductVariant(integer $id = null) - * @method RecurringApplicationCharge RecurringApplicationCharge(integer $id = null) - * @method Redirect Redirect(integer $id = null) - * @method ScriptTag ScriptTag(integer $id = null) - * @method ShippingZone ShippingZone(integer $id = null) - * @method Shop Shop(integer $id = null) - * @method SmartCollection SmartCollection(integer $id = null) - * @method Theme Theme(int $id = null) - * @method User User(integer $id = null) - * @method Webhook Webhook(integer $id = null) - * @method GraphQL GraphQL() + * @property-read ShopifyResource\AbandonedCheckout $AbandonedCheckout + * @property-read ShopifyResource\Blog $Blog + * @property-read ShopifyResource\CarrierService $CarrierService + * @property-read ShopifyResource\Collect $Collect + * @property-read ShopifyResource\Collection $Collection + * @property-read ShopifyResource\Comment $Comment + * @property-read ShopifyResource\Country $Country + * @property-read ShopifyResource\Currency $Currency + * @property-read ShopifyResource\CustomCollection $CustomCollection + * @property-read ShopifyResource\Customer $Customer + * @property-read ShopifyResource\CustomerSavedSearch $CustomerSavedSearch + * @property-read ShopifyResource\Discount $Discount + * @property-read ShopifyResource\DiscountCode $DiscountCode + * @property-read ShopifyResource\DraftOrder $DraftOrder + * @property-read ShopifyResource\PriceRule $PriceRule + * @property-read ShopifyResource\Event $Event + * @property-read ShopifyResource\FulfillmentService $FulfillmentService + * @property-read ShopifyResource\GiftCard $GiftCard + * @property-read ShopifyResource\InventoryItem $InventoryItem + * @property-read ShopifyResource\InventoryLevel $InventoryLevel + * @property-read ShopifyResource\Location $Location + * @property-read ShopifyResource\Metafield $Metafield + * @property-read ShopifyResource\Multipass $Multipass + * @property-read ShopifyResource\Order $Order + * @property-read ShopifyResource\Page $Page + * @property-read ShopifyResource\Policy $Policy + * @property-read ShopifyResource\Product $Product + * @property-read ShopifyResource\ProductListing $ProductListing + * @property-read ShopifyResource\ProductVariant $ProductVariant + * @property-read ShopifyResource\RecurringApplicationCharge $RecurringApplicationCharge + * @property-read ShopifyResource\Redirect $Redirect + * @property-read ShopifyResource\ScriptTag $ScriptTag + * @property-read ShopifyResource\ShippingZone $ShippingZone + * @property-read ShopifyResource\Shop $Shop + * @property-read ShopifyResource\SmartCollection $SmartCollection + * @property-read ShopifyResource\Theme $Theme + * @property-read ShopifyResource\User $User + * @property-read ShopifyResource\Webhook $Webhook + * @property-read ShopifyResource\GraphQL $GraphQL + * @method ShopifyResource\AbandonedCheckout AbandonedCheckout(integer $id = null) + * @method ShopifyResource\Blog Blog(integer $id = null) + * @method ShopifyResource\CarrierService CarrierService(integer $id = null) + * @method ShopifyResource\Collect Collect(integer $id = null) + * @method ShopifyResource\Collection Collection(integer $id = null) + * @method ShopifyResource\Comment Comment(integer $id = null) + * @method ShopifyResource\Country Country(integer $id = null) + * @method ShopifyResource\Currency Currency(integer $id = null) + * @method ShopifyResource\CustomCollection CustomCollection(integer $id = null) + * @method ShopifyResource\Customer Customer(integer $id = null) + * @method ShopifyResource\CustomerSavedSearch CustomerSavedSearch(integer $id = null) + * @method ShopifyResource\Discount Discount(integer $id = null) + * @method ShopifyResource\DraftOrder DraftOrder(integer $id = null) + * @method ShopifyResource\DiscountCode DiscountCode(integer $id = null) + * @method ShopifyResource\PriceRule PriceRule(integer $id = null) + * @method ShopifyResource\Event Event(integer $id = null) + * @method ShopifyResource\FulfillmentService FulfillmentService(integer $id = null) + * @method ShopifyResource\GiftCard GiftCard(integer $id = null) + * @method ShopifyResource\InventoryItem InventoryItem(integer $id = null) + * @method ShopifyResource\InventoryLevel InventoryLevel(integer $id = null) + * @method ShopifyResource\Location Location(integer $id = null) + * @method ShopifyResource\Metafield Metafield(integer $id = null) + * @method ShopifyResource\Multipass Multipass(integer $id = null) + * @method ShopifyResource\Order Order(integer $id = null) + * @method ShopifyResource\Page Page(integer $id = null) + * @method ShopifyResource\Policy Policy(integer $id = null) + * @method ShopifyResource\Product Product(integer $id = null) + * @method ShopifyResource\ProductListing ProductListing(integer $id = null) + * @method ShopifyResource\ProductVariant ProductVariant(integer $id = null) + * @method ShopifyResource\RecurringApplicationCharge RecurringApplicationCharge(integer $id = null) + * @method ShopifyResource\Redirect Redirect(integer $id = null) + * @method ShopifyResource\ScriptTag ScriptTag(integer $id = null) + * @method ShopifyResource\ShippingZone ShippingZone(integer $id = null) + * @method ShopifyResource\Shop Shop(integer $id = null) + * @method ShopifyResource\SmartCollection SmartCollection(integer $id = null) + * @method ShopifyResource\Theme Theme(int $id = null) + * @method ShopifyResource\User User(integer $id = null) + * @method ShopifyResource\Webhook Webhook(integer $id = null) + * @method ShopifyResource\GraphQL GraphQL() */ -class ShopifySDK -{ +class ShopifySDK { /** * List of available resources which can be called from this client * * @var string[] */ - protected $resources = array( + protected $resources = [ 'AbandonedCheckout', 'ApplicationCharge', 'Blog', @@ -196,7 +191,7 @@ class ShopifySDK 'User', 'Webhook', 'GraphQL' - ); + ]; /** * @var float microtime of last api call @@ -215,18 +210,19 @@ class ShopifySDK /** * Shop / API configurations - * * @var array */ - public static $config = array( - ); + private $config = []; + + /** @var HttpRequestJson */ + private $httpRequestJson; /** * List of resources which are only available through a parent resource * * @var array Array key is the child resource name and array value is the parent resource name */ - protected $childResources = array( + protected $childResources = [ 'Article' => 'Blog', 'Asset' => 'Theme', 'CustomerAddress' => 'Customer', @@ -239,21 +235,45 @@ class ShopifySDK 'Province' => 'Country', 'Refund' => 'Order', 'Transaction' => 'Order', - 'UsageCharge' => 'RecurringApplicationCharge', - ); + 'UsageCharge' => 'RecurringApplicationCharge' + ]; - /* - * ShopifySDK constructor - * - * @param array $config - * - * @return void - */ - public function __construct($config = array()) - { - if(!empty($config)) { - ShopifySDK::config($config); + public function __construct(array $config = [], ?HttpRequestJson $httpRequestJson = null) { + $config += ['ApiVersion' => self::$defaultApiVersion]; + + $shopUrl = $config['ShopUrl']; + $shopUrl = preg_replace('#^https?://|/$#', '', $shopUrl); + $apiVersion = $config['ApiVersion']; + + if (isset($config['ApiKey']) && isset($config['Password'])) { + $apiKey = $config['ApiKey']; + $apiPassword = $config['Password']; + $adminUrl = "https://{$apiKey}:{$apiPassword}@{$shopUrl}/admin/"; + } else { + $adminUrl = "https://{$shopUrl}/admin/"; + } + + $config['AdminUrl'] = $adminUrl; + $config['ApiUrl'] = "{$adminUrl}api/{$apiVersion}/"; + $this->config = $config; + + if ($httpRequestJson === null) { + $httpRequestJson = new HttpRequestJson(); } + + $this->httpRequestJson = $httpRequestJson; + } + + public function getConfig(): array { + return $this->config; + } + + public function getHttpRequestJson(): HttpRequestJson { + return $this->httpRequestJson; + } + + public function createAuthHelper(): AuthHelper { + return new AuthHelper($this->config, $this->httpRequestJson); } /** @@ -262,11 +282,9 @@ public function __construct($config = array()) * Called like an object properties (without parenthesis) * * @param string $resourceName - * * @return ShopifyResource */ - public function __get($resourceName) - { + public function __get($resourceName) { return $this->$resourceName(); } @@ -282,116 +300,52 @@ public function __get($resourceName) * * @return ShopifyResource */ - public function __call($resourceName, $arguments) - { + public function __call($resourceName, $arguments) { if (!in_array($resourceName, $this->resources)) { if (isset($this->childResources[$resourceName])) { $message = "$resourceName is a child resource of " . $this->childResources[$resourceName] . ". Cannot be accessed directly."; } else { $message = "Invalid resource name $resourceName. Pls check the API Reference to get the appropriate resource name."; } + throw new SdkException($message); } - $resourceClassName = __NAMESPACE__ . "\\$resourceName"; - - //If first argument is provided, it will be considered as the ID of the resource. - $resourceID = !empty($arguments) ? $arguments[0] : null; - - //Initiate the resource object - $resource = new $resourceClassName($resourceID); - - return $resource; + return $this->createResource($resourceName, $arguments); } - /** - * Configure the SDK client - * - * @param array $config - * - * @return ShopifySDK - */ - public static function config($config) - { - /** - * Reset config to it's initial values - */ - self::$config = array( - 'ApiVersion' => self::$defaultApiVersion - ); - - foreach ($config as $key => $value) { - self::$config[$key] = $value; - } - - //Re-set the admin url if shop url is changed - if(isset($config['ShopUrl'])) { - self::setAdminUrl(); - } + public function createResource(string $name, array $arguments, string $resourceUrl = '') { + $namespaces = [ShopifyResource::class]; - //If want to keep more wait time than .5 seconds for each call - if (isset($config['AllowedTimePerCall'])) { - static::$timeAllowedForEachApiCall = $config['AllowedTimePerCall']; + if (isset($this->config['ResourceNamespaces'])) { + $namespaces = array_merge($this->config['ResourceNamespaces'], $namespaces); } - return new ShopifySDK; - } + foreach ($namespaces as $namespace) { + $resourceClassName = "{$namespace}\\{$name}"; - /** - * Set the admin url, based on the configured shop url - * - * @return string - */ - public static function setAdminUrl() - { - $shopUrl = self::$config['ShopUrl']; + if (!class_exists($resourceClassName)) { + continue; + } - //Remove https:// and trailing slash (if provided) - $shopUrl = preg_replace('#^https?://|/$#', '', $shopUrl); - $apiVersion = self::$config['ApiVersion']; + //If first argument is provided, it will be considered as the ID of the resource. + $resourceId = $arguments[0] ?? null; - if(isset(self::$config['ApiKey']) && isset(self::$config['Password'])) { - $apiKey = self::$config['ApiKey']; - $apiPassword = self::$config['Password']; - $adminUrl = "https://$apiKey:$apiPassword@$shopUrl/admin/"; - } else { - $adminUrl = "https://$shopUrl/admin/"; + return new $resourceClassName($this, $resourceId, $resourceUrl); } - self::$config['AdminUrl'] = $adminUrl; - self::$config['ApiUrl'] = $adminUrl . "api/$apiVersion/"; - - return $adminUrl; - } - - /** - * Get the admin url of the configured shop - * - * @return string - */ - public static function getAdminUrl() { - return self::$config['AdminUrl']; - } - - /** - * Get the api url of the configured shop - * - * @return string - */ - public static function getApiUrl() { - return self::$config['ApiUrl']; + throw new SdkException("ShopifyResource class {$name} not found."); } /** * Maintain maximum 2 calls per second to the API * * @see https://help.shopify.com/api/guides/api-call-limit - * * @param bool $firstCallWait Whether to maintain the wait time even if it is the first API call */ - public static function checkApiCallLimit($firstCallWait = false) - { + public static function checkApiCallLimit($firstCallWait = false): void { $timeToWait = 0; + if (static::$microtimeOfLastApiCall == null) { if ($firstCallWait) { $timeToWait = static::$timeAllowedForEachApiCall; @@ -399,16 +353,14 @@ public static function checkApiCallLimit($firstCallWait = false) } else { $now = microtime(true); $timeSinceLastCall = $now - static::$microtimeOfLastApiCall; - //Ensure 2 API calls per second + if($timeSinceLastCall < static::$timeAllowedForEachApiCall) { $timeToWait = static::$timeAllowedForEachApiCall - $timeSinceLastCall; } } if ($timeToWait) { - //convert time to microseconds $microSecondsToWait = $timeToWait * 1000000; - //Wait to maintain the API call difference of .5 seconds usleep($microSecondsToWait); } diff --git a/lib/SmartCollection.php b/lib/SmartCollection.php deleted file mode 100644 index d39925c..0000000 --- a/lib/SmartCollection.php +++ /dev/null @@ -1,54 +0,0 @@ - - * Created at 8/19/16 7:40 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/smartcollection Shopify API Reference for SmartCollection - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * SmartCollection -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Event $Event - * - * @method Event Event(integer $id = null) - * - * -------------------------------------------------------------------------- - * SmartCollection -> Custom actions - * -------------------------------------------------------------------------- - * - */ -class SmartCollection extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'smart_collection'; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Event', - 'Metafield', - ); - - /** - * Set the ordering type and/or the manual order of products in a smart collection - * - * @param array $params - * - * @return array - */ - public function sortOrder($params) - { - $url = $this->generateUrl($params, 'order'); - - return $this->put(array(), $url); - } -} diff --git a/lib/Theme.php b/lib/Theme.php deleted file mode 100644 index 7aed344..0000000 --- a/lib/Theme.php +++ /dev/null @@ -1,40 +0,0 @@ - - * Created at 8/18/16 10:46 AM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/theme Shopify API Reference for Theme - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * Theme -> Child Resources - * -------------------------------------------------------------------------- - * @property-read Asset $Asset - * - * @method Asset Asset(integer $id = null) - * - */ -class Theme extends ShopifyResource -{ - /** - * @inheritDoc - */ - public $resourceKey = 'theme'; - - /** - * @inheritDoc - */ - public $countEnabled = false; - - /** - * @inheritDoc - */ - protected $childResource = array( - 'Asset' - ); -} \ No newline at end of file diff --git a/lib/Transaction.php b/lib/Transaction.php deleted file mode 100644 index 3222967..0000000 --- a/lib/Transaction.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 7:27 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/transaction Shopify API Reference for Transaction - */ - -namespace PHPShopify; - - -class Transaction extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'transaction'; -} \ No newline at end of file diff --git a/lib/UsageCharge.php b/lib/UsageCharge.php deleted file mode 100644 index 4300d93..0000000 --- a/lib/UsageCharge.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 7:49 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/usagecharge Shopify API Reference for UsageCharge - */ - -namespace PHPShopify; - - -class UsageCharge extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'usage_charge'; -} \ No newline at end of file diff --git a/lib/User.php b/lib/User.php deleted file mode 100644 index eb0652c..0000000 --- a/lib/User.php +++ /dev/null @@ -1,38 +0,0 @@ - - * Created at 8/19/16 8:00 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/user Shopify API Reference for User - */ - -namespace PHPShopify; - - -/** - * -------------------------------------------------------------------------- - * User -> Custom actions - * -------------------------------------------------------------------------- - * @method array current() Get the current logged-in user - * - */ -class User extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'user'; - - /** - * @inheritDoc - */ - public $readOnly = true; - - /** - * @inheritDoc - */ - protected $customGetActions = array ( - 'current' - ); -} \ No newline at end of file diff --git a/lib/Webhook.php b/lib/Webhook.php deleted file mode 100644 index aab7940..0000000 --- a/lib/Webhook.php +++ /dev/null @@ -1,19 +0,0 @@ - - * Created at 8/19/16 8:07 PM UTC+06:00 - * - * @see https://help.shopify.com/api/reference/webhook Shopify API Reference for Webhook - */ - -namespace PHPShopify; - - -class Webhook extends ShopifyResource -{ - /** - * @inheritDoc - */ - protected $resourceKey = 'webhook'; -} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index aeefd1a..3e65a9b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -16,4 +16,4 @@ - \ No newline at end of file + diff --git a/tests/AbandonedCheckoutTest.php b/tests/AbandonedCheckoutTest.php deleted file mode 100644 index 7df2ed0..0000000 --- a/tests/AbandonedCheckoutTest.php +++ /dev/null @@ -1,13 +0,0 @@ - - * Created at: 9/9/16 7:41 PM UTC+06:00 - */ - -namespace PHPShopify; - - -class AbandonedCheckoutTest extends TestSimpleResource -{ -} \ No newline at end of file diff --git a/tests/ApplicationChargeTest.php b/tests/ApplicationChargeTest.php deleted file mode 100644 index 27bdcf1..0000000 --- a/tests/ApplicationChargeTest.php +++ /dev/null @@ -1,13 +0,0 @@ - - * Created at: 9/9/16 9:59 PM UTC+06:00 - */ - -namespace PHPShopify; - - -class ApplicationChargeTest extends TestSimpleResource -{ -} \ No newline at end of file diff --git a/tests/BlogTest.php b/tests/BlogTest.php deleted file mode 100644 index ffbd52b..0000000 --- a/tests/BlogTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * Created at: 9/10/16 10:43 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class BlogTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "title" => "PHPShopify Test Blog", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "title" => "PHPShopify Test Blog Modified", - ); -} \ No newline at end of file diff --git a/tests/CarrierServiceTest.php b/tests/CarrierServiceTest.php deleted file mode 100644 index a601cdb..0000000 --- a/tests/CarrierServiceTest.php +++ /dev/null @@ -1,29 +0,0 @@ - - * Created at: 9/10/16 10:44 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CarrierServiceTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "name" => "Shipping Rate Provider", - "callback_url" => "http://shippingrateprovider.com", - "service_discovery" => true - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "name" => "Updated Shipping Rate Provider", - "active" => false, - ); -} \ No newline at end of file diff --git a/tests/CollectTest.php b/tests/CollectTest.php deleted file mode 100644 index fc2d507..0000000 --- a/tests/CollectTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:44 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CollectTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php deleted file mode 100644 index da7ef9d..0000000 --- a/tests/CollectionTest.php +++ /dev/null @@ -1,16 +0,0 @@ - - * Created at: 9/10/16 10:45 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CommentTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/CountryTest.php b/tests/CountryTest.php deleted file mode 100644 index 1a0ddc2..0000000 --- a/tests/CountryTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * Created at: 9/10/16 10:45 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CountryTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "code" => "BD", - "tax" => 0.25, - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "tax" => 0.01, - ); - - /** - * @inheritDoc - * TODO: Shopify count and get result doesn't match, remove this function if that issue is fixed. - */ - public function testGet() { - $this->assertEquals(1, 1); - } -} \ No newline at end of file diff --git a/tests/CurrencyTest.php b/tests/CurrencyTest.php deleted file mode 100644 index 70ac526..0000000 --- a/tests/CurrencyTest.php +++ /dev/null @@ -1,15 +0,0 @@ - - * Created at: 9/10/16 10:45 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CustomCollectionTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "title" => "Macbooks" - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "title" => "Updated - Macbooks", - "body_html" => "

The best selling Macbooks ever

", - ); -} \ No newline at end of file diff --git a/tests/CustomerSavedSearchTest.php b/tests/CustomerSavedSearchTest.php deleted file mode 100644 index 106365f..0000000 --- a/tests/CustomerSavedSearchTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * Created at: 9/10/16 10:46 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CustomerSavedSearchTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "name" => "Spent more than $50 and after 2015", - "query" => "total_spent:>50 order_date:>=2015-01-01", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "name" => "This Name Has Been Changed", - ); -} \ No newline at end of file diff --git a/tests/CustomerTest.php b/tests/CustomerTest.php deleted file mode 100644 index b9c0049..0000000 --- a/tests/CustomerTest.php +++ /dev/null @@ -1,36 +0,0 @@ - - * Created at: 9/10/16 10:45 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class CustomerTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "first_name" => "Steve", - "last_name" => "Lastnameson", - "email" => "steve.lastnameson@example.com", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "verified_email" => true, - ); - - /** - * @inheritDoc - * TODO: Shopify count and get result doesn't match, remove this function if that issue is fixed. - */ - public function testGet() { - $this->assertEquals(1, 1); - } -} \ No newline at end of file diff --git a/tests/FulfillmentServiceTest.php b/tests/FulfillmentServiceTest.php deleted file mode 100644 index d898c29..0000000 --- a/tests/FulfillmentServiceTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * Created at: 9/10/16 10:47 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class FulfillmentServiceTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "name" => "MarsFulfillment", - "callback_url" => "http://google.com", - "inventory_management" => true, - "tracking_support" => true, - "requires_shipping_method" => true, - "format" => "json" - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "tracking_support" => false - ); - -} \ No newline at end of file diff --git a/tests/LocationTest.php b/tests/LocationTest.php deleted file mode 100644 index 894e9ff..0000000 --- a/tests/LocationTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:48 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class LocationTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/MetafieldTest.php b/tests/MetafieldTest.php deleted file mode 100644 index 5038381..0000000 --- a/tests/MetafieldTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * Created at: 9/10/16 10:48 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class MetafieldTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "namespace" => "inventory", - "key" => "warehouse", - "value" => 25, - "value_type" => "integer", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "value" => "something new", - "value_type" => "string", - ); -} \ No newline at end of file diff --git a/tests/OrderTest.php b/tests/OrderTest.php deleted file mode 100644 index e5e4fa6..0000000 --- a/tests/OrderTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:48 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class OrderTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/PageTest.php b/tests/PageTest.php deleted file mode 100644 index ec135cd..0000000 --- a/tests/PageTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * Created at: 9/10/16 10:49 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class PageTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "title" => "Warranty information", - "body_html" => "

Warranty<\/h1>\n

Forget it<\/strong>, we aint giving you nothing<\/p>", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "title" => "Updated Warranty information" - ); -} \ No newline at end of file diff --git a/tests/PolicyTest.php b/tests/PolicyTest.php deleted file mode 100644 index e533e93..0000000 --- a/tests/PolicyTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:49 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class PolicyTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/ProductListingTest.php b/tests/ProductListingTest.php deleted file mode 100644 index 560650e..0000000 --- a/tests/ProductListingTest.php +++ /dev/null @@ -1,15 +0,0 @@ - - * Created at: 9/9/16 12:44 PM UTC+06:00 - */ - -namespace PHPShopify; - - -class ProductTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "title" => "Burton Custom Freestlye 151", - "body_html" => "Good snowboard!", - "vendor" => "Burton", - "product_type" => "Snowboard", - "variants" => [ - [ - "option1" => "First", - "price" => "10.00", - "sku" => 123 - ], - [ - "option1" => "Second", - "price" => "20.00", - "sku" => "123" - ] - ] - ); - - /** - * @inheritDoc - * Posting without title, triggers an error - */ - public $errorPostArray = array("description" => "A mystery!"); - - /** - * @inheritDoc - */ - public $putArray = array("title" => "New product title"); -} \ No newline at end of file diff --git a/tests/RecurringApplicationChargeTest.php b/tests/RecurringApplicationChargeTest.php deleted file mode 100644 index 7bf4129..0000000 --- a/tests/RecurringApplicationChargeTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:49 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class RecurringApplicationChargeTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/RedirectTest.php b/tests/RedirectTest.php deleted file mode 100644 index cbbf316..0000000 --- a/tests/RedirectTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * Created at: 9/10/16 10:49 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class RedirectTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "path" => "http://www.apple.com/forums", - "target" => "http://forums.apple.com", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "path" => "/tiger", - ); -} \ No newline at end of file diff --git a/tests/ReportTest.php b/tests/ReportTest.php deleted file mode 100644 index 8268489..0000000 --- a/tests/ReportTest.php +++ /dev/null @@ -1,21 +0,0 @@ - "A new app report", - "shopify_ql" => "SHOW total_sales BY country FROM order SINCE -1m UNTIL today ORDER BY total_sales", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "name" => "A new app report - updated", - ); -} \ No newline at end of file diff --git a/tests/ScriptTagTest.php b/tests/ScriptTagTest.php deleted file mode 100644 index 4f14923..0000000 --- a/tests/ScriptTagTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * Created at: 9/10/16 10:50 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class ScriptTagTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "event" => "onload", - "src" => "https://djavaskripped.org/fancy.js", - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "src" => "https://somewhere-else.com/another.js", - ); -} \ No newline at end of file diff --git a/tests/ShippingZoneTest.php b/tests/ShippingZoneTest.php deleted file mode 100644 index c71b36d..0000000 --- a/tests/ShippingZoneTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:50 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class ShippingZoneTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/ShopTest.php b/tests/ShopTest.php deleted file mode 100644 index 949737d..0000000 --- a/tests/ShopTest.php +++ /dev/null @@ -1,14 +0,0 @@ - - * Created at: 9/10/16 10:50 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class ShopTest extends TestSimpleResource -{ - -} \ No newline at end of file diff --git a/tests/ShopifyResource/AbandonedCheckoutTest.php b/tests/ShopifyResource/AbandonedCheckoutTest.php new file mode 100644 index 0000000..1732814 --- /dev/null +++ b/tests/ShopifyResource/AbandonedCheckoutTest.php @@ -0,0 +1,8 @@ + "Mega Test Blog" + ]; + public $putArray = [ + "title" => "Mega Test Blog Modified" + ]; +} diff --git a/tests/ShopifyResource/CarrierServiceTest.php b/tests/ShopifyResource/CarrierServiceTest.php new file mode 100644 index 0000000..29a7bae --- /dev/null +++ b/tests/ShopifyResource/CarrierServiceTest.php @@ -0,0 +1,17 @@ + "Shipping Rate Provider", + "callback_url" => "http://shippingrateprovider.com", + "service_discovery" => true + ]; + public $putArray = [ + "name" => "Updated Shipping Rate Provider", + "active" => false + ]; +} diff --git a/tests/ShopifyResource/CollectTest.php b/tests/ShopifyResource/CollectTest.php new file mode 100644 index 0000000..5767d24 --- /dev/null +++ b/tests/ShopifyResource/CollectTest.php @@ -0,0 +1,8 @@ + "BD", + "tax" => 0.25 + ]; + + public $putArray = [ + "tax" => 0.01 + ]; + + public function testGet() { + $this->assertEquals(1, 1); + } +} diff --git a/tests/ShopifyResource/CurrencyTest.php b/tests/ShopifyResource/CurrencyTest.php new file mode 100644 index 0000000..a6f28c8 --- /dev/null +++ b/tests/ShopifyResource/CurrencyTest.php @@ -0,0 +1,8 @@ + "Macbooks" + ]; + public $putArray = [ + "title" => "Updated - Macbooks", + "body_html" => "

The best selling Macbooks ever

" + ]; +} diff --git a/tests/ShopifyResource/CustomerSavedSearchTest.php b/tests/ShopifyResource/CustomerSavedSearchTest.php new file mode 100644 index 0000000..ac294a1 --- /dev/null +++ b/tests/ShopifyResource/CustomerSavedSearchTest.php @@ -0,0 +1,15 @@ + "Spent more than $50 and after 2015", + "query" => "total_spent:>50 order_date:>=2015-01-01" + ]; + public $putArray = [ + "name" => "This Name Has Been Changed" + ]; +} diff --git a/tests/ShopifyResource/CustomerTest.php b/tests/ShopifyResource/CustomerTest.php new file mode 100644 index 0000000..7549521 --- /dev/null +++ b/tests/ShopifyResource/CustomerTest.php @@ -0,0 +1,20 @@ + "Steve", + "last_name" => "Lastnameson", + "email" => "steve.lastnameson@example.com" + ]; + public $putArray = [ + "verified_email" => true + ]; + + public function testGet() { + $this->assertEquals(1, 1); + } +} diff --git a/tests/ShopifyResource/FulfillmentServiceTest.php b/tests/ShopifyResource/FulfillmentServiceTest.php new file mode 100644 index 0000000..d278a29 --- /dev/null +++ b/tests/ShopifyResource/FulfillmentServiceTest.php @@ -0,0 +1,20 @@ + "MarsFulfillment", + "callback_url" => "http://google.com", + "inventory_management" => true, + "tracking_support" => true, + "requires_shipping_method" => true, + "format" => "json" + ]; + + public $putArray = [ + "tracking_support" => false + ]; +} diff --git a/tests/ShopifyResource/LocationTest.php b/tests/ShopifyResource/LocationTest.php new file mode 100644 index 0000000..f25f839 --- /dev/null +++ b/tests/ShopifyResource/LocationTest.php @@ -0,0 +1,8 @@ + "inventory", + "key" => "warehouse", + "value" => 25, + "value_type" => "integer" + ]; + + public $putArray = [ + "value" => "something new", + "value_type" => "string" + ]; +} diff --git a/tests/ShopifyResource/OrderTest.php b/tests/ShopifyResource/OrderTest.php new file mode 100644 index 0000000..69f9e23 --- /dev/null +++ b/tests/ShopifyResource/OrderTest.php @@ -0,0 +1,8 @@ + "Warranty information", + "body_html" => "

Warranty

\n

Forget it, we ain't giving you nothing

" + ]; + public $putArray = [ + "title" => "Updated Warranty information" + ]; +} diff --git a/tests/ShopifyResource/PolicyTest.php b/tests/ShopifyResource/PolicyTest.php new file mode 100644 index 0000000..0f2df92 --- /dev/null +++ b/tests/ShopifyResource/PolicyTest.php @@ -0,0 +1,8 @@ + "Burton Custom Freestlye 151", + "body_html" => "Good snowboard!", + "vendor" => "Burton", + "product_type" => "Snowboard", + "variants" => [ + [ + "option1" => "First", + "price" => "10.00", + "sku" => 123 + ], + [ + "option1" => "Second", + "price" => "20.00", + "sku" => "123" + ] + ] + ]; + public $errorPostArray = ["description" => "A mystery!"]; + public $putArray = ["title" => "New product title"]; +} diff --git a/tests/ShopifyResource/RecurringApplicationChargeTest.php b/tests/ShopifyResource/RecurringApplicationChargeTest.php new file mode 100644 index 0000000..508c78c --- /dev/null +++ b/tests/ShopifyResource/RecurringApplicationChargeTest.php @@ -0,0 +1,8 @@ + "http://www.apple.com/forums", + "target" => "http://forums.apple.com" + ]; + + public $putArray = [ + "path" => "/tiger" + ]; +} \ No newline at end of file diff --git a/tests/ShopifyResource/ReportTest.php b/tests/ShopifyResource/ReportTest.php new file mode 100644 index 0000000..b9c783c --- /dev/null +++ b/tests/ShopifyResource/ReportTest.php @@ -0,0 +1,16 @@ + "A new app report", + "shopify_ql" => "SHOW total_sales BY country FROM order SINCE -1m UNTIL today ORDER BY total_sales" + ]; + + public $putArray = [ + "name" => "A new app report - updated" + ]; +} diff --git a/tests/ShopifyResource/ScriptTagTest.php b/tests/ShopifyResource/ScriptTagTest.php new file mode 100644 index 0000000..4c4d847 --- /dev/null +++ b/tests/ShopifyResource/ScriptTagTest.php @@ -0,0 +1,16 @@ + "onload", + "src" => "https://djavaskripped.org/fancy.js" + ]; + + public $putArray = [ + "src" => "https://somewhere-else.com/another.js" + ]; +} diff --git a/tests/ShopifyResource/ShippingZoneTest.php b/tests/ShopifyResource/ShippingZoneTest.php new file mode 100644 index 0000000..fffe123 --- /dev/null +++ b/tests/ShopifyResource/ShippingZoneTest.php @@ -0,0 +1,8 @@ + "McBooks", + "published" => false, + "rules"=> [ + [ + "column" => "vendor", + "relation" => "equals", + "condition" => "Pineapple" + ] + ] + ]; + public $putArray = [ + "body_html" => "

The most expensive McBook ever.

" + ]; +} diff --git a/tests/ShopifyResource/ThemeTest.php b/tests/ShopifyResource/ThemeTest.php new file mode 100644 index 0000000..97e8fe2 --- /dev/null +++ b/tests/ShopifyResource/ThemeTest.php @@ -0,0 +1,8 @@ + "orders/create", + "address" => "https://whatever.phpclassic.com/", + "format" => "json" + ]; + public $putArray = [ + "address" => "https://whatsoever.phpclassic.com/" + ]; +} diff --git a/tests/SmartCollectionTest.php b/tests/SmartCollectionTest.php deleted file mode 100644 index ddb52b3..0000000 --- a/tests/SmartCollectionTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * Created at: 9/10/16 10:52 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class SmartCollectionTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "title" => "Macbooks", - "published" => false, - "rules"=> [ - [ - "column" => "vendor", - "relation" => "equals", - "condition" => "Apple" - ] - ], - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "body_html" => "

The best selling Macbooks ever

", - ); -} \ No newline at end of file diff --git a/tests/TestResource.php b/tests/TestResource.php index 1c9a268..661551a 100644 --- a/tests/TestResource.php +++ b/tests/TestResource.php @@ -1,39 +1,23 @@ - * Created at: 9/9/16 12:28 PM UTC+06:00 - */ namespace PHPShopify; -class TestResource extends \PHPUnit_Framework_TestCase -{ - /** - * @var ShopifySDK $shopify; - */ +class TestResource extends \PHPUnit_Framework_TestCase { + /** @var ShopifySDK */ public static $shopify; - /** - * @inheritDoc - */ - public static function setUpBeforeClass() - { - $config = array( - 'ShopUrl' => getenv('SHOPIFY_SHOP_URL'), //Your shop URL - 'ApiKey' => getenv('SHOPIFY_API_KEY'), //Your Private API Key - 'Password' => getenv('SHOPIFY_API_PASSWORD'), //Your Private API Password - ); + public static function setUpBeforeClass() { + $config = [ + 'ShopUrl' => getenv('SHOPIFY_SHOP_URL'), + 'ApiKey' => getenv('SHOPIFY_API_KEY'), + 'Password' => getenv('SHOPIFY_API_PASSWORD'), + ]; - self::$shopify = ShopifySDK::config($config); + self::$shopify = new ShopifySDK($config); ShopifySDK::checkApiCallLimit(); } - /** - * @inheritDoc - */ - public static function tearDownAfterClass() - { + public static function tearDownAfterClass() { self::$shopify = null; } -} \ No newline at end of file +} diff --git a/tests/TestSimpleResource.php b/tests/TestSimpleResource.php index 1e6c28a..a8741de 100644 --- a/tests/TestSimpleResource.php +++ b/tests/TestSimpleResource.php @@ -1,15 +1,8 @@ - * Created at: 9/9/16 12:38 PM UTC+06:00 - */ namespace PHPShopify; -class TestSimpleResource extends TestResource -{ - +class TestSimpleResource extends TestResource { /** * @var string Resource name */ @@ -30,48 +23,36 @@ class TestSimpleResource extends TestResource */ public $errorPostArray; - - /** - * TestSimpleResource constructor. - */ - public function __construct() - { + public function __construct() { $this->resourceName = preg_replace('/.+\\\\(\w+)Test$/', '$1', get_called_class()); parent::__construct(); } - /** - * Test post resource - * - * @return int - */ - public function testPost() - { + public function testPost(): ?int { if ($this->postArray) { $result = static::$shopify->{$this->resourceName}->post($this->postArray); $this->assertTrue(is_array($result)); $this->assertNotEmpty($result); return $result['id']; } + + return null; } /** - * Test get resource - * * @depends testPost */ - public function testGet() - { + public function testGet() { $resource = static::$shopify->{$this->resourceName}; $result = $resource->get(); $this->assertTrue(is_array($result)); - //Data posted, so cannot be empty + if($this->postArray) { $this->assertNotEmpty($result); } + if($resource->countEnabled) { - //Count should match the result array count $count = static::$shopify->{$this->resourceName}->count(); $this->assertEquals($count, count($result)); } @@ -82,8 +63,7 @@ public function testGet() * * @depends testPost */ - public function testGetSelf($id) - { + public function testGetSelf($id) { if ($id) { $product = static::$shopify->{$this->resourceName}($id)->get(); @@ -98,8 +78,7 @@ public function testGetSelf($id) * * @depends testPost */ - public function testPut($id) - { + public function testPut($id) { if ($this->putArray) { $result = static::$shopify->{$this->resourceName}($id)->put($this->putArray); $this->assertTrue(is_array($result)); @@ -111,12 +90,9 @@ public function testPut($id) } /** - * Test delete resource - * * @depends testPost */ - public function testDelete($id) - { + public function testDelete($id) { if ($id) { $result = static::$shopify->{$this->resourceName}($id)->delete(); $this->assertEmpty($result); diff --git a/tests/ThemeTest.php b/tests/ThemeTest.php deleted file mode 100644 index 7901d1a..0000000 --- a/tests/ThemeTest.php +++ /dev/null @@ -1,13 +0,0 @@ - - * Created at: 9/10/16 10:52 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class ThemeTest extends TestSimpleResource -{ -} \ No newline at end of file diff --git a/tests/WebhookTest.php b/tests/WebhookTest.php deleted file mode 100644 index 390f074..0000000 --- a/tests/WebhookTest.php +++ /dev/null @@ -1,28 +0,0 @@ - - * Created at: 9/10/16 10:52 AM UTC+06:00 - */ - -namespace PHPShopify; - - -class WebhookTest extends TestSimpleResource -{ - /** - * @inheritDoc - */ - public $postArray = array( - "topic" => "orders/create", - "address" => "https://whatever.phpclassic.com/", - "format" => "json" - ); - - /** - * @inheritDoc - */ - public $putArray = array( - "address" => "https://whatsoever.phpclassic.com/", - ); -}