PluginProbe
Datafeedr API / 1.4.3
Datafeedr API v1.4.3
1.4.3 1.4.2 1.0.125 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.3 1.0.30 1.0.31 1.0.32 All 182 releases
← All changes | libraries/datafeedr.php +1956 -984 1.0.21 → 1.4.3 View file →
@@ -1,1136 +1,2108 @@
1 1 <?php
2 2
3 3 /**
4 - * Datafeedr Api Client Library.
4 + * Datafeedr API PHP Library
5 5 *
6 - * @version 0.1b.6928
7 - * @copyright Datafeedr 2007 ~ 2014 - All Rights Reserved
6 + * @version 3.0.0
8 7 *
9 - * @mainpage
8 + * Copyright (c) 2007 ~ 2017, Datafeedr - All Rights Reserved
10 9 *
11 - * Example of use:
10 + * Permission to use, copy, modify, and/or distribute this software for any
11 + * purpose with or without fee is hereby granted, provided that the above
12 + * copyright notice and this permission notice appear in all copies.
12 13 *
13 - * @code
14 - * $api = new DatafeedrApi('<access id>', '<secret key>');
14 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 + */
22 +
23 +/**
24 + * Class DatafeedrApi
15 25 *
16 - * foreach($api->getMerchants() as $merchant)
17 - * print $merchant['name'];
18 - *
19 - * $search = $api->searchRequest();
20 - * $search->addFilter("name LIKE shoe");
21 - * $search->addFilter("price < 100");
22 - * $search->addSort("price", DatafeedrApi::SORT_ASCENDING);
23 - * $search->setLimit(25);
24 - *
25 - * $products = $search->execute();
26 - *
27 - * foreach($products as $product)
28 - * print $product['name'];
29 - *
30 - * @endcode
31 - *
32 - *
33 - *
34 -**/
26 + * This is the core Datafeedr API class.
27 + */
28 +class DatafeedrApi {
35 29
36 -if(!class_exists('DatafeedrApi', false)) {
30 + protected $_accessId;
31 + protected $_secretKey;
37 32
38 -/**
39 - * Datafeedr API core class.
40 - **/
41 -class DatafeedrApi
42 -{
43 - protected $_accessId;
44 - protected $_secretKey;
33 + protected $_hasZlib;
34 + protected $_host;
35 + protected $_retry;
36 + protected $_retryTimeout;
37 + protected $_returnObjects;
38 + protected $_timeout;
39 + protected $_transport;
40 + protected $_https;
41 + protected $_url;
42 + protected $_userAgent;
43 + protected $_domain;
45 44
46 - protected $_transport;
47 - protected $_timeout;
48 - protected $_url;
49 - protected $_returnObjects;
45 + protected $_status;
46 + protected $_errors;
50 47
51 - protected $_status;
48 + const SORT_DESCENDING = - 1;
49 + const SORT_ASCENDING = + 1;
52 50
53 - const SORT_DESCENDING = -1;
54 - const SORT_ASCENDING = +1;
51 + const DEFAULT_HOST = 'api.datafeedr.com';
55 52
56 - const DEFAULT_URL = 'http://api.datafeedr.com';
57 - const DEFAULT_TIMEOUT = 30;
53 + const REQUEST_COMPRESSION_THRESHOLD = 1024;
58 54
59 - const VERSION = '0.1b.6928';
55 + const VERSION = '3.0.0';
60 56
61 - /**
62 - * Constructor.
63 - *
64 - * @param string $accessId Access ID.
65 - * @param object $secretKey Secret key.
66 - * @param string|callable $transport (optional) HTTP transport function.
67 - * @param int $timeout (optional) HTTP connection timeout, in seconds.
68 - * @param bool $returnObjects (optional) if TRUE, responses are objects, otherwise associative arrays.
69 - *
70 - * The optional $transport parameter tells how HTTP requests should be made.
71 - * It can be either a string that describes one of built-in transports ("curl", "file" or "socket"),
72 - * or a callable object that should accept an url, an array of headers and a string of post data and
73 - * should return an array [int http response status, string response body].
74 - *
75 - **/
76 - public function __construct($accessId, $secretKey, $transport = 'curl', $timeout = 0, $returnObjects = FALSE) {
77 - $this->_accessId = $accessId;
78 - $this->_secretKey = $secretKey;
57 + /**
58 + * DatafeedrApi constructor.
59 + *
60 + * @since 1.0.0
61 + *
62 + * @param string $secretKey Datafeedr API Secret Key.
63 + * @param array $options Options.
64 + *
65 + * Possble options:
66 + *
67 + * - host: API host name. Default: 'api.datafeedr.com'
68 + * - https: TRUE if using https. Default: FALSE.
69 + * - transport: HTTP transport name or function. Default: 'wordpress'
70 + * - timeout: HTTP connection timeout, in seconds. Default: 0
71 + * - returnObjects: True to return Objects. False to return associative arrays Default: false
72 + * - retry: How many times to repeat a request on a temporary failure. Default: 0 (do not repeat)
73 + * - retryTimeout: Timeout between retry requests, in seconds. Default: 5
74 + *
75 + * The `transport` option tells how HTTP requests should be made.
76 + * It can be either a string that describes one of built-in transports ("curl", "file" or "wordpress"),
77 + * or a callable object that should accept a URL, an array of headers and a string of post data and
78 + * should return an array [int http response status, string response body].
79 + *
80 + *
81 + * @param string $accessId Datafeedr API Access ID.
82 + *
83 + * @throws DatafeedrError Throws error if any option is invalid.
84 + */
85 + public function __construct( $accessId, $secretKey, $options = null ) {
79 86
80 - $this->_errors = array(
81 - 1 => 'DatafeedrBadRequestError',
82 - 2 => 'DatafeedrAuthenticationError',
83 - 3 => 'DatafeedrLimitExceededError',
84 - 4 => 'DatafeedrQueryError',
85 - 7 => 'DatafeedrExternalError',
86 - 9 => 'DatafeedrError',
87 - );
87 + $this->_accessId = $accessId;
88 + $this->_secretKey = $secretKey;
88 89
89 - $this->_url = self::DEFAULT_URL;
90 - $this->_timeout = $timeout ? $timeout : self::DEFAULT_TIMEOUT;
91 - $this->_returnObjects = $returnObjects;
90 + $this->_errors = array(
91 + 1 => 'DatafeedrBadRequestError',
92 + 2 => 'DatafeedrAuthenticationError',
93 + 3 => 'DatafeedrLimitExceededError',
94 + 4 => 'DatafeedrQueryError',
95 + 7 => 'DatafeedrExternalError',
96 + 9 => 'DatafeedrServerError',
97 + );
92 98
93 - switch($transport) {
94 - case 'curl':
95 - $this->_transport = array($this, '_transportCurl');
96 - break;
97 - case 'file':
98 - $this->_transport = array($this, '_transportFile');
99 - break;
100 - case 'socket':
101 - $this->_transport = array($this, '_transportSocket');
102 - break;
103 - default:
104 - if(!is_callable($transport)) {
105 - throw new DatafeedrError("Transport must be a function");
106 - }
107 - $this->_transport = $transport;
108 - }
109 - }
99 + $this->_parseOptions( $options );
100 + }
110 101
111 - /**
112 - * Return status information.
113 - *
114 - * @return array
115 - *
116 - **/
117 - public function getStatus() {
118 - $this->apiCall('status');
119 - return $this->_status;
120 - }
102 + /**
103 + * Returns API status information.
104 + *
105 + * @since 1.0.0
106 + *
107 + * @return array An array of API Status information.
108 + */
109 + public function getStatus() {
110 + $this->apiCall( 'status' );
121 111
122 - /**
123 - * Return status information from the last request.
124 - *
125 - * If no Api request have been made, return NULL
126 - *
127 - * @return array|null
128 - *
129 - **/
130 - public function lastStatus() {
131 - return $this->_status;
132 - }
112 + return $this->_status;
113 + }
133 114
134 - /**
135 - * Return the list of networks.
136 - *
137 - * @param int|array $networkId (optional) Network id or an array of network ids
138 - * @param bool $includeEmpty (optional) If FALSE, omit networks with 0 products
139 - * @param array $fields (optional) list of fields to retrieve
140 - * @return array
141 - *
142 - **/
143 - public function getNetworks($networkId = NULL, $includeEmpty = FALSE, $fields = NULL) {
144 - $request = array();
145 - if($networkId) {
146 - $request['_ids'] = $this->_intarray($networkId);
147 - }
148 - $request['skip_empty'] = intval(!$includeEmpty);
149 - if($fields) {
150 - $request['fields'] = $fields;
151 - }
152 - $response = $this->apiCall('networks', $request);
153 - return $this->_get($response, 'networks');
154 - }
115 + /**
116 + * Return status information from the last request.
117 + *
118 + * If no API request has been made, return NULL
119 + *
120 + * @since 1.0.0
121 + *
122 + * @return array|null Status information or NULL.
123 + */
124 + public function lastStatus() {
125 + return $this->_status;
126 + }
155 127
156 - /**
157 - * Return the list of merchants.
158 - *
159 - * @param int|array $networkId (optional) Network id or array of network ids
160 - * @param bool $includeEmpty (optional) If FALSE, omit merchants with 0 products
161 - * @param array $fields (optional) list of fields to retrieve
162 - * @return array
163 - *
164 - **/
165 - public function getMerchants($networkId = NULL, $includeEmpty = FALSE, $fields = NULL) {
166 - $request = array();
167 - if($networkId) {
168 - $request['source_ids'] = $this->_intarray($networkId);
169 - }
170 - $request['skip_empty'] = intval(!$includeEmpty);
171 - if($fields) {
172 - $request['fields'] = $fields;
173 - }
174 - $response = $this->apiCall('merchants', $request);
175 - return $this->_get($response, 'merchants');
176 - }
128 + /**
129 + * Return the list of networks.
130 + *
131 + * @since 1.0.0
132 + *
133 + * @param boolean $includeEmpty Optional. If FALSE, omit networks with 0 products.
134 + * @param array $fields Optional. An array of fields to retrieve.
135 + *
136 + * @param integer|array $networkId Optional. Network ID or an array of network IDs.
137 + *
138 + * @return array An array of Networks.
139 + */
140 + public function getNetworks( $networkId = null, $includeEmpty = false, $fields = null ) {
177 141
178 - /**
179 - * Return the list of merchants by their ids.
180 - *
181 - * @param int|array $merchantId Merchant id or array of network ids
182 - * @param bool $includeEmpty (optional) If FALSE, omit merchants with 0 products
183 - * @param array $fields (optional) list of fields to retrieve
184 - * @return array
185 - *
186 - **/
187 - public function getMerchantsById($merchantId, $includeEmpty = FALSE, $fields = NULL) {
188 - $request = array();
189 - $request['_ids'] = $this->_intarray($merchantId);
190 - $request['skip_empty'] = intval(!$includeEmpty);
191 - if($fields) {
192 - $request['fields'] = $fields;
193 - }
194 - $response = $this->apiCall('merchants', $request);
195 - return $this->_get($response, 'merchants');
196 - }
142 + $request = array();
197 143
198 - /**
199 - * Return the list of searchable fields.
200 - *
201 - * @param int|array $networkId (optional) Network id or array of network ids
202 - * @return array
203 - *
204 - **/
205 - public function getFields($networkId = NULL) {
206 - $request = array();
207 - if($networkId) {
208 - $request['source_ids'] = $this->_intarray($networkId);
209 - }
210 - $response = $this->apiCall('fields', $request);
211 - return $this->_get($response, 'fields');
212 - }
144 + if ( $networkId ) {
145 + $request['_ids'] = $this->_intarray( $networkId );
146 + }
213 147
214 - /**
215 - * Return the list of products by their ids.
216 - *
217 - * @param int|array $productId Product id or an array of products ids.
218 - * @param array $fields (optional) list of fields to retrieve.
219 - * @return array
220 - *
221 - **/
222 - public function getProducts($productId, $fields = NULL) {
223 - $request = array();
224 - $request['_ids'] = $this->_intarray($productId);
225 - $request['string_ids'] = 1;
226 - if($fields) {
227 - $request['fields'] = $fields;
228 - }
229 - $response = $this->apiCall('get', $request);
230 - return $this->_get($response, 'products');
231 - }
148 + $request['skip_empty'] = intval( ! $includeEmpty );
232 149
233 - /**
234 - * Return the list of Zanox merchant ids ("zmids").
235 - *
236 - * @param int|array $merchantId Merchant id or an array of merchant ids.
237 - * @param int $adspaceId Zanox adspace Id.
238 - * @param string $connectId Zanox connection Id.
239 - * @return array
240 - *
241 - **/
242 - public function getZanoxMerchantIds($merchantId, $adspaceId, $connectId) {
243 - $request = array();
244 - $request['merchant_ids'] = $this->_intarray($merchantId);
245 - $request['adspace_id'] = $adspaceId;
246 - $request['connect_id'] = $connectId;
247 - $response = $this->apiCall('zanox_merchant_ids', $request);
248 - return $this->_get($response, 'zanox_merchant_ids');
249 - }
150 + if ( $fields ) {
151 + $request['fields'] = $fields;
152 + }
250 153
251 - /**
252 - * Create a new DatafeedrSearchRequest object.
253 - *
254 - * @return DatafeedrSearchRequest
255 - *
256 - **/
257 - public function searchRequest() {
258 - return new DatafeedrSearchRequest($this);
259 - }
154 + $response = $this->apiCall( 'networks', $request );
260 155
261 - /**
262 - * Create a new DatafeedrMerchantSearchRequest object.
263 - *
264 - * @return DatafeedrMerchantSearchRequest
265 - *
266 - **/
267 - public function merchantSearchRequest() {
268 - return new DatafeedrMerchantSearchRequest($this);
269 - }
156 + return $this->_get( $response, 'networks' );
157 + }
270 158
271 - /**
272 - * Create a new DatafeedrAmazonSearchRequest object.
273 - *
274 - * @return DatafeedrAmazonSearchRequest
275 - *
276 - **/
277 - public function amazonSearchRequest($awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale="US") {
278 - return new DatafeedrAmazonSearchRequest($this, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale);
279 - }
159 + /**
160 + * Return the list of merchants.
161 + *
162 + * @since 1.0.0
163 + *
164 + * @param bool $includeEmpty Optional. If FALSE, omit merchants with 0 products.
165 + * @param array $fields Optional. An array of fields to retrieve.
166 + *
167 + * @param integer|array $networkId Optional. Network ID or array of Network IDs.
168 + *
169 + * @return array An array of merchants.
170 + */
171 + public function getMerchants( $networkId = null, $includeEmpty = false, $fields = null ) {
280 172
281 - /**
282 - * Create a new DatafeedrAmazonLookupRequest object.
283 - *
284 - * @return DatafeedrAmazonLookupRequest
285 - *
286 - **/
287 - public function amazonLookupRequest($awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale="US") {
288 - return new DatafeedrAmazonLookupRequest($this, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale);
289 - }
173 + $request = array();
290 174
291 - /**
292 - * Perform the raw Api call.
293 - *
294 - * @param string $action Api action.
295 - * @param array $request (optional) Request data.
296 - * @return array
297 - *
298 - **/
299 - public function apiCall($action, $request = NULL) {
300 - if(!$request) {
301 - $request = array();
302 - }
175 + if ( $networkId ) {
176 + $request['source_ids'] = $this->_intarray( $networkId );
177 + }
303 178
304 - $request['aid'] = $this->_accessId;
305 - $request['timestamp'] = gmdate('Y-m-d H:i:s');
179 + $request['skip_empty'] = intval( ! $includeEmpty );
306 180
307 - $message = $request['aid'] .$action . $request['timestamp'];
308 - $request['signature'] = hash_hmac('sha256', $message, $this->_secretKey, FALSE);
181 + if ( $fields ) {
182 + $request['fields'] = $fields;
183 + }
309 184
310 - $postdata = json_encode($request);
311 - $url = $this->_url . '/' . $action;
312 - $headers = array(
313 - 'Content-Type: application/json',
314 - 'Accept: application/json',
315 - 'Content-Length: '. strlen($postdata),
316 - 'Connection: close',
317 - 'User-Agent: datafeedr.php.' . self::VERSION
318 - );
319 - list($status, $response) = call_user_func($this->_transport, $url, $headers, $postdata);
320 - if(strlen($response)) {
321 - $response = json_decode($response, !$this->_returnObjects);
322 - }
185 + $response = $this->apiCall( 'merchants', $request );
323 186
324 - $error = $this->_get($response, 'error');
325 - if($error) {
326 - $type = $this->_get($response, 'type');
327 - $cls = isset($this->_errors[$type]) ? $this->_errors[$type] : 'DatafeedrError';
328 - throw new $cls($this->_get($response, 'message'), $error);
329 - }
187 + return $this->_get( $response, 'merchants' );
188 + }
330 189
331 - if($status != 200) {
332 - throw new DatafeedrHTTPError("Status $status");
333 - }
190 + /**
191 + * Return a list of merchants by their IDs.
192 + *
193 + * @since 1.0.0
194 + *
195 + * @param boolean $includeEmpty Optional. If FALSE, omit merchants with 0 products.
196 + * @param array $fields Optional. An array of fields to retrieve.
197 + *
198 + * @param integer|array $merchantId Merchant ID or array of Merchant IDs.
199 + *
200 + * @return array An array of merchants.
201 + */
202 + public function getMerchantsById( $merchantId, $includeEmpty = false, $fields = null ) {
334 203
335 - $this->_status = $this->_get($response, 'status');
336 - return $response;
337 - }
204 + $request = array();
205 + $request['_ids'] = $this->_intarray( $merchantId );
206 + $request['skip_empty'] = intval( ! $includeEmpty );
338 207
339 - protected function _intarray($id_or_ids) {
340 - if(is_numeric($id_or_ids)) {
341 - return array($id_or_ids);
342 - }
343 - if(is_array($id_or_ids)) {
344 - return $id_or_ids;
345 - }
346 - return array();
347 - }
208 + if ( $fields ) {
209 + $request['fields'] = $fields;
210 + }
348 211
349 - protected function _get($obj, $prop, $default=NULL) {
350 - if(is_array($obj) && isset($obj[$prop])) {
351 - return $obj[$prop];
352 - }
353 - if(is_object($obj) && isset($obj->$prop)) {
354 - return $obj->$prop;
355 - }
356 - return $default;
357 - }
212 + $response = $this->apiCall( 'merchants', $request );
358 213
214 + return $this->_get( $response, 'merchants' );
215 + }
359 216
360 - /**
361 - * Perform a HTTP post request by the means of the curl library.
362 - *
363 - * @param string $url Request url.
364 - * @param array $headers Array of headers.
365 - * @param string $postdata Post data.
366 - * @return array (int http status, string response body)
367 - *
368 - **/
369 - protected function _transportCurl($url, $headers, $postdata) {
370 - $ch = curl_init();
371 - curl_setopt($ch, CURLOPT_URL, $url);
372 - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_timeout);
373 - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
374 - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
375 - curl_setopt($ch, CURLOPT_POST, 1);
376 - curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
217 + /**
218 + * Return a list of searchable fields.
219 + *
220 + * @since 1.0.0
221 + *
222 + * @param integer|array $networkId Optional. Network ID or array of network IDs.
223 + *
224 + * @return array An array of searchable fields.
225 + * @todo - Does this return a list of all fields for a specific network or only indexed/searchable fields? Update docs accordingly.
226 + *
227 + */
228 + public function getFields( $networkId = null ) {
377 229
378 - $response = curl_exec($ch);
379 - $status = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
380 - $errno = curl_errno($ch);
381 - $errmsg = curl_error($ch);
230 + $request = array();
382 231
383 - curl_close($ch);
232 + if ( $networkId ) {
233 + $request['source_ids'] = $this->_intarray( $networkId );
234 + }
384 235
385 - if($errno) {
386 - throw new DatafeedrHTTPError($errmsg, $errno);
387 - }
236 + $response = $this->apiCall( 'fields', $request );
388 237
389 - return array($status, $response);
390 - }
238 + return $this->_get( $response, 'fields' );
239 + }
391 240
392 - /**
393 - * Perform a HTTP post request using file functions.
394 - *
395 - * @param string $url Request url.
396 - * @param array $headers Array of headers.
397 - * @param string $postdata Post data.
398 - * @return array (int http status, string response body)
399 - *
400 - **/
401 - protected function _transportFile($url, $headers, $postdata) {
402 - $options = array('http' => array(
403 - 'method' => 'POST',
404 - 'content' => $postdata,
405 - 'header' => implode("\r\n", $headers),
406 - 'ignore_errors' => TRUE,
407 - 'timeout' => $this->_timeout,
408 - ));
409 - $context = stream_context_create($options);
410 - $response = file_get_contents($url, false, $context);
241 + /**
242 + * Return a list of products by their IDs.
243 + *
244 + * @since 1.0.0
245 + *
246 + * @param array $fields Optional. An array of fields to retrieve.
247 + *
248 + * @param integer|array $productId Product ID or an array of products IDs.
249 + *
250 + * @return array An array of Products.
251 + */
252 + public function getProducts( $productId, $fields = null ) {
411 253
412 - $status = 200;
413 - if(isset($http_response_header) && isset($http_response_header[0])) {
414 - if(preg_match('/HTTP.+?(\d\d\d)/', $http_response_header[0], $match)) {
415 - $status = intval($match[1]);
416 - }
417 - } else if($response === false) {
418 - throw new DatafeedrHTTPError("HTTP error: invalid response");
419 - }
420 - return array($status, $response);
421 - }
254 + $request = array();
255 + $request['_ids'] = $this->_intarray( $productId );
256 + $request['string_ids'] = 1;
422 257
423 - /**
424 - * Perform a HTTP post request using sockets.
425 - *
426 - * @param string $url Request url.
427 - * @param array $headers Array of headers.
428 - * @param string $postdata Post data.
429 - * @return array (int http status, string response body)
430 - *
431 - **/
432 - protected function _transportSocket($url, $headers, $postdata) {
433 - $parts = parse_url($url);
434 - $errno = 0;
435 - $errmsg = '';
258 + if ( $fields ) {
259 + $request['fields'] = $fields;
260 + }
436 261
437 - $fp = fsockopen($parts['host'], 80, $errno, $errmsg, $this->_timeout);
438 - if(!$fp) {
439 - throw new DatafeedrHTTPError($errmsg, $errno);
440 - }
262 + $response = $this->apiCall( 'get', $request );
441 263
442 - fwrite($fp, "POST " . $parts['path'] . " HTTP/1.1\r\n");
443 - fwrite($fp, implode("\r\n", $headers) . "\r\n\r\n");
444 - fwrite($fp, $postdata);
264 + return $this->_get( $response, 'products' );
265 + }
445 266
446 - $buf = '';
447 - while(!feof($fp)) {
448 - $buf .= fgets($fp, 1024);
449 - }
450 - fclose($fp);
267 + /**
268 + * Return a list of Zanox merchant IDs ("zmids").
269 + *
270 + * @since 1.0.0
271 + *
272 + * @param integer $adspaceId Zanox Adspace ID.
273 + * @param string $connectId Zanox Connection ID.
274 + *
275 + * @param integer|array $merchantId Merchant ID or an array of merchant IDs.
276 + *
277 + * @return array An array of arrays (adspace_id, merchant_id, program_id, zmid).
278 + */
279 + public function getZanoxMerchantIds( $merchantId, $adspaceId, $connectId ) {
451 280
452 - $buf = explode("\r\n\r\n", $buf, 2);
453 - if(count($buf) != 2) {
454 - throw new DatafeedrHTTPError("Invalid response");
455 - }
456 - if(preg_match('/HTTP.+?(\d\d\d)/', $buf[0], $match)) {
457 - $status = intval($match[1]);
458 - } else {
459 - throw new DatafeedrHTTPError("Invalid status");
460 - }
461 - return array($status, $buf[1]);
462 - }
281 + $request = array();
282 +
283 + $request['merchant_ids'] = $this->_intarray( $merchantId );
284 + $request['adspace_id'] = $adspaceId;
285 + $request['connect_id'] = $connectId;
286 +
287 + $response = $this->apiCall( 'zanox_merchant_ids', $request );
288 +
289 + return $this->_get( $response, 'zanox_merchant_ids' );
290 + }
291 +
292 + /**
293 + * Return a list of PerformanceHorizon campaign references ("camrefs").
294 + *
295 + * @since 2.0.0
296 + *
297 + * @param string $applicationKey PerformanceHorizon application_key.
298 + * @param string $userApiKey PerformanceHorizon user_api_key.
299 + * @param string $publisherId PerformanceHorizon publisher_id.
300 + *
301 + * @param integer|array $merchantId Merchant ID or an array of merchant IDs.
302 + *
303 + * @return array An array of arrays (campaign_id, camref, merchant_id).
304 + */
305 +
306 + public function getPerformanceHorizonCamrefs( $merchantId, $applicationKey, $userApiKey, $publisherId ) {
307 +
308 + $request = array();
309 +
310 + $request['merchant_ids'] = $this->_intarray( $merchantId );
311 + $request['application_key'] = $applicationKey;
312 + $request['user_api_key'] = $userApiKey;
313 + $request['publisher_id'] = $publisherId;
314 +
315 + $response = $this->apiCall( 'performancehorizon_camrefs', $request );
316 +
317 + return $this->_get( $response, 'performancehorizon_camrefs' );
318 + }
319 +
320 + /**
321 + * Return a list of Effiliation affiliate ids.
322 + *
323 + * @since 2.0.2
324 + *
325 + * @param string $apiKey Effiliation api_key.
326 + *
327 + * @param integer|array $merchantId Merchant ID or an array of merchant IDs.
328 + *
329 + * @return array An array of arrays (affiliate_id, merchant_id).
330 + */
331 +
332 + public function getEffiliationAffiliateIds( $merchantId, $apiKey ) {
333 +
334 + $request = array();
335 +
336 + $request['merchant_ids'] = $this->_intarray( $merchantId );
337 + $request['api_key'] = $apiKey;
338 +
339 + $response = $this->apiCall( 'effiliation_affiliate_ids', $request );
340 +
341 + return $this->_get( $response, 'effiliation_affiliate_ids' );
342 + }
343 +
344 + /**
345 + * Create a new DatafeedrSearchRequest object.
346 + *
347 + * @since 1.0.0
348 + *
349 + * @return DatafeedrSearchRequest
350 + */
351 + public function searchRequest() {
352 + return new DatafeedrSearchRequest( $this );
353 + }
354 +
355 + /**
356 + * Create a new DatafeedrMerchantSearchRequest object.
357 + *
358 + * @since 1.0.0
359 + *
360 + * @return DatafeedrMerchantSearchRequest
361 + */
362 + public function merchantSearchRequest() {
363 + return new DatafeedrMerchantSearchRequest( $this );
364 + }
365 +
366 + /**
367 + * Create a new DatafeedrAmazonSearchRequest object.
368 + *
369 + * @since 1.0.0
370 + *
371 + * @param string $awsSecretKey Amazon Secret Key.
372 + * @param string $awsAssociateTag Amazon Associates tag.
373 + * @param string $locale The country locale code.
374 + *
375 + * @param string $awsAccessKeyId Amazon Access Key.
376 + *
377 + * @return DatafeedrAmazonSearchRequest
378 + */
379 + public function amazonSearchRequest( $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale = 'US' ) {
380 + return new DatafeedrAmazonSearchRequest( $this, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale );
381 + }
382 +
383 + /**
384 + * Create a new DatafeedrAmazonLookupRequest object.
385 + *
386 + * @since 1.0.0
387 + *
388 + * @param string $awsSecretKey Amazon Secret Key.
389 + * @param string $awsAssociateTag Amazon Associates tag.
390 + * @param string $locale The country locale code.
391 + *
392 + * @param string $awsAccessKeyId Amazon Access Key.
393 + *
394 + * @return DatafeedrAmazonLookupRequest
395 + */
396 + public function amazonLookupRequest( $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale = 'US' ) {
397 + return new DatafeedrAmazonLookupRequest( $this, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale );
398 + }
399 +
400 + /** CreatorAPI */
401 + public function amazonCreatorApiSearchRequest( $capiMarketplace = 'US' ) {
402 + return new DatafeedrAmazonCreatorApiSearchRequest( $this, $capiMarketplace = 'US' );
403 + }
404 +
405 + /** CreatorAPI */
406 +// public function amazonCreatorApiLookupRequest( $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale = 'US' ) {
407 +// return new DatafeedrAmazonCreatorApiLookupRequest( $this, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale );
408 +// }
409 +
410 + /**
411 + * Perform the raw API call.
412 + *
413 + * @since 1.0.0
414 + *
415 + * @param array $request Optional. Request data.
416 + *
417 + * @param string $action API Action. (Examples: status, merchants, networks, search, etc...)
418 + *
419 + * @return array Returns $response array.
420 + * @throws DatafeedrHTTPError Throws error if request status is not 200.
421 + *
422 + */
423 + public function apiCall( $action, $request = null ) {
424 +
425 + if ( ! $request ) {
426 + $request = array();
427 + }
428 +
429 + $request['aid'] = $this->_accessId;
430 + $request['timestamp'] = gmdate( 'Y-m-d H:i:s' );
431 + $request['domain'] = $this->_domain;
432 +
433 + if ( $this->_https ) {
434 + $request['akey'] = $this->_secretKey;
435 + } else {
436 + $message = $request['aid'] . $action . $request['timestamp'];
437 + $request['signature'] = hash_hmac( 'sha256', $message, $this->_secretKey, false );
438 + }
439 +
440 + $postdata = json_encode( $request );
441 + $url = $this->_url . '/' . $action;
442 + $headers = array(
443 + 'Host: ' . $this->_host,
444 + 'Content-Type: application/json',
445 + 'Accept: application/json',
446 + 'Connection: close',
447 + 'User-Agent: ' . $this->_userAgent
448 + );
449 +
450 + if ( $this->_hasZlib && strlen( $postdata ) >= self::REQUEST_COMPRESSION_THRESHOLD ) {
451 + $postdata = gzcompress( $postdata );
452 + $headers [] = 'Content-Encoding: deflate';
453 + }
454 +
455 + $headers [] = 'Content-Length: ' . strlen( $postdata );
456 +
457 + list( $status, $response ) = $this->_performRequest( $url, $headers, $postdata );
458 +
459 + if ( strlen( $response ) ) {
460 + $response = json_decode( $response, ! $this->_returnObjects );
461 + }
462 +
463 + $error = $this->_get( $response, 'error' );
464 + if ( $error ) {
465 + $type = $this->_get( $response, 'type' );
466 + $cls = isset( $this->_errors[ $type ] ) ? $this->_errors[ $type ] : 'DatafeedrError';
467 + throw new $cls( $this->_get( $response, 'message' ), $error );
468 + }
469 +
470 + if ( 200 != $status ) {
471 + throw new DatafeedrHTTPError( "Status $status" );
472 + }
473 +
474 + $this->_status = $this->_get( $response, 'status' );
475 +
476 + return $response;
477 + }
478 +
479 + /**
480 + * Returns the default set of options.
481 + *
482 + * @since 2.0.0
483 + *
484 + * @returns array $options.
485 + *
486 + */
487 + protected function _defaultOptions() {
488 + return array(
489 + 'host' => self::DEFAULT_HOST,
490 + 'https' => false,
491 + 'transport' => 'wordpress_or_curl',
492 + 'timeout' => 30,
493 + 'returnObjects' => false,
494 + 'retry' => 0,
495 + 'retryTimeout' => 5,
496 + 'domain' => '',
497 + );
498 + }
499 +
500 + /**
501 + * Parse constructor options.
502 + *
503 + * @since 2.0.0
504 + *
505 + * @param array $options .
506 + *
507 + * @throws DatafeedrError Throws error if any option is invalid.
508 + */
509 + protected function _parseOptions( $options ) {
510 + $opts = $this->_defaultOptions();
511 +
512 + if ( ! is_null( $options ) ) {
513 + if ( ! is_array( $options ) ) {
514 + throw new DatafeedrError( "Options must be an array" );
515 + }
516 +
517 + foreach ( $options as $key => $value ) {
518 + if ( isset( $opts[ $key ] ) ) {
519 + $opts[ $key ] = $value;
520 + }
521 + }
522 + }
523 +
524 + $pt = $opts['https'] ? 'https' : 'http';
525 + $tr = $opts['transport'];
526 +
527 + $this->_url = $pt . '://' . $opts['host'];
528 + $this->_https = $opts['https'];
529 + $this->_host = $opts['host'];
530 + $this->_timeout = (int) $opts['timeout'];
531 + $this->_returnObjects = (int) $opts['returnObjects'];
532 + $this->_retry = (int) $opts['retry'];
533 + $this->_retryTimeout = (int) $opts['retryTimeout'];
534 + $this->_domain = (string) $opts['domain'];
535 +
536 + switch ( $tr ) {
537 + case 'curl':
538 + $this->_transport = array( $this, '_transportCurl' );
539 + break;
540 + case 'file':
541 + $this->_transport = array( $this, '_transportFile' );
542 + break;
543 + case 'wordpress':
544 + if ( ! function_exists( 'wp_remote_post' ) ) {
545 + throw new DatafeedrError( "Wordpress transport requires wp_remote_post" );
546 + }
547 + $this->_transport = array( $this, '_transportWordpress' );
548 + break;
549 + case 'wordpress_or_curl':
550 + if ( ! function_exists( 'wp_remote_post' ) ) {
551 + $this->_transport = array( $this, '_transportCurl' );
552 + $tr = 'curl';
553 + } else {
554 + $this->_transport = array( $this, '_transportWordpress' );
555 + $tr = 'wordpress';
556 + }
557 + break;
558 +
559 + default:
560 + if ( ! is_callable( $tr ) ) {
561 + throw new DatafeedrError( "Transport must be a function" );
562 + }
563 + $this->_transport = $tr;
564 + $tr = 'custom';
565 + }
566 +
567 + $this->_hasZlib = function_exists( 'gzcompress' );
568 + $this->_userAgent = sprintf( 'datafeedr.php.%s/%s/zlib=%s', self::VERSION, $tr,
569 + $this->_hasZlib ? 'yes' : 'no' );
570 + }
571 +
572 + /**
573 + * Perform an HTTP request.
574 + *
575 + * @since 2.0.0
576 + *
577 + * @param array $headers
578 + * @param string $postdata
579 + *
580 + * @param string $url
581 + *
582 + * @return array An array of (status, responseBody)
583 + * @throws DatafeedrConnectionError
584 + *
585 + */
586 + protected function _performRequest( $url, $headers, $postdata ) {
587 + $retry = $this->_retry;
588 +
589 + while ( true ) {
590 + try {
591 + return call_user_func( $this->_transport, $url, $headers, $postdata );
592 + } catch ( DatafeedrConnectionError $err ) {
593 + if ( $retry <= 0 ) {
594 + throw $err;
595 + }
596 + sleep( $this->_retryTimeout );
597 + $retry --;
598 + }
599 + }
600 +
601 + return array();
602 + }
603 +
604 + /**
605 + * Convert an ID or an array of IDs to a simple array of IDs.
606 + *
607 + * @since 1.0.0
608 + *
609 + * @param integer|string|array $id_or_ids An ID or an array of IDs.
610 + *
611 + * @return array An array of IDs.
612 + */
613 + protected function _intarray( $id_or_ids ) {
614 +
615 + if ( is_numeric( $id_or_ids ) ) {
616 + return array( $id_or_ids );
617 + }
618 +
619 + if ( is_array( $id_or_ids ) ) {
620 + return array_values( $id_or_ids );
621 + }
622 +
623 + return array();
624 + }
625 +
626 + /**
627 + * Returns a specific value from an array or object for a given key or property. If key or
628 + * property does not exist, returns $default.
629 + *
630 + * @since 1.0.0
631 + *
632 + * @param string $prop The array key or object property to get the value for.
633 + * @param null $default Optional. The value to return if $obj or $prop does not exist.
634 + *
635 + * @param array|object $obj An array or object to extract value from.
636 + *
637 + * @return mixed|null The returned value.
638 + */
639 + protected function _get( $obj, $prop, $default = null ) {
640 +
641 + if ( is_array( $obj ) && isset( $obj[ $prop ] ) ) {
642 + return $obj[ $prop ];
643 + }
644 +
645 + if ( is_object( $obj ) && isset( $obj->$prop ) ) {
646 + return $obj->$prop;
647 + }
648 +
649 + return $default;
650 + }
651 +
652 + /**
653 + * Perform an HTTP POST request using the CURL library.
654 + *
655 + * @since 1.0.0
656 + *
657 + * @param array $headers Array of headers.
658 + * @param string $postdata Post data.
659 + *
660 + * @param string $url Request url.
661 + *
662 + * @return array (int http status, string response body)
663 + * @throws DatafeedrConnectionError Throws error if curl_errno() returns an error.
664 + *
665 + */
666 + protected function _transportCurl( $url, $headers, $postdata ) {
667 +
668 + $ch = curl_init();
669 + curl_setopt( $ch, CURLOPT_URL, $url );
670 + curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $this->_timeout );
671 + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
672 + curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
673 + curl_setopt( $ch, CURLOPT_POST, 1 );
674 + curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata );
675 + curl_setopt( $ch, CURLOPT_ENCODING, '' );
676 + $response = curl_exec( $ch );
677 + $status = intval( curl_getinfo( $ch, CURLINFO_HTTP_CODE ) );
678 + $errno = curl_errno( $ch );
679 + $errmsg = curl_error( $ch );
680 +
681 + curl_close( $ch );
682 +
683 + if ( $errno ) {
684 + throw new DatafeedrConnectionError( $errmsg, $errno );
685 + }
686 +
687 + return array( $status, $response );
688 + }
689 +
690 + /**
691 + * Perform a HTTP post request using file functions.
692 + *
693 + * @since 1.0.0
694 + *
695 + * @param array $headers Array of headers.
696 + * @param string $postdata Post data.
697 + *
698 + * @param string $url Request url.
699 + *
700 + * @return array (int http status, string response body)
701 + * @throws DatafeedrConnectionError Throws error if $response is false.
702 + *
703 + */
704 + protected function _transportFile( $url, $headers, $postdata ) {
705 +
706 + $options = array(
707 + 'http' => array(
708 + 'method' => 'POST',
709 + 'content' => $postdata,
710 + 'header' => implode( "\r\n", $headers ),
711 + 'ignore_errors' => true,
712 + 'timeout' => $this->_timeout,
713 + )
714 + );
715 + $context = stream_context_create( $options );
716 + $response = file_get_contents( $url, false, $context );
717 +
718 + $status = 200;
719 + if ( isset( $http_response_header ) && isset( $http_response_header[0] ) ) {
720 + if ( preg_match( '/HTTP.+?(\d\d\d)/', $http_response_header[0], $match ) ) {
721 + $status = intval( $match[1] );
722 + }
723 + } else if ( $response === false ) {
724 + throw new DatafeedrConnectionError( "Invalid response" );
725 + }
726 +
727 + return array( $status, $response );
728 + }
729 +
730 + /**
731 + * Perform a HTTP post request using Wordpress functions.
732 + *
733 + * @since 1.0.0
734 + *
735 + * @param array $headers Array of headers.
736 + * @param string $postdata Post data.
737 + *
738 + * @param string $url Request url.
739 + *
740 + * @return array (int http status, string response body)
741 + * @throws DatafeedrConnectionError Throws error if $response is WP_Error and the error code is 'http_request_failed'.
742 + * @throws DatafeedrHTTPError Throws error if $response is WP_Error.
743 + *
744 + */
745 + protected function _transportWordpress( $url, $headers, $postdata ) {
746 +
747 + $ha = array();
748 + foreach ( $headers as $h ) {
749 + $h = explode( ':', $h, 2 );
750 + $ha[ strtolower( $h[0] ) ] = $h[1];
751 + }
752 +
753 + $args = array(
754 + 'method' => 'POST',
755 + 'headers' => $ha,
756 + 'body' => $postdata,
757 + 'httpversion' => '1.1',
758 + 'timeout' => $this->_timeout,
759 + 'blocking' => true,
760 + 'compress' => false,
761 + 'decompress' => true,
762 + 'user-agent' => $ha['user-agent']
763 + );
764 +
765 + $res = wp_remote_post( $url, $args );
766 +
767 + if ( is_wp_error( $res ) ) {
768 + $code = $res->get_error_code();
769 + $message = $res->get_error_message();
770 +
771 + if ( $code === 'http_request_failed' ) {
772 + throw new DatafeedrConnectionError( $message );
773 + } else {
774 + throw new DatafeedrHTTPError( $message );
775 + }
776 + }
777 +
778 + return array( $res['response']['code'], $res['body'] );
779 + }
463 780 }
464 -}
465 781
466 -if(!class_exists('DatafeedrSearchRequestBase', false)) {
467 782 /**
468 783 * Generic Datafeedr API search request.
469 - **/
470 -class DatafeedrSearchRequestBase
471 -{
472 - protected $_api;
473 - protected $_lastResponse;
784 + */
785 +class DatafeedrSearchRequestBase {
474 786
475 - /**
476 - * Constructor.
477 - *
478 - * @param object $api DatafeedrApi object.
479 - *
480 - **/
481 - public function __construct($api) {
482 - $this->_api = $api;
483 - }
787 + /**
788 + * The DatafeedrAPI object.
789 + *
790 + * @since 1.0.0
791 + * @var DatafeedrAPI $_api
792 + */
793 + protected $_api;
484 794
485 - /**
486 - * Get the number of found products.
487 - *
488 - * @return int
489 - *
490 - **/
491 - public function getFoundCount() {
492 - return $this->_responseItem('found_count', 0);
493 - }
795 + /**
796 + * An array containing the full response of the last API request.
797 + *
798 + * @since 1.0.0
799 + * @var array $_lastResponse Response array.
800 + */
801 + protected $_lastResponse;
494 802
495 - /**
496 - * Get the number of products that can be retrieved from the server.
497 - *
498 - * @return int
499 - *
500 - **/
501 - public function getResultCount() {
502 - return $this->_responseItem('result_count', 0);
503 - }
803 + /**
804 + * DatafeedrSearchRequestBase constructor.
805 + *
806 + * @since 1.0.0
807 + *
808 + * @param DatafeedrApi $api
809 + *
810 + */
811 + public function __construct( $api ) {
812 + $this->_api = $api;
813 + }
504 814
505 - /**
506 - * Return the response from the last search.
507 - *
508 - * @return array
509 - *
510 - **/
511 - public function getResponse() {
512 - return $this->_lastResponse;
513 - }
815 + /**
816 + * Get the number of found products.
817 + *
818 + * @since 1.0.0
819 + *
820 + * @return integer
821 + */
822 + public function getFoundCount() {
823 + return $this->_responseItem( 'found_count', 0 );
824 + }
514 825
515 - protected function _responseItem($prop, $default) {
516 - if(is_null($this->_lastResponse)) {
517 - throw new DatafeedrError("Reading from an empty request");
518 - }
519 - if(is_object($this->_lastResponse) && isset($this->_lastResponse->$prop)) {
520 - return $this->_lastResponse->$prop;
521 - }
522 - if(is_array($this->_lastResponse) && isset($this->_lastResponse[$prop])) {
523 - return $this->_lastResponse[$prop];
524 - }
525 - return $default;
526 - }
826 + /**
827 + * Get the number of products that can be retrieved from the server.
828 + *
829 + * @since 1.0.0
830 + *
831 + * @return integer
832 + */
833 + public function getResultCount() {
834 + return $this->_responseItem( 'result_count', 0 );
835 + }
527 836
528 - function _apiCall($action, $request = NULL) {
529 - $this->_lastResponse = $this->_api->apiCall($action, $request);
530 - }
837 + /**
838 + * Get the complexity score of the current query.
839 + *
840 + * @since 1.2.12
841 + * @return int
842 + * @throws DatafeedrError
843 + */
844 + public function getQueryScore() {
845 + return abs( (int) $this->_responseItem( 'score', 0 ) );
846 + }
531 847
848 + /**
849 + * Returns the full response from the last search.
850 + *
851 + * Possible items in array include the following:
852 + *
853 + * Array (
854 + * 'found_count' => integer,
855 + * 'length' => integer,
856 + * 'merchants' => array,
857 + * 'networks' => array,
858 + * 'price_groups' => array,
859 + * 'products' => array,
860 + * 'result_count' => integer,
861 + * 'status' => array,
862 + * 'time' => integer,
863 + * 'version' => string,
864 + * )
865 + *
866 + * @since 1.0.0
867 + *
868 + * @return array An array of the full response.
869 + */
870 + public function getResponse() {
871 + return $this->_lastResponse;
872 + }
873 +
874 + /**
875 + * Returns a specific item or property from the response data.
876 + *
877 + * @since 1.0.0
878 + *
879 + * @param mixed $default Return if $prop is not found in the array or object.
880 + *
881 + * @param string $prop The item or property to get from the response array or object.
882 + *
883 + * @return mixed Specific item or property from response data.
884 + * @throws DatafeedrError Throws error if $this->_lastResponse is NULL.
885 + *
886 + */
887 + protected function _responseItem( $prop, $default ) {
888 +
889 + if ( is_null( $this->_lastResponse ) ) {
890 + throw new DatafeedrError( "Reading from an empty request" );
891 + }
892 +
893 + if ( is_object( $this->_lastResponse ) && isset( $this->_lastResponse->$prop ) ) {
894 + return $this->_lastResponse->$prop;
895 + }
896 +
897 + if ( is_array( $this->_lastResponse ) && isset( $this->_lastResponse[ $prop ] ) ) {
898 + return $this->_lastResponse[ $prop ];
899 + }
900 +
901 + return $default;
902 + }
903 +
904 + /**
905 + * Sets the $_lastResponse property to the the full response from the last API request.
906 + *
907 + * @since 1.0.0
908 + *
909 + * @param array $request The current API request.
910 + *
911 + * @param string $action The request action (ex. status, search, merchants, networks, etc...)
912 + */
913 + function _apiCall( $action, $request = null ) {
914 + $this->_lastResponse = $this->_api->apiCall( $action, $request );
915 + }
532 916 }
533 -}
534 917
535 -if(!class_exists('DatafeedrSearchRequest', false)) {
536 918 /**
919 + * Class DatafeedrSearchRequest
920 + *
537 921 * Search request for Datafeedr API.
538 -**/
539 -class DatafeedrSearchRequest extends DatafeedrSearchRequestBase
540 -{
541 - /**
542 - * Constructor.
543 - *
544 - * @param object $api DatafeedrApi object.
545 - *
546 - **/
547 - public function __construct($api) {
548 - parent::__construct($api);
922 + */
923 +class DatafeedrSearchRequest extends DatafeedrSearchRequestBase {
549 924
550 - $this->_query = array();
551 - $this->_sort = array();
552 - $this->_fields = array();
553 - $this->_limit = 0;
554 - $this->_offset = 0;
555 - $this->_priceGroups = 0;
556 - $this->_excludeDuplicates = "";
557 - }
925 + protected $_query;
926 + protected $_sort;
927 + protected $_fields;
928 + protected $_limit;
929 + protected $_offset;
930 + protected $_priceGroups;
931 + protected $_excludeDuplicates;
932 + protected $_merchantLimit;
558 933
559 - /**
560 - * Add a query filter.
561 - *
562 - * @param string $filter Query filter.
563 - * @return $this
564 - *
565 - **/
566 - public function addFilter($filter) {
567 - $this->_query []= $filter;
568 - return $this;
569 - }
934 + /**
935 + * DatafeedrSearchRequest constructor.
936 + *
937 + * @since 1.0.0
938 + *
939 + * @param DatafeedrApi $api
940 + *
941 + */
942 + public function __construct( $api ) {
570 943
571 - /**
572 - * Add a sort field.
573 - *
574 - * @param string $field Field name.
575 - * @param int $order One of DatafeedrApi::SORT_ASCENDING or DatafeedrApi::SORT_DESCENDING
576 - * @return $this
577 - *
578 - **/
579 - public function addSort($field, $order = DatafeedrApi::SORT_ASCENDING) {
580 - if(strlen($field) && ($field[0] == '+' || $field[0] == '-')) {
581 - $this->_sort []= $field;
582 - } else if($order == DatafeedrApi::SORT_ASCENDING) {
583 - $this->_sort []= '+' . $field;
584 - } else if($order == DatafeedrApi::SORT_DESCENDING) {
585 - $this->_sort []= '-' . $field;
586 - } else {
587 - throw new DatafeedrError("Invalid sort order");
588 - }
589 - return $this;
590 - }
944 + parent::__construct( $api );
591 945
592 - /**
593 - * Set which fields to retrieve.
594 - *
595 - * @param array $fields List of field names.
596 - * @return $this
597 - *
598 - **/
599 - public function setFields($fields) {
600 - $this->_fields = $fields;
601 - return $this;
602 - }
946 + $this->_query = array();
947 + $this->_sort = array();
948 + $this->_fields = array();
949 + $this->_limit = 0;
950 + $this->_offset = 0;
951 + $this->_priceGroups = 0;
952 + $this->_excludeDuplicates = '';
953 + $this->_merchantLimit = 0;
954 + }
603 955
604 - /**
605 - * Exclude duplicate results.
606 - *
607 - * @param string $filter Equality filter in form "field1 field2 | field3".
608 - * @return $this
609 - *
610 - **/
611 - public function excludeDuplicates($filter) {
612 - if(is_array($filter)) {
613 - $filter = implode(' ', $filter);
614 - }
615 - $this->_excludeDuplicates = $filter;
616 - return $this;
617 - }
956 + /**
957 + * Add a query filter.
958 + *
959 + * @since 1.0.0
960 + *
961 + * @param string $filter Query filter.
962 + *
963 + * @return DatafeedrSearchRequest Returns $this.
964 + */
965 + public function addFilter( $filter ) {
966 + $this->_query[] = $filter;
618 967
619 - /**
620 - * Set a limit.
621 - *
622 - * @param int $limit The limit.
623 - * @return $this
624 - *
625 - **/
626 - public function setLimit($limit) {
627 - $this->_limit = $limit;
628 - return $this;
629 - }
968 + return $this;
969 + }
630 970
631 - /**
632 - * Set an offset.
633 - *
634 - * @param int $offset The offset.
635 - * @return $this
636 - *
637 - **/
638 - public function setOffset($offset) {
639 - $this->_offset = $offset;
640 - return $this;
641 - }
971 + /**
972 + * Adds a sort field.
973 + *
974 + * @since 1.0.0
975 + *
976 + * @param integer $order One of DatafeedrApi::SORT_ASCENDING or DatafeedrApi::SORT_DESCENDING
977 + *
978 + * @param string $field Field name.
979 + *
980 + * @return DatafeedrSearchRequest Returns $this.
981 + * @throws DatafeedrError Throws error if sort order is invalid.
982 + *
983 + */
984 + public function addSort( $field, $order = DatafeedrApi::SORT_ASCENDING ) {
642 985
643 - /**
644 - * Set a price group count.
645 - *
646 - * @param int $groups Group count.
647 - * @return $this
648 - *
649 - **/
650 - public function setPriceGroups($groups) {
651 - $this->_priceGroups = $groups;
652 - return $this;
653 - }
986 + if ( strlen( $field ) && ( $field[0] == '+' || $field[0] == '-' ) ) {
987 + $this->_sort [] = $field;
988 + } else if ( $order == DatafeedrApi::SORT_ASCENDING ) {
989 + $this->_sort [] = '+' . $field;
990 + } else if ( $order == DatafeedrApi::SORT_DESCENDING ) {
991 + $this->_sort [] = '-' . $field;
992 + } else {
993 + throw new DatafeedrError( "Invalid sort order" );
994 + }
654 995
655 - /**
656 - * Get found networks.
657 - *
658 - * @return array
659 - *
660 - **/
661 - public function getNetworks() {
662 - return $this->_responseItem('networks', array());
663 - }
996 + return $this;
997 + }
664 998
665 - /**
666 - * Get found merchants.
667 - *
668 - * @return array
669 - *
670 - **/
671 - public function getMerchants() {
672 - return $this->_responseItem('merchants', array());
673 - }
999 + /**
1000 + * Set which fields to retrieve.
1001 + *
1002 + * @since 1.0.0
1003 + *
1004 + * @param array $fields An array of fields to return for each requested item.
1005 + *
1006 + * Example:
1007 + *
1008 + * Array (
1009 + * 'name',
1010 + * 'price',
1011 + * 'description',
1012 + * 'url',
1013 + * )
1014 + *
1015 + * @return DatafeedrSearchRequest Returns $this.
1016 + */
1017 + public function setFields( $fields ) {
1018 + $this->_fields = $fields;
674 1019
675 - /**
676 - * Get found price groups.
677 - *
678 - * @return array
679 - *
680 - **/
681 - public function getPriceGroups() {
682 - return $this->_responseItem('price_groups', array());
683 - }
1020 + return $this;
1021 + }
684 1022
685 - /**
686 - * Create a request object to use with the API.
687 - *
688 - * @return array
689 - *
690 - **/
691 - public function getParams() {
692 - $request = array();
693 - if($this->_query) {
694 - $request['query'] = $this->_query;
695 - }
696 - if($this->_sort) {
697 - $request['sort'] = $this->_sort;
698 - }
699 - if($this->_fields) {
700 - $request['fields'] = $this->_fields;
701 - }
702 - if($this->_limit) {
703 - $request['limit'] = $this->_limit;
704 - }
705 - if($this->_offset) {
706 - $request['offset'] = $this->_offset;
707 - }
708 - if($this->_priceGroups) {
709 - $request['price_groups'] = $this->_priceGroups;
710 - }
711 - if($this->_excludeDuplicates) {
712 - $request['exclude_duplicates'] = $this->_excludeDuplicates;
713 - }
714 - $request['string_ids'] = 1;
715 - return $request;
716 - }
1023 + /**
1024 + * Exclude duplicate filter.
1025 + *
1026 + * @since 1.0.0
1027 + *
1028 + * @param string $filter Equality filter in form "field1 field2 | field3".
1029 + *
1030 + * @return DatafeedrSearchRequest Returns $this.
1031 + */
1032 + public function excludeDuplicates( $filter ) {
717 1033
718 - /**
719 - * Run search and return a list of products.
720 - *
721 - * @return array
722 - *
723 - **/
724 - public function execute() {
725 - $params = $this->getParams();
726 - if(!isset($params['query'])) {
727 - throw new DatafeedrError("Query can't be empty");
728 - }
729 - $this->_apiCall('search', $params);
730 - return $this->_responseItem('products', array());
731 - }
1034 + if ( is_array( $filter ) ) {
1035 + $filter = implode( ' ', $filter );
1036 + }
732 1037
1038 + $this->_excludeDuplicates = $filter;
1039 +
1040 + return $this;
1041 + }
1042 +
1043 + /**
1044 + * Set a limit of number of records to return.
1045 + *
1046 + * @since 1.0.0
1047 + *
1048 + * @param integer $limit The maximum number of records to return.
1049 + *
1050 + * @return DatafeedrSearchRequest Returns $this.
1051 + */
1052 + public function setLimit( $limit ) {
1053 + $this->_limit = $limit;
1054 +
1055 + return $this;
1056 + }
1057 +
1058 + /**
1059 + * Set an offset for the search.
1060 + *
1061 + * @since 1.0.0
1062 + *
1063 + * @param integer $offset The offset.
1064 + *
1065 + * @return DatafeedrSearchRequest Returns $this.
1066 + */
1067 + public function setOffset( $offset ) {
1068 + $this->_offset = $offset;
1069 +
1070 + return $this;
1071 + }
1072 +
1073 + /**
1074 + * Set a limit of results by merchant.
1075 + *
1076 + * @since 2.0.3
1077 + *
1078 + * @param integer $limit The limit.
1079 + *
1080 + * @return DatafeedrSearchRequest Returns $this.
1081 + */
1082 + public function setMerchantLimit( $limit ) {
1083 + $this->_merchantLimit = $limit;
1084 +
1085 + return $this;
1086 + }
1087 +
1088 + /**
1089 + * Set a price group count.
1090 + *
1091 + * This should be used in conjunction with the $this->getPriceGroups() method.
1092 + *
1093 + * Setting $groups to 3 will organize the products into 3 price groups like this:
1094 + *
1095 + * Array (
1096 + * [0] => Array (
1097 + * [product_count] => 321
1098 + * [max] => 9633332
1099 + * [min] => 0
1100 + * )
1101 + * [1] => Array (
1102 + * [product_count] => 116
1103 + * [max] => 19266665
1104 + * [min] => 9633333
1105 + * )
1106 + * [2] => Array (
1107 + * [product_count] => 43
1108 + * [max] => 28900000
1109 + * [min] => 19266666
1110 + * )
1111 + * )
1112 + *
1113 + * @since 1.0.0
1114 + *
1115 + * @param integer $groups Number of price groups to create.
1116 + *
1117 + * @return DatafeedrSearchRequest Returns $this.
1118 + */
1119 + public function setPriceGroups( $groups ) {
1120 + $this->_priceGroups = $groups;
1121 +
1122 + return $this;
1123 + }
1124 +
1125 + /**
1126 + * Get networks found in this request.
1127 + *
1128 + * @since 1.0.0
1129 + *
1130 + * @return array
1131 + */
1132 + public function getNetworks() {
1133 + return $this->_responseItem( 'networks', array() );
1134 + }
1135 +
1136 + /**
1137 + * Get merchants found in this request.
1138 + *
1139 + * @since 1.0.0
1140 + *
1141 + * @return array
1142 + */
1143 + public function getMerchants() {
1144 + return $this->_responseItem( 'merchants', array() );
1145 + }
1146 +
1147 + /**
1148 + * Get price groups found in this request.
1149 + *
1150 + * This must be used in conjunction with $this->setPriceGroups();
1151 + *
1152 + * Returns an array like this:
1153 + *
1154 + * Array (
1155 + * [0] => Array (
1156 + * [product_count] => 321
1157 + * [max] => 9633332
1158 + * [min] => 0
1159 + * )
1160 + * [1] => Array (
1161 + * [product_count] => 116
1162 + * [max] => 19266665
1163 + * [min] => 9633333
1164 + * )
1165 + * [2] => Array (
1166 + * [product_count] => 43
1167 + * [max] => 28900000
1168 + * [min] => 19266666
1169 + * )
1170 + * )
1171 + *
1172 + * @since 1.0.0
1173 + *
1174 + * @return array An array of price groups and the product count, min and max prices in each group.
1175 + */
1176 + public function getPriceGroups() {
1177 + return $this->_responseItem( 'price_groups', array() );
1178 + }
1179 +
1180 + /**
1181 + * Create a request array to use for querying the API.
1182 + *
1183 + * @since 1.0.0
1184 + *
1185 + * @return array The $request array().
1186 + */
1187 + public function getParams() {
1188 +
1189 + $request = array();
1190 +
1191 + if ( $this->_query ) {
1192 + $request['query'] = $this->_query;
1193 + }
1194 +
1195 + if ( $this->_sort ) {
1196 + $request['sort'] = $this->_sort;
1197 + }
1198 +
1199 + if ( $this->_fields ) {
1200 + $request['fields'] = $this->_fields;
1201 + }
1202 +
1203 + if ( $this->_limit ) {
1204 + $request['limit'] = $this->_limit;
1205 + }
1206 +
1207 + if ( $this->_offset ) {
1208 + $request['offset'] = $this->_offset;
1209 + }
1210 +
1211 + if ( $this->_priceGroups ) {
1212 + $request['price_groups'] = $this->_priceGroups;
1213 + }
1214 +
1215 + if ( $this->_merchantLimit ) {
1216 + $request['merchant_limit'] = $this->_merchantLimit;
1217 + }
1218 +
1219 + if ( $this->_excludeDuplicates ) {
1220 + $request['exclude_duplicates'] = $this->_excludeDuplicates;
1221 + }
1222 +
1223 + $request['string_ids'] = 1;
1224 +
1225 + return $request;
1226 + }
1227 +
1228 + /**
1229 + * Run search and return a list of products.
1230 + *
1231 + * @since 1.0.0
1232 + *
1233 + * @return array An array of products.
1234 + * @throws DatafeedrError Throw error if query is empty.
1235 + *
1236 + */
1237 + public function execute() {
1238 +
1239 + $params = $this->getParams();
1240 +
1241 + if ( ! isset( $params['query'] ) ) {
1242 + throw new DatafeedrError( "Query can't be empty" );
1243 + }
1244 +
1245 + $this->_apiCall( 'search', $params );
1246 +
1247 + return $this->_responseItem( 'products', array() );
1248 + }
733 1249 }
734 -}
735 1250
736 -if(!class_exists('DatafeedrMerchantSearchRequest', false)) {
737 1251 /**
738 1252 * Search request for Datafeedr Merchants.
739 - **/
740 -class DatafeedrMerchantSearchRequest extends DatafeedrSearchRequestBase
741 -{
742 - /**
743 - * Constructor.
744 - *
745 - * @param object $api DatafeedrApi object.
746 - *
747 - **/
748 - public function __construct($api) {
749 - parent::__construct($api);
1253 + */
1254 +class DatafeedrMerchantSearchRequest extends DatafeedrSearchRequestBase {
750 1255
751 - $this->_query = array();
752 - $this->_sort = array();
753 - $this->_fields = array();
754 - $this->_limit = 0;
755 - $this->_offset = 0;
756 - }
1256 + protected $_query;
1257 + protected $_sort;
1258 + protected $_fields;
1259 + protected $_limit;
1260 + protected $_offset;
757 1261
758 - /**
759 - * Add a query filter.
760 - *
761 - * @param string $filter Query filter.
762 - * @return $this
763 - *
764 - **/
765 - public function addFilter($filter) {
766 - $this->_query []= $filter;
767 - return $this;
768 - }
1262 + /**
1263 + * DatafeedrMerchantSearchRequest constructor.
1264 + *
1265 + * @since 1.0.0
1266 + *
1267 + * @param DatafeedrApi $api
1268 + *
1269 + */
1270 + public function __construct( $api ) {
769 1271
770 - /**
771 - * Add a sort field.
772 - *
773 - * @param string $field Field name.
774 - * @param int $order One of DatafeedrApi::SORT_ASCENDING or DatafeedrApi::SORT_DESCENDING
775 - * @throws DatafeedrError
776 - * @return $this
777 - *
778 - **/
779 - public function addSort($field, $order = DatafeedrApi::SORT_ASCENDING) {
780 - if(strlen($field) && ($field[0] == '+' || $field[0] == '-')) {
781 - $this->_sort []= $field;
782 - } else if($order == DatafeedrApi::SORT_ASCENDING) {
783 - $this->_sort []= '+' . $field;
784 - } else if($order == DatafeedrApi::SORT_DESCENDING) {
785 - $this->_sort []= '-' . $field;
786 - } else {
787 - throw new DatafeedrError("Invalid sort order");
788 - }
789 - return $this;
790 - }
1272 + parent::__construct( $api );
791 1273
792 - /**
793 - * Set which fields to retrieve.
794 - *
795 - * @param array $fields List of field names.
796 - * @return $this
797 - *
798 - **/
799 - public function setFields($fields) {
800 - $this->_fields = $fields;
801 - return $this;
802 - }
1274 + $this->_query = array();
1275 + $this->_sort = array();
1276 + $this->_fields = array();
1277 + $this->_limit = 0;
1278 + $this->_offset = 0;
1279 + }
803 1280
804 - /**
805 - * Set a limit.
806 - *
807 - * @param int $limit The limit.
808 - * @return $this
809 - *
810 - **/
811 - public function setLimit($limit) {
812 - $this->_limit = $limit;
813 - return $this;
814 - }
1281 + /**
1282 + * Add a query filter.
1283 + *
1284 + * @since 1.0.0
1285 + *
1286 + * @param string $filter Query filter.
1287 + *
1288 + * @return DatafeedrMerchantSearchRequest Returns $this.
1289 + */
1290 + public function addFilter( $filter ) {
1291 + $this->_query [] = $filter;
815 1292
816 - /**
817 - * Set an offset.
818 - *
819 - * @param int $offset The offset.
820 - * @return $this
821 - *
822 - **/
823 - public function setOffset($offset) {
824 - $this->_offset = $offset;
825 - return $this;
826 - }
1293 + return $this;
1294 + }
827 1295
828 - /**
829 - * Get found networks.
830 - *
831 - * @return array
832 - *
833 - **/
834 - public function getNetworks() {
835 - return $this->_responseItem('networks', array());
836 - }
1296 + /**
1297 + * Add a sort field.
1298 + *
1299 + * @since 1.0.0
1300 + *
1301 + * @param integer $order One of DatafeedrApi::SORT_ASCENDING or DatafeedrApi::SORT_DESCENDING
1302 + *
1303 + * @param string $field Field name.
1304 + *
1305 + * @return DatafeedrMerchantSearchRequest Returns $this.
1306 + * @throws DatafeedrError Throw error if invalid sort order.
1307 + *
1308 + */
1309 + public function addSort( $field, $order = DatafeedrApi::SORT_ASCENDING ) {
837 1310
838 - /**
839 - * Get found merchants.
840 - *
841 - * @return array
842 - *
843 - **/
844 - public function getMerchants() {
845 - return $this->_responseItem('merchants', array());
846 - }
1311 + if ( strlen( $field ) && ( $field[0] == '+' || $field[0] == '-' ) ) {
1312 + $this->_sort [] = $field;
1313 + } else if ( $order == DatafeedrApi::SORT_ASCENDING ) {
1314 + $this->_sort [] = '+' . $field;
1315 + } else if ( $order == DatafeedrApi::SORT_DESCENDING ) {
1316 + $this->_sort [] = '-' . $field;
1317 + } else {
1318 + throw new DatafeedrError( "Invalid sort order" );
1319 + }
847 1320
848 - /**
849 - * Run search and return a list of merchants.
850 - *
851 - * @throws DatafeedrError
852 - * @return array
853 - *
854 - **/
855 - public function execute() {
856 - $params = $this->getParams();
857 - if(!isset($params['query'])) {
858 - throw new DatafeedrError("Query can't be empty");
859 - }
860 - $this->_apiCall('merchant_search', $params);
861 - return $this->_responseItem('merchants', array());
862 - }
1321 + return $this;
1322 + }
863 1323
864 - /**
865 - * Create a request object to use with the API.
866 - *
867 - * @return array
868 - *
869 - **/
870 - public function getParams() {
871 - $request = array();
872 - if($this->_query) {
873 - $request['query'] = $this->_query;
874 - }
875 - if($this->_sort) {
876 - $request['sort'] = $this->_sort;
877 - }
878 - if($this->_fields) {
879 - $request['fields'] = $this->_fields;
880 - }
881 - if($this->_limit) {
882 - $request['limit'] = $this->_limit;
883 - }
884 - if($this->_offset) {
885 - $request['offset'] = $this->_offset;
886 - }
887 - return $request;
888 - }
1324 + /**
1325 + * Set which fields to retrieve.
1326 + *
1327 + * @since 1.0.0
1328 + *
1329 + * @param array $fields An array of field names.
1330 + *
1331 + * @return DatafeedrMerchantSearchRequest Returns $this.
1332 + */
1333 + public function setFields( $fields ) {
1334 + $this->_fields = $fields;
1335 +
1336 + return $this;
1337 + }
1338 +
1339 + /**
1340 + * Set a limit.
1341 + *
1342 + * @since 1.0.0
1343 + *
1344 + * @param integer $limit Number of items to return.
1345 + *
1346 + * @return DatafeedrMerchantSearchRequest Returns $this.
1347 + */
1348 + public function setLimit( $limit ) {
1349 + $this->_limit = $limit;
1350 +
1351 + return $this;
1352 + }
1353 +
1354 + /**
1355 + * Set an offset.
1356 + *
1357 + * @since 1.0.0
1358 + *
1359 + * @param integer $offset The offset.
1360 + *
1361 + * @return DatafeedrMerchantSearchRequest Returns $this.
1362 + */
1363 + public function setOffset( $offset ) {
1364 + $this->_offset = $offset;
1365 +
1366 + return $this;
1367 + }
1368 +
1369 + /**
1370 + * Get networks found in this request.
1371 + *
1372 + * @since 1.0.0
1373 + *
1374 + * @return array
1375 + */
1376 + public function getNetworks() {
1377 + return $this->_responseItem( 'networks', array() );
1378 + }
1379 +
1380 + /**
1381 + * Get merchants found in this request.
1382 + *
1383 + * @since 1.0.0
1384 + *
1385 + * @return array
1386 + */
1387 + public function getMerchants() {
1388 + return $this->_responseItem( 'merchants', array() );
1389 + }
1390 +
1391 + /**
1392 + * Run search and return an array of merchants.
1393 + *
1394 + * @since 1.0.0
1395 + *
1396 + * @return array Array of merchants
1397 + * @throws DatafeedrError Throws error if query is empty.
1398 + *
1399 + */
1400 + public function execute() {
1401 +
1402 + $params = $this->getParams();
1403 +
1404 + if ( ! isset( $params['query'] ) ) {
1405 + throw new DatafeedrError( "Query can't be empty" );
1406 + }
1407 +
1408 + $this->_apiCall( 'merchant_search', $params );
1409 +
1410 + return $this->_responseItem( 'merchants', array() );
1411 + }
1412 +
1413 + /**
1414 + * Create a request array to use for querying the API.
1415 + *
1416 + * @since 1.0.0
1417 + *
1418 + * @return array The $request array().
1419 + */
1420 + public function getParams() {
1421 +
1422 + $request = array();
1423 +
1424 + if ( $this->_query ) {
1425 + $request['query'] = $this->_query;
1426 + }
1427 +
1428 + if ( $this->_sort ) {
1429 + $request['sort'] = $this->_sort;
1430 + }
1431 +
1432 + if ( $this->_fields ) {
1433 + $request['fields'] = $this->_fields;
1434 + }
1435 +
1436 + if ( $this->_limit ) {
1437 + $request['limit'] = $this->_limit;
1438 + }
1439 +
1440 + if ( $this->_offset ) {
1441 + $request['offset'] = $this->_offset;
1442 + }
1443 +
1444 + return $request;
1445 + }
889 1446 }
890 -}
891 1447
892 -if(!class_exists('DatafeedrAmazonRequest', false)) {
893 1448 /**
894 1449 * Generic Amazon request.
895 - **/
896 -class DatafeedrAmazonRequest extends DatafeedrSearchRequestBase
897 -{
898 - protected $_found = -1;
1450 + */
1451 +class DatafeedrAmazonRequest extends DatafeedrSearchRequestBase {
899 1452
900 - const AWS_VERSION = "2011-08-01";
1453 + protected $_found = - 1;
901 1454
902 - /**
903 - * Constructor
904 - *
905 - * @param object $api DatafeedrApi object.
906 - * @param string $awsAccessKeyId Amazon access key.
907 - * @param string $awsSecretKey Amazon secret key.
908 - * @param string $awsAssociateTag Amazon associate tag.
909 - * @param string $locale Amazon locale (two-letter code).
910 - */
911 - public function __construct($api, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale="US") {
912 - parent::__construct($api);
913 - $this->_hosts = array(
914 - "CA" => "webservices.amazon.ca",
915 - "CN" => "webservices.amazon.cn",
916 - "DE" => "webservices.amazon.de",
917 - "ES" => "webservices.amazon.es",
918 - "FR" => "webservices.amazon.fr",
919 - "IT" => "webservices.amazon.it",
920 - "JP" => "webservices.amazon.co.jp",
921 - "UK" => "webservices.amazon.co.uk",
922 - "US" => "webservices.amazon.com",
923 - );
1455 + protected $_hosts;
1456 + protected $_params;
1457 + protected $_locale;
1458 + protected $_awsAccessKeyId;
1459 + protected $_awsSecretKey;
1460 + protected $_awsAssociateTag;
924 1461
925 - $this->_params = array();
926 - $this->_locale = strtoupper($locale);
1462 + const AWS_VERSION = "2011-08-01";
927 1463
928 - if(!isset($this->_hosts[$this->_locale])) {
929 - throw new DatafeedrError("Invalid Amazon locale");
930 - }
1464 + /**
1465 + * DatafeedrAmazonRequest constructor
1466 + *
1467 + * @since 1.0.0
1468 + *
1469 + * @param string $awsAccessKeyId Amazon Access Key.
1470 + * @param string $awsSecretKey Amazon Secret Key.
1471 + * @param string $awsAssociateTag Amazon Associate tag.
1472 + * @param string $locale Optional. Amazon locale (two-letter code).
1473 + *
1474 + * @param DatafeedrApi $api
1475 + *
1476 + * @throws DatafeedrError Throws error if Amazon Locale is invalid.
1477 + */
1478 + public function __construct( $api, $awsAccessKeyId, $awsSecretKey, $awsAssociateTag, $locale = 'US' ) {
931 1479
932 - $this->_awsAccessKeyId = $awsAccessKeyId;
933 - $this->_awsSecretKey = $awsSecretKey;
934 - $this->_awsAssociateTag = $awsAssociateTag;
935 - }
1480 + parent::__construct( $api );
936 1481
937 - /**
938 - * Returns all parameters.
939 - *
940 - * @return array
941 - *
942 - **/
943 - public function getParams() {
944 - return $this->_params;
945 - }
1482 + $this->_hosts = array(
1483 + 'AU' => 'webservices.amazon.com.au',
1484 + 'BR' => 'webservices.amazon.com.br',
1485 + 'CA' => 'webservices.amazon.ca',
1486 + 'FR' => 'webservices.amazon.fr',
1487 + 'DE' => 'webservices.amazon.de',
1488 + 'IN' => 'webservices.amazon.in',
1489 + 'IT' => 'webservices.amazon.it',
1490 + 'JP' => 'webservices.amazon.co.jp',
1491 + 'MX' => 'webservices.amazon.com.mx',
1492 + 'NL' => 'webservices.amazon.nl',
1493 + 'SG' => 'webservices.amazon.sg',
1494 + 'SA' => 'webservices.amazon.sa',
1495 + 'ES' => 'webservices.amazon.es',
1496 + 'SE' => 'webservices.amazon.se',
1497 + 'TR' => 'webservices.amazon.com.tr',
1498 + 'AE' => 'webservices.amazon.ae',
1499 + 'UK' => 'webservices.amazon.co.uk',
1500 + 'US' => 'webservices.amazon.com',
1501 + );
946 1502
947 - protected function _amazonUrl($operation, $params, $defaults=NULL) {
948 - $params = array_filter($params);
1503 + $this->_params = array();
1504 + $this->_locale = strtoupper( $locale );
949 1505
950 - if(!is_null($defaults)) {
951 - foreach($defaults as $k => $v) {
952 - if(!isset($params[$k])) {
953 - $params[$k] = $v;
954 - }
955 - }
956 - }
1506 + if ( ! isset( $this->_hosts[ $this->_locale ] ) ) {
1507 + throw new DatafeedrError( 'Invalid Amazon locale' );
1508 + }
957 1509
958 - $params["Operation"] = $operation;
959 - $params["Service"] = "AWSECommerceService";
960 - $params["AWSAccessKeyId"] = $this->_awsAccessKeyId;
961 - $params["AssociateTag"] = $this->_awsAssociateTag;
962 - $params["Version"] = self::AWS_VERSION;
963 - $params["Timestamp"] = gmdate("Y-m-d\\TH:i:s\\Z");
1510 + $this->_awsAccessKeyId = $awsAccessKeyId;
1511 + $this->_awsSecretKey = $awsSecretKey;
1512 + $this->_awsAssociateTag = $awsAssociateTag;
1513 + }
964 1514
965 - ksort($params);
966 - $query = array();
967 - foreach($params as $k => $v) {
968 - if(is_array($v)) {
969 - $v = implode(',', $v);
970 - }
971 - $query []= $k . '=' . rawurlencode($v);
972 - }
973 - $query = implode('&', $query);
974 - $host = $this->_hosts[$this->_locale];
975 - $path = "/onca/xml";
976 - $subj = sprintf("GET\n%s\n%s\n%s", $host, $path, $query);
977 - $sign = rawurlencode(base64_encode(hash_hmac("sha256", $subj, $this->_awsSecretKey, TRUE)));
978 - return "http://{$host}{$path}?{$query}&Signature={$sign}";
979 - }
1515 + /**
1516 + * Returns all parameters.
1517 + *
1518 + * @since 1.0.0
1519 + *
1520 + * @return array
1521 + */
1522 + public function getParams() {
1523 + return $this->_params;
1524 + }
1525 +
1526 + /**
1527 + * Prepare am API request for Amazon.
1528 + *
1529 + * @since 3.0.0
1530 + *
1531 + * @param array $params
1532 + *
1533 + * @param string $operation
1534 + *
1535 + * @return array
1536 + */
1537 + protected function _amazonRequest( $operation, $params ) {
1538 + return array(
1539 + 'amz_access' => $this->_awsAccessKeyId,
1540 + 'amz_key' => $this->_awsSecretKey,
1541 + 'amz_tag' => $this->_awsAssociateTag,
1542 + 'locale' => $this->_locale,
1543 + 'operation' => $operation,
1544 + 'params' => $params,
1545 + );
1546 + }
980 1547 }
981 -}
982 1548
983 -if(!class_exists('DatafeedrAmazonSearchRequest', false)) {
984 1549 /**
985 - * Amazon search request.
986 - **/
987 -class DatafeedrAmazonSearchRequest extends DatafeedrAmazonRequest
988 -{
989 - /**
990 - * Add a parameter.
991 - *
992 - * @param string $name Parameter name.
993 - * @param string $value Parameter value.
994 - * @return $this
995 - *
996 - * @see http://docs.aws.amazon.com/AWSECommerceService/latest/DG/ItemSearch.html
997 - *
998 - **/
999 - public function addParam($name, $value) {
1000 - $this->_params[$name] = $value;
1001 - return $this;
1002 - }
1550 + * Class DatafeedrAmazonSearchRequest
1551 + *
1552 + * Amazon search request class.
1553 + */
1554 +class DatafeedrAmazonSearchRequest extends DatafeedrAmazonRequest {
1003 1555
1004 - /**
1005 - * Run search and return a list of products.
1006 - *
1007 - * @return array
1008 - *
1009 - **/
1010 - public function execute() {
1011 - $defaults = array(
1012 - 'ResponseGroup' => 'ItemAttributes,Images,OfferFull,BrowseNodes,EditorialReview,VariationSummary',
1013 - 'SearchIndex' => 'All',
1014 - );
1015 - $url = $this->_amazonUrl('ItemSearch', $this->_params, $defaults);
1016 - $this->_apiCall('amazon_search', array('url' => $url));
1017 - return $this->_responseItem('products', array());
1018 - }
1556 + /**
1557 + * Add a parameter.
1558 + *
1559 + * @since 1.0.0
1560 + *
1561 + * @param string $value Parameter value.
1562 + *
1563 + * @param string $name Parameter name.
1564 + *
1565 + * @return DatafeedrAmazonSearchRequest Returns $this.
1566 + *
1567 + * @see https://webservices.amazon.com/paapi5/documentation/search-items.html#ItemLookup-rp
1568 + */
1569 + public function addParam( $name, $value ) {
1570 + $this->_params[ $name ] = $value;
1571 +
1572 + return $this;
1573 + }
1574 +
1575 + /**
1576 + * Run search and return an array of products.
1577 + *
1578 + * IMPORTANT - The Amazon API returns a MAXIMUM of 10 products per API request and a maximum of
1579 + * 50 products per search query.
1580 + *
1581 + * @since 1.0.0
1582 + *
1583 + * @return array An array of products.
1584 + * @throws DatafeedrError
1585 + */
1586 + public function execute() {
1587 +
1588 + $params = array_filter( $this->_params );
1589 + $req = $this->_amazonRequest( 'SearchItems', $params );
1590 + $this->_apiCall( 'amazon_find', $req );
1591 +
1592 + return $this->_responseItem( 'products', array() );
1593 + }
1019 1594 }
1020 -}
1021 1595
1022 -if(!class_exists('DatafeedrAmazonLookupRequest', false)) {
1023 1596 /**
1597 + * Class DatafeedrAmazonLookupRequest
1598 + *
1024 1599 * Amazon lookup request.
1025 - **/
1026 -class DatafeedrAmazonLookupRequest extends DatafeedrAmazonRequest
1027 -{
1028 - /**
1029 - * Add a parameter.
1030 - *
1031 - * @param string $name Parameter name - one of 'ASIN', 'SKU', 'UPC', 'EAN', 'ISBN'
1032 - * @param string|array $value Parameter value or an array of values (up to 10).
1033 - * @return $this
1034 - *
1035 - * @see http://docs.aws.amazon.com/AWSECommerceService/latest/DG/ItemLookup.html
1036 - *
1037 - **/
1038 - public function addParam($name, $value) {
1039 - $this->_params[$name] = $value;
1040 - return $this;
1041 - }
1600 + */
1601 +class DatafeedrAmazonLookupRequest extends DatafeedrAmazonRequest {
1042 1602
1043 - /**
1044 - * Run search and return a list of products.
1045 - *
1046 - * @return array
1047 - *
1048 - **/
1049 - public function execute() {
1050 - $params = array_filter($this->_params);
1051 - $types = array('ASIN', 'SKU', 'UPC', 'EAN', 'ISBN', 'asin', 'sku', 'upc', 'ean', 'isbn');
1052 - foreach($types as $type) {
1053 - if(isset($params[$type])) {
1054 - $params['IdType'] = strtoupper($type);
1055 - $params['ItemId'] = $params[$type];
1056 - unset($params[$type]);
1057 - }
1058 - }
1603 + /**
1604 + * Add a parameter.
1605 + *
1606 + * @since 1.0.0
1607 + *
1608 + * @param string|array $value Parameter value or an array of values (up to 10).
1609 + *
1610 + * @param string $name Parameter name - one of 'ASIN', 'SKU', 'UPC', 'EAN', 'ISBN'
1611 + *
1612 + * @return DatafeedrAmazonLookupRequest Returns $this.
1613 + *
1614 + * @see https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp
1615 + */
1616 + public function addParam( $name, $value ) {
1617 + $this->_params[ $name ] = $value;
1059 1618
1060 - $defaults = array(
1061 - 'ResponseGroup' => 'ItemAttributes,Images,OfferFull,BrowseNodes,EditorialReview,VariationSummary',
1062 - );
1063 - if(isset($params['IdType']) && $params['IdType'] != 'ASIN') {
1064 - $defaults['SearchIndex'] = 'All';
1065 - }
1066 - $url = $this->_amazonUrl('ItemLookup', $params, $defaults);
1067 - $this->_apiCall('amazon_search', array('url' => $url));
1068 - return $this->_responseItem('products', array());
1069 - }
1619 + return $this;
1620 + }
1621 +
1622 + /**
1623 + * Run search and return an array of products.
1624 + *
1625 + * @since 1.0.0
1626 + *
1627 + * @return array An array of products.
1628 + */
1629 + public function execute() {
1630 +
1631 + $params = array_filter( $this->_params );
1632 + $types = array( 'ASIN', 'SKU', 'UPC', 'EAN', 'ISBN', 'asin', 'sku', 'upc', 'ean', 'isbn' );
1633 +
1634 + foreach ( $types as $type ) {
1635 + if ( isset( $params[ $type ] ) ) {
1636 + $params['ItemIdType'] = strtoupper( $type );
1637 + $params['ItemIds'] = $params[ $type ];
1638 + if ( is_string( $params['ItemIds'] ) ) {
1639 + $params['ItemIds'] = explode( ',', $params['ItemIds'] );
1640 + }
1641 + unset( $params[ $type ] );
1642 + }
1643 + }
1644 +
1645 + $req = $this->_amazonRequest( 'GetItems', $params );
1646 + $this->_apiCall( 'amazon_find', $req );
1647 +
1648 + return $this->_responseItem( 'products', array() );
1649 + }
1070 1650 }
1651 +
1652 +/** CreatorAPI */
1653 +class DatafeedrAmazonCreatorApiRequest extends DatafeedrSearchRequestBase {
1654 +
1655 + protected $_found = - 1;
1656 +
1657 + protected $_hosts;
1658 + protected $_params;
1659 +// protected $_capiCredentialId;
1660 +// protected $_capiCredentialSecret;
1661 +// protected $_capiVersion;
1662 + protected $_capiPartnerTag;
1663 + protected $_capiMarketplace;
1664 +
1665 + public const AWS_VERSION = "2026-01-05";
1666 +
1667 + public function __construct( $api, $capiMarketplace = 'US' ) {
1668 +
1669 + parent::__construct( $api );
1670 +
1671 + $capiMarketplace = strtoupper( trim( $capiMarketplace ) );
1672 +
1673 + foreach ( dfrapi_get_capi_marketplaces() as $code => $marketplace ) {
1674 + $this->_hosts[ $code ] = $marketplace['domain'];
1675 + }
1676 +
1677 + if ( ! isset( $this->_hosts[ $capiMarketplace ] ) ) {
1678 + throw new DatafeedrError( 'Invalid Amazon CAPI locale' );
1679 + }
1680 +
1681 + $this->_params = array();
1682 +
1683 +// $capiVersion = dfrapi_get_capi_marketplace( $capiMarketplace )['region']['version'];
1684 +
1685 +// $this->_capiCredentialId = $capiCredentialId;
1686 +// $this->_capiCredentialSecret = $capiCredentialSecret;
1687 +// $this->_capiVersion = $capiVersion;
1688 +// $this->_capiPartnerTag = $capiPartnerTag;
1689 + $this->_capiMarketplace = $capiMarketplace;
1690 + }
1691 +
1692 + /**
1693 + * Returns all parameters.
1694 + *
1695 + * @since 1.0.0
1696 + *
1697 + * @return array
1698 + */
1699 + public function getParams() {
1700 + return $this->_params;
1701 + }
1702 +
1703 + /**
1704 + * Prepare am API request for Amazon.
1705 + *
1706 + * @since 3.0.0
1707 + *
1708 + * @param array $params
1709 + *
1710 + * @param string $operation
1711 + *
1712 + * @return array
1713 + */
1714 +// protected function _amazonRequest( $operation, $params ) {
1715 +// return array(
1716 +// 'capi_credential_id' => $this->_capiCredentialId,
1717 +// 'capi_credential_secret' => $this->_capiCredentialSecret,
1718 +// 'capi_version' => $this->_capiVersion,
1719 +// 'capi_partner_tag' => $this->_capiPartnerTag,
1720 +// 'capi_marketplace' => $this->_capiMarketplace,
1721 +// 'operation' => $operation,
1722 +// 'params' => $params,
1723 +// );
1724 +// }
1071 1725 }
1072 1726
1073 -if(!class_exists('DatafeedrError', false)) {
1727 +/** CreatorAPI */
1728 +class DatafeedrAmazonCreatorApiSearchRequest extends DatafeedrAmazonCreatorApiRequest {
1729 +
1730 + /**
1731 + * Add a parameter.
1732 + *
1733 + * @since 1.0.0
1734 + *
1735 + * @param string $value Parameter value.
1736 + *
1737 + * @param string $name Parameter name.
1738 + *
1739 + * @return DatafeedrAmazonCreatorApiSearchRequest Returns $this.
1740 + *
1741 + * @see https://webservices.amazon.com/paapi5/documentation/search-items.html#ItemLookup-rp
1742 + */
1743 + public function addParam( $name, $value ) {
1744 + $this->_params[ $name ] = $value;
1745 +
1746 + return $this;
1747 + }
1748 +
1749 + /**
1750 + * Run search and return an array of products.
1751 + *
1752 + * IMPORTANT - The Amazon API returns a MAXIMUM of 10 products per API request and a maximum of
1753 + * 50 products per search query.
1754 + *
1755 + * @since 1.0.0
1756 + *
1757 + * @return array An array of products.
1758 + * @throws DatafeedrError
1759 + */
1760 + public function execute() {
1761 +
1762 + $access_token = dfrapi_get_capi_access_token();
1763 +
1764 + if ( is_wp_error( $access_token ) ) {
1765 + throw new DatafeedrError( $access_token->get_error_message() );
1766 + }
1767 +
1768 + $body = array_merge( array_filter( $this->_params ), [] );
1769 +
1770 + $credentials = dfrapi_get_capi_credentials();
1771 + $marketplace = dfrapi_get_capi_marketplace( $this->_capiMarketplace );
1772 +
1773 + $domain = $marketplace['domain'];
1774 + $credential_version = $marketplace['region']['version'];
1775 + $body['partnerTag'] = $credentials['partner_tag'];
1776 +
1777 + // https://affiliate-program.amazon.com/creatorsapi/docs/en-us/api-reference/operations/search-items
1778 + $resources = [
1779 +// 'browseNodeInfo.browseNodes',
1780 +// 'browseNodeInfo.browseNodes.ancestor',
1781 +// 'browseNodeInfo.browseNodes.salesRank',
1782 +// 'browseNodeInfo.websiteSalesRank',
1783 + 'customerReviews.count',
1784 + 'customerReviews.starRating',
1785 + 'images.primary.highRes',
1786 + 'images.primary.large',
1787 + 'images.primary.medium',
1788 + 'images.primary.small',
1789 +// 'images.variants.highRes',
1790 +// 'images.variants.large',
1791 +// 'images.variants.medium',
1792 +// 'images.variants.small',
1793 + 'itemInfo.byLineInfo',
1794 +// 'itemInfo.classifications',
1795 +// 'itemInfo.contentInfo',
1796 +// 'itemInfo.contentRating',
1797 + 'itemInfo.externalIds',
1798 +// 'itemInfo.features',
1799 +// 'itemInfo.manufactureInfo',
1800 + 'itemInfo.productInfo',
1801 +// 'itemInfo.technicalInfo',
1802 + 'itemInfo.title',
1803 + 'itemInfo.tradeInInfo',
1804 + 'offersV2.listings.availability',
1805 + 'offersV2.listings.condition',
1806 +// 'offersV2.listings.dealDetails',
1807 +// 'offersV2.listings.isBuyBoxWinner',
1808 +// 'offersV2.listings.loyaltyPoints',
1809 +// 'offersV2.listings.merchantInfo',
1810 + 'offersV2.listings.price',
1811 + 'offersV2.listings.type',
1812 + 'parentASIN',
1813 +// 'searchRefinements',
1814 + ];
1815 +
1816 + $body['resources'] = $resources;
1817 +
1818 + $response = wp_remote_post(
1819 + 'https://creatorsapi.amazon/catalog/v1/searchItems',
1820 + [
1821 + 'headers' => [
1822 + 'Authorization' => sprintf(
1823 + 'Bearer %s, Version %s',
1824 + $access_token,
1825 + $credential_version
1826 + ),
1827 + 'Content-Type' => 'application/json',
1828 + 'x-marketplace' => $domain,
1829 + ],
1830 + 'body' => wp_json_encode( $body ),
1831 + 'timeout' => 20,
1832 + 'httpversion' => '1.1', // important for Amazon APIs
1833 + ]
1834 + );
1835 +
1836 + if ( is_wp_error( $response ) ) {
1837 + error_log( $response->get_error_message() );
1838 +
1839 + throw new DatafeedrConnectionError( $response->get_error_message() );
1840 + }
1841 +
1842 + $status = wp_remote_retrieve_response_code( $response );
1843 +
1844 + if ( 404 === $status ) {
1845 + $body = wp_remote_retrieve_body( $response );
1846 + $data = json_decode( $body, true );
1847 + if ( isset( $data['type'] ) && 'ResourceNotFoundException' === $data['type'] ) {
1848 + return [];
1849 + }
1850 + }
1851 +
1852 + if ( 200 !== $status ) {
1853 + $error_body = wp_remote_retrieve_body( $response );
1854 + $error_data = json_decode( $error_body, true );
1855 + $status_message = wp_remote_retrieve_response_message( $response );
1856 +
1857 + if ( ! empty( $error_data['message'] ) ) {
1858 + $message = $error_data['message'];
1859 + } elseif ( ! empty( $error_data['reason'] ) ) {
1860 + $message = $error_data['reason'];
1861 + } else {
1862 + $message = $status_message;
1863 + }
1864 +
1865 + error_log( sprintf( '[Datafeedr CAPI] SearchItems error (%d): %s | Response: %s', $status, $message, $error_body ) );
1866 +
1867 + throw new DatafeedrHTTPError( $message, $status );
1868 + }
1869 +
1870 + $body = wp_remote_retrieve_body( $response );
1871 +
1872 +
1873 + /*
1874 +
1875 + [
1876 + "errors" => null,
1877 + "searchResult" => [
1878 + "items" => [
1879 + [
1880 + "asin" => "0545162076",
1881 + "browseNodeInfo" => null,
1882 + "customerReviews" => null,
1883 + "detailPageURL" => "https://www.amazon.com/dp/0545162076?tag=xyz-20&linkCode=osi&th=1&psc=1",
1884 + "images" => null,
1885 + "itemInfo" => [
1886 + "byLineInfo" => null,
1887 + "classifications" => null,
1888 + "contentInfo" => null,
1889 + "contentRating" => null,
1890 + "externalIds" => null,
1891 + "features" => null,
1892 + "manufactureInfo" => null,
1893 + "productInfo" => null,
1894 + "technicalInfo" => null,
1895 + "title" => [
1896 + "displayValue" => "Harry Potter Paperback Box Set (Books 1-7)",
1897 + "label" => "Title",
1898 + "locale" => "en_US",
1899 + ],
1900 + "tradeInInfo" => null,
1901 + ],
1902 + "offersV2" => null,
1903 + "parentASIN" => null,
1904 + "score" => null,
1905 + "variationAttributes" => null,
1906 + ],
1907 + [ ... ],
1908 + [ ... ],
1909 + [ ... ],
1910 + ],
1911 + "searchRefinements" => null,
1912 + "searchURL" => "https://www.amazon.com/s?k=Harry+Potter&rh=p_n_availability%3A2661600011&tag=xyz-20&linkCode=osi",
1913 + "totalResultCount" => 306,
1914 + ],
1915 + ]
1916 +
1917 +
1918 + */
1919 + /**
1920 + * [
1921 + * "errors" => null,
1922 + * "searchResult" => [
1923 + * "items" => [
1924 + * [
1925 + * "asin" => "0545162076",
1926 + * "browseNodeInfo" => null,
1927 + * "customerReviews" => null,
1928 + * "detailPageURL" => "https://www.amazon.com/dp/0545162076?tag=xyz-20&linkCode=osi&th=1&psc=1",
1929 + * "images" => null,
1930 + * "itemInfo" => [
1931 + * "byLineInfo" => null,
1932 + * "classifications" => null,
1933 + * "contentInfo" => null,
1934 + * "contentRating" => null,
1935 + * "externalIds" => null,
1936 + * "features" => null,
1937 + * "manufactureInfo" => null,
1938 + * "productInfo" => null,
1939 + * "technicalInfo" => null,
1940 + * "title" => [
1941 + * "displayValue" => "Harry Potter Paperback Box Set (Books 1-7)",
1942 + * "label" => "Title",
1943 + * "locale" => "en_US",
1944 + * ],
1945 + * "tradeInInfo" => null,
1946 + * ],
1947 + * "offersV2" => null,
1948 + * "parentASIN" => null,
1949 + * "score" => null,
1950 + * "variationAttributes" => null,
1951 + * ],
1952 + * [ ... ],
1953 + * [ ... ],
1954 + * [ ... ],
1955 + * ],
1956 + * "searchRefinements" => null,
1957 + * "searchURL" => "https://www.amazon.com/s?k=Harry+Potter&rh=p_n_availability%3A2661600011&tag=xyz-20&linkCode=osi",
1958 + * "totalResultCount" => 306,
1959 + * ],
1960 + * ]
1961 + */
1962 + $data = json_decode( $body, true );
1963 +
1964 + if ( ! empty( $data['errors'] ) ) {
1965 + $error = $data['errors'][0];
1966 + error_log( $error['message'] );
1967 +
1968 + throw new DatafeedrExternalError( $error['message'] );
1969 + }
1970 +
1971 + $items = $data['searchResult']['items'] ?? [];
1972 + $products = [];
1973 +
1974 + foreach ( $items as $item ) {
1975 + $products[] = dfrapi_transform_capi_item_into_datafeedr_product_array( $item );
1976 + }
1977 +
1978 + return $products;
1979 +
1980 +// $data now contains the API response
1981 +
1982 +
1983 + }
1984 +}
1985 +
1986 +/** CreatorAPI */
1987 +//class DatafeedrAmazonCreatorApiLookupRequest extends DatafeedrAmazonCreatorApiRequest {
1988 +//
1989 +// /**
1990 +// * Add a parameter.
1991 +// *
1992 +// * @since 1.0.0
1993 +// *
1994 +// * @param string|array $value Parameter value or an array of values (up to 10).
1995 +// *
1996 +// * @param string $name Parameter name - one of 'ASIN', 'SKU', 'UPC', 'EAN', 'ISBN'
1997 +// *
1998 +// * @return DatafeedrAmazonCreatorApiLookupRequest Returns $this.
1999 +// *
2000 +// * @see https://webservices.amazon.com/paapi5/documentation/get-items.html#ItemLookup-rp
2001 +// */
2002 +// public function addParam( $name, $value ) {
2003 +// $this->_params[ $name ] = $value;
2004 +//
2005 +// return $this;
2006 +// }
2007 +//
2008 +// /**
2009 +// * Run search and return an array of products.
2010 +// *
2011 +// * @since 1.0.0
2012 +// *
2013 +// * @return array An array of products.
2014 +// */
2015 +// public function execute() {
2016 +//
2017 +// $params = array_filter( $this->_params );
2018 +// $types = array( 'ASIN', 'SKU', 'UPC', 'EAN', 'ISBN', 'asin', 'sku', 'upc', 'ean', 'isbn' );
2019 +//
2020 +// foreach ( $types as $type ) {
2021 +// if ( isset( $params[ $type ] ) ) {
2022 +// $params['itemIdType'] = strtoupper( $type );
2023 +// $params['itemIds'] = $params[ $type ];
2024 +// if ( is_string( $params['itemIds'] ) ) {
2025 +// $params['itemIds'] = explode( ',', $params['itemIds'] );
2026 +// }
2027 +// unset( $params[ $type ] );
2028 +// }
2029 +// }
2030 +//
2031 +// $req = $this->_amazonRequest( 'GetItems', $params );
2032 +// $this->_apiCall( 'amazon_find', $req );
2033 +//
2034 +// return $this->_responseItem( 'products', array() );
2035 +// }
2036 +//}
2037 +
1074 2038 /**
2039 + * Class DatafeedrError.
2040 + *
1075 2041 * Generic Api error.
1076 -**/
1077 -class DatafeedrError extends Exception
1078 -{
2042 + */
2043 +class DatafeedrError extends Exception {
1079 2044 }
1080 -}
1081 2045
1082 -if(!class_exists('DatafeedrBadRequestError', false)) {
1083 2046 /**
2047 + * Class DatafeedrBadRequestError.
2048 + *
1084 2049 * API error: Invalid Request.
1085 -**/
1086 -class DatafeedrBadRequestError extends DatafeedrError
1087 -{
2050 + */
2051 +class DatafeedrBadRequestError extends DatafeedrError {
1088 2052 }
1089 -}
1090 2053
1091 -if(!class_exists('DatafeedrAuthenticationError', false)) {
1092 2054 /**
2055 + * Class DatafeedrAuthenticationError.
2056 + *
1093 2057 * API error: Authentication failed.
1094 -**/
1095 -class DatafeedrAuthenticationError extends DatafeedrError
1096 -{
2058 + */
2059 +class DatafeedrAuthenticationError extends DatafeedrError {
1097 2060 }
1098 -}
1099 2061
1100 -if(!class_exists('DatafeedrLimitExceededError', false)) {
1101 2062 /**
2063 + * Class DatafeedrLimitExceededError.
2064 + *
1102 2065 * API error: Query limit exceeded.
1103 -**/
1104 -class DatafeedrLimitExceededError extends DatafeedrError
1105 -{
2066 + */
2067 +class DatafeedrLimitExceededError extends DatafeedrError {
1106 2068 }
1107 -}
1108 2069
1109 -if(!class_exists('DatafeedrHTTPError', false)) {
1110 2070 /**
2071 + * Class DatafeedrHTTPError.
2072 + *
1111 2073 * API error: Unspecified HTTP error.
1112 - **/
1113 -class DatafeedrHTTPError extends DatafeedrError
1114 -{
2074 + */
2075 +class DatafeedrHTTPError extends DatafeedrError {
1115 2076 }
2077 +
2078 +/**
2079 + * Class DatafeedrConnectionError.
2080 + *
2081 + * API error: Connection error.
2082 + */
2083 +class DatafeedrConnectionError extends DatafeedrError {
1116 2084 }
1117 2085
1118 -if(!class_exists('DatafeedrQueryError', false)) {
1119 2086 /**
2087 + * Class DatafeedrQueryError.
2088 + *
1120 2089 * API error: Error in the search query.
1121 -**/
1122 -class DatafeedrQueryError extends DatafeedrError
1123 -{
2090 + */
2091 +class DatafeedrQueryError extends DatafeedrError {
1124 2092 }
1125 -}
1126 2093
1127 -if(!class_exists('DatafeedrExternalError', false)) {
1128 2094 /**
2095 + * Class DatafeedrExternalError.
2096 + *
1129 2097 * API error: External service error.
1130 -**/
1131 -class DatafeedrExternalError extends DatafeedrError
1132 -{
2098 + */
2099 +class DatafeedrExternalError extends DatafeedrError {
1133 2100 }
2101 +
2102 +/**
2103 + * Class DatafeedrServerError.
2104 + *
2105 + * API error: Internal server error.
2106 + */
2107 +class DatafeedrServerError extends DatafeedrError {
1134 2108 }
1135 -
1136 -?>