diff --git a/README.md b/README.md
index 4869177..c371b40 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,8 @@
Amazon Product Advertising API V5.0 (**Without Amazon SDK**).
-This repository contains a PHP Lightweight (155 Ko) Wrapper Library, Allows you accessing the [Amazon Product Advertising API V5.0](https://webservices.amazon.com/paapi5/documentation/index.html) from your PHP App, Quickly & easily!
+This repository contains a PHP Lightweight (155 Ko) Wrapper Library,
+Easily access the [Amazon Product Advertising API V5.0](https://webservices.amazon.com/paapi5/documentation/index.html) from your PHP app.
-- Become an Amazon Affiliate With PHP --
@@ -30,41 +31,56 @@ include('apaapi-master/src/Autoloader.php');
* **4** - You can now use the [Quickstart examples](#quickstart).
-## 🔨 Upgrade :
+## 💡 Upgrade :
**See changes before migrate**:
This version includes:
-* Support for **disabled cURL** (*Used Stream*).
-* Throws exception if **cURL** AND **Stream** are disabled.
-* Error reporting (Including semantic errors with **status 200** & **HTTP Client Errors**), [More](https://webservices.amazon.com/paapi5/documentation/troubleshooting/processing-of-errors.html#processing-of-errors).
-* HTTP Client helpers (*RequestClient::hasCurl() & RequestClient::hasStream()*).
-* Response parsing (*object/array/serialized*).
-* Throws exception if Locale (*Region/TLD*) is invalid, [More](https://webservices.amazon.fr/paapi5/documentation/locale-reference.html).
-* Throws exception if Resource (*e.g. Images.Primary.Large*) is invalid, [More](https://webservices.amazon.fr/paapi5/documentation/resources.html).
+* Basic built-in **Caching System**.
+* **Request Builder** (Easier way to fetch data).
+* **Response Normalizer** (Normalize response items).
+* **Search Filters** (Using builder).
+* **Geotargeting** (Automatically redirect links based on the visitor's region).
+* **Rating** (Lagacy).
+* **Keyword Converter** (ASIN, ISBN, EAN, Node, Root).
-And had many improvements:
-
-* Uses default [Ressources](https://webservices.amazon.fr/paapi5/documentation/resources.html) for each [Operation](https://webservices.amazon.fr/paapi5/documentation/operations.html).
-* Clean ecosystem.
-* [Extendable HTTP Client](#advanced-custom-http-request-client).
+[Full Changelog](#).
## ⚡ Getting Started:
### Variables (Basics):
-* "{Your-partner-tag}" : From your Amazon Associates (*your locale*), [More](https://webservices.amazon.com/paapi5/documentation/troubleshooting/sign-up-as-an-associate.html).
-* "{Your-secrect-key}" : From your Amazon Associates (*your locale*), [More](https://affiliate-program.amazon.com/help/node/topic/GTPNVFFUV2GQ8AZV).
-* "{Your-key-id}" : From your Amazon Associates (*your locale*), [More](https://affiliate-program.amazon.com/help/node/topic/GTPNVFFUV2GQ8AZV).
-* "{Your-keywords}" : What you are looking for (*Products*), [More](https://webservices.amazon.com/paapi5/documentation/search-items.html).
-* "{Your-region}" : **TLD** of the target to which you are sending requests (*com/fr/com.be/de*), [Get TLD](https://webservices.amazon.com/paapi5/documentation/common-request-parameters.html#host-and-region).
-* "{ASIN}" : Amazon Standard Identification Number (*your locale*), [More](https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp).
+* "_TAG_" : From your Amazon Associates (*your locale*), [More](https://webservices.amazon.com/paapi5/documentation/troubleshooting/sign-up-as-an-associate.html).
+* "_SECRET_" : From your Amazon Associates (*your locale*), [More](https://affiliate-program.amazon.com/help/node/topic/GTPNVFFUV2GQ8AZV).
+* "_KEY_" : From your Amazon Associates (*your locale*), [More](https://affiliate-program.amazon.com/help/node/topic/GTPNVFFUV2GQ8AZV).
+* "_KEYWORDS_" : What you are looking for (*Products*), [More](https://webservices.amazon.com/paapi5/documentation/search-items.html).
+* "_REGION_" : **TLD** of the target to which you are sending requests (*com/fr/com.be/de*), [Get TLD](https://webservices.amazon.com/paapi5/documentation/common-request-parameters.html#host-and-region).
+* "_ASIN_" : Amazon Standard Identification Number (*your locale*), [More](https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp).
### Quickstart:
+```php
+
+/**
+ * @see Use Composer,
+ * Or include Apaapi Autoloader Here.
+ */
+
+use Apaapi\includes\Builder;
+
+// Init request builder
+$builder = new Builder('_KEY_', '_SECRET_', '_TAG_', '_REGION_');
+
+// Get response
+$data = $builder->searchOne('Sony Xperia Pro-I') // Normalized array
+
+```
+
+### Quickstart (OLD):
+
```php
@@ -86,11 +102,11 @@ use Apaapi\lib\Response;
// (1) Set Operation
$operation = new SearchItems();
-$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}');
+$operation->setPartnerTag('_TAG_')->setKeywords('_KEYWORDS_');
// (2) Prapere Request
-$request = new Request('{Your-key-id}','{Your-secrect-key}');
-$request->setLocale('{Your-region}')->setPayload($operation);
+$request = new Request('_KEY_','_SECRET_');
+$request->setLocale('_REGION_')->setPayload($operation);
// (3) Get Response
$response = new Response($request);
@@ -116,22 +132,22 @@ use Apaapi\operations\GetBrowseNodes;
// GetItems
$operation = new GetItems();
-$operation->setPartnerTag('{Your-partner-tag}')
-->setItemIds(['{ASIN}']); // Array|String
+$operation->setPartnerTag('_TAG_')
+->setItemIds(['_ASIN_']); // Array|String
// SearchItems
$operation = new SearchItems();
-$operation->setPartnerTag('{Your-partner-tag}')
-->setKeywords('{Your-keywords}'); // Array|String
+$operation->setPartnerTag('_TAG_')
+->setKeywords('_KEYWORDS_'); // Array|String
// GetVariations
$operation = new GetVariations();
-$operation->setPartnerTag('{Your-partner-tag}')
-->setASIN('{ASIN}'); // String
+$operation->setPartnerTag('_TAG_')
+->setASIN('_ASIN_'); // String
// GetBrowseNodes
$operation = new GetBrowseNodes();
-$operation->setPartnerTag('{Your-partner-tag}')
+$operation->setPartnerTag('_TAG_')
->setBrowseNodeIds(['{NodeId}']); // Array|String
```
@@ -147,7 +163,7 @@ $operation->setPartnerTag('{Your-partner-tag}')
*/
// Set Operation
-$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}')
+$operation->setPartnerTag('_TAG_')->setKeywords('_KEYWORDS_')
->setResources(['Images.Primary.Small','ItemInfo.Title','Offers.Listings.Price']);
```
@@ -174,10 +190,10 @@ class MyRequestClient extends RequestClient
// Set Operation
$operation = new GetItems();
-$operation->setPartnerTag('{Your-partner-tag}')->setItemIds('{ASIN}');
+$operation->setPartnerTag('_TAG_')->setItemIds('_ASIN_');
// Prapere Request
-$request = new Request('{Your-key-id}','{Your-secrect-key}');
+$request = new Request('_KEY_','_SECRET_');
$request->setLocale('{your-region}')->setPayload($operation);
// Set Custom Client After Payload
@@ -249,11 +265,11 @@ if ( $response->hasError() ) {
// Set Cart
$cart = new Cart();
$cart->setLocale('{Your-locale}');
-$cart->setPartnerTag('{Your-partner-tag}');
+$cart->setPartnerTag('_TAG_');
// Set Items
$items = [
- '{ASIN1}' => '3', // ({ASIN} => {Quantity})
+ '{ASIN1}' => '3', // (_ASIN_ => {Quantity})
'{ASIN2}' => '5'
];
diff --git a/examples/add-to-cart.php b/examples/add-to-cart.php
index d9bb906..77cdf68 100644
--- a/examples/add-to-cart.php
+++ b/examples/add-to-cart.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,26 +12,26 @@
/**
* @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
+ * Or include Apaapi standalone autoloader here.
*/
include('../src/Autoloader.php');
\apaapi\Autoloader::init();
use Apaapi\lib\Cart;
-// Set Cart
+// init cart
$cart = new Cart();
$cart->setLocale('{Your-locale}');
$cart->setPartnerTag('{Your-partner-tag}');
-// Set Items
+// Set items
$items = [
- '{ASIN1}' => '3', // ({ASIN} => {Quantity})
- '{ASIN2}' => '5'
+ '{ASIN1|ISBN1}' => '3', // ({ASIN|ISBN} => {Quantity})
+ '{ASIN2|ISBN2}' => '5'
];
-// Get Response
-$url = $cart->add($items);
-var_dump($url); // String URL
+// Get response
+$url = $cart->set($items);
+echo $url; // String
-// Hope you found this useful, any suggestions (Pull requests) are welcome!
+// Any suggestions (PR) are welcome!
diff --git a/examples/basic.php b/examples/basic.php
index 699450f..0d1188b 100644
--- a/examples/basic.php
+++ b/examples/basic.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,7 +12,7 @@
/**
* @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
+ * Or include Apaapi standalone autoloader here.
*/
include('../src/Autoloader.php');
\apaapi\Autoloader::init();
@@ -21,16 +21,18 @@
use Apaapi\lib\Request;
use Apaapi\lib\Response;
-// Set Operation
+// Set operation
$operation = new SearchItems();
$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}');
-// Prapere Request
+// Prapere request
$request = new Request('{Your-key-id}','{Your-secrect-key}');
$request->setLocale('{Your-locale}')->setPayload($operation);
-// Get Response
+// Get response
$response = new Response($request);
-echo $response->get(); // JSON ready to be parsed
+$data = $response->get(); // Array
+$body = $response->getBody(); // String
+print_r($data);
-// Hope you found this useful, any suggestions (Pull requests) are welcome!
+// Any suggestions (PR) are welcome!
diff --git a/examples/custom-client.php b/examples/custom-client.php
index 87b03be..4793a64 100644
--- a/examples/custom-client.php
+++ b/examples/custom-client.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,7 +12,7 @@
/**
* @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
+ * Or include Apaapi standalone autoloader here.
*/
include('../src/Autoloader.php');
\apaapi\Autoloader::init();
@@ -20,58 +20,65 @@
use Apaapi\operations\SearchItems;
use Apaapi\lib\Request;
use Apaapi\lib\Response;
-use Apaapi\includes\RequestClient;
+use Apaapi\includes\Client;
/**
- * Create Custom Request Client Class.
+ * Custom request client class.
*/
-class MyRequestClient extends RequestClient
+class MyClient extends Client
{
- protected function init()
+ // Enable request client exception
+ public function __construct(string $endpoint, array $params = [])
+ {
+ parent::__construct($endpoint, $params, true);
+ }
+
+ // Override handler behavior
+ protected function setHandler()
{
if ( self::hasCurl() ) {
- // cURL override example
+ // Override curl
$this->handler = curl_init();
curl_setopt($this->handler, CURLOPT_URL, $this->endpoint);
curl_setopt($this->handler, CURLOPT_HTTPHEADER, $this->getRequestHeader());
curl_setopt($this->handler, CURLOPT_POSTFIELDS, $this->getRequestContent());
curl_setopt($this->handler, CURLOPT_POST, true);
curl_setopt($this->handler, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($this->handler, CURLOPT_SSL_VERIFYPEER, true); // Force SSL instead of Auto
- curl_setopt($this->handler, CURLOPT_TIMEOUT, 10); // Custom Timeout instead of 30
+ curl_setopt($this->handler, CURLOPT_SSL_VERIFYPEER, true); // Force SSL
+ curl_setopt($this->handler, CURLOPT_TIMEOUT, 10); // Set custom timeout
} elseif ( self::hasStream() ) {
- // Stream override example
- $this->handler = [
+ // Override stream
+ $this->handler = stream_context_create([
'http' => [
'method' => 'POST',
'header' => $this->getRequestHeader(),
'content' => $this->getRequestContent(),
- 'timeout' => 10 // Custom Timeout instead of 30
+ 'timeout' => $this->timeout // Set custom timeout
]
- ];
+ ]);
}
}
}
-// Set Operation
+// Set operation
$operation = new SearchItems();
-$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}')
-->setResources(['Images.Primary.Small','ItemInfo.Title','Offers.Listings.Price']);
+$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}');
-// Prapere Request
+// Prapere request
$request = new Request('{Your-key-id}','{Your-secrect-key}');
$request->setLocale('{Your-locale}')->setPayload($operation);
-// Set Custom Client after Payload
+// Set custom client after payload
$request->setClient(
- new MyRequestClient($request->getEndpoint(), $request->getParams())
+ new MyClient($request->getEndpoint(), $request->getParams())
);
-// Get Response
+// Get response
$response = new Response($request);
-echo $response->get(); // JSON ready to be parsed
+$data = $response->get(); // Array
+print_r($data);
-// Hope you found this useful, any suggestions (Pull requests) are welcome!
+// Any suggestions (PR) are welcome!
diff --git a/examples/custom-error-handling.php b/examples/custom-error-handling.php
index d615746..f720312 100644
--- a/examples/custom-error-handling.php
+++ b/examples/custom-error-handling.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -23,8 +23,7 @@
// Set Operation
$operation = new SearchItems();
-$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}')
-->setResources(['Images.Primary.Small','ItemInfo.Title','Offers.Listings.Price']);
+$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}');
// Prapere Request
$request = new Request('{Your-key-id}','{Your-secrect-key}');
diff --git a/examples/custom-response.php b/examples/custom-response.php
index ff87430..c2d788d 100644
--- a/examples/custom-response.php
+++ b/examples/custom-response.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,7 +12,7 @@
/**
* @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
+ * Or include Apaapi standalone autoloader here.
*/
include('../src/Autoloader.php');
\apaapi\Autoloader::init();
@@ -20,18 +20,18 @@
use Apaapi\operations\SearchItems;
use Apaapi\lib\Request;
use Apaapi\lib\Response;
-use Apaapi\includes\ResponseType;
-// Set Operation
+// Set operation
$operation = new SearchItems();
$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}');
-// Prapere Request
+// Prapere request
$request = new Request('{Your-key-id}','{Your-secrect-key}');
$request->setLocale('{Your-locale}')->setPayload($operation);
-// Get Response
+// Get response
$response = new Response($request, new ResponseType('array'), Response::PARSE);
-var_dump($response->get()); // Array ready to be used
+$body = $response->getBody(); // String
+print_r($body);
// Hope you found this useful, any suggestions (Pull requests) are welcome!
diff --git a/examples/custom-ressources.php b/examples/custom-ressources.php
index 2c54e9f..9ce6854 100644
--- a/examples/custom-ressources.php
+++ b/examples/custom-ressources.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,7 +12,7 @@
/**
* @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
+ * Or include Apaapi standalone autoloader here.
*/
include('../src/Autoloader.php');
\apaapi\Autoloader::init();
@@ -21,17 +21,22 @@
use Apaapi\lib\Request;
use Apaapi\lib\Response;
-// Set Operation
+// Set operation
$operation = new SearchItems();
$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}')
-->setResources(['Images.Primary.Small','ItemInfo.Title','Offers.Listings.Price']);
+->setResources([
+ 'Images.Primary.Small',
+ 'ItemInfo.Title',
+ 'Offers.Listings.Price'
+]);
-// Prapere Request
+// Prapere request
$request = new Request('{Your-key-id}','{Your-secrect-key}');
$request->setLocale('{Your-locale}')->setPayload($operation);
-// Get Response
+// Get response
$response = new Response($request);
-echo $response->get(); // JSON ready to be parsed
+$data = $response->get(); // Array
+print_r($data);
-// Hope you found this useful, any suggestions (Pull requests) are welcome!
+// Any suggestions (PR) are welcome!
diff --git a/examples/disable-client-exception.php b/examples/disable-client-exception.php
deleted file mode 100644
index b213d77..0000000
--- a/examples/disable-client-exception.php
+++ /dev/null
@@ -1,64 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-/**
- * @see You can use Composer,
- * Or include Apaapi Standalone Autoloader Here.
- */
-include('../src/Autoloader.php');
-\apaapi\Autoloader::init();
-
-use Apaapi\operations\SearchItems;
-use Apaapi\lib\Request;
-use Apaapi\lib\Response;
-use Apaapi\includes\RequestClient;
-
-/**
- * Create Custom Request Client Class.
- */
-class MyRequestClient extends RequestClient
-{
- public function __construct($endpoint, $params)
- {
- // Disable request client exception when both cURL & Stream functions are disabled
- parent::__construct($endpoint,$params,false);
- }
-}
-
-// Set Operation
-$operation = new SearchItems();
-$operation->setPartnerTag('{Your-partner-tag}')->setKeywords('{Your-keywords}')
-->setResources(['Images.Primary.Small','ItemInfo.Title','Offers.Listings.Price']);
-
-// Prapere Request
-$request = new Request('{Your-key-id}','{Your-secrect-key}');
-$request->setLocale('{Your-locale}')->setPayload($operation);
-
-// Set Custom Client after Payload
-$request->setClient(
- new MyRequestClient($request->getEndpoint(), $request->getParams())
-);
-
-// Get Response
-$response = new Response($request);
-$data = $response->get(); // JSON error ready for parsing
-
-// Get formated error without exception handling
-if ( $response->hasError() ) {
- /**
- * @param bool $single error
- * @return string|array
- */
- echo $response->getError(true); // Parsed error
-}
-
-// Hope you found this useful, any suggestions (Pull requests) are welcome!
diff --git a/examples/simple.php b/examples/simple.php
new file mode 100644
index 0000000..8c55a5b
--- /dev/null
+++ b/examples/simple.php
@@ -0,0 +1,29 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+/**
+ * @see You can use Composer,
+ * Or include Apaapi standalone autoloader here.
+ */
+include('../src/Autoloader.php');
+\apaapi\Autoloader::init();
+
+use Apaapi\includes\Builder;
+
+// Prapere request
+$builder = new Builder('{Your-key-id}', '{Your-secrect-key}', '{Your-partner-tag}', '{Your-locale}');
+
+// Get response
+$data = $builder->search('{Your-keywords}'); // Array
+print_r($data);
+
+// Any suggestions (PR) are welcome!
diff --git a/src/Autoloader.php b/src/Autoloader.php
index 3d0d3d1..d89eb7b 100644
--- a/src/Autoloader.php
+++ b/src/Autoloader.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,7 +13,7 @@
namespace Apaapi;
/**
- * Apaapi Standalone Autoloader.
+ * Apaapi standalone autoloader.
*/
final class Autoloader
{
@@ -24,24 +24,22 @@ final class Autoloader
private static $initialized = false;
/**
- * Register Apaapi autoloader.
- *
- * @param void
+ * Register autoloader.
*/
public function __construct()
{
if ( !static::$initialized ) {
- spl_autoload_register([__CLASS__,'autoload']);
+ spl_autoload_register([__CLASS__, 'autoload']);
static::$initialized = true;
}
}
/**
- * Unregister Apaapi autoloader.
+ * Unregister autoloader.
*/
public function __destruct()
{
- spl_autoload_unregister([__CLASS__,'autoload']);
+ spl_autoload_unregister([__CLASS__, 'autoload']);
}
/**
@@ -53,43 +51,42 @@ public function __clone()
}
/**
- * Restrict object clone.
+ * Restrict object unserialize.
*/
public function __wakeup()
{
die(__METHOD__.': Unserialize denied');
}
+ /**
+ * Initialize autoloader.
+ *
+ * @access public
+ * @return void
+ */
+ public static function init()
+ {
+ if ( !static::$initialized ) {
+ new static;
+ }
+ }
+
/**
* Autoloader method.
*
* @access private
- * @param string $class __CLASS__
+ * @param string $class
* @return void
* @see https://www.php-fig.org/psr/psr-4/
* @see https://www.php-fig.org/psr/psr-0/
*/
- private function autoload($class)
+ private function autoload(string $class)
{
if ( strpos($class, __NAMESPACE__ . '\\') === 0 ) {
$class = str_replace(__NAMESPACE__ . '\\', '', $class);
- $class = str_replace('\\','/',$class);
- $root = str_replace('\\','/',dirname(__DIR__));
+ $class = str_replace('\\', '/', $class);
+ $root = str_replace('\\', '/', dirname(__DIR__));
require_once("{$root}/src/{$class}.php");
}
}
-
- /**
- * Initialize autoloader.
- *
- * @access public
- * @param void
- * @return void
- */
- public static function init()
- {
- if ( !static::$initialized ) {
- new static;
- }
- }
}
diff --git a/src/exceptions/OperationException.php b/src/exceptions/OperationException.php
index fcca1c0..9eb5db4 100644
--- a/src/exceptions/OperationException.php
+++ b/src/exceptions/OperationException.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,12 +13,13 @@
namespace Apaapi\exceptions;
/**
- * Basic Apaapi Operation Exception Class.
+ * Apaapi operation exception.
*/
final class OperationException extends \Exception
{
- public static function invalidOperationRessource($ressource = null)
+ public static function invalidRessources(?string $item = null) : string
{
- return "Invalid operation ressource '{$ressource}'";
+ if ( !$item ) $item = 'undefined';
+ return "Invalid operation ressources '{$item}'";
}
}
diff --git a/src/exceptions/RequestException.php b/src/exceptions/RequestException.php
index 4280633..90805a8 100644
--- a/src/exceptions/RequestException.php
+++ b/src/exceptions/RequestException.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,17 +13,18 @@
namespace Apaapi\exceptions;
/**
- * Basic Apaapi Request Exception Class.
+ * Apaapi request exception.
*/
final class RequestException extends \Exception
{
- public static function invalidRequestClientMessage()
+ public static function invalidClient() : string
{
return 'Could not send request (Missing cURL and Stream functions)';
}
- public static function invalidRequestLocaleMessage($local = null)
+ public static function invalidLocale(?string $locale = null) : string
{
- return "Invalid request locale '{$local}'";
+ if ( !$locale ) $locale = 'undefined';
+ return "Invalid request locale '{$locale}'";
}
}
diff --git a/src/exceptions/ResponseTypeException.php b/src/exceptions/ResponseTypeException.php
deleted file mode 100644
index 4e739e3..0000000
--- a/src/exceptions/ResponseTypeException.php
+++ /dev/null
@@ -1,24 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\exceptions;
-
-/**
- * Basic Apaapi Response Type Exception Class.
- */
-final class ResponseTypeException extends \Exception
-{
- public static function invalidResponseTypeFormat($type = null)
- {
- return "Invalid response type format '{$type}', Expected (Object/Array/Serialized)";
- }
-}
diff --git a/src/includes/Builder.php b/src/includes/Builder.php
new file mode 100644
index 0000000..760af96
--- /dev/null
+++ b/src/includes/Builder.php
@@ -0,0 +1,881 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+use Apaapi\lib\{
+ Request,
+ Response,
+ Cart
+};
+use Apaapi\operations\{
+ GetItems,
+ SearchItems,
+ GetVariations,
+ GetBrowseNodes
+};
+
+/**
+ * Apaapi request builder.
+ */
+final class Builder
+{
+ /**
+ * @access private
+ * @var string $key, API key
+ * @var string $secret, API secret
+ * @var string $tag, API tag
+ * @var string $locale, API locale|region
+ * @var object $operation, API operation
+ * @var object $request, API request
+ * @var string $error, API response error
+ * @var array $redirect, Geotargeting args
+ * @var mixed $order, Response order
+ */
+ private $key;
+ private $secret;
+ private $tag;
+ private $locale;
+ private $operation;
+ private $request;
+ private $error = false;
+ private $redirect;
+ private $order = ['title', 'price'];
+
+ /**
+ * Set request authentication.
+ *
+ * @param string $key
+ * @param string $secret
+ * @param string $tag
+ * @param string $locale
+ */
+ public function __construct(string $key, string $secret, string $tag, string $locale)
+ {
+ $this->key = $key;
+ $this->secret = $secret;
+ $this->tag = $tag;
+ $this->locale = $locale;
+ }
+
+ /**
+ * Check authorization.
+ *
+ * @access public
+ * @return bool
+ */
+ public function isAuthorized() : bool
+ {
+ $this->setup('search');
+
+ $this->operation->setResources(['ItemInfo.Title']);
+ $this->operation->setItemCount(1)->setKeywords('amazon');
+
+ $this->prepare();
+ $response = new Response($this->request, false, false);
+ $response->get();
+
+ if ( $response->hasError() ) {
+ $this->error = $response->getError();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get items.
+ *
+ * @access public
+ * @param mixed $ids
+ * @param array $filter
+ * @return array
+ */
+ public function get($ids, array $filter = []) : array
+ {
+ $this->setup('get')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources()
+ );
+
+ $this->operation->setItemIds(
+ Normalizer::formatIds($ids)
+ );
+
+ $items = $this->prepare()->fetch();
+ return Normalizer::order($items, $this->order);
+ }
+
+ /**
+ * Get single item.
+ *
+ * @access public
+ * @param string $id
+ * @param array $filter
+ * @return array
+ */
+ public function getOne(string $id, array $filter = []) : array
+ {
+ $this->setup('get')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources()
+ );
+
+ $this->operation->setItemIds([
+ Normalizer::formatId($id)
+ ]);
+
+ $item = $this->prepare()->fetch();
+ return $item[0] ?? [];
+ }
+
+ /**
+ * Search items.
+ *
+ * @access public
+ * @param mixed $keywords
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function search($keywords, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources()
+ );
+
+ $this->operation->setItemCount($count)->setItemPage($page);
+ $this->operation->setKeywords(
+ Normalizer::formatKeywords($keywords)
+ );
+
+ $items = $this->prepare()->fetch();
+ return Normalizer::order($items, $this->order);
+ }
+
+ /**
+ * Search single item.
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return array
+ */
+ public function searchOne(string $keyword, array $filter = []) : array
+ {
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources()
+ );
+
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ return $item[0] ?? [];
+ }
+
+ /**
+ * Get item variations.
+ *
+ * @access public
+ * @param string $id
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function getVariation(string $id, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $this->setup('variation')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources()
+ );
+
+ $this->operation->setVariationCount($count)->setVariationPage($page);
+ $this->operation->setASIN(
+ Normalizer::formatId($id)
+ );
+
+ $items = $this->prepare()->fetch();
+ return Normalizer::order($items, $this->order);
+ }
+
+ /**
+ * Seatch item variations.
+ *
+ * @access public
+ * @param string $keyword
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function searchVariation(string $keyword, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $id = Normalizer::formatId($keyword);
+ if ( !Keyword::isASIN($id) ) {
+ $keyword = $this->toASIN($keyword, $filter);
+ }
+ return $this->getVariation($keyword, $count, $page, $filter);
+ }
+
+ /**
+ * Convert keyword to ASIN (ISBN).
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return string
+ */
+ public function toASIN(string $keyword, array $filter = []) : string
+ {
+ $id = Normalizer::formatId($keyword);
+ if ( Keyword::isASIN($id) ) {
+ return $id;
+ }
+
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(['ItemInfo.Title']);
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ $item = $item[0] ?? [];
+ return $item['asin'] ?? '';
+ }
+
+ /**
+ * Convert keyword to EAN.
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return string
+ */
+ public function toEAN(string $keyword, array $filter = []) : string
+ {
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(['ItemInfo.ExternalIds']);
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ $item = $item[0] ?? [];
+ return $item['ean'] ?? '';
+ }
+
+ /**
+ * Convert keyword to node Id.
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @param bool $root
+ * @return string
+ */
+ public function toNode(string $keyword, array $filter = [], bool $root = false) : string
+ {
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources([
+ 'BrowseNodeInfo.BrowseNodes.Ancestor'
+ ]);
+
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ $item = $item[0] ?? [];
+
+ if ( $root ) {
+ return $item['root'] ?? '';
+ }
+ return $item['node'] ?? '';
+ }
+
+ /**
+ * Convert keyword to node Id (root).
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return string
+ */
+ public function toRoot(string $keyword, array $filter = []) : string
+ {
+ return $this->toNode($keyword, $filter, true);
+ }
+
+ /**
+ * Get node (Category).
+ *
+ * @access public
+ * @param string $id
+ * @return array
+ */
+ public function getNode(string $id) : array
+ {
+ $this->setup('node');
+
+ $this->operation->setBrowseNodeIds([
+ Normalizer::formatId($id)
+ ]);
+
+ $node = $this->prepare()->fetch();
+ $node = Normalizer::applyArgs($node, [
+ '{locale}' => $this->locale,
+ '{tag}' => $this->tag
+ ]);
+
+ return (array)$node;
+ }
+
+ /**
+ * Search node (Category).
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return array
+ */
+ public function searchNode(string $keyword, array $filter = []) : array
+ {
+ $id = Normalizer::formatId($keyword);
+ if ( Keyword::isASIN($id) || !Keyword::isBarcode($id) ) {
+ $id = $this->toNode($id, $filter);
+ }
+ return $this->getNode($id);
+ }
+
+ /**
+ * Get item root category Id (Search Index).
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return string
+ */
+ public function getCategory(string $keyword, array $filter = []) : string
+ {
+ unset($filter['category']);
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources([
+ 'BrowseNodeInfo.BrowseNodes.Ancestor'
+ ]);
+
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ $item = $item[0] ?? [];
+
+ $category = $item['category'] ?? '';
+ return Provider::getCategoryId($category, $this->locale);
+ }
+
+ /**
+ * Search item category (Search Index).
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return array
+ */
+ public function searchCategory(string $keyword, array $filter = []) : array
+ {
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources([
+ 'SearchRefinements'
+ ]);
+
+ $this->operation->setItemCount(1);
+ $this->operation->setKeywords(
+ Normalizer::formatKeyword($keyword)
+ );
+
+ $item = $this->prepare()->fetch();
+ return $item[0] ?? [];
+ }
+
+ /**
+ * Get bestseller items (Id).
+ *
+ * @access public
+ * @param string $id
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function getBestseller(string $id, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $id = Normalizer::formatId($id);
+ if ( !Keyword::isBarcode($id) ) {
+ return [];
+ }
+
+ unset($filter['node']);
+ $filter['node'] = $id;
+
+ $node = $this->searchNode($id);
+ if ( !$this->hasError() ) {
+ $id = $node['name'];
+ }
+
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources([
+ 'BrowseNodeInfo.BrowseNodes.SalesRank'
+ ])
+ );
+
+ $this->operation->setItemCount($count)->setItemPage($page);
+ $this->operation->setKeywords($id);
+
+ $items = $this->prepare()->fetch();
+ return Normalizer::order($items, ['rank', 'title']);
+ }
+
+ /**
+ * Search bestseller items (Keyword).
+ *
+ * @access public
+ * @param string $keyword
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function searchBestseller(string $keyword, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $keyword = Normalizer::formatKeyword($keyword);
+ if ( Keyword::isBarcode($keyword) ) {
+ return [];
+ }
+ $filter['title'] = $keyword;
+
+ $this->setup('search')->filter($filter);
+
+ $this->operation->setResources(
+ $this->getDefaultResources([
+ 'BrowseNodeInfo.BrowseNodes.SalesRank'
+ ])
+ );
+
+ $this->operation->setItemCount($count)->setItemPage($page);
+ $this->operation->setKeywords($keyword);
+
+ $items = $this->prepare()->fetch();
+ return Normalizer::order($items, ['rank', 'title']);
+ }
+
+ /**
+ * Get newest items.
+ *
+ * @access public
+ * @param string $keyword
+ * @param int $count
+ * @param int $page
+ * @param array $filter
+ * @return array
+ */
+ public function getNewest(string $keyword, int $count = 5, int $page = 1, array $filter = []) : array
+ {
+ $keyword = Normalizer::formatKeyword($keyword);
+ $filter['sort'] = 'newest';
+ $filter['title'] = $keyword;
+ return $this->search($keyword, $count, $page, $filter);
+ }
+
+ /**
+ * Get cart (URL).
+ *
+ * @access public
+ * @param mixed $items
+ * @return string
+ */
+ public function getCart($items) : string
+ {
+ $cart = new Cart();
+ $cart->setLocale($this->locale);
+ $cart->setPartnerTag($this->tag);
+
+ return $cart->set(
+ Normalizer::formatCart($items)
+ );
+ }
+
+ /**
+ * Get rating.
+ *
+ * @access public
+ * @param string $keyword
+ * @return array
+ */
+ public function getRating(string $keyword) : array
+ {
+ $rating = new Rating($keyword, $this->locale, $this->tag);
+ return $rating->get();
+ }
+
+ /**
+ * Search rating.
+ *
+ * @access public
+ * @param string $keyword
+ * @param array $filter
+ * @return array
+ */
+ public function searchRating(string $keyword, array $filter = []) : array
+ {
+ $id = Normalizer::formatId($keyword);
+ if ( !Keyword::isASIN($id) ) {
+ $keyword = $this->toASIN($keyword, $filter);
+ }
+ return $this->getRating($keyword);
+ }
+
+ /**
+ * Enable geotargeting.
+ *
+ * @access public
+ * @param array $redirect
+ * @return object
+ */
+ public function redirect(array $redirect) : self
+ {
+ $this->redirect = array_merge([
+ 'tag' => $this->tag,
+ 'locale' => $this->locale
+ ], $redirect);
+ return $this;
+ }
+
+ /**
+ * Get response error.
+ *
+ * @access public
+ * @return string
+ */
+ public function getError() : string
+ {
+ return (string)$this->error;
+ }
+
+ /**
+ * Check response error.
+ *
+ * @access public
+ * @return bool
+ */
+ public function hasError() : bool
+ {
+ return (bool)$this->error;
+ }
+
+ /**
+ * Setup operation.
+ *
+ * @access private
+ * @param string $operation
+ * @return object
+ */
+ private function setup(string $operation) : self
+ {
+ switch ($operation) {
+ case 'get':
+ $this->operation = new GetItems();
+ break;
+
+ case 'search':
+ $this->operation = new SearchItems();
+ break;
+
+ case 'variation':
+ $this->operation = new GetVariations();
+ break;
+
+ case 'node':
+ $this->operation = new GetBrowseNodes();
+ break;
+ }
+
+ $this->operation->setPartnerTag($this->tag);
+
+ return $this;
+ }
+
+ /**
+ * Get default resources.
+ *
+ * @access private
+ * @param array $resources
+ * @return array
+ */
+ private function getDefaultResources(array $resources = []) : array
+ {
+ return array_merge([
+ 'BrowseNodeInfo.BrowseNodes.Ancestor',
+ 'Images.Primary.Large',
+ 'Images.Variants.Large',
+ 'Offers.Listings.Price',
+ 'Offers.Listings.Condition',
+ 'Offers.Listings.Promotions',
+ 'Offers.Listings.SavingBasis',
+ 'Offers.Listings.DeliveryInfo.IsAmazonFulfilled',
+ 'Offers.Listings.DeliveryInfo.IsFreeShippingEligible',
+ 'Offers.Listings.DeliveryInfo.IsPrimeEligible',
+ 'Offers.Listings.Availability.Message',
+ 'ItemInfo.ExternalIds',
+ 'ItemInfo.Features',
+ 'ItemInfo.Title'
+ ], $resources);
+ }
+
+ /**
+ * Filter request.
+ *
+ * @access private
+ * @param array $filter
+ * @return object
+ */
+ private function filter(array $filter) : self
+ {
+ if ( $this->isSearch() ) {
+
+ $min = $filter['min'] ?? null;
+ if ( $min ) {
+ $this->operation->setMinPrice(
+ Normalizer::formatPrice($min)
+ );
+ }
+
+ $max = $filter['max'] ?? null;
+ if ( $max ) {
+ $this->operation->setMaxPrice(
+ Normalizer::formatPrice($max)
+ );
+ }
+
+ $available = $filter['available'] ?? null;
+ if ( $available === false ) {
+ $this->operation->setAvailability('IncludeOutOfStock');
+ }
+
+ $delivery = $filter['delivery'] ?? null;
+ if ( $delivery ) {
+ $this->operation->setDeliveryFlags(
+ Normalizer::formatDelivery($delivery)
+ );
+ }
+
+ $reviews = $filter['reviews'] ?? null;
+ $reviews = (int)$reviews;
+ if ( $reviews ) {
+ $this->operation->setMinReviewsRating($reviews);
+ }
+
+ $saving = $filter['saving'] ?? null;
+ $saving = (int)$saving;
+ if ( $saving ) {
+ $this->operation->setMinSavingPercent($saving);
+ }
+
+ $sort = $filter['sort'] ?? null;
+ $sort = (string)$sort;
+ if ( $sort ) {
+ $this->operation->setSortBy(
+ Normalizer::formatSort($sort)
+ );
+ }
+
+ $category = $filter['category'] ?? null;
+ $category = (string)$category;
+ if ( $category ) {
+ $this->operation->setSearchIndex(
+ Normalizer::formatCategory($category)
+ );
+ }
+
+ $brand = $filter['brand'] ?? null;
+ $brand = (string)$brand;
+ if ( $brand ) {
+ $this->operation->setBrand($brand);
+ }
+
+ $node = $filter['node'] ?? null;
+ $node = (string)$node;
+ if ( $node ) {
+ $this->operation->setBrowseNodeId($node);
+ }
+
+ $title = $filter['title'] ?? null;
+ $title = (string)$title;
+ if ( $title ) {
+ $this->operation->setTitle($title);
+ }
+
+ $actor = $filter['actor'] ?? null;
+ $actor = (string)$actor;
+ if ( $actor ) {
+ $this->operation->setActor($actor);
+ }
+
+ $artist = $filter['artist'] ?? null;
+ $artist = (string)$artist;
+ if ( $artist ) {
+ $this->operation->setArtist($artist);
+ }
+
+ $author = $filter['author'] ?? null;
+ $author = (string)$author;
+ if ( $author ) {
+ $this->operation->setAuthor($author);
+ }
+
+ }
+
+ $condition = $filter['condition'] ?? null;
+ $condition = (string)$condition;
+ if ( $condition ) {
+ $this->operation->setCondition(
+ Normalizer::formatCondition($condition)
+ );
+ }
+
+ $merchant = $filter['merchant'] ?? null;
+ $merchant = (string)$merchant;
+ if ( $merchant ) {
+ $this->operation->setMerchant($merchant);
+ }
+
+ $language = $filter['lang'] ?? null;
+ if ( $language ) {
+ $this->operation->setLanguages(
+ Normalizer::formatLanguage($language)
+ );
+ }
+
+ $currency = $filter['currency'] ?? null;
+ $currency = (string)$currency;
+ if ( $currency ) {
+ $this->operation->setCurrency(
+ Normalizer::formatCurrency($currency)
+ );
+ }
+
+ $marketplace = $filter['marketplace'] ?? null;
+ $marketplace = (string)$marketplace;
+ if ( $marketplace ) {
+ $this->operation->setMarketplace(
+ Normalizer::formatMarketplace($marketplace)
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set order.
+ *
+ * @access public
+ * @param mixed $order
+ * @return self
+ */
+ public function order($order) : self
+ {
+ $this->order = $order;
+ return $this;
+ }
+
+ /**
+ * Check search operation.
+ *
+ * @access private
+ * @return bool
+ */
+ private function isSearch() : bool
+ {
+ $class = 'Apaapi\operations\SearchItems';
+ return is_a($this->operation, $class, true);
+ }
+
+ /**
+ * Check node operation.
+ *
+ * @access private
+ * @return bool
+ */
+ private function isNode() : bool
+ {
+ $class = 'Apaapi\operations\GetBrowseNodes';
+ return is_a($this->operation, $class, true);
+ }
+
+ /**
+ * Prepare request.
+ *
+ * @access private
+ * @return object
+ */
+ private function prepare() : self
+ {
+ $this->request = new Request($this->key, $this->secret);
+ $this->request->setLocale($this->locale)->setPayload($this->operation);
+ return $this;
+ }
+
+ /**
+ * Fetch response.
+ *
+ * @access private
+ * @return array
+ */
+ private function fetch() : array
+ {
+ $response = new Response($this->request, Response::NORMALIZE);
+
+ $this->error = false;
+ if ( $response->hasError() ) {
+ $this->error = $response->getError();
+ }
+
+ return $response->get(
+ $this->redirect
+ );
+ }
+}
diff --git a/src/includes/Cache.php b/src/includes/Cache.php
new file mode 100644
index 0000000..15b83a6
--- /dev/null
+++ b/src/includes/Cache.php
@@ -0,0 +1,198 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+use Apaapi\interfaces\RequestInterface;
+
+/**
+ * Apaapi built-in cache helper.
+ * For high-performance applications use a dedicated caching system like Memcached or Redis.
+ * @see https://webservices.amazon.com/paapi5/documentation/best-programming-practices.html
+ */
+final class Cache
+{
+ private const TTL = 3600;
+ private const SALT = '0RhuksYDF';
+ private const EXT = 'db';
+
+ /**
+ * @access private
+ * @var int $ttl, Cache TTL
+ * @var string $salt, Cache salt
+ * @var string $ext, Cache extension
+ */
+ private static $ttl;
+ private static $salt;
+ private static $ext;
+
+ /**
+ * Set custom cache TTL.
+ *
+ * @access public
+ * @param int $ttl
+ * @return void
+ */
+ public static function setTtl(int $ttl = self::TTL)
+ {
+ self::$ttl = $ttl;
+ }
+
+ /**
+ * Set hash salt.
+ *
+ * @access public
+ * @param string $salt
+ * @return void
+ */
+ public static function setSalt(string $salt = self::SALT)
+ {
+ self::$salt = $salt;
+ }
+
+ /**
+ * Set cache extension.
+ *
+ * @access public
+ * @param string $ext
+ * @return void
+ */
+ public static function setExt(string $ext = self::EXT)
+ {
+ self::$ext = $ext;
+ }
+
+ /**
+ * Get request cache key.
+ *
+ * @access public
+ * @param RequestInterface $request
+ * @return string
+ */
+ public static function getKey(RequestInterface $request) : string
+ {
+ $params = $request->getParams();
+ $payload = $params['payload'] ?? '';
+ return self::generateKey((string)$payload);
+ }
+
+ /**
+ * Generate cache key.
+ *
+ * @access public
+ * @param string $item
+ * @return string
+ */
+ public static function generateKey(string $item) : string
+ {
+ self::init();
+ $item = self::$salt . $item;
+ return hash('sha256', $item);
+ }
+
+ /**
+ * Get cache value.
+ *
+ * @access public
+ * @param string $key
+ * @return mixed
+ */
+ public static function get(string $key)
+ {
+ if ( self::isCached($key) ) {
+ $file = self::getFile($key);
+ $value = @file_get_contents($file);
+ return unserialize($value);
+ }
+ return false;
+ }
+
+ /**
+ * Set cache value.
+ *
+ * @access public
+ * @param string $key
+ * @param mixed $value
+ * @return bool
+ */
+ public static function set(string $key, $value) : bool
+ {
+ self::init();
+ if ( $key == self::$salt ) {
+ return false;
+ }
+ $file = self::getFile($key);
+ $value = serialize($value);
+ return (bool)@file_put_contents($file, $value);
+ }
+
+ /**
+ * Check cache key.
+ *
+ * @access private
+ * @param string $key
+ * @return bool
+ */
+ private static function isCached(string $key) : bool
+ {
+ self::init();
+ $file = self::getFile($key);
+
+ if ( @file_exists($file) ) {
+ $time = time() - self::$ttl;
+ if ( $time < filemtime($file) ) {
+ return true;
+
+ } else {
+ @unlink($file);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get cache file.
+ *
+ * @access private
+ * @param string $key
+ * @return string
+ */
+ private static function getFile(string $key) : string
+ {
+ self::init();
+ $path = sys_get_temp_dir();
+ $path = "{$path}/{$key}." . self::$ext;
+ return Normalizer::formatPath($path);
+ }
+
+ /**
+ * Init cache settings.
+ *
+ * @access private
+ * @return void
+ */
+ private static function init()
+ {
+ if ( !self::$ttl ) {
+ self::setTTL();
+ }
+ if ( !self::$salt ) {
+ self::setSalt();
+ }
+ if ( !self::$ext ) {
+ self::setExt();
+ }
+ }
+}
diff --git a/src/includes/Client.php b/src/includes/Client.php
new file mode 100644
index 0000000..d117caa
--- /dev/null
+++ b/src/includes/Client.php
@@ -0,0 +1,391 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+use Apaapi\interfaces\ClientInterface;
+use Apaapi\exceptions\RequestException;
+
+/**
+ * Apaapi request client wrapper class.
+ */
+class Client implements ClientInterface
+{
+ /**
+ * @access private
+ */
+ private const CURL = 'curl';
+ private const STREAM = 'stream';
+
+ /**
+ * @access protected
+ * @var string $endpoint, Request URL
+ * @var string $method, Request method
+ * @var int $timeout, Request timeout
+ * @var int $redirect, Request redirect
+ * @var string $encoding, Request encoding
+ * @var array $params, Request params
+ * @var CurlHandle|ressource $handler, Request handler
+ * @var string $gateway, curl|stream
+ * @var mixed $response, Request response content
+ * @var bool $throwable, Request exception throw
+ * @var string $error, Response error content
+ * @var int $code, Response code
+ */
+ protected $endpoint;
+ protected $method = 'POST';
+ protected $timeout = 30;
+ protected $redirect = false;
+ protected $encoding = false;
+ protected $params;
+ protected $handler;
+ protected $gateway;
+ protected $throwable = false;
+ protected $response = false;
+ protected $error = false;
+ protected $code = 200;
+
+ /**
+ * @inheritdoc
+ */
+ public function __construct(string $endpoint, array $params = [], bool $throwable = false)
+ {
+ $this->endpoint = $endpoint;
+ $this->params = $params;
+ $this->throwable = $throwable;
+ $this->setGateway();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setMethod(string $method) : self
+ {
+ $this->method = strtoupper($method);
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setTimeout(int $timeout) : self
+ {
+ $this->timeout = $timeout;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setRedirect(int $redirect) : self
+ {
+ $this->redirect = $redirect;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setEncoding(string $encoding) : self
+ {
+ $this->encoding = $encoding;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getResponse() : string
+ {
+ $this->setHandler();
+ $this->send();
+
+ if ( $this->hasError() ) {
+ return $this->error;
+ }
+
+ return (string)$this->response;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getCode() : int
+ {
+ return $this->code;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function close()
+ {
+ if ( $this->isCurl() ) {
+ curl_close($this->handler);
+
+ } elseif ( $this->isStream() ) {
+ fclose($this->handler);
+ }
+ }
+
+ /**
+ * Check curl status.
+ *
+ * @access public
+ * @return bool
+ */
+ public static function hasCurl() : bool
+ {
+ return function_exists('curl_init');
+ }
+
+ /**
+ * Check stream status.
+ *
+ * @access public
+ * @return bool
+ */
+ public static function hasStream() : bool
+ {
+ $val = intval(ini_get('allow_url_fopen'));
+ return (bool)$val;
+ }
+
+ /**
+ * Set HTTP handler.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function setHandler()
+ {
+ if ( $this->isCurl() ) {
+
+ $this->handler = curl_init();
+
+ curl_setopt($this->handler, CURLOPT_URL, $this->endpoint);
+ curl_setopt($this->handler, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->handler, CURLOPT_HTTPHEADER, $this->getRequestHeader());
+ curl_setopt($this->handler, CURLOPT_SSL_VERIFYPEER, $this->isSsl());
+ curl_setopt($this->handler, CURLOPT_TIMEOUT, $this->timeout);
+
+ if ( $this->encoding !== false ) {
+ curl_setopt($this->handler, CURLOPT_ENCODING, $this->encoding);
+ }
+
+ if ( $this->redirect ) {
+ curl_setopt($this->handler, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($this->handler, CURLOPT_MAXREDIRS, $this->redirect);
+ }
+
+ if ( $this->isPost() ) {
+ curl_setopt($this->handler, CURLOPT_POSTFIELDS, $this->getRequestPayload());
+ curl_setopt($this->handler, CURLOPT_POST, true);
+ }
+
+ } elseif ( $this->isStream() ) {
+ $this->handler = stream_context_create([
+ 'http' => [
+ 'method' => $this->method,
+ 'header' => $this->getRequestHeader(),
+ 'content' => $this->getRequestPayload(),
+ 'timeout' => $this->timeout
+ ]
+ ]);
+ }
+ }
+
+ /**
+ * Check client error.
+ *
+ * @access protected
+ * @return bool
+ */
+ protected function hasError() : bool
+ {
+ return (bool)$this->error;
+ }
+
+ /**
+ * Send request.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function send()
+ {
+ if ( $this->isCurl() ) {
+ $this->sendCurl();
+
+ } elseif ( $this->isStream() ) {
+ $this->sendStream();
+ }
+ }
+
+ /**
+ * Check SSL status.
+ *
+ * @access protected
+ * @return bool
+ */
+ protected function isSsl() : bool
+ {
+ if ( isset($_SERVER['HTTPS']) ) {
+ if ( strtolower($_SERVER['HTTPS']) === 'on' ) {
+ return true;
+ }
+ if ( $_SERVER['HTTPS'] === '1' ) {
+ return true;
+ }
+
+ } elseif ( isset($_SERVER['SERVER_PORT']) ) {
+ return ($_SERVER['SERVER_PORT'] === '443');
+ }
+ return false;
+ }
+
+ /**
+ * Set client gateway.
+ *
+ * @access protected
+ * @return void
+ * @throws RequestException
+ */
+ protected function setGateway()
+ {
+ if ( !self::hasCurl() && !self::hasStream() ) {
+ $this->code = 0;
+ $this->error = RequestException::invalidClient();
+ if ( $this->throwable ) {
+ throw new RequestException($this->error);
+ }
+
+ } else {
+ if ( self::hasCurl() ) {
+ $this->gateway = self::CURL;
+
+ } elseif ( self::hasStream() ) {
+ $this->gateway = self::STREAM;
+ }
+ }
+ }
+
+ /**
+ * Get request payload.
+ *
+ * @access protected
+ * @return string
+ */
+ protected function getRequestPayload() : string
+ {
+ $payload = $this->params['payload'] ?? '';
+ return (string)$payload;
+ }
+
+ /**
+ * Get request header.
+ *
+ * @access protected
+ * @return array
+ */
+ protected function getRequestHeader() : array
+ {
+ $header = $this->params['header'] ?? '';
+ if ( is_array($header)) {
+ return $header;
+ }
+ $header = explode("\r\n", (string)$header);
+ return ($header) ? $header : [];
+ }
+
+ /**
+ * Send curl request.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function sendCurl()
+ {
+ $this->response = curl_exec($this->handler);
+ $info = curl_getinfo($this->handler);
+ $this->code = $info['http_code'] ?? 0;
+
+ if ( curl_errno($this->handler) ) {
+ $this->code = 0;
+ $this->error = curl_error($this->handler);
+ }
+
+ if ( $this->response && $this->code !== 200 ) {
+ $this->error = $this->response;
+ $this->response = false;
+ }
+ }
+
+ /**
+ * Send stream request.
+ *
+ * @access protected
+ * @return void
+ */
+ protected function sendStream()
+ {
+ $this->response = @file_get_contents($this->endpoint, false, $this->handler);
+ $headers = @get_headers($this->endpoint, false, $this->handler);
+
+ if ( $headers ) {
+ $status = $headers[0] ?? '';
+ $this->code = (int)substr($status, 9, 3);
+ if ( !$this->response || $this->code !== 200 ) {
+ $this->error = $status;
+ }
+
+ } else {
+ $this->code = 0;
+ $this->error = 'Failed to open stream';
+ }
+ }
+
+ /**
+ * Check curl gateway.
+ *
+ * @access private
+ * @return bool
+ */
+ private function isCurl() : bool
+ {
+ return ($this->gateway == self::CURL);
+ }
+
+ /**
+ * Check stream gateway.
+ *
+ * @access private
+ * @return bool
+ */
+ private function isStream() : bool
+ {
+ return ($this->gateway == self::STREAM);
+ }
+
+ /**
+ * Check post method.
+ *
+ * @access private
+ * @return bool
+ */
+ private function isPost() : bool
+ {
+ return ($this->method == 'POST');
+ }
+}
diff --git a/src/includes/Geotargeting.php b/src/includes/Geotargeting.php
new file mode 100644
index 0000000..2eaf13b
--- /dev/null
+++ b/src/includes/Geotargeting.php
@@ -0,0 +1,359 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+/**
+ * Apaapi built-in geotargeting helper.
+ * For high-performance applications use MaxMind GeoIP2 database.
+ * @see https://dev.maxmind.com/geoip
+ */
+final class Geotargeting
+{
+ /**
+ * @access private
+ * @var string $visitorKey, Cache key
+ * @var array $exception, Exception IP addresses
+ * @var bool $redirectNotFound, Redirect 404 result
+ */
+ private static $visitorKey = '--visitor-id';
+ private static $exception = ['::1', '127.0.0.1', '0.0.0.0'];
+ private static $redirectNotFound = false;
+
+ /**
+ * @access private
+ * @var bool $isDetected, Geotargeting status
+ * @var array $api, Geotargeting APIs
+ * @var array $target, Geotargeting partner tags
+ * @var mixed $code, External country code
+ * @var string $tag, Current partner tag
+ * @var string $locale, Current locale
+ * @var array $redirect, Redirection target
+ */
+ private $isDetected = false;
+ private $api = [];
+ private $target = [];
+ private $code = false;
+ private $tag;
+ private $locale;
+ private $redirect = [];
+
+ /**
+ * Set redirection args.
+ *
+ * @param array $args
+ */
+ public function __construct(array $args)
+ {
+ $this->api = $args['api'] ?? [];
+ $this->target = $args['target'] ?? [];
+ $this->tag = $args['tag'] ?? '';
+ $this->locale = $args['locale'] ?? '';
+ $this->code = $args['code'] ?? '';
+
+ $this->api = array_merge([
+ 'ip' => ['address' => null, 'param' => null],
+ 'geo' => ['address' => null, 'param' => null]
+ ], $this->api);
+
+ $this->detect();
+ }
+
+ /**
+ * Get redirected response data.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ public function get(array $data) : array
+ {
+ if ( $this->isDetected ) {
+ $data = array_map(function($item) {
+ return self::redirect($item);
+ }, $data);
+ }
+ return $data;
+ }
+
+ /**
+ * Set visitor key.
+ *
+ * @access public
+ * @param string $visitorKey
+ * @return void
+ */
+ public static function setVisitorKey(string $visitorKey)
+ {
+ self::$visitorKey = $visitorKey;
+ }
+
+ /**
+ * Set exception IP addresses.
+ *
+ * @access public
+ * @param array $exception
+ * @return void
+ */
+ public static function setException(array $exception)
+ {
+ self::$exception = $exception;
+ }
+
+ /**
+ * Redirect 404 result.
+ *
+ * @access public
+ * @return void
+ */
+ public static function redirectNotFound()
+ {
+ self::$redirectNotFound = true;
+ }
+
+ /**
+ * Redirect item.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private function redirect(array $item) : array
+ {
+ if ( isset($item['url']) ) {
+
+ $host = Provider::HOST;
+ $from = str_replace('{locale}', $this->locale, $host);
+ $to = str_replace('{locale}', $this->redirect['tld'], $host);
+
+ $item['url'] = str_replace([
+ $from,
+ "?tag={$this->tag}"
+ ], [
+ $to,
+ "?tag={$this->redirect['tag']}"
+ ], $item['url']);
+
+ if ( self::$redirectNotFound ) {
+
+ $client = new Client($item['url'], [
+ 'header' => Provider::generateHeader(
+ $this->redirect['tld']
+ )
+ ]);
+
+ $client->setMethod('GET')
+ ->setRedirect(2)
+ ->setTimeout(0);
+
+ $client->getResponse();
+ $client->close();
+
+ if ( $client->getCode() == 404 ) {
+
+ $title = $item['title'] ?? '';
+ $keyword = substr($title, 0, 20);
+ $keyword = preg_replace('/[^a-zA-Z0-9\s]/', '', $keyword);
+ $keyword = urlencode($keyword);
+
+ $url = "{$to}/s?k={$keyword}&tag={$this->redirect['tag']}";
+ $url = "{$url}&linkCode=ll2";
+ $item['url'] = $url;
+
+ }
+ }
+ }
+
+ return $item;
+ }
+
+ /**
+ * Detect redirection target.
+ *
+ * @access private
+ * @return void
+ */
+ private function detect()
+ {
+ $code = $this->getCountryCode();
+ if ( $this->target ) {
+ if ( isset($this->target[$code]) && !empty($this->target[$code]) ) {
+ $this->isDetected = true;
+ $this->redirect = [
+ 'tld' => Normalizer::formatTLD($code),
+ 'tag' => $this->target[$code]
+ ];
+ }
+
+ } else {
+ $this->isDetected = false;
+ }
+ }
+
+ /**
+ * Get current country code.
+ *
+ * @access private
+ * @return string
+ */
+ private function getCountryCode() : string
+ {
+ if ( $this->code ) {
+ return $this->code;
+ }
+
+ // Get visitor IP
+ if ( !($ip = $this->getIp()) ) {
+ $ip = '0.0.0.0';
+ }
+
+ // Get IP from external API
+ if ( in_array($ip, self::$exception) ) {
+ $ip = $this->getApiAddressIp();
+ }
+
+ // Get code from external API
+ return $this->getApiCountryCode($ip);
+ }
+
+ /**
+ * Get current country code using API.
+ *
+ * @access private
+ * @param string $ip
+ * @return string
+ */
+ private function getApiCountryCode(string $ip = '0.0.0.0') : string
+ {
+ $code = 'us';
+ $address = $this->api['geo']['address'] ?? '';
+ $param = $this->api['geo']['param'] ?? '';
+
+ if ( !$address || !$param ) {
+ return $code;
+ }
+
+ $key = Cache::generateKey("geo-{$this->getVisitorId()}");
+ if ( !($code = Cache::get($key)) ) {
+
+ $address = str_replace('{ip}', $ip, $address);
+ $client = new Client($address);
+ $client->setMethod('GET')->setTimeout(5);
+ $response = $client->getResponse();
+ $client->close();
+
+ if ( $client->getCode() == 200 ) {
+ $response = Normalizer::decode($response);
+ $code = $response[$param] ?? '';
+ }
+
+ Cache::set($key, $code);
+
+ }
+
+ $code = (string)$code;
+ return Normalizer::formatCountryCode($code);
+ }
+
+ /**
+ * Get current IP address using API.
+ *
+ * @access private
+ * @return string
+ */
+ private function getApiAddressIp() : string
+ {
+ $ip = '0.0.0.0';
+ $address = $this->api['ip']['address'] ?? '';
+ $param = $this->api['ip']['param'] ?? '';
+
+ if ( !$address || !$param ) {
+ return $ip;
+ }
+
+ $key = Cache::generateKey("ip-{$this->getVisitorId()}");
+ if ( !($ip = Cache::get($key)) ) {
+
+ $client = new Client($address);
+ $client->setMethod('GET')->setTimeout(5);
+ $response = $client->getResponse();
+ $client->close();
+
+ if ( $client->getCode() == 200 ) {
+ $response = Normalizer::decode($response);
+ $ip = $response[$param] ?? '';
+ }
+
+ Cache::set($key, $ip);
+
+ }
+
+ return (string)$ip;
+ }
+
+ /**
+ * Get remote IP address.
+ *
+ * @access private
+ * @return string
+ */
+ private function getIp() : string
+ {
+ if ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
+ return $this->parseIp($_SERVER['HTTP_X_FORWARDED_FOR']);
+
+ } elseif ( isset($_SERVER['HTTP_X_REAL_IP']) ) {
+ return $this->parseIp($_SERVER['HTTP_X_REAL_IP']);
+
+ } elseif ( isset($_SERVER['HTTP_CF_CONNECTING_IP']) ) {
+ return $this->parseIp($_SERVER['HTTP_CF_CONNECTING_IP']);
+ }
+
+ $ip = $_SERVER['REMOTE_ADDR'] ?? '';
+ return $this->parseIp($ip);
+ }
+
+ /**
+ * Parse remote IP address.
+ *
+ * @access private
+ * @param string $ip
+ * @return string
+ */
+ private function parseIp(string $ip) : string
+ {
+ $ip = stripslashes($ip);
+ $ip = preg_split('/,/', $ip, -1, 0);
+ $ip = (string)current($ip);
+ return trim($ip);
+ }
+
+ /**
+ * Get visitor ID.
+ *
+ * @access private
+ * @return string
+ */
+ private function getVisitorId() : string
+ {
+ if ( isset($_COOKIE[self::$visitorKey]) ) {
+ return $_COOKIE[self::$visitorKey];
+ }
+
+ $visitorId = uniqid();
+ setcookie(self::$visitorKey, $visitorId, time() + (86400 * 30), '/');
+
+ return $visitorId;
+ }
+}
diff --git a/src/includes/Keyword.php b/src/includes/Keyword.php
new file mode 100644
index 0000000..9b90dad
--- /dev/null
+++ b/src/includes/Keyword.php
@@ -0,0 +1,171 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+final class Keyword
+{
+ /**
+ * Check GTIN (EAN, UPC, ISBN).
+ *
+ * /^(?:\d{8,14}|(?:\d{3}-)?\d{9}[\dX])$/
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isGTIN(string $keyword) : bool
+ {
+ return (bool)preg_match('/^(?:\d{8,14}|(?:\d{3}-)?\d{9}[\dX])$/', $keyword);
+ }
+
+ /**
+ * Check EAN (EAN-8, EAN-13).
+ *
+ * /^\d{7}\d$/
+ * /^\d{12}\d$/
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isEAN(string $keyword) : bool
+ {
+ if ( preg_match('/^\d{7}\d$/', $keyword) ) {
+ return true;
+
+ } elseif ( preg_match('/^\d{12}\d$/', $keyword) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check UPC (UPC-E, UPC-A).
+ *
+ * /^\d{6,8}$/
+ * /^\d{12}$/
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isUPC(string $keyword) : bool
+ {
+ if ( preg_match('/^\d{6,8}$/', $keyword) ) {
+ return true;
+
+ } elseif ( preg_match('/^\d{12}$/', $keyword) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check ISBN (ISBN-10, ISBN-13).
+ *
+ * /^(?:\d{9}[\dX]|\d{13})$/
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isISBN(string $keyword) : bool
+ {
+ return (bool)preg_match('/^(?:\d{9}[\dX]|\d{13})$/', $keyword);
+ }
+
+ /**
+ * Check ASIN.
+ *
+ * /^B0[A-Z0-9]{8}$/
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isASIN(string $keyword) : bool
+ {
+ return (bool)preg_match('/^B0[A-Z0-9]{8}$/', $keyword);
+ }
+
+ /**
+ * Check barcode (GTIN, ASIN).
+ *
+ * @access public
+ * @param string $keyword
+ * @return bool
+ */
+ public static function isBarcode(string $keyword) : bool
+ {
+ if ( self::isGTIN($keyword) || self::isASIN($keyword) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Parse ISBN.
+ *
+ * /(?:\d{9}[\dX]|\d{13})/
+ *
+ * @access public
+ * @param string $keyword
+ * @return string
+ */
+ public static function parseISBN(string $keyword) : string
+ {
+ preg_match('/(?:\d{9}[\dX]|\d{13})/', $keyword, $match);
+ if ( $match ) {
+ $keyword = $match[0] ?? '';
+ }
+ return (self::isISBN($keyword)) ? $keyword : '';
+ }
+
+ /**
+ * Parse ASIN.
+ *
+ * /B0[A-Z0-9]{8}/
+ *
+ * @access public
+ * @param string $keyword
+ * @return string
+ */
+ public static function parseASIN(string $keyword) : string
+ {
+ preg_match('/B0[A-Z0-9]{8}/', $keyword, $match);
+ if ( $match ) {
+ $keyword = $match[0] ?? '';
+ }
+ return (self::isASIN($keyword)) ? $keyword : '';
+ }
+
+ /**
+ * Parse barcode (GTIN, ASIN).
+ *
+ * @access public
+ * @param string $keyword
+ * @return string
+ */
+ public static function parseBarcode(string $keyword) : string
+ {
+ if ( ($isbn = self::parseISBN($keyword)) ) {
+ $keyword = $isbn;
+
+ } elseif ( ($asin = self::parseASIN($keyword)) ) {
+ $keyword = $asin;
+ }
+ return $keyword;
+ }
+}
diff --git a/src/includes/Normalizer.php b/src/includes/Normalizer.php
new file mode 100644
index 0000000..afe8bc7
--- /dev/null
+++ b/src/includes/Normalizer.php
@@ -0,0 +1,1115 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+/**
+ * Apaapi data normalizer.
+ */
+final class Normalizer
+{
+ /**
+ * @access private
+ * @var int $limit, List limit
+ * @var bool $format, String format
+ * @var bool $order, Data order
+ */
+ private static $limit = 5;
+ private static $format = false;
+ private static $order = true;
+
+ /**
+ * Set lists limit.
+ *
+ * @access public
+ * @param int $limit
+ * @return void
+ */
+ public static function limit(int $limit)
+ {
+ self::$limit = $limit;
+ }
+
+ /**
+ * Keep default string format.
+ *
+ * @access public
+ * @return void
+ */
+ public static function noFormat()
+ {
+ self::$format = true;
+ }
+
+ /**
+ * Disable order.
+ *
+ * @access public
+ * @return void
+ */
+ public static function noOrder()
+ {
+ self::$order = false;
+ }
+
+ /**
+ * Get normalized response data.
+ *
+ * @access public
+ * @param array $data
+ * @param string $operation
+ * @return array
+ */
+ public static function get(array $data, string $operation) : array
+ {
+ $data = self::parse($data, $operation);
+ if ( isset($data['node']) ) {
+ return self::normalizeNode($data['node']);
+ }
+ if ( isset($data['category']) ) {
+ return self::normalizeCategory($data['category']);
+ return $data['category'];
+ }
+ return array_map(function($item) {
+ return self::normalize($item);
+ }, $data);
+ }
+
+ /**
+ * Parse response data items.
+ *
+ * @access public
+ * @param array $data
+ * @param string $operation
+ * @return array
+ */
+ public static function parse(array $data, string $operation) : array
+ {
+ switch ($operation) {
+ case 'GetItems':
+ return self::parseItem($data);
+ break;
+
+ case 'SearchItems':
+ return self::parseSearch($data);
+ break;
+
+ case 'GetVariations':
+ return self::parseVariation($data);
+ break;
+
+ case 'GetBrowseNodes':
+ return self::parseNode($data);
+ break;
+ }
+ return $data;
+ }
+
+ /**
+ * Format single id.
+ *
+ * @access public
+ * @param string $id
+ * @return string
+ */
+ public static function formatId(string $id) : string
+ {
+ $id = self::stripSpace(
+ strtoupper($id)
+ );
+ if ( self::isUrl($id) ) {
+ return Keyword::parseBarcode($id);
+ }
+ return $id;
+ }
+
+ /**
+ * Format ids.
+ *
+ * @access public
+ * @param mixed $ids
+ * @return array
+ */
+ public static function formatIds($ids) : array
+ {
+ if ( is_string($ids) ) {
+ $ids = self::stripSpace(
+ strtoupper($ids)
+ );
+ $ids = explode(',', $ids);
+ }
+
+ $ids = array_map(function($id) {
+ return self::formatId($id);
+ }, (array)$ids);
+
+ return $ids;
+ }
+
+ /**
+ * Format single keyword.
+ *
+ * @access public
+ * @param string $keyword
+ * @param bool $single
+ * @return string
+ */
+ public static function formatKeyword(string $keyword) : string
+ {
+ $keyword = trim($keyword);
+
+ if ( strpos($keyword, ',') !== false ) {
+ $keyword = explode(',', $keyword);
+ $keyword = (string)array_shift($keyword);
+ }
+
+ if ( self::isUrl($keyword) ) {
+ return Keyword::parseBarcode($keyword);
+ }
+
+ return $keyword;
+ }
+
+ /**
+ * Format keywords.
+ *
+ * @access public
+ * @param mixed $keywords
+ * @return string
+ */
+ public static function formatKeywords($keywords) : string
+ {
+ if ( !is_array($keywords) ) {
+ $keywords = trim((string)$keywords);
+ $keywords = explode(',', $keywords);
+ }
+
+ $keywords = array_map(function($keyword) {
+ return self::formatKeyword($keyword);
+ }, $keywords);
+
+ return implode(', ', $keywords);
+ }
+
+ /**
+ * Format cart items.
+ *
+ * @access public
+ * @param mixed $items
+ * @return array
+ */
+ public static function formatCart($items) : array
+ {
+ if ( is_string($items) ) {
+ $items = self::formatIds($items);
+ }
+
+ $items = (array)$items;
+ $cart = [];
+
+ foreach ($items as $key => $item) {
+ if ( is_int($key) ) {
+ $item = self::formatId((string)$item);
+ $cart[$item] = '1';
+
+ } else {
+ $key = self::formatId($key);
+ $cart[$key] = (string)intval($item);
+ }
+ }
+
+ return $cart;
+ }
+
+ /**
+ * Format filter price.
+ *
+ * @access public
+ * @param mixed $price
+ * @return int
+ */
+ public static function formatPrice($price) : int
+ {
+ $price = (string)$price;
+
+ if ( strpos($price, '.') === false ) {
+ $price = "{$price}00";
+
+ } else {
+ $price = str_replace('.', '', $price);
+ }
+
+ return (int)$price;
+ }
+
+ /**
+ * Format filter delivery.
+ *
+ * @access public
+ * @param mixed $delivery
+ * @return array
+ */
+ public static function formatDelivery($delivery) : array
+ {
+ if ( is_string($delivery) ) {
+ $delivery = self::stripSpace(
+ strtolower($delivery)
+ );
+ $delivery = explode(',', $delivery);
+ }
+
+ $delivery = (array)$delivery;
+ $flags = [];
+
+ $delivery = array_map(function($item) {
+ return trim($item);
+ }, $delivery);
+
+ foreach ($delivery as $key => $item) {
+ if ( $item === 'global' ) {
+ $flags[] = 'AmazonGlobal';
+
+ } elseif ( $item === 'free' ) {
+ $flags[] = 'FreeShipping';
+
+ } elseif ( $item === 'fulfilled' ) {
+ $flags[] = 'FulfilledByAmazon';
+
+ } elseif ( $item === 'prime' ) {
+ $flags[] = 'Prime';
+ }
+ }
+
+ return $flags;
+ }
+
+ /**
+ * Format filter sort.
+ *
+ * @access public
+ * @param string $sort
+ * @return string
+ */
+ public static function formatSort(string $sort) : string
+ {
+ $sort = self::stripSpace(
+ strtolower($sort)
+ );
+
+ if ( $sort == 'reviews' ) {
+ $sort = 'AvgCustomerReviews';
+
+ } elseif ( $sort == 'featured' ) {
+ $sort = 'Featured';
+
+ } elseif ( $sort == 'newest' ) {
+ $sort = 'NewestArrivals';
+
+ } elseif ( $sort == 'highest' ) {
+ $sort = 'Price:HighToLow';
+
+ } elseif ( $sort == 'lowest' ) {
+ $sort = 'Price:LowToHigh';
+
+ } elseif ( $sort == 'relevance' ) {
+ $sort = 'Relevance';
+ }
+
+ return $sort;
+ }
+
+ /**
+ * Format filter condition.
+ *
+ * @access public
+ * @param string $condition
+ * @return string
+ */
+ public static function formatCondition(string $condition) : string
+ {
+ $condition = self::stripSpace(
+ strtolower($condition)
+ );
+ return ucfirst($condition);
+ }
+
+ /**
+ * Format filter category.
+ *
+ * @access public
+ * @param string $category
+ * @return string
+ */
+ public static function formatCategory(string $category) : string
+ {
+ return self::stripSpace($category);
+ }
+
+ /**
+ * Format filter language.
+ *
+ * @access public
+ * @param mixed $language
+ * @return array
+ */
+ public static function formatLanguage($language) : array
+ {
+ return (array)$language;
+ }
+
+ /**
+ * Format filter currency.
+ *
+ * @access public
+ * @param string $currency
+ * @return string
+ */
+ public static function formatCurrency(string $currency) : string
+ {
+ return $currency;
+ }
+
+ /**
+ * Format filter marketplace.
+ *
+ * @access public
+ * @param string $marketplace
+ * @return string
+ */
+ public static function formatMarketplace(string $marketplace) : string
+ {
+ return $marketplace;
+ }
+
+ /**
+ * Format request locale.
+ *
+ * @access public
+ * @param string $locale
+ * @return mixed
+ */
+ public static function formatLocale(string $locale)
+ {
+ $locale = self::stripSpace(
+ strtolower($locale)
+ );
+ if ( ($l = explode('_', $locale)) ) {
+ $locale = $l[0];
+ }
+ if ( !in_array($locale, Provider::getLocales()) ) {
+ $locale = false;
+ }
+ return $locale;
+ }
+
+ /**
+ * Format response error.
+ *
+ * @access public
+ * @param string $body
+ * @return string
+ */
+ public static function formatError(string $body) : string
+ {
+ $error = false;
+ if ( ($data = self::decode($body)) ) {
+ $error = $data['Errors'][0]['Message'] ?? '';
+ $regex = [
+ '/\s(? 'asc'];
+ }
+
+ $order = (array)$order;
+
+ foreach ($order as $key => $dir) {
+ if ( is_int($key) ) {
+ unset($order[$key]);
+ $key = (string)$dir;
+ $dir = 'asc';
+
+ } else {
+ $key = (string)$key;
+ $dir = (string)$dir;
+ }
+ $order[$key] = $dir;
+ }
+
+ return $order;
+ }
+
+ /**
+ * Decode data.
+ *
+ * @access public
+ * @param string $data
+ * @return array
+ */
+ public static function decode(string $data) : array
+ {
+ return (array)@json_decode($data, true);
+ }
+
+ /**
+ * Format country code (Fix 3 DIGIT ISO),
+ * Lowercased ISO (3166‑1 alpha‑2).
+ *
+ * @access private
+ * @param string $code
+ * @return string
+ * @see https://countrycode.org/
+ */
+ public static function formatCountryCode(string $code) : string
+ {
+ return substr(strtolower($code), 0, 2);
+ }
+
+ /**
+ * Format TLD from country code.
+ *
+ * @access public
+ * @param string $code
+ * @return string
+ */
+ public static function formatTLD(string $code) : string
+ {
+ switch ($code) {
+ case 'au':
+ return 'com.au';
+ break;
+ case 'be':
+ return 'com.be';
+ break;
+ case 'br':
+ return 'com.br';
+ break;
+ case 'jp':
+ return 'co.jp';
+ break;
+ case 'mx':
+ return 'com.mx';
+ break;
+ case 'tr':
+ return 'com.tr';
+ break;
+ case 'uk':
+ case 'gb':
+ return 'co.uk';
+ break;
+ case 'us':
+ return 'com';
+ break;
+ default:
+ return $code;
+ break;
+ };
+ }
+
+ /**
+ * Apply dynamic args recursively.
+ *
+ * @access public
+ * @param mixed $data
+ * @param array $args
+ * @return mixed
+ */
+ public static function applyArgs($data, array $args)
+ {
+ $recursive = function ($item) use (&$recursive, $args) {
+ if ( is_array($item) ) {
+ foreach ($item as $key => $value) {
+ $item[$key] = $recursive($value);
+ }
+
+ } elseif ( is_string($item) ) {
+ $item = str_replace(
+ array_keys($args),
+ array_values($args),
+ $item
+ );
+ }
+ return $item;
+ };
+ return $recursive($data);
+ }
+
+ /**
+ * Order data.
+ *
+ * @access public
+ * @param array $data
+ * @param mixed $orderby
+ * @param string $order
+ * @param bool $preserve (keys)
+ * @return array
+ */
+ public static function order(array $data, $orderby, string $order = 'asc') : array
+ {
+ if ( !self::$order ) {
+ return $data;
+ }
+
+ $orderby = self::formatOrderBy($orderby);
+
+ foreach ($orderby as $key => $dir) {
+ $orderby[$key] = ('desc' === strtolower($dir)) ? 'desc' : 'asc';
+ }
+
+ $sort = function($a, $b) use ($orderby) {
+
+ $a = (array)$a;
+ $b = (array)$b;
+
+ foreach ($orderby as $key => $dir) {
+
+ if ( !isset($a[$key]) || !isset($b[$key]) ) {
+ continue;
+ }
+
+ if ($a[$key] == 0) return 1;
+ if ($b[$key] == 0) return -1;
+
+ if ( $a[$key] == $b[$key] ) {
+ continue;
+ }
+
+ $val = ('desc' === $dir) ? [1, -1] : [-1, 1];
+
+ if ( is_numeric($a[$key]) && is_numeric($b[$key]) ) {
+ return ($a[$key] < $b[$key]) ? $val[0] : $val[1];
+ }
+
+ return 0 > strcmp($a[$key], $b[$key]) ? $val[0] : $val[1];
+ }
+
+ return 0;
+ };
+
+ usort($data, $sort);
+ return $data;
+ }
+
+ /**
+ * Normalize item.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function normalize(array $item) : array
+ {
+ return [
+ 'asin' => self::sanitizeASIN($item),
+ 'ean' => self::sanitizeEAN($item),
+ 'node' => self::sanitizeNode($item),
+ 'root' => self::sanitizeRoot($item),
+ 'rank' => self::sanitizeRank($item),
+ 'title' => self::sanitizeTitle($item),
+ 'category' => self::sanitizeCategory($item),
+ 'url' => self::sanitizeUrl($item),
+ 'image' => self::sanitizeImage($item),
+ 'gallery' => self::sanitizeGallery($item),
+ 'price' => self::sanitizePrice($item),
+ 'discount' => self::sanitizeDiscount($item),
+ 'discounted' => self::sanitizeDiscounted($item),
+ 'percent' => self::sanitizePercent($item),
+ 'currency' => self::sanitizeCurrency($item),
+ 'availability' => self::sanitizeAvailability($item),
+ 'shipping' => self::sanitizeShipping($item),
+ 'features' => self::sanitizeFeatures($item)
+ ];
+ }
+
+ /**
+ * Normalize node.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function normalizeNode(array $data) : array
+ {
+ $node = [];
+ if ( ($id = $data['Id'] ?? false) ) {
+ $node = [
+ 'id' => $id,
+ 'name' => $data['ContextFreeName'] ?? '',
+ 'root' => $data['IsRoot'] ?? false,
+ 'url' => Provider::getNodeUrl($id),
+ 'ancestor' => self::parseAncestor($data),
+ 'children' => self::parseChildren($data)
+ ];
+ }
+ return $node;
+ }
+
+ /**
+ * Normalize category.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function normalizeCategory(array $data) : array
+ {
+ $categories = [];
+ foreach ($data as $category) {
+ if ( ($id = $category['Id'] ?? false) ) {
+ $categories[] = [
+ 'id' => $id,
+ 'name' => $category['DisplayName'] ?? ''
+ ];
+ }
+ }
+ return $categories;
+ }
+
+ /**
+ * Parse node.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function parseNode(array $data) : array
+ {
+ $data = $data['BrowseNodesResult']['BrowseNodes'][0] ?? [];
+ return ['node' => $data];
+ }
+
+ /**
+ * Parse item.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function parseItem(array $data) : array
+ {
+ return $data['ItemsResult']['Items'] ?? [];
+ }
+
+ /**
+ * Parse search.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function parseSearch(array $data) : array
+ {
+ if ( isset($data['SearchResult']['SearchRefinements']) ) {
+ $data = $data['SearchResult']['SearchRefinements'];
+ $data = $data['SearchIndex']['Bins'] ?? [];
+ return ['category' => $data];
+ }
+ return $data['SearchResult']['Items'] ?? [];
+ }
+
+ /**
+ * Parse variation.
+ *
+ * @access private
+ * @param array $data
+ * @return array
+ */
+ private static function parseVariation(array $data) : array
+ {
+ return $data['VariationsResult']['Items'] ?? [];
+ }
+
+ /**
+ * Parse node ancestor.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function parseAncestor(array $item) : array
+ {
+ $ancestor = [];
+ if ( ($id = $item['Ancestor']['Id'] ?? false) ) {
+ $ancestor = [
+ 'id' => $id,
+ 'name' => $item['Ancestor']['ContextFreeName'] ?? '',
+ 'url' => Provider::getNodeUrl($id)
+ ];
+ }
+ return $ancestor;
+ }
+
+ /**
+ * Parse node children.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function parseChildren(array $item) : array
+ {
+ $children = [];
+ $item = $item['Children'] ?? [];
+ foreach ($item as $child) {
+ if ( ($id = $child['Id']) ) {
+ $children[] = [
+ 'id' => $id,
+ 'name' => $child['ContextFreeName'] ?? '',
+ 'url' => Provider::getNodeUrl($id)
+ ];
+ }
+ }
+ return $children;
+ }
+
+ /**
+ * Sanitize item EAN.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeEAN(array $item) : string
+ {
+ return $item['ItemInfo']['ExternalIds']['EANs']['DisplayValues'][0] ?? '';
+ }
+
+ /**
+ * Sanitize item ASIN.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeASIN(array $item) : string
+ {
+ return $item['ASIN'] ?? '';
+ }
+
+ /**
+ * Sanitize item title.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeTitle(array $item) : string
+ {
+ $title = $item['ItemInfo']['Title']['DisplayValue'] ?? '';
+ return self::formatString($title);
+ }
+
+ /**
+ * Sanitize item url.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeUrl(array $item) : string
+ {
+ return $item['DetailPageURL'] ?? '';
+ }
+
+ /**
+ * Sanitize item image.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeImage(array $item) : string
+ {
+ return $item['Images']['Primary']['Large']['URL'] ?? '';
+ }
+
+ /**
+ * Sanitize item gallery.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function sanitizeGallery(array $item) : array
+ {
+ $gallery = [];
+ $variants = $item['Images']['Variants'] ?? [];
+ foreach ($variants as $variant) {
+ $gallery[] = $variant['Large']['URL'];
+ }
+ if ( self::$limit ) {
+ $gallery = array_slice($gallery, 0, self::$limit);
+ }
+ return $gallery;
+ }
+
+ /**
+ * Sanitize item category.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeCategory(array $item) : string
+ {
+ $node = $item['BrowseNodeInfo']['BrowseNodes'][0] ?? [];
+ $count = count($node);
+ for ($i = 0; $i < $count; $i++) {
+ if ( !isset($node['Ancestor']) ) break;
+ $node = $node['Ancestor'];
+ }
+ return $node['ContextFreeName'] ?? '';
+ }
+
+ /**
+ * Sanitize item node Id.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeNode(array $item) : string
+ {
+ $node = $item['BrowseNodeInfo']['BrowseNodes'][0] ?? [];
+ return $node['Id'] ?? '';
+ }
+
+ /**
+ * Sanitize item root Id.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeRoot(array $item) : string
+ {
+ $node = $item['BrowseNodeInfo']['BrowseNodes'][0] ?? [];
+ $count = count($node);
+ for ($i = 0; $i < $count; $i++) {
+ if ( !isset($node['Ancestor']) ) break;
+ $node = $node['Ancestor'];
+ }
+ return $node['Id'] ?? '';
+ }
+
+ /**
+ * Sanitize item rank.
+ *
+ * @access private
+ * @param array $item
+ * @return int
+ */
+ private static function sanitizeRank(array $item) : int
+ {
+ $node = $item['BrowseNodeInfo']['BrowseNodes'][0] ?? [];
+ return $node['SalesRank'] ?? 0;
+ }
+
+ /**
+ * Sanitize item price.
+ *
+ * @access private
+ * @param array $item
+ * @return float
+ */
+ private static function sanitizePrice(array $item) : float
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return $listing['Price']['Amount'] ?? 0;
+ }
+
+ /**
+ * Sanitize item currency.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeCurrency(array $item) : string
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return $listing['Price']['Currency'] ?? '';
+ }
+
+ /**
+ * Sanitize item discount.
+ *
+ * @access private
+ * @param array $item
+ * @return float
+ */
+ private static function sanitizeDiscount(array $item) : float
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return $listing['Price']['Savings']['Amount'] ?? 0;
+ }
+
+ /**
+ * Sanitize item discount percent.
+ *
+ * @access private
+ * @param array $item
+ * @return float
+ */
+ private static function sanitizePercent(array $item) : float
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return $listing['Price']['Savings']['Percentage'] ?? 0;
+ }
+
+ /**
+ * Sanitize item discounted.
+ *
+ * @access private
+ * @param array $item
+ * @return float
+ */
+ private static function sanitizeDiscounted(array $item) : float
+ {
+ return (self::sanitizePrice($item) + self::sanitizeDiscount($item));
+ }
+
+ /**
+ * Sanitize item shipping.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function sanitizeShipping(array $item) : array
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return [
+ 'fulfilled' => $listing['DeliveryInfo']['IsAmazonFulfilled'] ?? false,
+ 'free' => $listing['DeliveryInfo']['IsFreeShippingEligible'] ?? false,
+ 'prime' => $listing['DeliveryInfo']['IsPrimeEligible'] ?? false
+ ];
+ }
+
+ /**
+ * Sanitize item availability.
+ *
+ * @access private
+ * @param array $item
+ * @return string
+ */
+ private static function sanitizeAvailability(array $item) : string
+ {
+ $listing = $item['Offers']['Listings'][0] ?? [];
+ return $listing['Availability']['Message'] ?? '';
+ }
+
+ /**
+ * Sanitize item features.
+ *
+ * @access private
+ * @param array $item
+ * @return array
+ */
+ private static function sanitizeFeatures(array $item) : array
+ {
+ $features = $item['ItemInfo']['Features']['DisplayValues'] ?? [];
+ if ( self::$limit ) {
+ $features = array_slice($features, 0, self::$limit);
+ }
+ foreach ($features as $key => $feature) {
+ $feature = self::formatString($feature);
+ $features[$key] = $feature;
+ }
+ return $features;
+ }
+
+ /**
+ * Format string.
+ *
+ * @access private
+ * @param string $string
+ * @return string
+ */
+ private static function formatString(string $string) : string
+ {
+ if ( !self::$format ) {
+ $string = preg_replace('/[^\x{0000}-\x{FFFF}]/u', ' ', $string);
+ $string = str_replace(['【', ], ' [', $string);
+ $string = str_replace(['】', ], '] ', $string);
+ }
+
+ $string = trim($string);
+ $string = str_replace("\r", "\n", $string);
+ $string = preg_replace(['/\n+/', '/[ \t]+/'], ["\n", ' '], $string);
+
+ return $string;
+ }
+
+ /**
+ * Strip space.
+ *
+ * @access private
+ * @param string $string
+ * @return string
+ */
+ private static function stripSpace(string $string) : string
+ {
+ $string = trim($string);
+ $string = preg_replace('/\s+/', '', $string);
+ return $string;
+ }
+
+ /**
+ * Check URL.
+ *
+ * @access private
+ * @param string $keyword
+ * @return bool
+ */
+ private static function isUrl(string $keyword) : bool
+ {
+ if ( strpos(strtolower($keyword), 'amazon') !== false ) {
+ return (bool)filter_var($keyword, FILTER_VALIDATE_URL);
+ }
+ return false;
+ }
+}
diff --git a/src/includes/OperationParser.php b/src/includes/OperationParser.php
deleted file mode 100644
index 7d0f735..0000000
--- a/src/includes/OperationParser.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\includes;
-
-use Apaapi\interfaces\OperationInterface;
-
-/**
- * Basic Apaapi Request Operation Parsing Helper.
- */
-final class OperationParser extends Parser
-{
- /**
- * @access public
- * @param OperationInterface $operation
- * @return string
- */
- public static function toString(OperationInterface $operation)
- {
- $wrapper = [];
- foreach ($operation as $key => $value) {
- if ( $value ) {
- $wrapper[ucfirst($key)] = $value;
- }
- }
- return json_encode($wrapper);
- }
-}
diff --git a/src/includes/Parser.php b/src/includes/Parser.php
index 60ea574..c961717 100644
--- a/src/includes/Parser.php
+++ b/src/includes/Parser.php
@@ -1,31 +1,92 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
* This file if a part of Apaapi Lib.
*/
+declare(strict_types=1);
+
namespace Apaapi\includes;
use Apaapi\interfaces\ParsableInterface;
/**
- * Basic Apaapi Request Parser.
+ * Apaapi request parser.
*/
-class Parser
+final class Parser
{
/**
+ * Get class name.
+ *
* @access public
* @param ParsableInterface $parsable
* @return string
*/
- public static function getName(ParsableInterface $parsable)
+ public static function getName(ParsableInterface $parsable) : string
+ {
+ $class = get_class($parsable);
+ return basename(str_replace('\\', '/', $class));
+ }
+
+ /**
+ * Convert items.
+ *
+ * @access public
+ * @param mixed $items
+ * @return mixed
+ */
+ public static function convert($items)
+ {
+ if ( is_array($items) ) {
+ return self::resourcesToArray($items);
+ }
+ return self::operationToString($items);
+ }
+
+ /**
+ * Convert resources object to array.
+ *
+ * @access private
+ * @param array $resources
+ * @return array
+ */
+ private static function resourcesToArray(array $resources) : array
+ {
+ $wrapper = [];
+ foreach ($resources as $resource) {
+ $parent = self::getName($resource);
+ if ( is_array($resource->items) ) {
+ foreach ($resource->items as $item) {
+ $wrapper[] = "{$parent}.{$item}";
+ }
+ } elseif ( $resource->items === false ) {
+ $wrapper[] = $parent;
+ }
+ }
+ return $wrapper;
+ }
+
+ /**
+ * Convert operation to string.
+ *
+ * @access private
+ * @param ParsableInterface $operation
+ * @return string
+ */
+ private static function operationToString(ParsableInterface $operation) : string
{
- return basename(str_replace('\\', '/', get_class($parsable)));
+ $wrapper = [];
+ foreach ($operation as $key => $value) {
+ if ( $value ) {
+ $wrapper[ucfirst($key)] = $value;
+ }
+ }
+ return json_encode($wrapper);
}
}
diff --git a/src/includes/Provider.php b/src/includes/Provider.php
new file mode 100644
index 0000000..217dbf6
--- /dev/null
+++ b/src/includes/Provider.php
@@ -0,0 +1,267 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+/**
+ * Apaapi static helper.
+ * @see https://webservices.amazon.com/paapi5/documentation/locale-reference.html
+ */
+final class Provider
+{
+ /**
+ * @access public
+ * @var string HOST, Dynamic API host
+ * @var array CONDITIONS, API product conditions
+ */
+ public const HOST = 'https://www.amazon.{locale}';
+ public const CONDITIONS = ['Any', 'New', 'Used', 'Refurbished', 'Collectible'];
+
+ /**
+ * Get request regions.
+ *
+ * @access public
+ * @return array
+ */
+ public static function getRegions() : array
+ {
+ return self::load('regions');
+ }
+
+ /**
+ * Get request region by locale.
+ *
+ * @access public
+ * @param string $locale
+ * @return string
+ */
+ public static function getRegion(string $locale) : string
+ {
+ $default = 'eu-west-1';
+ foreach (self::getRegions() as $name => $region) {
+ if ( in_array($locale, $region) ) {
+ $default = $name;
+ break;
+ }
+ }
+ return $default;
+ }
+
+ /**
+ * Get request locales.
+ *
+ * @access public
+ * @return array
+ */
+ public static function getLocales() : array
+ {
+ $locales = [];
+ foreach (self::getRegions() as $region => $locale) {
+ $locales = array_merge($locales, $locale);
+ }
+ return $locales;
+ }
+
+ /**
+ * Get languages.
+ *
+ * @access public
+ * @param string $locale
+ * @return array
+ */
+ public static function getLanguages(?string $locale = null) : array
+ {
+ $languages = self::load('languages');
+ if ( $locale ) {
+ return $languages[$locale] ?? [];
+ }
+ return $languages;
+ }
+
+ /**
+ * Get country.
+ *
+ * @access public
+ * @param string $locale
+ * @return string
+ */
+ public static function getCountry(string $locale) : string
+ {
+ return self::getCountries()[$locale] ?? '';
+ }
+
+ /**
+ * Get countries.
+ *
+ * @access public
+ * @return array
+ */
+ public static function getCountries() : array
+ {
+ return self::load('countries');
+ }
+
+ /**
+ * Get currency.
+ *
+ * @access public
+ * @param string $locale
+ * @return array
+ */
+ public static function getCurrency(string $locale) : array
+ {
+ return self::getCurrencies()[$locale] ?? [];
+ }
+
+ /**
+ * Get currencies.
+ *
+ * @access public
+ * @return array
+ */
+ public static function getCurrencies() : array
+ {
+ return self::load('currencies');
+ }
+
+ /**
+ * Get symbols (currency).
+ *
+ * @access public
+ * @return array
+ */
+ public static function getSymbols() : array
+ {
+ return self::load('symbols');
+ }
+
+ /**
+ * Get symbol (currency).
+ *
+ * @access public
+ * @param string $currency
+ * @return string
+ */
+ public static function getSymbol(string $currency) : string
+ {
+ return self::getSymbols()[$currency] ?? '';
+ }
+
+ /**
+ * Get static categories (Search Index).
+ *
+ * @access public
+ * @param string $locale
+ * @return array
+ */
+ public static function getCategories(?string $locale = null) : array
+ {
+ $categories = self::load('categories');
+ if ( $locale ) {
+ return $categories[$locale] ?? [];
+ }
+ return $categories;
+ }
+
+ /**
+ * Get static category Id (Search Index).
+ *
+ * @access public
+ * @param string $category
+ * @param string $locale
+ * @return string
+ */
+ public static function getCategoryId(string $category, string $locale) : string
+ {
+ $key = Cache::generateKey("category-id-{$category}-{$locale}");
+
+ if ( !($cached = Cache::get($key)) ) {
+
+ $categories = self::getCategories($locale);
+ $column = array_column($categories, 'name');
+ $index = array_search($category, $column);
+ if ( is_int($index) ) {
+ $cached = $categories[$index]['id'] ?? '';
+ Cache::set($key, $cached);
+ }
+ }
+
+ return (string)$cached;
+ }
+
+ /**
+ * Get node url.
+ *
+ * @access public
+ * @param string $id
+ * @return string
+ */
+ public static function getNodeUrl(string $id) : string
+ {
+ return self::HOST . "/b?node={$id}&tag={tag}";
+ }
+
+ /**
+ * Generate header.
+ *
+ * @access public
+ * @return string
+ */
+ public static function generateHeader(string $locale = 'com') : string
+ {
+ $currency = 'USD';
+ if ( $locale !== 'com' ) {
+ $currency = self::getCurrency($locale)[0] ?? $currency;
+ }
+
+ $time = time() . 'l';
+
+ $id = mt_rand(100, 999);
+ $id .= '-' . mt_rand(1000000, 9999999);
+ $id .= '-' . mt_rand(1000000, 9999999);
+
+ $cookie = [
+ "i18n-prefs={$currency}",
+ "session-id={$id}",
+ "session-id-time={$time}"
+ ];
+
+ $header = [
+ 'Cookie' => implode('; ', $cookie),
+ 'Connection' => 'close'
+ ];
+
+ return implode("\r\n", array_map(function($key, $value) {
+ return "{$key}: {$value}";
+ }, array_keys($header), $header));
+ }
+
+ /**
+ * Load file.
+ *
+ * @access private
+ * @param string $name
+ * @return array
+ */
+ private static function load(string $name) : array
+ {
+ $file = __DIR__ . "/bin/{$name}.json";
+ $data = [];
+ if ( file_exists($file) ) {
+ $content = @file_get_contents($file);
+ $data = Normalizer::decode($content);
+ }
+ return $data;
+ }
+}
diff --git a/src/includes/Rating.php b/src/includes/Rating.php
new file mode 100644
index 0000000..3ed9f26
--- /dev/null
+++ b/src/includes/Rating.php
@@ -0,0 +1,161 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+declare(strict_types=1);
+
+namespace Apaapi\includes;
+
+use DOMDocument;
+use DOMNodeList;
+use DOMXPath;
+
+final class Rating
+{
+ /**
+ * @access private
+ * @var string $keyword
+ * @var string $locale
+ * @var string $tag
+ */
+ private $keyword;
+ private $locale;
+ private $tag;
+
+ private const ACTION = '/product-reviews/';
+ private const VALUExPATH = "//i[contains(@class,'averageStarRating')]";
+ private const COUNTxPATH = "//div[contains(@class,'averageStarRatingNumerical')]";
+
+ /**
+ * Init rating.
+ *
+ * @param string $keyword
+ * @param string $locale
+ * @param string $tag
+ */
+ public function __construct(string $keyword, string $locale = 'com', ?string $tag = null)
+ {
+ $this->keyword = Normalizer::formatId($keyword);
+ $this->locale = Normalizer::formatTLD($locale);
+ $this->tag = $tag;
+ }
+
+ /**
+ * Get rating data.
+ *
+ * @access public
+ * @return array
+ */
+ public function get() : array
+ {
+ $rating = $this->getDefault();
+
+ if ( !Keyword::isASIN($this->keyword)
+ && !Keyword::isISBN($this->keyword) ) {
+ return $rating;
+ }
+
+ $key = "rating-{$this->locale}-{$this->keyword}";
+ $key = Cache::generateKey($key);
+
+ if ( !($rating = Cache::get($key)) ) {
+
+ $host = Provider::HOST;
+ $url = str_replace('{locale}', $this->locale, $host);
+ $url .= self::ACTION;
+ $url .= $this->keyword;
+
+ $client = new Client($url, [
+ 'header' => Provider::generateHeader()
+ ]);
+
+ $client->setMethod('GET')
+ ->setRedirect(1)
+ ->setEncoding('')
+ ->setTimeout(0);
+
+ $response = $client->getResponse();
+ $client->close();
+
+ if ( $client->getCode() == 200 ) {
+ $rating = $this->extract($response);
+ $rating['url'] = "{$url}?tag={$this->tag}&linkCode=ll2";
+ Cache::set($key, $rating);
+ }
+
+ }
+
+ return ($rating) ? $rating : $this->getDefault();
+ }
+
+ /**
+ * Extract rating data from HTML.
+ *
+ * @access private
+ * @param string $html
+ * @return array
+ */
+ private function extract(string $html) : array
+ {
+ $rating = [];
+
+ if ( class_exists('DomDocument') ) {
+
+ // Ignore XML errors
+ libxml_use_internal_errors(true);
+
+ // Init DOM document
+ $dom = new DOMDocument();
+ $dom->loadHTML($html);
+ $xPath = new DOMXPath($dom);
+
+ // Extract rating value
+ $nodes = $xPath->query(self::VALUExPATH);
+ if ( $nodes instanceof DOMNodeList && ($nodes->length > 0) ) {
+ $node = $nodes[0];
+ $data = explode(' ', (string)$node->nodeValue);
+ $value = $data[0];
+ $value = str_replace(',', '.', $value);
+ $rating['value'] = (float)$value;
+ }
+
+ // Extract rating count
+ $nodes = $xPath->query(self::COUNTxPATH);
+ if ( $nodes instanceof DOMNodeList && ($nodes->length > 0) ) {
+ $node = $nodes[0];
+ $count = (string)$node->nodeValue;
+ $count = preg_replace('/\D/', '', $count);
+ $rating['count'] = (int)$count;
+ }
+
+ // Clear XML errors
+ libxml_clear_errors();
+
+ }
+
+ return $rating;
+ }
+
+ /**
+ * Get default rating.
+ *
+ * @access private
+ * @return array
+ */
+ private function getDefault() : array
+ {
+ return [
+ 'value' => null,
+ 'count' => null,
+ 'url' => null
+ ];
+ }
+}
diff --git a/src/includes/RequestClient.php b/src/includes/RequestClient.php
deleted file mode 100644
index 5e90897..0000000
--- a/src/includes/RequestClient.php
+++ /dev/null
@@ -1,326 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\includes;
-
-use Apaapi\interfaces\RequestClientInterface;
-use Apaapi\exceptions\RequestException;
-
-/**
- * Basic Apaapi Request Client Wrapper Class.
- */
-class RequestClient implements RequestClientInterface
-{
- /**
- * @access protected
- * @var string $endpoint, Request URL
- * @var array $params, Request params
- * @var mixed $handler, resource|array Request handler
- * @var string $method, curl|stream
- * @var string $response, Request response content
- * @var string $error, Response error content
- * @var int $code, Response code
- */
- protected $endpoint;
- protected $params;
- protected $handler;
- protected $method;
- protected $response = false;
- protected $error = false;
- protected $code = 200;
-
- /**
- * @param string $endpoint
- * @param array $params
- * @param bool $throwClientException
- * @throws bool RequestException
- */
- public function __construct($endpoint, $params, $throwClientException = true)
- {
- if ( !self::hasCurl() && !self::hasStream() ) {
- if ( $throwClientException ) {
- throw new RequestException(
- RequestException::invalidRequestClientMessage()
- );
- } else {
- $this->code = 0;
- $this->error = $this->setError(
- 'HTTP Client',
- RequestException::invalidRequestClientMessage()
- );
- }
- }
-
- $this->endpoint = $endpoint;
- $this->params = $params;
-
- if ( self::hasCurl() ) {
- $this->method = 'curl';
-
- } elseif ( self::hasStream() ) {
- $this->method = 'stream';
- }
-
- $this->init();
- }
-
- /**
- * Get response including error(s).
- *
- * @access public
- * @param void
- * @return mixed
- */
- public function getResponse()
- {
- // Send request
- $this->send();
-
- // Return error
- if ( $this->hasError() ) {
- return $this->error;
- }
-
- // Return response
- return $this->response;
- }
-
- /**
- * Get HTTP response code.
- *
- * @access public
- * @param void
- * @return int
- */
- public function getCode()
- {
- return $this->code;
- }
-
- /**
- * Close handler.
- *
- * @access public
- * @param void
- * @return void
- */
- public function close()
- {
- if ( $this->method == 'curl' ) {
- curl_close($this->handler);
- }
- }
-
- /**
- * Check if Curl activated,
- * Requires: "Curl" extension.
- *
- * @access public
- * @param void
- * @return bool
- */
- public static function hasCurl()
- {
- return function_exists('curl_init');
- }
-
- /**
- * Check if Stream activated,
- * Requires: "allow_url_fopen" parameter.
- *
- * @access public
- * @param void
- * @return bool
- */
- public static function hasStream()
- {
- return intval(ini_get('allow_url_fopen'));
- }
-
- /**
- * Init HTTP client.
- *
- * @access protected
- * @param void
- * @return void
- */
- protected function init()
- {
- if ( $this->method == 'curl' ) {
- $this->handler = curl_init();
- curl_setopt($this->handler, CURLOPT_URL, $this->endpoint);
- curl_setopt($this->handler, CURLOPT_HTTPHEADER, $this->getRequestHeader());
- curl_setopt($this->handler, CURLOPT_POSTFIELDS, $this->getRequestContent());
- curl_setopt($this->handler, CURLOPT_POST, true);
- curl_setopt($this->handler, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($this->handler, CURLOPT_SSL_VERIFYPEER, $this->isSSL());
- curl_setopt($this->handler, CURLOPT_TIMEOUT, 30);
-
- } elseif ( $this->method == 'stream' ) {
- $this->handler = [
- 'http' => [
- 'method' => 'POST',
- 'header' => $this->getRequestHeader(),
- 'content' => $this->getRequestContent(),
- 'timeout' => 30
- ]
- ];
- }
- }
-
- /**
- * Check for HTTP error.
- *
- * @access protected
- * @param void
- * @return bool
- */
- protected function hasError()
- {
- return (bool)$this->error;
- }
-
- /**
- * Normalize HTTP error,
- * Uses "Amazon API error" format (JSON).
- *
- * @access protected
- * @param string $method
- * @param string $error
- * @return string
- */
- protected function setError($method, $error)
- {
- return json_encode([
- '__type' => basename(__CLASS__) . 'Exception',
- 'Errors' => [
- [
- 'Code' => basename(__CLASS__) . "{$method}Error",
- 'Message' => "{$method}: {$error}."
- ]
- ]
- ]);
- }
-
- /**
- * Send request & catch errors.
- *
- * @access protected
- * @param void
- * @return void
- */
- protected function send()
- {
- if ( $this->method == 'curl' ) {
-
- // Get cURL response & HTTP status code
- $this->response = curl_exec($this->handler);
- $this->code = curl_getinfo($this->handler)['http_code'];
-
- // Catch cURL error content
- if ( curl_errno($this->handler) ) {
- $this->error = $this->setError(
- 'Curl',
- curl_error($this->handler)
- );
- }
-
- // Catch HTTP error content from response
- if ( $this->response && $this->code !== 200 ) {
- $this->error = $this->response;
- $this->response = false;
- }
-
- } elseif ( $this->method == 'stream' ) {
-
- // Create stream context
- $context = stream_context_create($this->handler);
-
- // Get stream response
- $this->response = @file_get_contents($this->endpoint, false, $context);
-
- // Catch HTTP response headers
- $headers = @get_headers($this->endpoint, false, $context);
-
- if ( isset($headers[0]) ) {
-
- // Catch HTTP status code from headers
- $this->code = (int)substr($headers[0], 9, 3);
-
- // Catch HTTP error content from headers
- if ( !$this->response || $this->code !== 200 ) {
- $this->error = $this->setError(
- 'Stream',
- $headers[0]
- );
- }
-
- } else {
- $this->code = 0;
- $this->error = $this->setError(
- 'Stream',
- 'Failed to open stream, operation failed'
- );
- }
- }
- }
-
- /**
- * Check SSL.
- *
- * @access protected
- * @param void
- * @return bool
- */
- protected function isSSL()
- {
- if ( isset($_SERVER['HTTPS']) ) {
- if ( strtolower($_SERVER['HTTPS']) === 'on' ) {
- return true;
- }
- if ( $_SERVER['HTTPS'] == '1' ) {
- return true;
- }
- } elseif ( isset($_SERVER['SERVER_PORT'])
- && ( $_SERVER['SERVER_PORT'] == '443' ) ) {
- return true;
- }
- return false;
- }
-
- /**
- * Get request content.
- *
- * @access protected
- * @param void
- * @return mixed
- */
- protected function getRequestContent()
- {
- return isset($this->params['http']['content'])
- ? $this->params['http']['content'] : '';
- }
-
- /**
- * Get request header.
- *
- * @access protected
- * @param void
- * @return mixed
- */
- protected function getRequestHeader()
- {
- $header = isset($this->params['http']['header'])
- ? $this->params['http']['header'] : [];
- return explode("\n", $header);
- }
-}
diff --git a/src/includes/ResourceParser.php b/src/includes/ResourceParser.php
deleted file mode 100644
index 5a4662f..0000000
--- a/src/includes/ResourceParser.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\includes;
-
-/**
- * Basic Apaapi Request Resource Parsing Helper.
- */
-final class ResourceParser extends Parser
-{
- /**
- * @access public
- * @param array $resources
- * @return array
- */
- public static function toString($resources)
- {
- $wrapper = [];
- foreach ($resources as $resource) {
- $parent = self::getName($resource);
- if ( is_array($resource->items) ) {
- foreach ($resource->items as $item) {
- $wrapper[] = "{$parent}.{$item}";
- }
- } elseif ( $resource->items === false ) {
- $wrapper[] = $parent;
- }
- }
- return $wrapper;
- }
-}
diff --git a/src/includes/ResponseType.php b/src/includes/ResponseType.php
deleted file mode 100644
index 1232992..0000000
--- a/src/includes/ResponseType.php
+++ /dev/null
@@ -1,129 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\includes;
-
-use Apaapi\interfaces\ResponseTypeInterface;
-use Apaapi\exceptions\ResponseTypeException;
-
-/**
- * Basic Apaapi Response Helper.
- */
-class ResponseType implements ResponseTypeInterface
-{
- /**
- * @access private
- * @var string $type
- */
- private $type;
-
- /**
- * @param string $type
- */
- public function __construct($type = 'object')
- {
- $this->type = strtolower($type);
- }
-
- /**
- * @access public
- * @param string $response
- * @return mixed
- * @throws ResponseTypeException
- */
- public function format($response)
- {
- if ( $this->isValidFormat() !== true ) {
- throw new ResponseTypeException(
- ResponseTypeException::invalidResponseTypeFormat($this->type)
- );
- }
-
- switch ($this->type) {
- case 'array':
- return self::decode($response,true);
- break;
- case 'object':
- return self::decode($response);
- break;
- case 'serialized':
- return serialize(self::decode($response));
- break;
- }
- }
-
- /**
- * @access public
- * @param object $response
- * @param string $operation
- * @return string
- */
- public function parse($response, $operation)
- {
- // JSON Decode
- $response = self::decode($response);
-
- if ( $operation == 'GetItems' ) {
- $response = isset($response->ItemsResult->Items)
- ? $response->ItemsResult->Items : [];
-
- } elseif ( $operation == 'SearchItems' ) {
- $response = isset($response->SearchResult->Items)
- ? $response->SearchResult->Items : [];
-
- } elseif ( $operation == 'GetVariations' ) {
- $response = isset($response->VariationsResult->Items)
- ? $response->VariationsResult->Items : [];
-
- } elseif ( $operation == 'GetBrowseNodes' ) {
- $response = isset($response->BrowseNodesResult->BrowseNodes)
- ? $response->BrowseNodesResult->BrowseNodes : [];
- }
-
- // JSON Encode for format
- return self::encode($response);
- }
-
- /**
- * @access public
- * @param string $json
- * @param bool $object
- * @return array|object
- */
- public static function decode($json, $object = false)
- {
- return json_decode((string)$json, $object);
- }
-
- /**
- * @access public
- * @param array|object $json
- * @return string
- */
- public static function encode($json)
- {
- return json_encode($json);
- }
-
- /**
- * @access private
- * @param void
- * @return bool
- */
- private function isValidFormat()
- {
- if ( !in_array($this->type, ['object','array','serialized']) ) {
- return false;
- }
- return true;
- }
-}
diff --git a/src/includes/bin/categories.json b/src/includes/bin/categories.json
new file mode 100644
index 0000000..f239c73
--- /dev/null
+++ b/src/includes/bin/categories.json
@@ -0,0 +1,2408 @@
+{
+ "com.au":[
+ {
+ "id":"Automotive",
+ "name":"Automotive"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Clothing & Shoes"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Personal Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Lighting",
+ "name":"Lighting"
+ },
+ {
+ "id":"Luggage",
+ "name":"Luggage & Travel Gear"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV"
+ },
+ {
+ "id":"Music",
+ "name":"CDs & Vinyl"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Stationery & Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports, Fitness & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ }
+ ],
+ "com.be":[
+ {
+ "id":"Automotive",
+ "name":"Auto et Moto"
+ },
+ {
+ "id":"Baby",
+ "name":"B\u00e9b\u00e9"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beaut\u00e9 et Parfum"
+ },
+ {
+ "id":"Books",
+ "name":"Livres"
+ },
+ {
+ "id":"Electronics",
+ "name":"High-Tech"
+ },
+ {
+ "id":"Fashion",
+ "name":"Mode"
+ },
+ {
+ "id":"Garden",
+ "name":"Jardin"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Boutique ch\u00e8ques-cadeaux"
+ },
+ {
+ "id":"Grocery",
+ "name":"Alimentation"
+ },
+ {
+ "id":"HomeImprovement",
+ "name":"Bricolage"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Sant\u00e9 & Hygi\u00e8ne personnelle"
+ },
+ {
+ "id":"Industrial",
+ "name":"Secteur industriel et scientifique"
+ },
+ {
+ "id":"Music",
+ "name":"Musique : CD & Vinyles"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Instruments de musique"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Cin\u00e9ma & TV"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Produits de bureau"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Animalerie"
+ },
+ {
+ "id":"Software",
+ "name":"Logiciels"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports & Activit\u00e9s en plein-air"
+ },
+ {
+ "id":"Toys",
+ "name":"Jeux et Jouets"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Jeux vid\u00e9o"
+ }
+ ],
+ "com.br":[
+ {
+ "id":"Books",
+ "name":"Livros"
+ },
+ {
+ "id":"Computers",
+ "name":"Computadores e Inform\u00e1tica"
+ },
+ {
+ "id":"Electronics",
+ "name":"Eletr\u00f4nicos"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Casa e Cozinha"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Loja Kindle"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps e Jogos"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Material para Escrit\u00f3rio e Papelaria"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Ferramentas e Materiais de Constru\u00e7\u00e3o"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Games"
+ }
+ ],
+ "ca":[
+ {
+ "id":"Apparel",
+ "name":"Clothing & Accessories"
+ },
+ {
+ "id":"Automotive",
+ "name":"Automotive"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Classical",
+ "name":"Classical Music"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"English Books"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Patio, Lawn & Garden"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery & Gourmet Food"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health & Personal Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Jewelry"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Luggage",
+ "name":"Luggage & Bags"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Luxury Beauty"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV"
+ },
+ {
+ "id":"Music",
+ "name":"Music"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments, Stage & Studio"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Shoes",
+ "name":"Shoes & Handbags"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VHS",
+ "name":"VHS"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Watches"
+ }
+ ],
+ "eg":[
+ {
+ "id":"ArtsAndCrafts",
+ "name":"Arts, Crafts & Sewing"
+ },
+ {
+ "id":"Automotive",
+ "name":"Automotive Parts & Accessories"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty & Personal Care"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"Fashion",
+ "name":"Amazon Fashion"
+ },
+ {
+ "id":"Garden",
+ "name":"Home & Garden"
+ },
+ {
+ "id":"Grocery",
+ "name":"Grocery & Gourmet Food"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Baby Care"
+ },
+ {
+ "id":"Home",
+ "name":"Home Related"
+ },
+ {
+ "id":"HomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports"
+ },
+ {
+ "id":"Toys",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ }
+ ],
+ "fr":[
+ {
+ "id":"Apparel",
+ "name":"V\u00eatements et accessoires"
+ },
+ {
+ "id":"Appliances",
+ "name":"Gros \u00e9lectrom\u00e9nager"
+ },
+ {
+ "id":"Automotive",
+ "name":"Auto et Moto"
+ },
+ {
+ "id":"Baby",
+ "name":"B\u00e9b\u00e9s & Pu\u00e9riculture"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beaut\u00e9 et Parfum"
+ },
+ {
+ "id":"Books",
+ "name":"Livres en fran\u00e7ais"
+ },
+ {
+ "id":"Computers",
+ "name":"Informatique"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"T\u00e9l\u00e9chargement de musique"
+ },
+ {
+ "id":"Electronics",
+ "name":"High-Tech"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Autres"
+ },
+ {
+ "id":"Fashion",
+ "name":"Mode"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"Livres anglais et \u00e9trangers"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Jardin"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Boutique ch\u00e8ques-cadeaux"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Epicerie"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Hygi\u00e8ne et Sant\u00e9"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Cuisine & Maison"
+ },
+ {
+ "id":"Industrial",
+ "name":"Secteur industriel & scientifique"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Bijoux"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Boutique Kindle"
+ },
+ {
+ "id":"Lighting",
+ "name":"Luminaires et Eclairage"
+ },
+ {
+ "id":"Luggage",
+ "name":"Bagages"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Beaut\u00e9 Prestige"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Applis & Jeux"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"DVD & Blu-ray"
+ },
+ {
+ "id":"Music",
+ "name":"Musique : CD & Vinyles"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Instruments de musique & Sono"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Fournitures de bureau"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Animalerie"
+ },
+ {
+ "id":"Shoes",
+ "name":"Chaussures et Sacs"
+ },
+ {
+ "id":"Software",
+ "name":"Logiciels"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports et Loisirs"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Bricolage"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Jeux et Jouets"
+ },
+ {
+ "id":"VHS",
+ "name":"VHS"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Jeux vid\u00e9o"
+ },
+ {
+ "id":"Watches",
+ "name":"Montres"
+ }
+ ],
+ "de":[
+ {
+ "id":"AmazonVideo",
+ "name":"Prime Video"
+ },
+ {
+ "id":"Apparel",
+ "name":"Bekleidung"
+ },
+ {
+ "id":"Appliances",
+ "name":"Elektro-Gro\u00dfger\u00e4te"
+ },
+ {
+ "id":"Automotive",
+ "name":"Auto & Motorrad"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"B\u00fccher"
+ },
+ {
+ "id":"Classical",
+ "name":"Klassik"
+ },
+ {
+ "id":"Computers",
+ "name":"Computer & Zubeh\u00f6r"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"Musik-Downloads"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elektronik & Foto"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Sonstiges"
+ },
+ {
+ "id":"Fashion",
+ "name":"Fashion"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"B\u00fccher (Fremdsprachig)"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Garten"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Geschenkgutscheine"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Lebensmittel & Getr\u00e4nke"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Drogerie & K\u00f6rperpflege"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"K\u00fcche, Haushalt & Wohnen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Gewerbe, Industrie & Wissenschaft"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Schmuck"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle-Shop"
+ },
+ {
+ "id":"Lighting",
+ "name":"Beleuchtung"
+ },
+ {
+ "id":"Luggage",
+ "name":"Koffer, Rucks\u00e4cke & Taschen"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Luxury Beauty"
+ },
+ {
+ "id":"Magazines",
+ "name":"Zeitschriften"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Spiele"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"DVD & Blu-ray"
+ },
+ {
+ "id":"Music",
+ "name":"Musik-CDs & Vinyl"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musikinstrumente & DJ-Equipment"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"B\u00fcrobedarf & Schreibwaren"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Haustier"
+ },
+ {
+ "id":"Photo",
+ "name":"Kamera & Foto"
+ },
+ {
+ "id":"Shoes",
+ "name":"Schuhe & Handtaschen"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sport & Freizeit"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Baumarkt"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Spielzeug"
+ },
+ {
+ "id":"VHS",
+ "name":"VHS"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Uhren"
+ }
+ ],
+ "in":[
+ {
+ "id":"Apparel",
+ "name":"Clothing & Accessories"
+ },
+ {
+ "id":"Appliances",
+ "name":"Appliances"
+ },
+ {
+ "id":"Automotive",
+ "name":"Car & Motorbike"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Collectibles",
+ "name":"Collectibles"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers & Accessories"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Amazon Fashion"
+ },
+ {
+ "id":"Furniture",
+ "name":"Furniture"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Garden & Outdoors"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery & Gourmet Foods"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health & Personal Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Jewellery"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Luggage",
+ "name":"Luggage & Bags"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Luxury Beauty"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV Shows"
+ },
+ {
+ "id":"Music",
+ "name":"Music"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Shoes",
+ "name":"Shoes & Handbags"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports, Fitness & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Watches"
+ }
+ ],
+ "it":[
+ {
+ "id":"Apparel",
+ "name":"Abbigliamento"
+ },
+ {
+ "id":"Appliances",
+ "name":"Grandi elettrodomestici"
+ },
+ {
+ "id":"Automotive",
+ "name":"Auto e Moto"
+ },
+ {
+ "id":"Baby",
+ "name":"Prima infanzia"
+ },
+ {
+ "id":"Beauty",
+ "name":"Bellezza"
+ },
+ {
+ "id":"Books",
+ "name":"Libri"
+ },
+ {
+ "id":"Computers",
+ "name":"Informatica"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"Musica Digitale"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elettronica"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Altro"
+ },
+ {
+ "id":"Fashion",
+ "name":"Moda"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"Libri in altre lingue"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Giardino e giardinaggio"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Buoni Regalo"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Alimentari e cura della casa"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Salute e cura della persona"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Casa e cucina"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industria e Scienza"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Gioielli"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Lighting",
+ "name":"Illuminazione"
+ },
+ {
+ "id":"Luggage",
+ "name":"Valigeria"
+ },
+ {
+ "id":"MobileApps",
+ "name":"App e Giochi"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Film e TV"
+ },
+ {
+ "id":"Music",
+ "name":"CD e Vinili"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Strumenti musicali e DJ"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Cancelleria e prodotti per ufficio"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Prodotti per animali domestici"
+ },
+ {
+ "id":"Shoes",
+ "name":"Scarpe e borse"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sport e tempo libero"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Fai da te"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Giochi e giocattoli"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Videogiochi"
+ },
+ {
+ "id":"Watches",
+ "name":"Orologi"
+ }
+ ],
+ "co.jp":[
+ {
+ "id":"AmazonVideo",
+ "name":"Prime Video"
+ },
+ {
+ "id":"Apparel",
+ "name":"Clothing & Accessories"
+ },
+ {
+ "id":"Appliances",
+ "name":"Large Appliances"
+ },
+ {
+ "id":"Automotive",
+ "name":"Car & Bike Products"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby & Maternity"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"Japanese Books"
+ },
+ {
+ "id":"Classical",
+ "name":"Classical"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers & Accessories"
+ },
+ {
+ "id":"CreditCards",
+ "name":"Credit Cards"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"Digital Music"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics & Cameras"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Fashion"
+ },
+ {
+ "id":"FashionBaby",
+ "name":"Kids & Baby"
+ },
+ {
+ "id":"FashionMen",
+ "name":"Men"
+ },
+ {
+ "id":"FashionWomen",
+ "name":"Women"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"English Books"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Food & Beverage"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health & Personal Care"
+ },
+ {
+ "id":"Hobbies",
+ "name":"Hobby"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Kitchen & Housewares"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Jewelry"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV"
+ },
+ {
+ "id":"Music",
+ "name":"Music"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Stationery and Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Shoes",
+ "name":"Shoes & Bags"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"DIY, Tools & Garden"
+ },
+ {
+ "id":"Toys",
+ "name":"Toys"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Computer & Video Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Watches"
+ }
+ ],
+ "com.mx":[
+ {
+ "id":"Automotive",
+ "name":"Auto"
+ },
+ {
+ "id":"Baby",
+ "name":"Beb\u00e9"
+ },
+ {
+ "id":"Books",
+ "name":"Libros"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electr\u00f3nicos"
+ },
+ {
+ "id":"Fashion",
+ "name":"Ropa, Zapatos y Accesorios"
+ },
+ {
+ "id":"FashionBaby",
+ "name":"Ropa, Zapatos y Accesorios Beb\u00e9"
+ },
+ {
+ "id":"FashionBoys",
+ "name":"Ropa, Zapatos y Accesorios Ni\u00f1os"
+ },
+ {
+ "id":"FashionGirls",
+ "name":"Ropa, Zapatos y Accesorios Ni\u00f1as"
+ },
+ {
+ "id":"FashionMen",
+ "name":"Ropa, Zapatos y Accesorios Hombres"
+ },
+ {
+ "id":"FashionWomen",
+ "name":"Ropa, Zapatos y Accesorios Mujeres"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Alimentos y Bebidas"
+ },
+ {
+ "id":"Handmade",
+ "name":"Productos Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Salud, Belleza y Cuidado Personal"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Hogar y Cocina"
+ },
+ {
+ "id":"IndustrialAndScientific",
+ "name":"Industria y ciencia"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Tienda Kindle"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Pel\u00edculas y Series de TV"
+ },
+ {
+ "id":"Music",
+ "name":"M\u00fasica"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Instrumentos musicales"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Oficina y Papeler\u00eda"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Mascotas"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Deportes y Aire Libre"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Herramientas y Mejoras del Hogar"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Juegos y juguetes"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Videojuegos"
+ },
+ {
+ "id":"Watches",
+ "name":"Relojes"
+ }
+ ],
+ "nl":[
+ {
+ "id":"Automotive",
+ "name":"Auto en motor"
+ },
+ {
+ "id":"Baby",
+ "name":"Babyproducten"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty en persoonlijke verzorging"
+ },
+ {
+ "id":"Books",
+ "name":"Boeken"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elektronica"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Overig"
+ },
+ {
+ "id":"Fashion",
+ "name":"Kleding, schoenen en sieraden"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Tuin, terras en gazon"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Cadeaubonnen"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Levensmiddelen"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Gezondheid en persoonlijke verzorging"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Wonen en keuken"
+ },
+ {
+ "id":"Industrial",
+ "name":"Zakelijk, industrie en wetenschap"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Films en tv"
+ },
+ {
+ "id":"Music",
+ "name":"Cd's en lp's"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Muziekinstrumenten"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Kantoorproducten"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Huisdierbenodigdheden"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sport en outdoor"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Klussen en gereedschap"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Speelgoed en spellen"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Videogames"
+ }
+ ],
+ "pl":[
+ {
+ "id":"ArtsAndCrafts",
+ "name":"Arts & crafts"
+ },
+ {
+ "id":"Automotive",
+ "name":"Motoryzacja"
+ },
+ {
+ "id":"Baby",
+ "name":"Dziecko"
+ },
+ {
+ "id":"Beauty",
+ "name":"Uroda"
+ },
+ {
+ "id":"Books",
+ "name":"Ksi\u0105\u017cki"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elektronika"
+ },
+ {
+ "id":"Fashion",
+ "name":"Odzie\u017c, obuwie i akcesoria"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Ogr\u00f3d"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Karty podarunkowe"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Zdrowie i gospodarstwo domowe"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Dom i kuchnia"
+ },
+ {
+ "id":"Industrial",
+ "name":"Biznes, przemys\u0142 i nauka"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Filmy i programy TV"
+ },
+ {
+ "id":"Music",
+ "name":"Muzyka"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Instrumenty muzyczne"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Biuro"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Zwierz\u0119ta"
+ },
+ {
+ "id":"Software",
+ "name":"Oprogramowanie"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sport i turystyka"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Renowacja domu"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Zabawki i gry"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Gry wideo"
+ }
+ ],
+ "sg":[
+ {
+ "id":"Automotive",
+ "name":"Automotive"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty & Personal Care"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Personal Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home, Kitchen & Dining"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ }
+ ],
+ "sa":[
+ {
+ "id":"ArtsAndCrafts",
+ "name":"Arts, Crafts & Sewing"
+ },
+ {
+ "id":"Automotive",
+ "name":"Automotive Parts & Accessories"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty & Personal Care"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Computers",
+ "name":"Computer & Accessories"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"Fashion",
+ "name":"Clothing, Shoes & Jewelry"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Home & Garden"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery & Gourmet Food"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Baby Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Kitchen & Dining"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Miscellaneous",
+ "name":"Everything Else"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV"
+ },
+ {
+ "id":"Music",
+ "name":"CDs & Vinyl"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ }
+ ],
+ "es":[
+ {
+ "id":"AmazonVideo",
+ "name":"Prime Video"
+ },
+ {
+ "id":"Apparel",
+ "name":"Ropa y accesorios"
+ },
+ {
+ "id":"Appliances",
+ "name":"Grandes electrodom\u00e9sticos"
+ },
+ {
+ "id":"Automotive",
+ "name":"Coche y moto"
+ },
+ {
+ "id":"Baby",
+ "name":"Beb\u00e9"
+ },
+ {
+ "id":"Beauty",
+ "name":"Belleza"
+ },
+ {
+ "id":"Books",
+ "name":"Libros"
+ },
+ {
+ "id":"Computers",
+ "name":"Inform\u00e1tica"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"M\u00fasica Digital"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electr\u00f3nica"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Otros Productos"
+ },
+ {
+ "id":"Fashion",
+ "name":"Moda"
+ },
+ {
+ "id":"ForeignBooks",
+ "name":"Libros en idiomas extranjeros"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Jard\u00edn"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Cheques regalo"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Alimentaci\u00f3n y bebidas"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Salud y cuidado personal"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Hogar y cocina"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industria y ciencia"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Joyer\u00eda"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Tienda Kindle"
+ },
+ {
+ "id":"Lighting",
+ "name":"Iluminaci\u00f3n"
+ },
+ {
+ "id":"Luggage",
+ "name":"Equipaje"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Appstore para Android"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Pel\u00edculas y TV"
+ },
+ {
+ "id":"Music",
+ "name":"M\u00fasica: CDs y vinilos"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Instrumentos musicales"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Oficina y papeler\u00eda"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Productos para mascotas"
+ },
+ {
+ "id":"Shoes",
+ "name":"Zapatos y complementos"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Deportes y aire libre"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Bricolaje y herramientas"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Juguetes y juegos"
+ },
+ {
+ "id":"Vehicles",
+ "name":"Coche - renting"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Videojuegos"
+ },
+ {
+ "id":"Watches",
+ "name":"Relojes"
+ }
+ ],
+ "se":[
+ {
+ "id":"Automotive",
+ "name":"Delar och tillbeh\u00f6r till bilar"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Sk\u00f6nhet och kroppsv\u00e5rd"
+ },
+ {
+ "id":"Books",
+ "name":"B\u00f6cker"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elektronik"
+ },
+ {
+ "id":"Fashion",
+ "name":"Kl\u00e4der, skor och smycken"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Livsmedel och gourmetmat"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"H\u00e4lsa, hush\u00e5ll och barnv\u00e5rd"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Hem"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Filmer och TV"
+ },
+ {
+ "id":"Music",
+ "name":"CD och vinyl"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Kontorsprodukter"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Husdjursprodukter"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sport och outdoor"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Verktyg och husrenovering"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Leksaker och spel"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Videospel"
+ }
+ ],
+ "com.tr":[
+ {
+ "id":"Baby",
+ "name":"Bebek"
+ },
+ {
+ "id":"Books",
+ "name":"Kitaplar"
+ },
+ {
+ "id":"Computers",
+ "name":"Bilgisayarlar"
+ },
+ {
+ "id":"Electronics",
+ "name":"Elektronik"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Di\u011fer Her \u015eey"
+ },
+ {
+ "id":"Fashion",
+ "name":"Moda"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Ev ve Mutfak"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Ofis \u00dcr\u00fcnleri"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Spor"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Yap\u0131 Market"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Oyuncaklar ve Oyunlar"
+ },
+ {
+ "id":"VideoGames",
+ "name":"PC ve Video Oyunlar\u0131"
+ }
+ ],
+ "ae":[
+ {
+ "id":"Appliances",
+ "name":"Appliances"
+ },
+ {
+ "id":"ArtsAndCrafts",
+ "name":"Arts, Crafts & Sewing"
+ },
+ {
+ "id":"Automotive",
+ "name":"Automotive Parts & Accessories"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty & Personal Care"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Clothing, Shoes & Jewelry"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Home & Garden"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery & Gourmet Food"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Baby Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Lighting",
+ "name":"Lighting"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ }
+ ],
+ "co.uk":[
+ {
+ "id":"AmazonVideo",
+ "name":"Amazon Video"
+ },
+ {
+ "id":"Apparel",
+ "name":"Clothing"
+ },
+ {
+ "id":"Appliances",
+ "name":"Large Appliances"
+ },
+ {
+ "id":"Automotive",
+ "name":"Car & Motorbike"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Classical",
+ "name":"Classical Music"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers & Accessories"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"Digital Music"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics & Photo"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Fashion"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Garden & Outdoors"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health & Personal Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Jewellery"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"Lighting",
+ "name":"Lighting"
+ },
+ {
+ "id":"Luggage",
+ "name":"Luggage"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Luxury Beauty"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"DVD & Blu-ray"
+ },
+ {
+ "id":"Music",
+ "name":"CDs & Vinyl"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments & DJ"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Stationery & Office Supplies"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Shoes",
+ "name":"Shoes & Bags"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"DIY & Tools"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VHS",
+ "name":"VHS"
+ },
+ {
+ "id":"VideoGames",
+ "name":"PC & Video Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Watches"
+ }
+ ],
+ "com":[
+ {
+ "id":"AmazonVideo",
+ "name":"Prime Video"
+ },
+ {
+ "id":"Apparel",
+ "name":"Clothing & Accessories"
+ },
+ {
+ "id":"Appliances",
+ "name":"Appliances"
+ },
+ {
+ "id":"ArtsAndCrafts",
+ "name":"Arts, Crafts & Sewing"
+ },
+ {
+ "id":"Automotive",
+ "name":"Automotive Parts & Accessories"
+ },
+ {
+ "id":"Baby",
+ "name":"Baby"
+ },
+ {
+ "id":"Beauty",
+ "name":"Beauty & Personal Care"
+ },
+ {
+ "id":"Books",
+ "name":"Books"
+ },
+ {
+ "id":"Classical",
+ "name":"Classical"
+ },
+ {
+ "id":"Collectibles",
+ "name":"Collectibles & Fine Art"
+ },
+ {
+ "id":"Computers",
+ "name":"Computers"
+ },
+ {
+ "id":"DigitalMusic",
+ "name":"Digital Music"
+ },
+ {
+ "id":"DigitalEducationalResources",
+ "name":"Digital Educational Resources"
+ },
+ {
+ "id":"Electronics",
+ "name":"Electronics"
+ },
+ {
+ "id":"EverythingElse",
+ "name":"Everything Else"
+ },
+ {
+ "id":"Fashion",
+ "name":"Clothing, Shoes & Jewelry"
+ },
+ {
+ "id":"FashionBaby",
+ "name":"Clothing, Shoes & Jewelry Baby"
+ },
+ {
+ "id":"FashionBoys",
+ "name":"Clothing, Shoes & Jewelry Boys"
+ },
+ {
+ "id":"FashionGirls",
+ "name":"Clothing, Shoes & Jewelry Girls"
+ },
+ {
+ "id":"FashionMen",
+ "name":"Clothing, Shoes & Jewelry Men"
+ },
+ {
+ "id":"FashionWomen",
+ "name":"Clothing, Shoes & Jewelry Women"
+ },
+ {
+ "id":"GardenAndOutdoor",
+ "name":"Garden & Outdoor"
+ },
+ {
+ "id":"GiftCards",
+ "name":"Gift Cards"
+ },
+ {
+ "id":"GroceryAndGourmetFood",
+ "name":"Grocery & Gourmet Food"
+ },
+ {
+ "id":"Handmade",
+ "name":"Handmade"
+ },
+ {
+ "id":"HealthPersonalCare",
+ "name":"Health, Household & Baby Care"
+ },
+ {
+ "id":"HomeAndKitchen",
+ "name":"Home & Kitchen"
+ },
+ {
+ "id":"Industrial",
+ "name":"Industrial & Scientific"
+ },
+ {
+ "id":"Jewelry",
+ "name":"Jewelry"
+ },
+ {
+ "id":"KindleStore",
+ "name":"Kindle Store"
+ },
+ {
+ "id":"LocalServices",
+ "name":"Home & Business Services"
+ },
+ {
+ "id":"Luggage",
+ "name":"Luggage & Travel Gear"
+ },
+ {
+ "id":"LuxuryBeauty",
+ "name":"Luxury Beauty"
+ },
+ {
+ "id":"Magazines",
+ "name":"Magazine Subscriptions"
+ },
+ {
+ "id":"MobileAndAccessories",
+ "name":"Cell Phones & Accessories"
+ },
+ {
+ "id":"MobileApps",
+ "name":"Apps & Games"
+ },
+ {
+ "id":"MoviesAndTV",
+ "name":"Movies & TV"
+ },
+ {
+ "id":"Music",
+ "name":"CDs & Vinyl"
+ },
+ {
+ "id":"MusicalInstruments",
+ "name":"Musical Instruments"
+ },
+ {
+ "id":"OfficeProducts",
+ "name":"Office Products"
+ },
+ {
+ "id":"PetSupplies",
+ "name":"Pet Supplies"
+ },
+ {
+ "id":"Photo",
+ "name":"Camera & Photo"
+ },
+ {
+ "id":"Shoes",
+ "name":"Shoes"
+ },
+ {
+ "id":"Software",
+ "name":"Software"
+ },
+ {
+ "id":"SportsAndOutdoors",
+ "name":"Sports & Outdoors"
+ },
+ {
+ "id":"ToolsAndHomeImprovement",
+ "name":"Tools & Home Improvement"
+ },
+ {
+ "id":"ToysAndGames",
+ "name":"Toys & Games"
+ },
+ {
+ "id":"VHS",
+ "name":"VHS"
+ },
+ {
+ "id":"VideoGames",
+ "name":"Video Games"
+ },
+ {
+ "id":"Watches",
+ "name":"Watches"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/includes/bin/countries.json b/src/includes/bin/countries.json
new file mode 100644
index 0000000..6210018
--- /dev/null
+++ b/src/includes/bin/countries.json
@@ -0,0 +1,23 @@
+{
+ "com.au":"Australia",
+ "com.be":"Belgium",
+ "com.br":"Brazil",
+ "ca":"Canada",
+ "eg":"Egypt",
+ "fr":"France",
+ "de":"Germany",
+ "in":"India",
+ "it":"Italy",
+ "co.jp":"Japan",
+ "com.mx":"Mexico",
+ "nl":"Netherlands",
+ "pl":"Poland",
+ "sa":"Saudi Arabia",
+ "sg":"Singapore",
+ "es":"Spain",
+ "se":"Sweden",
+ "com.tr":"Turkey",
+ "ae":"United Arab Emirates",
+ "co.uk":"United Kingdom",
+ "com":"United States"
+}
\ No newline at end of file
diff --git a/src/includes/bin/currencies.json b/src/includes/bin/currencies.json
new file mode 100644
index 0000000..a5080f9
--- /dev/null
+++ b/src/includes/bin/currencies.json
@@ -0,0 +1,129 @@
+{
+ "com.au":[
+ "AUD"
+ ],
+ "com.be":[
+ "EUR"
+ ],
+ "com.br":[
+ "BRL"
+ ],
+ "ca":[
+ "CAD"
+ ],
+ "eg":[
+ "EGP"
+ ],
+ "fr":[
+ "EUR"
+ ],
+ "de":[
+ "EUR"
+ ],
+ "in":[
+ "INR"
+ ],
+ "it":[
+ "EUR"
+ ],
+ "co.jp":[
+ "JPY"
+ ],
+ "com.mx":[
+ "MXN"
+ ],
+ "nl":[
+ "EUR"
+ ],
+ "pl":[
+ "PLN"
+ ],
+ "sg":[
+ "SGD"
+ ],
+ "sa":[
+ "SAR"
+ ],
+ "es":[
+ "EUR"
+ ],
+ "se":[
+ "SEK"
+ ],
+ "com.tr":[
+ "TRY"
+ ],
+ "ae":[
+ "AED"
+ ],
+ "co.uk":[
+ "GBP"
+ ],
+ "com":[
+ "AED",
+ "AMD",
+ "ARS",
+ "AUD",
+ "AWG",
+ "AZN",
+ "BGN",
+ "BND",
+ "BOB",
+ "BRL",
+ "BSD",
+ "BZD",
+ "CAD",
+ "CLP",
+ "CNY",
+ "COP",
+ "CRC",
+ "DOP",
+ "EGP",
+ "EUR",
+ "GBP",
+ "GHS",
+ "GTQ",
+ "HKD",
+ "HNL",
+ "HUF",
+ "IDR",
+ "ILS",
+ "INR",
+ "JMD",
+ "JPY",
+ "KES",
+ "KHR",
+ "KRW",
+ "KYD",
+ "KZT",
+ "LBP",
+ "MAD",
+ "MNT",
+ "MOP",
+ "MUR",
+ "MXN",
+ "MYR",
+ "NAD",
+ "NGN",
+ "NOK",
+ "NZD",
+ "PAB",
+ "PEN",
+ "PHP",
+ "PYG",
+ "QAR",
+ "RUB",
+ "SAR",
+ "SGD",
+ "THB",
+ "TRY",
+ "TTD",
+ "TWD",
+ "TZS",
+ "USD",
+ "UYU",
+ "VND",
+ "XCD",
+ "ZAR"
+ ]
+}
\ No newline at end of file
diff --git a/src/includes/bin/languages.json b/src/includes/bin/languages.json
new file mode 100644
index 0000000..f121949
--- /dev/null
+++ b/src/includes/bin/languages.json
@@ -0,0 +1,89 @@
+{
+ "com.au": [
+ "en_AU"
+ ],
+ "com.be": [
+ "fr_BE",
+ "nl_BE",
+ "en_GB"
+ ],
+ "com.br": [
+ "pt_BR"
+ ],
+ "ca": [
+ "en_CA",
+ "fr_CA"
+ ],
+ "eg": [
+ "en_AE",
+ "ar_AE"
+ ],
+ "fr": [
+ "fr_FR"
+ ],
+ "de": [
+ "cs_CZ",
+ "de_DE",
+ "en_GB",
+ "nl_NL",
+ "pl_PL",
+ "tr_TR"
+ ],
+ "in": [
+ "en_IN",
+ "hi_IN",
+ "kn_IN",
+ "ml_IN",
+ "ta_IN",
+ "te_IN"
+ ],
+ "it": [
+ "it_IT"
+ ],
+ "co.jp": [
+ "en_US",
+ "ja_JP",
+ "zh_CN"
+ ],
+ "com.mx": [
+ "es_MX"
+ ],
+ "nl": [
+ "nl_NL"
+ ],
+ "pl": [
+ "pl_PL"
+ ],
+ "sg": [
+ "en_SG"
+ ],
+ "sa": [
+ "en_AE",
+ "ar_AE"
+ ],
+ "es": [
+ "es_ES"
+ ],
+ "se": [
+ "sv_SE"
+ ],
+ "com.tr": [
+ "tr_TR"
+ ],
+ "ae": [
+ "en_AE",
+ "ar_AE"
+ ],
+ "co.uk": [
+ "en_GB"
+ ],
+ "com": [
+ "de_DE",
+ "en_US",
+ "es_US",
+ "ko_KR",
+ "pt_BR",
+ "zh_CN",
+ "zh_TW"
+ ]
+}
\ No newline at end of file
diff --git a/src/includes/bin/regions.json b/src/includes/bin/regions.json
new file mode 100644
index 0000000..01fb6c5
--- /dev/null
+++ b/src/includes/bin/regions.json
@@ -0,0 +1,29 @@
+{
+ "eu-west-1":[
+ "ae",
+ "co.uk",
+ "com.be",
+ "com.tr",
+ "de",
+ "eg",
+ "es",
+ "fr",
+ "in",
+ "it",
+ "nl",
+ "pl",
+ "sa",
+ "se"
+ ],
+ "us-east-1":[
+ "ca",
+ "com",
+ "com.br",
+ "com.mx"
+ ],
+ "us-west-2":[
+ "co.jp",
+ "com.au",
+ "sg"
+ ]
+}
\ No newline at end of file
diff --git a/src/includes/bin/symbols.json b/src/includes/bin/symbols.json
new file mode 100644
index 0000000..d5a8657
--- /dev/null
+++ b/src/includes/bin/symbols.json
@@ -0,0 +1,18 @@
+{
+ "AED":"DH",
+ "AUD":"$",
+ "BRL":"R$",
+ "CAD":"$",
+ "EGP":"\u00a3E",
+ "EUR":"\u20ac",
+ "GBP":"\u00a3",
+ "INR":"\u20b9",
+ "JPY":"\u00a5",
+ "MXN":"$",
+ "PLN":"z\u0142",
+ "SAR":"SR",
+ "SEK":"kr",
+ "SGD":"S$",
+ "TRY":"\u20ba",
+ "USD":"$"
+}
\ No newline at end of file
diff --git a/src/interfaces/CartInterface.php b/src/interfaces/CartInterface.php
new file mode 100644
index 0000000..28209b3
--- /dev/null
+++ b/src/interfaces/CartInterface.php
@@ -0,0 +1,44 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+namespace Apaapi\interfaces;
+
+/**
+ * Cart interface.
+ */
+interface CartInterface
+{
+ /**
+ * Set request locale.
+ *
+ * @param string $locale
+ * @return object
+ * @throws RequestException
+ */
+ function setLocale(string $locale) : object;
+
+ /**
+ * Set partner tag.
+ *
+ * @param string $tag
+ * @return object
+ */
+ function setPartnerTag(string $tag) : object;
+
+ /**
+ * Set cart items.
+ *
+ * @param array $items
+ * @return string
+ */
+ function set(array $items) : string;
+}
diff --git a/src/interfaces/ClientInterface.php b/src/interfaces/ClientInterface.php
new file mode 100644
index 0000000..cc927f5
--- /dev/null
+++ b/src/interfaces/ClientInterface.php
@@ -0,0 +1,80 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+namespace Apaapi\interfaces;
+
+/**
+ * Apaapi request client interface.
+ */
+interface ClientInterface
+{
+ /**
+ * Setup client.
+ *
+ * @param string $endpoint
+ * @param array $params
+ */
+ function __construct(string $endpoint, array $params = []);
+
+ /**
+ * Set HTTP request method.
+ *
+ * @param string $method
+ * @return object
+ */
+ function setMethod(string $method) : self;
+
+ /**
+ * Set HTTP response timeout.
+ *
+ * @param int $timeout
+ * @return object
+ */
+ function setTimeout(int $timeout) : self;
+
+ /**
+ * Set HTTP redirect location.
+ *
+ * @param int $redirect
+ * @return object
+ */
+ function setRedirect(int $redirect) : self;
+
+ /**
+ * Set HTTP encoding.
+ *
+ * @param string $encoding
+ * @return object
+ */
+ function setEncoding(string $encoding) : self;
+
+ /**
+ * Get HTTP response content.
+ *
+ * @return string
+ */
+ function getResponse() : string;
+
+ /**
+ * Get HTTP response code.
+ *
+ * @return int
+ */
+ function getCode() : int;
+
+ /**
+ * Close request handler.
+ *
+ * @return void
+ */
+ function close();
+}
diff --git a/src/interfaces/ItemOperationInterface.php b/src/interfaces/ItemOperationInterface.php
index 66fd44c..452f5f3 100644
--- a/src/interfaces/ItemOperationInterface.php
+++ b/src/interfaces/ItemOperationInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,37 +13,47 @@
namespace Apaapi\interfaces;
/**
- * Interface Group Items Operations.
+ * Group items operations.
*/
interface ItemOperationInterface
{
/**
+ * Set condition.
+ *
* @param string $condition
* @return object
*/
- function setCondition($condition);
+ function setCondition(string $condition) : object;
/**
- * @param string $currencyOfPreference
+ * Set currency.
+ *
+ * @param string $currency
* @return object
*/
- function setCurrency($currencyOfPreference);
+ function setCurrency(string $currency) : object;
/**
+ * Set merchant.
+ *
* @param string $merchant
* @return object
*/
- function setMerchant($merchant);
+ function setMerchant(string $merchant) : object;
/**
- * @param string $offerCount
+ * Set offer count.
+ *
+ * @param int $count
* @return object
*/
- function setOfferCount($offerCount);
+ function setOfferCount(int $count) : object;
/**
+ * Set properties.
+ *
* @param string $properties
* @return object
*/
- function setProperties($properties);
+ function setProperties(string $properties) : object;
}
diff --git a/src/interfaces/OperationInterface.php b/src/interfaces/OperationInterface.php
index 2c32057..77fb0e0 100644
--- a/src/interfaces/OperationInterface.php
+++ b/src/interfaces/OperationInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,37 +13,49 @@
namespace Apaapi\interfaces;
/**
- * Interface Group All Operations.
+ * Group all operations.
*/
interface OperationInterface extends ParsableInterface
{
- /**
- * @param string $type
- * @return object
- */
- function setPartnerType($type);
-
/**
- * @param string $tag
+ * Set partner type.
+ *
+ * @param string $type
* @return object
*/
- function setPartnerTag($tag);
+ function setPartnerType(string $type) : object;
+
+ /**
+ * Set partner tag.
+ *
+ * @param string $tag
+ * @return object
+ */
+ function setPartnerTag(string $tag) : object;
/**
+ * Set resources.
+ *
* @param array $resources
+ * @param bool $throwable
* @return object
+ * @throws OperationException
*/
- function setResources($resources);
+ function setResources(array $resources, bool $throwable = true) : object;
/**
+ * Set languages of preference.
+ *
* @param array $languagesOfPreference
* @return object
*/
- function setLanguages($languagesOfPreference);
+ function setLanguages(array $languagesOfPreference) : object;
/**
+ * Set marketplace.
+ *
* @param string $marketplace
* @return object
*/
- function setMarketplace($marketplace);
+ function setMarketplace(string $marketplace) : object;
}
diff --git a/src/interfaces/ParsableInterface.php b/src/interfaces/ParsableInterface.php
index b071396..5c3d12b 100644
--- a/src/interfaces/ParsableInterface.php
+++ b/src/interfaces/ParsableInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,6 +13,6 @@
namespace Apaapi\interfaces;
/**
- * Basic Apaapi Resource Interface.
+ * Apaapi parsable interface.
*/
interface ParsableInterface {}
diff --git a/src/interfaces/RequestClientInterface.php b/src/interfaces/RequestClientInterface.php
deleted file mode 100644
index 215ef5e..0000000
--- a/src/interfaces/RequestClientInterface.php
+++ /dev/null
@@ -1,43 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\interfaces;
-
-/**
- * Basic Apaapi Request Client Interface.
- */
-interface RequestClientInterface
-{
- /**
- * @param string $endpoint
- * @param array $params
- */
- function __construct($endpoint, $params);
-
- /**
- * @param void
- * @return mixed
- */
- function getResponse();
-
- /**
- * @param void
- * @return int
- */
- function getCode();
-
- /**
- * @param void
- * @return void
- */
- function close();
-}
diff --git a/src/interfaces/RequestInterface.php b/src/interfaces/RequestInterface.php
index 69b78c3..b5fd1c6 100644
--- a/src/interfaces/RequestInterface.php
+++ b/src/interfaces/RequestInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,50 +13,63 @@
namespace Apaapi\interfaces;
/**
- * Basic Apaapi Request Interface.
+ * Apaapi request interface.
*/
interface RequestInterface
{
- /**
- * @param string $accessKeyID
- * @param string $secretAccessKey
- */
- function __construct($accessKeyID = '', $secretAccessKey = '');
+ /**
+ * Prepare request.
+ * @see https://webservices.amazon.com/paapi5/scratchpad/index.html
+ *
+ * @param string $accessKeyID
+ * @param string $secretAccessKey
+ */
+ function __construct(string $accessKeyID, string $secretAccessKey);
/**
- * @param void
+ * Get request client.
+ *
* @return object
*/
- function getClient();
+ function getClient() : object;
/**
- * @param void
+ * Get request endpoint.
+ *
* @return string
*/
- function getEndpoint();
+ function getEndpoint() : string;
/**
- * @param void
+ * Get request parameters.
+ *
* @return array
*/
- function getParams();
+ function getParams() : array;
/**
- * @param void
+ * Get request operation.
+ *
* @return string
*/
- function getOperation();
+ function getOperation() : string;
/**
+ * Set request header.
+ *
* @param string $name
- * @param string $value
+ * @param mixed $value
* @return void
*/
- function setRequestHeader($name, $value);
+ function setRequestHeader(string $name, $value);
/**
+ * Set request locale.
+ * @see https://webservices.amazon.fr/paapi5/documentation/locale-reference.html
+ *
* @param string $locale
* @return object
+ * @throws RequestException
*/
- function setLocale($locale);
+ function setLocale(string $locale) : object;
}
diff --git a/src/interfaces/ResourceInterface.php b/src/interfaces/ResourceInterface.php
index 58c10ab..1adfe81 100644
--- a/src/interfaces/ResourceInterface.php
+++ b/src/interfaces/ResourceInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,6 +13,6 @@
namespace Apaapi\interfaces;
/**
- * Basic Apaapi Resource Interface.
+ * Apaapi resource interface.
*/
interface ResourceInterface extends ParsableInterface {}
diff --git a/src/interfaces/ResponseInterface.php b/src/interfaces/ResponseInterface.php
index 2a3a9b1..fa0b6ba 100644
--- a/src/interfaces/ResponseInterface.php
+++ b/src/interfaces/ResponseInterface.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,14 +13,45 @@
namespace Apaapi\interfaces;
/**
- * Basic Apaapi Response Interface.
+ * Apaapi response interface.
*/
interface ResponseInterface
{
/**
+ * Send request then get response.
+ *
* @param RequestInterface $request
- * @param ResponseTypeInterface $type
- * @param bool $parse
+ * @param bool $normalize
+ * @param bool $cache
*/
- public function __construct(RequestInterface $request, ResponseTypeInterface $type = null, $parse = null);
+ function __construct(RequestInterface $request, bool $normalize = false, bool $cache = true);
+
+ /**
+ * Get response data.
+ *
+ * @param array $geo
+ * @return array
+ */
+ function get(?array $geo = null) : array;
+
+ /**
+ * Get response body.
+ *
+ * @return string
+ */
+ function getBody() : string;
+
+ /**
+ * Get response error.
+ *
+ * @return string
+ */
+ function getError() : string;
+
+ /**
+ * Check response error.
+ *
+ * @return bool
+ */
+ function hasError() : bool;
}
diff --git a/src/interfaces/ResponseParseInterface.php b/src/interfaces/ResponseParseInterface.php
deleted file mode 100644
index a37e556..0000000
--- a/src/interfaces/ResponseParseInterface.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\interfaces;
-
-/**
- * Basic Apaapi Response Interface.
- */
-interface ResponseParseInterface
-{
- /**
- * @param RequestInterface $request
- * @param array $params
- */
- function __construct(RequestInterface $request, $params = []);
-}
diff --git a/src/interfaces/ResponseTypeInterface.php b/src/interfaces/ResponseTypeInterface.php
deleted file mode 100644
index e231cae..0000000
--- a/src/interfaces/ResponseTypeInterface.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\interfaces;
-
-/**
- * Basic Apaapi Response Interface.
- */
-interface ResponseTypeInterface
-{
- /**
- * @param string $type
- */
- function __construct($type = 'Object');
-
- /**
- * @param string $response
- * @return mixed
- */
- function format($response);
-
- /**
- * @param object $response
- * @param string $operation
- * @return mixed
- */
- function parse($response, $operation);
-}
diff --git a/src/lib/Cart.php b/src/lib/Cart.php
index db9997a..502ed45 100644
--- a/src/lib/Cart.php
+++ b/src/lib/Cart.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,74 +13,67 @@
namespace Apaapi\lib;
use Apaapi\exceptions\RequestException;
+use Apaapi\interfaces\CartInterface;
+use Apaapi\includes\{
+ Provider,
+ Normalizer
+};
/**
- * Basic Apaapi Cart Wrapper Class.
+ * Basic Apaapi cart wrapper class.
* @see https://webservices.amazon.com/paapi5/documentation/add-to-cart-form.html
*/
-final class Cart
+class Cart implements CartInterface
{
/**
* @access public
- * @var string HOST, API Host
- * @var string ENDPOINT, API Endpoint
+ * @var string ENDPOINT, Dynamic API endpoint
*/
- const HOST = 'https://www.amazon.{locale}';
- const ENDPOINT = '/gp/aws/cart/add.html?AssociateTag={tag}';
+ public const ENDPOINT = '/gp/aws/cart/add.html?AssociateTag={tag}';
/**
- * @access private
+ * @access protected
* @var mixed $locale
* @var string $tag
+ * @var int $limit, Items limit
*/
- private $locale = false;
- private $tag;
+ protected $locale = false;
+ protected $tag;
+ protected static $limit = 5;
/**
- * Set request locale.
- *
- * @access public
- * @param string $locale
- * @return object
- * @throws RequestException
+ * @inheritdoc
*/
- public function setLocale($locale)
+ public function setLocale(string $locale) : object
{
- $locale = strtolower($locale);
- if ( in_array($locale, $this->getRegions()) ) {
- $this->locale = $locale;
- }
+ $this->locale = Normalizer::formatLocale($locale);
if ( !$this->locale ) {
throw new RequestException(
- RequestException::invalidRequestLocaleMessage($locale)
+ RequestException::invalidLocale($locale)
);
}
return $this;
}
/**
- * Set request tag.
- *
- * @access public
- * @param string $tag
- * @return object
+ * @inheritdoc
*/
- public function setPartnerTag($tag)
+ public function setPartnerTag(string $tag) : object
{
$this->tag = $tag;
return $this;
}
/**
- * Add items to cart.
- *
- * @access public
- * @param array $items
- * @return string
+ * @inheritdoc
*/
- public function add($items = [])
+ public function set(array $items) : string
{
- $url = self::HOST . self::ENDPOINT;
+ if ( static::$limit ) {
+ $items = array_slice($items, 0, static::$limit);
+ }
+
+ $url = Provider::HOST . self::ENDPOINT;
$url = str_replace('{locale}', $this->locale, $url);
$url = str_replace('{tag}', $this->tag, $url);
$i = 0;
@@ -92,18 +85,14 @@ public function add($items = [])
}
/**
- * Get request regions.
- *
- * @access private
- * @param void
- * @return array
- */
- private function getRegions()
- {
- return [
- 'fr','com.be','de','in','it','es','nl','pl','com.tr','ae','sa','co.uk','se','eg',
- 'com','com.br','ca','com.mx',
- 'com.au','co.jp','sg'
- ];
- }
+ * Set limit.
+ *
+ * @access public
+ * @param int $limit
+ * @return void
+ */
+ public static function limit(int $limit)
+ {
+ self::$limit = $limit;
+ }
}
diff --git a/src/lib/ItemOperation.php b/src/lib/ItemOperation.php
index aba24bb..9b9de82 100644
--- a/src/lib/ItemOperation.php
+++ b/src/lib/ItemOperation.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,10 +15,9 @@
use Apaapi\interfaces\ItemOperationInterface;
/**
- * Basic Apaapi Grouped Item Operation Wrapper Class.
+ * Apaapi item operation wrapper class.
*/
-class ItemOperation extends Operation
-implements ItemOperationInterface
+class ItemOperation extends Operation implements ItemOperationInterface
{
/**
* @access public
@@ -35,55 +34,45 @@ class ItemOperation extends Operation
public $properties = null;
/**
- * @access public
- * @param string $condition
- * @return object
+ * @inheritdoc
*/
- public function setCondition($condition)
+ public function setCondition(string $condition) : object
{
$this->condition = $condition;
return $this;
}
/**
- * @access public
- * @param string $currencyOfPreference
- * @return object
+ * @inheritdoc
*/
- public function setCurrency($currencyOfPreference)
+ public function setCurrency(string $currency) : object
{
- $this->currencyOfPreference = $currencyOfPreference;
+ $this->currencyOfPreference = $currency;
return $this;
}
/**
- * @access public
- * @param string $merchant
- * @return object
+ * @inheritdoc
*/
- public function setMerchant($merchant)
+ public function setMerchant(string $merchant) : object
{
$this->merchant = $merchant;
return $this;
}
/**
- * @access public
- * @param string $offerCount
- * @return object
+ * @inheritdoc
*/
- public function setOfferCount($offerCount)
+ public function setOfferCount(int $count) : object
{
- $this->offerCount = $offerCount;
+ $this->offerCount = $count;
return $this;
}
/**
- * @access public
- * @param string $properties
- * @return object
+ * @inheritdoc
*/
- public function setProperties($properties)
+ public function setProperties(string $properties) : object
{
$this->properties = $properties;
return $this;
diff --git a/src/lib/Operation.php b/src/lib/Operation.php
index 5765fe8..46badfc 100644
--- a/src/lib/Operation.php
+++ b/src/lib/Operation.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,99 +12,95 @@
namespace Apaapi\lib;
-use Apaapi\exceptions\OperationException;
use Apaapi\interfaces\OperationInterface;
+use Apaapi\exceptions\OperationException;
/**
- * Basic Apaapi All Operation Wrapper Class.
+ * Apaapi operation wrapper class.
*/
class Operation implements OperationInterface
{
/**
* @access public
- * @var string $partnerType
* @var array $resources
+ * @var string $partnerType
* @var string $partnerTag
- * @var array $marketplace
+ * @var string $marketplace
* @var array $languagesOfPreference
*/
- public $partnerType = 'Associates';
public $resources = [];
+ public $partnerType = 'Associates';
public $partnerTag = null;
public $marketplace = null;
public $languagesOfPreference = [];
- /**
- * @access public
- * @param string $type
- * @return object
- */
- public function setPartnerType($type)
+ /**
+ * @inheritdoc
+ */
+ public function setPartnerType(string $type) : object
{
$this->partnerType = $type;
return $this;
}
/**
- * @access public
- * @param string $tag
- * @return object
+ * @inheritdoc
*/
- public function setPartnerTag($tag)
+ public function setPartnerTag(string $tag) : object
{
$this->partnerTag = $tag;
return $this;
}
- /**
- * @access public
- * @param array $resources
- * @return object
- * @throws OperationException
- */
- public function setResources($resources = [])
+ /**
+ * @inheritdoc
+ */
+ public function setResources(array $resources, bool $throwable = true) : object
{
- if ( ($ressource = $this->isValidResources($resources)) !== true ) {
- throw new OperationException(
- OperationException::invalidOperationRessource($ressource)
- );
+ if ( $throwable ) {
+ if ( ($ressource = $this->isValidResources($resources)) !== true ) {
+ throw new OperationException(
+ OperationException::invalidRessources($ressource)
+ );
+ }
}
- $this->resources = !empty($resources)
- ? $resources : $this->resources;
+
+ if ( !empty($resources) ) {
+ $this->resources = $resources;
+ }
+
return $this;
}
/**
- * @access public
- * @param array $languagesOfPreference
- * @return object
+ * @inheritdoc
*/
- public function setLanguages($languagesOfPreference)
+ public function setLanguages(array $languages) : object
{
- $this->languagesOfPreference = (array)$languagesOfPreference;
+ $this->languagesOfPreference = $languages;
return $this;
}
/**
- * @access public
- * @param string $marketplace
- * @return object
+ * @inheritdoc
*/
- public function setMarketplace($marketplace)
+ public function setMarketplace(string $marketplace) : object
{
$this->marketplace = $marketplace;
return $this;
}
/**
+ * Check valid resources.
+ *
* @access private
* @param array $resources
* @return mixed
*/
- private function isValidResources($resources = [])
+ private function isValidResources(array $resources)
{
- foreach ((array)$resources as $resource) {
- if ( !in_array($resource,$this->resources) ) {
+ foreach ($resources as $resource) {
+ if ( !in_array($resource, $this->resources) ) {
return $resource;
}
}
diff --git a/src/lib/Request.php b/src/lib/Request.php
index ac9dbf2..c98bfc3 100644
--- a/src/lib/Request.php
+++ b/src/lib/Request.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,64 +12,67 @@
namespace Apaapi\lib;
-use Apaapi\interfaces\RequestInterface;
-use Apaapi\interfaces\ParsableInterface;
-use Apaapi\interfaces\RequestClientInterface;
-use Apaapi\includes\OperationParser;
-use Apaapi\includes\RequestClient;
+use Apaapi\interfaces\{
+ RequestInterface,
+ ClientInterface,
+ OperationInterface
+};
+use Apaapi\includes\{
+ Client,
+ Parser,
+ Provider,
+ Normalizer
+};
use Apaapi\exceptions\RequestException;
/**
- * Basic Apaapi Request Wrapper Class.
+ * Apaapi request wrapper class.
*/
-final class Request extends SignatureRequest
-implements RequestInterface
+final class Request extends Signature implements RequestInterface
{
/**
* @access public
* @var string HOST, API Host
*/
- const HOST = 'webservices.amazon';
+ public const HOST = 'webservices.amazon';
/**
* @access private
* @var array $params
- * @var array $endpoint
- * @var RequestClient $client
+ * @var string $endpoint
+ * @var Client $client
* @var string $operation
*/
private $params = [];
- private $endpoint = [];
+ private $endpoint;
private $client;
private $operation;
/**
- * @param string $accessKeyID
- * @param string $secretAccessKey
- * @see https://webservices.amazon.com/paapi5/scratchpad/index.html
+ * @inheritdoc
*/
- public function __construct($accessKeyID = '', $secretAccessKey = '')
+ public function __construct(string $accessKeyID, string $secretAccessKey)
{
$this->accessKeyID = $accessKeyID;
$this->secretAccessKey = $secretAccessKey;
- $this->init();
+
+ $this->setTimeStamp();
+ $this->setDate();
+ $this->setRequestHeader('content-encoding', 'amz-1.0');
+ $this->setRequestHeader('content-type', 'application/json; charset=utf-8');
}
/**
- * Set request payload.
- *
- * @access public
- * @param ParsableInterface $operation
- * @return void
+ * @inheritdoc
*/
- public function setPayload(ParsableInterface $operation)
+ public function setPayload(OperationInterface $operation)
{
// Setup params
- $this->operation = OperationParser::getName($operation);
- $this->path = $this->path . strtolower($this->operation);
- $this->target = "{$this->target}.{$this->operation}";
+ $this->operation = Parser::getName($operation);
+ $this->path = $this->path . strtolower($this->operation);
+ $this->target = "{$this->target}.{$this->operation}";
+ $this->payload = Parser::convert($operation);
$host = self::HOST . ".{$this->locale}";
- $this->payload = OperationParser::toString($operation);
// Setup headers
$this->setRequestHeader('host', $host);
@@ -77,33 +80,27 @@ public function setPayload(ParsableInterface $operation)
$this->setRequestHeader('x-amz-date', $this->timestamp);
$headers = $this->getHeaders();
- $headerString = '';
+ $header = '';
foreach ( $headers as $key => $value ) {
- $headerString .= "{$key}:{$value}\r\n";
+ $header .= "{$key}:{$value}\r\n";
}
$this->endpoint = "https://{$host}{$this->path}";
$this->params = [
- 'http' => [
- 'method' => 'POST',
- 'header' => $headerString,
- 'content' => $this->payload
- ]
+ 'method' => 'POST',
+ 'header' => $header,
+ 'payload' => $this->payload
];
}
/**
- * Set request client.
- *
- * @access public
- * @param RequestClientInterface $client
- * @return void
+ * @inheritdoc
*/
- public function setClient(RequestClientInterface $client = null)
+ public function setClient(?ClientInterface $client = null)
{
if ( !($this->client = $client) ) {
- $this->client = new RequestClient(
+ $this->client = new Client(
$this->getEndpoint(),
$this->getParams()
);
@@ -111,25 +108,9 @@ public function setClient(RequestClientInterface $client = null)
}
/**
- * Check request has valid client.
- *
- * @access public
- * @param void
- * @return bool
- */
- public function hasClient()
- {
- return is_object($this->client);
- }
-
- /**
- * Set request timestamp.
- *
- * @access public
- * @param string $timestamp
- * @return object
+ * @inheritdoc
*/
- public function setTimeStamp($timestamp = null)
+ public function setTimeStamp(?string $timestamp = null) : object
{
$this->timestamp = ($timestamp)
? $timestamp : gmdate('Ymd\THis\Z');
@@ -137,13 +118,9 @@ public function setTimeStamp($timestamp = null)
}
/**
- * Set request date.
- *
- * @access public
- * @param string $date
- * @return object
+ * @inheritdoc
*/
- public function setDate($date = null)
+ public function setDate(?string $date = null) : object
{
$this->currentDate = ($date)
? $date : gmdate('Ymd');
@@ -151,123 +128,71 @@ public function setDate($date = null)
}
/**
- * Get request client.
+ * Check valid client.
*
* @access public
- * @param void
- * @return object
+ * @return bool
+ */
+ public function hasClient() : bool
+ {
+ $interface = 'Apaapi\interfaces\RequestInterface';
+ return is_subclass_of($this->client, $interface);
+ }
+
+ /**
+ * @inheritdoc
*/
- public function getClient()
+ public function getClient() : object
{
return $this->client;
}
/**
- * Get request endpoint.
- *
- * @access public
- * @param void
- * @return string
+ * @inheritdoc
*/
- public function getEndpoint()
+ public function getEndpoint() : string
{
return $this->endpoint;
}
/**
- * Get request parameters.
- *
- * @access public
- * @param void
- * @return array
+ * @inheritdoc
*/
- public function getParams()
+ public function getParams() : array
{
return $this->params;
}
/**
- * Get request operation.
- *
- * @access public
- * @param void
- * @return string
+ * @inheritdoc
*/
- public function getOperation()
+ public function getOperation() : string
{
return $this->operation;
}
/**
- * Set request header.
- *
- * @access public
- * @param string $name
- * @param string $value
- * @return void
+ * @inheritdoc
*/
- public function setRequestHeader($name, $value)
+ public function setRequestHeader(string $name, $value)
{
$this->headers[$name] = $value;
}
/**
- * Set request locale.
- *
- * @access public
- * @param string $locale
- * @return object
- * @throws RequestException
- * @see https://webservices.amazon.fr/paapi5/documentation/locale-reference.html
+ * @inheritdoc
*/
- public function setLocale($locale)
+ public function setLocale(string $locale) : object
{
- $locale = strtolower($locale);
- foreach ($this->getRegions() as $name => $value) {
- if ( in_array($locale,$value) ) {
- $this->locale = $locale;
- $this->region = $name;
- break;
- } else {
- $this->locale = false;
- }
- }
+ $this->locale = Normalizer::formatLocale($locale);
+ $this->region = Provider::getRegion($locale);
+
if ( !$this->locale ) {
throw new RequestException(
- RequestException::invalidRequestLocaleMessage($locale)
+ RequestException::invalidLocale($locale)
);
}
+
return $this;
}
-
- /**
- * Init request.
- *
- * @access private
- * @param void
- * @return void
- */
- private function init()
- {
- $this->setTimeStamp();
- $this->setDate();
- $this->setRequestHeader('content-encoding', 'amz-1.0');
- $this->setRequestHeader('content-type', 'application/json; charset=utf-8');
- }
-
- /**
- * Get request regions.
- *
- * @access private
- * @param void
- * @return array
- */
- private function getRegions()
- {
- return [
- 'eu-west-1' => ['fr','com.be','de','in','it','es','nl','pl','com.tr','ae','sa','co.uk','se','eg'],
- 'us-east-1' => ['com','com.br','ca','com.mx'],
- 'us-west-2' => ['com.au','co.jp','sg']
- ];
- }
}
diff --git a/src/lib/Resource.php b/src/lib/Resource.php
index 336c0e4..ab60d1f 100644
--- a/src/lib/Resource.php
+++ b/src/lib/Resource.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,7 +15,7 @@
use Apaapi\interfaces\ResourceInterface;
/**
- * Basic Apaapi Resource Wrapper Class.
+ * Apaapi resource wrapper class.
*/
class Resource implements ResourceInterface
{
diff --git a/src/lib/Response.php b/src/lib/Response.php
index 746402e..6817809 100644
--- a/src/lib/Response.php
+++ b/src/lib/Response.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -12,136 +12,139 @@
namespace Apaapi\lib;
-use Apaapi\interfaces\ResponseInterface;
-use Apaapi\interfaces\RequestInterface;
-use Apaapi\interfaces\ResponseTypeInterface;
-use Apaapi\includes\ResponseType;
+use Apaapi\interfaces\{
+ ResponseInterface,
+ RequestInterface
+};
+use Apaapi\includes\{
+ Cache,
+ Geotargeting,
+ Normalizer
+};
/**
- * Basic Apaapi Response Wrapper Class.
- * Based on the Product Advertising API 5.0 Scratchpad.
+ * Basic Apaapi response wrapper class.
* @see https://webservices.amazon.com/paapi5/scratchpad/index.html
*/
-final class Response implements ResponseInterface
+class Response implements ResponseInterface
{
/**
* @access public
*/
- const PARSE = true;
+ public const NORMALIZE = true;
+ public const NOCACHE = false;
/**
- * @access private
- * @var int $code, Response status code
- * @var mixed $body, Response body
- * @var bool $error, Data error
+ * @access protected
+ * @var int $code, Response code
+ * @var string $body, Response body
+ * @var array $data, Response data
*/
- private $code = 200;
- private $body = false;
- private $error = false;
+ protected $code = 200;
+ protected $body = false;
+ protected $data = [];
/**
- * @param RequestInterface $request
- * @param ResponseTypeInterface $type
- * @param bool $parse
+ * @inheritdoc
*/
- public function __construct(RequestInterface $request, ResponseTypeInterface $type = null, $parse = null)
+ public function __construct(RequestInterface $request, bool $normalize = false, bool $cache = true)
{
- // Set HTTP client
- if ( !$request->hasClient() ) {
- // Set default HTTP Client
- $request->setClient();
- }
- $client = $request->getClient();
-
- // Set response body
- $this->body = $client->getResponse();
+ ($cache) ? $this->getCached($request) : $this->send($request);
- // Set response status code
- $this->code = $client->getCode();
+ if ( !$this->hasError() ) {
- // Close HTTP client
- $client->close();
+ $this->data = Normalizer::decode($this->body);
+
+ if ( $normalize ) {
+ $this->data = Normalizer::get($this->data, $request->getOperation());
+ }
- // Set data error on status 200
- if ( $this->hasDataError() ) {
- $this->error = true;
}
+ }
- // Apply response format on success
- if ( !$this->hasError() && $type ) {
- if ( $parse ) {
- $this->body = $type->parse($this->body,$request->getOperation());
- }
- $this->body = $type->format($this->body);
+ /**
+ * @inheritdoc
+ */
+ public function get(?array $geo = null) : array
+ {
+ if ( $geo ) {
+ return (new Geotargeting($geo))->get($this->data);
}
+ return $this->data;
}
/**
- * Get response body.
- *
- * @access public
- * @param void
- * @return mixed
+ * @inheritdoc
*/
- public function get()
+ public function getBody() : string
{
- return $this->body;
+ return (string)$this->body;
}
/**
- * Get response error.
- *
- * @see https://webservices.amazon.com/paapi5/documentation/troubleshooting/error-messages.html
- * @access public
- * @param bool $single
- * @return mixed
+ * @inheritdoc
*/
- public function getError($single = false)
+ public function getError() : string
{
- $error = false;
- if ( $this->hasError() ) {
- if ( ($response = ResponseType::decode((string)$this->body)) ) {
- foreach ($response->Errors as $err) {
- if ( $single ) {
- return $err->Message;
- }
- $error[] = $err->Message;
- }
- }
- }
- return $error;
+ return Normalizer::formatError(
+ $this->getBody()
+ );
}
/**
- * Check if response has any error (>=400).
- *
- * @access public
- * @param void
- * @return bool
+ * @inheritdoc
*/
- public function hasError()
+ public function hasError() : bool
{
if ( !$this->code || $this->code >= 400 ) {
return true;
+ }
- } elseif ( $this->code == 200 && $this->error ) {
- return true;
+ if ( $this->code == 200 ) {
+ return (strpos($this->body, '#ErrorData') !== false);
}
+
return false;
}
/**
- * Check if response has data error (==200).
+ * Get cached response.
*
- * @access private
- * @param void
- * @return bool
+ * @access protected
+ * @param RequestInterface $request
+ * @return void
*/
- private function hasDataError()
+ protected function getCached(RequestInterface $request)
{
- if ( strpos($this->body, '#ErrorData') !== false ) {
- return true;
+ $key = Cache::getKey($request);
+ if ( ($cached = Cache::get($key)) ) {
+ $this->body = $cached;
+
+ } else {
+ $this->send($request);
+ if ( !$this->hasError() ) {
+ Cache::set($key, $this->body);
+ }
}
- return false;
+ }
+
+ /**
+ * Send request.
+ *
+ * @access protected
+ * @param RequestInterface $request
+ * @return void
+ */
+ protected function send(RequestInterface $request)
+ {
+ if ( !$request->hasClient() ) {
+ $request->setClient();
+ }
+ $client = $request->getClient();
+
+ $this->body = $client->getResponse();
+ $this->code = $client->getCode();
+
+ $client->close();
}
}
diff --git a/src/lib/Signature.php b/src/lib/Signature.php
new file mode 100644
index 0000000..82734e9
--- /dev/null
+++ b/src/lib/Signature.php
@@ -0,0 +1,241 @@
+
+ * @link : https://jakiboy.github.io/apaapi/
+ * @license : MIT
+ *
+ * This file if a part of Apaapi Lib.
+ */
+
+namespace Apaapi\lib;
+
+use Apaapi\interfaces\{
+ OperationInterface,
+ ClientInterface
+};
+
+/**
+ * Apaapi Amazon signature request wrapper class.
+ * @see https://webservices.amazon.com/paapi5/documentation/without-sdk.html
+ */
+abstract class Signature
+{
+ /**
+ * @access protected
+ * @var string $path, API path
+ * @var string $locale, API region locale
+ * @var string $region, API region name
+ * @var string $target, API request target
+ * @var array $headers, HTTP request Headers
+ * @var string $payload, HTTP request payload
+ * @var string $accessKeyID, Amazon access key Id
+ * @var string $secretAccessKey, Amazon secret access key
+ * @var string $timestamp, API request timestamp
+ * @var string $currentDate, API request current date
+ */
+ protected $path = '/paapi5/';
+ protected $locale = 'com';
+ protected $region = 'us-east-1';
+ protected $target = 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1';
+ protected $headers = [];
+ protected $payload;
+ protected $accessKeyID;
+ protected $secretAccessKey;
+ protected $timestamp;
+ protected $currentDate;
+
+ /**
+ * @access private
+ * @var string $service, API service
+ * @var string $method, HTTP request method
+ * @var string $hmac, HTTP request HMAC algorithm
+ * @var string $request, HTTP request
+ * @var string $algo, Hash algorithm
+ * @var string $signedHeaders, HTTP request signed headers
+ */
+ private $service = 'ProductAdvertisingAPI';
+ private $method = 'POST';
+ private $hmac = 'AWS4-HMAC-SHA256';
+ private $request = 'aws4_request';
+ private $algo = 'sha256';
+ private $signedHeaders;
+
+ /**
+ * Set request payload.
+ *
+ * @access public
+ * @param OperationInterface $operation
+ * @return void
+ */
+ abstract public function setPayload(OperationInterface $operation);
+
+ /**
+ * Set request client.
+ *
+ * @access public
+ * @param ClientInterface $client
+ * @return void
+ */
+ abstract public function setClient(?ClientInterface $client = null);
+
+ /**
+ * Set request timestamp.
+ *
+ * @access public
+ * @param string $timestamp
+ * @return object
+ */
+ abstract public function setTimeStamp(?string $timestamp = null) : object;
+
+ /**
+ * Set request date.
+ *
+ * @access public
+ * @param string $date
+ * @return object
+ */
+ abstract public function setDate(?string $date = null) : object;
+
+ /**
+ * Get request headers.
+ *
+ * @access protected
+ * @return array
+ */
+ protected function getHeaders() : array
+ {
+ ksort($this->headers);
+ $canonicalUrl = $this->prepareCanonicalRequest();
+ $stringToSign = $this->prepareStringToSign($canonicalUrl);
+ if ( ($signature = $this->calculateSignature($stringToSign)) ) {
+ $this->headers['Authorization'] = $this->buildAuthorizationString($signature);
+ }
+ return $this->headers;
+ }
+
+ /**
+ * Prepare canonical request.
+ *
+ * @access private
+ * @return string
+ */
+ private function prepareCanonicalRequest() : string
+ {
+ $url = "{$this->method}\n";
+ $url .= "{$this->path}\n\n";
+ $signedHeaders = '';
+ foreach ( $this->headers as $key => $value ) {
+ $signedHeaders .= "{$key};";
+ $url .= "{$key}:{$value}\n";
+ }
+ $url .= "\n";
+ $this->signedHeaders = substr($signedHeaders, 0, -1);
+ $url .= "{$this->signedHeaders}\n";
+ $url .= $this->generateHex($this->payload);
+ return $url;
+ }
+
+ /**
+ * Prepare string to be sign.
+ *
+ * @access private
+ * @param string $url
+ * @return string
+ */
+ private function prepareStringToSign(string $url) : string
+ {
+ $string = "{$this->hmac}\n";
+ $string .= "{$this->timestamp}\n";
+ $string .= "{$this->currentDate}/{$this->region}/";
+ $string .= "{$this->service}/{$this->request}\n";
+ $string .= $this->generateHex($url);
+ return $string;
+ }
+
+ /**
+ * Calculate signature.
+ *
+ * @access private
+ * @param string $data
+ * @return string
+ */
+ private function calculateSignature(string $data) : string
+ {
+ $key = $this->getSignatureKey(
+ $this->secretAccessKey,
+ $this->currentDate,
+ $this->region,
+ $this->service
+ );
+ $signature = $this->hash($data, $key);
+ return strtolower(bin2hex($signature));
+ }
+
+ /**
+ * Build authorization string.
+ *
+ * @access private
+ * @param string $signature
+ * @return string
+ */
+ private function buildAuthorizationString(string $signature) : string
+ {
+ $auth = "{$this->hmac} ";
+ $auth .= "Credential={$this->accessKeyID}/";
+ $auth .= "{$this->currentDate}/";
+ $auth .= "{$this->region}/";
+ $auth .= "{$this->service}/";
+ $auth .= "{$this->request},";
+ $auth .= "SignedHeaders={$this->signedHeaders},";
+ $auth .= "Signature={$signature}";
+ return $auth;
+ }
+
+ /**
+ * Generate hex.
+ *
+ * @access private
+ * @param string $date
+ * @return string
+ */
+ private function generateHex(string $date) : string
+ {
+ $hex = bin2hex(hash($this->algo, $date, true));
+ return strtolower($hex);
+ }
+
+ /**
+ * Get signature key.
+ *
+ * @access private
+ * @param string $key
+ * @param string $date
+ * @param string $region
+ * @param string $service
+ * @return string
+ */
+ private function getSignatureKey(string $key, string $date, string $region, string $service) : string
+ {
+ $secret = "AWS4{$key}";
+ $date = $this->hash($date, $secret);
+ $region = $this->hash($region, $date);
+ $service = $this->hash($service, $region);
+ return $this->hash($this->request, $service);
+ }
+
+ /**
+ * Hash data.
+ *
+ * @access private
+ * @param string $data
+ * @param string $key
+ * @return string
+ */
+ private function hash(string $data, string $key) : string
+ {
+ return hash_hmac($this->algo, $data, $key, true);
+ }
+}
diff --git a/src/lib/SignatureRequest.php b/src/lib/SignatureRequest.php
deleted file mode 100644
index 911f77f..0000000
--- a/src/lib/SignatureRequest.php
+++ /dev/null
@@ -1,212 +0,0 @@
-
- * @link : https://jakiboy.github.io/apaapi/
- * @license : MIT
- *
- * This file if a part of Apaapi Lib.
- */
-
-namespace Apaapi\lib;
-
-use Apaapi\interfaces\ParsableInterface;
-use Apaapi\interfaces\RequestClientInterface;
-
-/**
- * Basic Apaapi Amazon Signature Request Wrapper Class.
- * @see https://webservices.amazon.com/paapi5/documentation/without-sdk.html
- */
-abstract class SignatureRequest
-{
- /**
- * @access protected
- * @var string $path, API path
- * @var string $locale, API region locale
- * @var string $region, API region name
- * @var string $target, API request target
- * @var array $headers, HTTP Headers
- * @var string $payload, HTTP request content
- * @var string $accessKeyID, Amazon API Key ID
- * @var string $secretAccessKey, API Secret Key
- * @var string $timestamp, API request timestamp
- * @var string $currentDate, API request current date
- */
- protected $path = '/paapi5/';
- protected $locale = 'com';
- protected $region = 'us-east-1';
- protected $target = 'com.amazon.paapi5.v1.ProductAdvertisingAPIv1';
- protected $headers = [];
- protected $payload;
- protected $accessKeyID;
- protected $secretAccessKey;
- protected $timestamp;
- protected $currentDate;
-
- /**
- * @access private
- * @var string $serviceName, API service name
- * @var string $httpMethodName, HTTP method
- * @var string $HMACAlgorithm, HTTP Request Hash
- * @var string $request, HTTP Request Method
- * @var string $strSignedHeader
- */
- private $serviceName = 'ProductAdvertisingAPI';
- private $httpMethodName = 'POST';
- private $HMACAlgorithm = 'AWS4-HMAC-SHA256';
- private $request = 'aws4_request';
- private $strSignedHeader;
-
- /**
- * @access public
- * @param ParsableInterface $operation
- * @return void
- */
- abstract public function setPayload(ParsableInterface $operation);
-
- /**
- * @access public
- * @param RequestClientInterface $client
- * @return void
- */
- abstract public function setClient(RequestClientInterface $client = null);
-
- /**
- * @access public
- * @param string $timestamp
- * @return object
- */
- abstract public function setTimeStamp($timestamp = null);
-
- /**
- * @access public
- * @param string $date
- * @return object
- */
- abstract public function setDate($date = null);
-
- /**
- * @access protected
- * @param void
- * @return array
- */
- protected function getHeaders()
- {
- ksort($this->headers);
- $canonicalUrl = $this->prepareCanonicalRequest();
- $stringToSign = $this->prepareStringToSign($canonicalUrl);
- if ( ($signature = $this->calculateSignature($stringToSign)) ) {
- $this->headers['Authorization'] = $this->buildAuthorizationString($signature);
- }
- return $this->headers;
- }
-
- /**
- * Prepare canonical request
- *
- * @access private
- * @param void
- * @return string
- */
- private function prepareCanonicalRequest()
- {
- $canonicalUrl = "{$this->httpMethodName}\n";
- $canonicalUrl .= "{$this->path}\n\n";
- $signedHeaders = '';
- foreach ( $this->headers as $key => $value ) {
- $signedHeaders .= "{$key};";
- $canonicalUrl .= "{$key}:{$value}\n";
- }
- $canonicalUrl .= "\n";
- $this->strSignedHeader = substr($signedHeaders, 0, -1);
- $canonicalUrl .= "{$this->strSignedHeader}\n";
- $canonicalUrl .= $this->generateHex($this->payload);
- return $canonicalUrl;
- }
-
- /**
- * Prepare string to be signed
- *
- * @access private
- * @param string $canonicalUrl
- * @return string
- */
- private function prepareStringToSign($canonicalUrl)
- {
- $string = "{$this->HMACAlgorithm}\n";
- $string .= "{$this->timestamp}\n";
- $string .= "{$this->currentDate}/{$this->region}/";
- $string .= "{$this->serviceName}/{$this->request}\n";
- $string .= $this->generateHex($canonicalUrl);
- return $string;
- }
-
- /**
- * Calculate signature
- *
- * @access private
- * @param string $stringToSign
- * @return string
- */
- private function calculateSignature($stringToSign)
- {
- $signatureKey = $this->getSignatureKey(
- $this->secretAccessKey,
- $this->currentDate,
- $this->region,
- $this->serviceName
- );
- $signature = hash_hmac('sha256', $stringToSign, $signatureKey, true);
- $strHexSignature = strtolower(bin2hex($signature));
- return $strHexSignature;
- }
-
- /**
- * @access private
- * @param string $strSignature
- * @return string
- */
- private function buildAuthorizationString($strSignature)
- {
- $auth = "{$this->HMACAlgorithm} ";
- $auth .= "Credential={$this->accessKeyID}/";
- $auth .= "{$this->currentDate}/";
- $auth .= "{$this->region}/";
- $auth .= "{$this->serviceName}/";
- $auth .= "{$this->request},";
- $auth .= "SignedHeaders={$this->strSignedHeader},";
- $auth .= "Signature={$strSignature}";
- return $auth;
- }
-
- /**
- * Generate Hex
- *
- * @access private
- * @param string $data
- * @return string
- */
- private function generateHex($data)
- {
- return strtolower(bin2hex(hash('sha256', $data, true)));
- }
-
- /**
- * @access private
- * @param string $key
- * @param string $date
- * @param string $region
- * @param string $serviceName
- * @return string
- */
- private function getSignatureKey($key, $date, $region, $serviceName)
- {
- $kSecret = "AWS4{$key}";
- $kDate = hash_hmac('sha256', $date, $kSecret, true);
- $kRegion = hash_hmac('sha256', $region, $kDate, true);
- $kService = hash_hmac('sha256', $serviceName, $kRegion, true);
- return hash_hmac('sha256', $this->request, $kService, true);
- }
-}
diff --git a/src/operations/GetBrowseNodes.php b/src/operations/GetBrowseNodes.php
index 2b2ce23..cec5831 100644
--- a/src/operations/GetBrowseNodes.php
+++ b/src/operations/GetBrowseNodes.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -14,10 +14,10 @@
use Apaapi\lib\Operation;
use Apaapi\resources\BrowseNodes;
-use Apaapi\includes\ResourceParser;
+use Apaapi\includes\Parser;
/**
- * Basic Apaapi GetBrowseNodes Operation.
+ * Apaapi operation.
* @see https://webservices.amazon.com/paapi5/documentation/getbrowsenodes.html
*/
final class GetBrowseNodes extends Operation
@@ -29,23 +29,25 @@ final class GetBrowseNodes extends Operation
public $browseNodeIds = [];
/**
- * @param void
+ * Set resources.
*/
public function __construct()
{
- $this->resources = ResourceParser::toString([
+ $this->resources = Parser::convert([
new BrowseNodes
]);
}
/**
+ * Set browsing node Ids.
+ *
* @access public
- * @param array|string $browseNodeIds
+ * @param array $ids
* @return object
*/
- public function setBrowseNodeIds($browseNodeIds)
+ public function setBrowseNodeIds(array $ids) : object
{
- $this->browseNodeIds = (array)$browseNodeIds;
+ $this->browseNodeIds = $ids;
return $this;
}
}
diff --git a/src/operations/GetItems.php b/src/operations/GetItems.php
index 12d897f..57cf845 100644
--- a/src/operations/GetItems.php
+++ b/src/operations/GetItems.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,17 +13,19 @@
namespace Apaapi\operations;
use Apaapi\lib\ItemOperation;
-use Apaapi\resources\BrowseNodeInfo;
-use Apaapi\resources\Images;
-use Apaapi\resources\ItemInfo;
-use Apaapi\resources\Offers;
-use Apaapi\resources\RentalOffers;
-use Apaapi\resources\CustomerReviews;
-use Apaapi\resources\ParentASIN;
-use Apaapi\includes\ResourceParser;
+use Apaapi\resources\{
+ BrowseNodeInfo,
+ Images,
+ ItemInfo,
+ Offers,
+ RentalOffers,
+ CustomerReviews,
+ ParentASIN
+};
+use Apaapi\includes\Parser;
/**
- * Basic Apaapi GetItems Operation.
+ * Apaapi operation.
* @see https://webservices.amazon.com/paapi5/documentation/get-items.html
*/
final class GetItems extends ItemOperation
@@ -37,11 +39,11 @@ final class GetItems extends ItemOperation
public $itemIds = [];
/**
- * @param void
+ * Set resources.
*/
public function __construct()
{
- $this->resources = ResourceParser::toString([
+ $this->resources = Parser::convert([
new BrowseNodeInfo,
new Images,
new ItemInfo,
@@ -53,24 +55,28 @@ public function __construct()
}
/**
+ * Set item Id type.
+ *
* @access public
- * @param array|string $type
+ * @param string $type
* @return object
*/
- public function setItemIdType($type)
+ public function setItemIdType(string $type) : object
{
- $this->itemIdType = (array)$type;
+ $this->itemIdType = $type;
return $this;
}
/**
+ * Set item Ids.
+ *
* @access public
- * @param array|string $itemIds
+ * @param array $ids
* @return object
*/
- public function setItemIds($itemIds)
+ public function setItemIds(array $ids) : object
{
- $this->itemIds = (array)$itemIds;
+ $this->itemIds = $ids;
return $this;
}
}
diff --git a/src/operations/GetVariations.php b/src/operations/GetVariations.php
index b25f4db..57d4931 100644
--- a/src/operations/GetVariations.php
+++ b/src/operations/GetVariations.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,17 +13,19 @@
namespace Apaapi\operations;
use Apaapi\lib\ItemOperation;
-use Apaapi\resources\BrowseNodeInfo;
-use Apaapi\resources\Images;
-use Apaapi\resources\ItemInfo;
-use Apaapi\resources\Offers;
-use Apaapi\resources\RentalOffers;
-use Apaapi\resources\VariationSummary;
-use Apaapi\resources\ParentASIN;
-use Apaapi\includes\ResourceParser;
+use Apaapi\resources\{
+ BrowseNodeInfo,
+ Images,
+ ItemInfo,
+ Offers,
+ RentalOffers,
+ VariationSummary,
+ ParentASIN
+};
+use Apaapi\includes\Parser;
/**
- * Basic Apaapi GetVariations Operation.
+ * Apaapi operation.
* @see https://webservices.amazon.com/paapi5/documentation/get-variations.html
*/
final class GetVariations extends ItemOperation
@@ -39,11 +41,11 @@ final class GetVariations extends ItemOperation
public $variationPage = 1;
/**
- * @param void
+ * Set resources.
*/
public function __construct()
{
- $this->resources = ResourceParser::toString([
+ $this->resources = Parser::convert([
new BrowseNodeInfo,
new Images,
new ItemInfo,
@@ -55,35 +57,41 @@ public function __construct()
}
/**
+ * Set ASIN.
+ *
* @access public
* @param string $ASIN
* @return object
*/
- public function setASIN($ASIN)
+ public function setASIN(string $ASIN) : object
{
$this->ASIN = $ASIN;
return $this;
}
/**
+ * Set variation count.
+ *
* @access public
- * @param int $variationCount
+ * @param int $count
* @return object
*/
- public function setVariationCount($variationCount)
+ public function setVariationCount(int $count) : object
{
- $this->variationCount = $variationCount;
+ $this->variationCount = $count;
return $this;
}
/**
+ * Set variation page.
+ *
* @access public
- * @param int $variationPage
+ * @param int $page
* @return object
*/
- public function setVariationPage($variationPage)
+ public function setVariationPage(int $page) : object
{
- $this->variationPage = $variationPage;
+ $this->variationPage = $page;
return $this;
}
}
diff --git a/src/operations/SearchItems.php b/src/operations/SearchItems.php
index afe7726..99d3e79 100644
--- a/src/operations/SearchItems.php
+++ b/src/operations/SearchItems.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -13,17 +13,19 @@
namespace Apaapi\operations;
use Apaapi\lib\ItemOperation;
-use Apaapi\resources\BrowseNodeInfo;
-use Apaapi\resources\Images;
-use Apaapi\resources\ItemInfo;
-use Apaapi\resources\Offers;
-use Apaapi\resources\RentalOffers;
-use Apaapi\resources\SearchRefinements;
-use Apaapi\resources\ParentASIN;
-use Apaapi\includes\ResourceParser;
+use Apaapi\resources\{
+ BrowseNodeInfo,
+ Images,
+ ItemInfo,
+ Offers,
+ RentalOffers,
+ SearchRefinements,
+ ParentASIN
+};
+use Apaapi\includes\Parser;
/**
- * Basic Apaapi SearchItems Operation.
+ * Apaapi operation.
* @see https://webservices.amazon.com/paapi5/documentation/search-items.html
*/
final class SearchItems extends ItemOperation
@@ -66,12 +68,12 @@ final class SearchItems extends ItemOperation
public $sortBy = null;
public $title = null;
- /**
- * @param void
- */
+ /**
+ * Set resources.
+ */
public function __construct()
{
- $this->resources = ResourceParser::toString([
+ $this->resources = Parser::convert([
new BrowseNodeInfo,
new Images,
new ItemInfo,
@@ -83,190 +85,221 @@ public function __construct()
}
/**
+ * Set keywords.
+ *
* @access public
- * @param string|array $keywords
+ * @param string $keywords
* @return object
*/
- public function setKeywords($keywords)
+ public function setKeywords(string $keywords) : object
{
- if ( is_array($keywords) ) {
- $keywords = implode(',', $keywords);
- }
$this->keywords = $keywords;
return $this;
}
/**
+ * Set actor.
+ *
* @access public
* @param string $actor
* @return object
*/
- public function setActor($actor)
+ public function setActor(string $actor) : object
{
$this->actor = $actor;
return $this;
}
/**
+ * Set artist.
+ *
* @access public
* @param string $artist
* @return object
*/
- public function setArtist($artist)
+ public function setArtist(string $artist) : object
{
$this->artist = $artist;
return $this;
}
/**
+ * Set author.
+ *
* @access public
* @param string $author
* @return object
*/
- public function setAuthor($author)
+ public function setAuthor(string $author) : object
{
$this->author = $author;
return $this;
}
/**
+ * Set availability.
+ *
* @access public
* @param string $availability
* @return object
*/
- public function setAvailability($availability)
+ public function setAvailability(string $availability) : object
{
$this->availability = $availability;
return $this;
}
/**
+ * Set brand.
+ *
* @access public
* @param string $brand
* @return object
*/
- public function setBrand($brand)
+ public function setBrand(string $brand) : object
{
$this->brand = $brand;
return $this;
}
/**
+ * Set browse node id.
+ *
* @access public
- * @param string $browseNodeId
+ * @param string $id
* @return object
*/
- public function setBrowseNodeId($browseNodeId)
+ public function setBrowseNodeId(string $id) : object
{
- $this->browseNodeId = $browseNodeId;
+ $this->browseNodeId = $id;
return $this;
}
/**
+ * Set delivery flags.
+ *
* @access public
- * @param array $deliveryFlags
+ * @param array $flags
* @return object
*/
- public function setDeliveryFlags($deliveryFlags)
+ public function setDeliveryFlags(array $flags) : object
{
- $this->deliveryFlags = (array)$deliveryFlags;
+ $this->deliveryFlags = $flags;
return $this;
}
/**
+ * Set item count.
+ *
* @access public
- * @param int $itemCount
+ * @param int $count
* @return object
*/
- public function setItemCount($itemCount)
+ public function setItemCount(int $count) : object
{
- $this->itemCount = (int)$itemCount;
+ $this->itemCount = $count;
return $this;
}
/**
+ * Set item page.
+ *
* @access public
- * @param int $itemPage
+ * @param int $page
* @return object
*/
- public function setItemPage($itemPage)
+ public function setItemPage(int $page) : object
{
- $this->itemPage = (int)$itemPage;
+ $this->itemPage = $page;
return $this;
}
/**
+ * Set max price.
+ *
* @access public
- * @param int $maxPrice
+ * @param int $price
* @return object
*/
- public function setMaxPrice($maxPrice)
+ public function setMaxPrice(int $price) : object
{
- $this->maxPrice = (int)$maxPrice;
+ $this->maxPrice = $price;
return $this;
}
/**
+ * Set min price.
+ *
* @access public
- * @param int $minPrice
+ * @param int $price
* @return object
*/
- public function setMinPrice($minPrice)
+ public function setMinPrice(int $price) : object
{
- $this->minPrice = (int)$minPrice;
+ $this->minPrice = $price;
return $this;
}
/**
+ * Set min reviews rating.
+ *
* @access public
- * @param int $minReviewsRating
+ * @param int $rating
* @return object
*/
- public function setMinReviewsRating($minReviewsRating)
+ public function setMinReviewsRating(int $rating) : object
{
- $this->minReviewsRating = (int)$minReviewsRating;
+ $this->minReviewsRating = $rating;
return $this;
}
/**
+ * Set min saving percent.
+ *
* @access public
- * @param int $minSavingPercent
+ * @param int $percent
* @return object
*/
- public function setMinSavingPercent($minSavingPercent)
+ public function setMinSavingPercent(int $percent) : object
{
- $this->minSavingPercent = (int)$minSavingPercent;
+ $this->minSavingPercent = $percent;
return $this;
}
/**
+ * Set sort by.
+ *
* @access public
* @param string $sortBy
* @return object
*/
- public function setSortBy($sortBy)
+ public function setSortBy(string $sortBy) : object
{
$this->sortBy = $sortBy;
return $this;
}
/**
+ * Set title.
+ *
* @access public
* @param string $title
* @return object
*/
- public function setTitle($title)
+ public function setTitle(string $title) : object
{
$this->title = $title;
return $this;
}
/**
+ * Set search index.
+ *
* @access public
* @param string $index
* @return object
*/
- public function setSearchIndex($index)
+ public function setSearchIndex(string $index) : object
{
$this->searchIndex = $index;
return $this;
diff --git a/src/resources/BrowseNodeInfo.php b/src/resources/BrowseNodeInfo.php
index f11c90a..74bbc11 100644
--- a/src/resources/BrowseNodeInfo.php
+++ b/src/resources/BrowseNodeInfo.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * BrowseNodeInfo : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/browsenodeinfo.html
*/
final class BrowseNodeInfo extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/BrowseNodes.php b/src/resources/BrowseNodes.php
index be4dc65..e6c208a 100644
--- a/src/resources/BrowseNodes.php
+++ b/src/resources/BrowseNodes.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * BrowseNodes : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/browsenodes.html
*/
final class BrowseNodes extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/CustomerReviews.php b/src/resources/CustomerReviews.php
index a51f359..c586b9b 100644
--- a/src/resources/CustomerReviews.php
+++ b/src/resources/CustomerReviews.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,12 +15,12 @@
use Apaapi\lib\Resource;
/**
- * Offers : High Level Resource.
+ * Apaapi : Sub-level resource.
*/
final class CustomerReviews extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/Images.php b/src/resources/Images.php
index 82e5f1d..4f838ae 100644
--- a/src/resources/Images.php
+++ b/src/resources/Images.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * Images : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/images.html
*/
final class Images extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/ItemInfo.php b/src/resources/ItemInfo.php
index 9548df5..e610f55 100644
--- a/src/resources/ItemInfo.php
+++ b/src/resources/ItemInfo.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * ItemInfo : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/item-info.html
*/
final class ItemInfo extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/Offers.php b/src/resources/Offers.php
index bcdbf87..911fd33 100644
--- a/src/resources/Offers.php
+++ b/src/resources/Offers.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * Offers : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/offers.html
*/
final class Offers extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/ParentASIN.php b/src/resources/ParentASIN.php
index 280750b..e44f5cb 100644
--- a/src/resources/ParentASIN.php
+++ b/src/resources/ParentASIN.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,7 +15,7 @@
use Apaapi\lib\Resource;
/**
- * ParentASIN : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/parent-asin.html
*/
final class ParentASIN extends Resource {}
diff --git a/src/resources/RentalOffers.php b/src/resources/RentalOffers.php
index df989e2..e1a238f 100644
--- a/src/resources/RentalOffers.php
+++ b/src/resources/RentalOffers.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,12 +15,12 @@
use Apaapi\lib\Resource;
/**
- * Offers : High Level Resource.
+ * Apaapi : Sub-level resource.
*/
final class RentalOffers extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/src/resources/SearchRefinements.php b/src/resources/SearchRefinements.php
index d39ad9b..2e5c0bc 100644
--- a/src/resources/SearchRefinements.php
+++ b/src/resources/SearchRefinements.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,7 +15,7 @@
use Apaapi\lib\Resource;
/**
- * SearchRefinements : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/search-refinements.html
*/
final class SearchRefinements extends Resource {}
diff --git a/src/resources/VariationSummary.php b/src/resources/VariationSummary.php
index 21fcc66..add689b 100644
--- a/src/resources/VariationSummary.php
+++ b/src/resources/VariationSummary.php
@@ -1,9 +1,9 @@
+ * @author : Jakiboy
+ * @package : Amazon Product Advertising API Library (v5)
+ * @version : 1.2.0
+ * @copyright : (c) 2019 - 2024 Jihad Sinnaour
* @link : https://jakiboy.github.io/apaapi/
* @license : MIT
*
@@ -15,13 +15,13 @@
use Apaapi\lib\Resource;
/**
- * VariationSummary : High Level Resource.
+ * Apaapi : High level resource.
* @see https://webservices.amazon.com/paapi5/documentation/variation-summary.html
*/
final class VariationSummary extends Resource
{
/**
- * @param void
+ * Set items.
*/
public function __construct()
{
diff --git a/tests/CacheTest.php b/tests/CacheTest.php
new file mode 100644
index 0000000..5c50d4b
--- /dev/null
+++ b/tests/CacheTest.php
@@ -0,0 +1,55 @@
+assertEquals($ttl, Cache::getTtl());
+ }
+
+ public function testSetAndGetSalt()
+ {
+ $salt = 'newSalt';
+ Cache::setSalt($salt);
+ $this->assertEquals($salt, Cache::getSalt());
+ }
+
+ public function testSetAndGetExt()
+ {
+ $ext = 'newExt';
+ Cache::setExt($ext);
+ $this->assertEquals($ext, Cache::getExt());
+ }
+
+ public function testGetKey()
+ {
+ $request = $this->createMock(RequestInterface::class);
+ $request->method('getParams')
+ ->willReturn(['http' => ['content' => 'testContent']]);
+
+ $key = Cache::getKey($request);
+ $this->assertIsString($key);
+ }
+
+ public function testGenerateKey()
+ {
+ $item = 'testItem';
+ $key = Cache::generateKey($item);
+ $this->assertIsString($key);
+ }
+
+ public function testSetAndGet()
+ {
+ $key = 'testKey';
+ $value = 'testValue';
+
+ Cache::set($key, $value);
+ $this->assertEquals($value, Cache::get($key));
+ }
+}
\ No newline at end of file