PluginProbe
Datafeedr API / 1.0.78
Datafeedr API v1.0.78
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 1.0.33 All 181 releases
datafeedr-api / functions / api.php

api.php in Datafeedr API 1.0.78, at functions/api.php

641 lines 17.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 function dfrapi_api_get_status() {
4 $api = dfrapi_api( dfrapi_get_transport_method() );
5 try {
6 $status = $api->getStatus();
7 dfrapi_api_update_status( $api );
8 return $status;
9 } catch( Exception $err ) {
10 return dfrapi_api_error( $err );
11 }
12
13 }
14
15 /**
16 * Removed configuration. Always returns 'wordpress'. 2017-02-21 10:23:10
17 */
18 function dfrapi_get_transport_method() {
19 return 'wordpress';
20 // $configuration = (array) get_option( 'dfrapi_configuration' );
21 // $transport = ( isset( $configuration['transport_method'] ) ) ? $configuration['transport_method'] : $transport;
22 // return $transport;
23 }
24
25 /**
26 * This instantiates the Datafeedr API Library and returns the $api object.
27 */
28 function dfrapi_api( $transport='curl', $timeout=0, $returnObjects=FALSE ) {
29
30 $configuration = (array) get_option( 'dfrapi_configuration' );
31
32 if ( isset( $configuration['disable_api'] ) && ( $configuration['disable_api'] == 'yes' ) ) {
33 $configuration['disable_api'] = 'no';
34 update_option( 'dfrapi_configuration', $configuration );
35 }
36
37 $access_id = false;
38 $secret_key = false;
39 $transport = dfrapi_get_transport_method();
40
41 if ( isset( $configuration['access_id'] ) && ( $configuration['access_id'] != '' ) ) {
42 $access_id = $configuration['access_id'];
43 }
44
45 if ( isset( $configuration['secret_key'] ) && ( $configuration['secret_key'] != '' ) ) {
46 $secret_key = $configuration['secret_key'];
47 }
48
49 if ( $access_id && $secret_key ) {
50
51 $options = array(
52 'transport' => 'wordpress',
53 'timeout' => 60,
54 'returnObjects' => false,
55 'retry' => 0, // The number of retries if an API request times-out.
56 'retryTimeout' => 5, // The number of seconds to wait between retries.
57 );
58
59 $options = apply_filters( 'dfrapi_api_options', $options );
60
61 $api = new DatafeedrApi( $access_id, $secret_key, $options );
62
63 return $api;
64
65 } else {
66 return false;
67 }
68 }
69
70 /**
71 * Creates an associate array with the API's error details.
72 */
73 function dfrapi_api_error( $error, $params=FALSE ) {
74
75 // Change "request_count" to "max_requests" because sometimes there's
76 // not even enough API requests left to update the Account info with
77 // the most update to date information.
78 if ( $error->getCode() == 301 ) {
79 $account = get_option( 'dfrapi_account', array() );
80 $account['request_count'] = $account['max_requests'];
81 update_option( 'dfrapi_account', $account );
82 }
83
84 return array(
85 'dfrapi_api_error' => array(
86 'class' => get_class( $error ),
87 'code' => $error->getCode(),
88 'msg' => $error->getMessage(),
89 'params' => $params,
90 )
91 );
92 }
93
94 /**
95 * Creates the proper API request from the $query.
96 */
97 function dfrapi_api_query_to_filters( $query, $useSelected=TRUE ) {
98 $sform = new Dfrapi_SearchForm();
99 return $sform->makeFilters( $query, $useSelected );
100 }
101
102 /**
103 * Returns a parameter value from the $query array.
104 */
105 function dfrapi_api_get_query_param( $query, $param ) {
106 if ( is_array( $query ) && !empty( $query ) ) {
107 foreach( $query as $k => $v ) {
108 if ( $v['field'] == $param ) {
109 return array(
110 'field' => @$v['field'],
111 'operator' => @$v['operator'],
112 'value' => @$v['value'],
113 );
114 }
115 }
116 }
117 return false;
118 }
119
120 /**
121 * This updates the "dfrapi_account" option with the most recent
122 * API status information for this user.
123 */
124 function dfrapi_api_update_status( &$api ) {
125 if ( $status = $api->lastStatus() ) {
126 $account = get_option( 'dfrapi_account', array() );
127 $account['user_id'] = $status['user_id'];
128 $account['plan_id'] = $status['plan_id'];
129 $account['bill_day'] = $status['bill_day'];
130 $account['max_total'] = $status['max_total'];
131 $account['max_length'] = $status['max_length'];
132 $account['max_requests'] = $status['max_requests'];
133 $account['request_count'] = $status['request_count'];
134 $account['network_count'] = $status['network_count'];
135 $account['product_count'] = $status['product_count'];
136 $account['merchant_count'] = $status['merchant_count'];
137 update_option( 'dfrapi_account', $account );
138 }
139 }
140
141 /**
142 * This returns all affiliate networks' information.
143 * This accepts an array of source_ids (network ids)
144 * to return a subset of networks.
145 */
146 function dfrapi_api_get_all_networks( $nids=array() ) {
147 $option_name = 'dfrapi_all_networks';
148 $use_cache = wp_using_ext_object_cache( false );
149 $networks = get_transient( $option_name );
150 wp_using_ext_object_cache( $use_cache );
151 if ( false === $networks || empty ( $networks ) ) {
152 $api = dfrapi_api( dfrapi_get_transport_method() );
153 try {
154 $networks = $api->getNetworks( $nids, TRUE );
155 dfrapi_api_set_network_types( $networks );
156 dfrapi_api_update_status( $api );
157 } catch( Exception $err ) {
158 return dfrapi_api_error( $err );
159 }
160 $use_cache = wp_using_ext_object_cache( false );
161 set_transient( $option_name, $networks, DAY_IN_SECONDS );
162 wp_using_ext_object_cache( $use_cache );
163 }
164 dfrapi_update_transient_whitelist( $option_name );
165 return $networks;
166 }
167
168 /**
169 * Returns a Zanox zmid value.
170 */
171 function dfrapi_api_get_zanox_zmid( $merchant_id, $adspace_id ) {
172
173 $option_name = 'zmid_' . $merchant_id . '_' . $adspace_id;
174 $use_cache = wp_using_ext_object_cache( false );
175 $zmid = get_transient( $option_name );
176 wp_using_ext_object_cache( $use_cache );
177
178 if ( $zmid ) {
179 return $zmid;
180 }
181
182 $keys = dfrapi_get_zanox_keys();
183 $api = dfrapi_api();
184
185 try {
186 $zmid = $api->getZanoxMerchantIds(
187 $merchant_id,
188 $adspace_id,
189 $keys['connection_key']
190 );
191 } catch ( Exception $err ) {
192 $zmid = 'dfrapi_unapproved_zanox_merchant';
193 }
194
195 $use_cache = wp_using_ext_object_cache( false );
196 set_transient( $option_name, $zmid, WEEK_IN_SECONDS );
197 wp_using_ext_object_cache( $use_cache );
198
199 dfrapi_update_transient_whitelist( $option_name );
200
201 return $zmid;
202 }
203
204 /**
205 * Returns a Performance Horizon camref value.
206 */
207 function dfrapi_api_get_ph_camref( $merchant_id ) {
208
209 $option_name = 'camref_' . $merchant_id;
210 $use_cache = wp_using_ext_object_cache( false );
211 $camref = get_transient( $option_name );
212 wp_using_ext_object_cache( $use_cache );
213
214 if ( $camref ) {
215 return $camref;
216 }
217
218 $keys = dfrapi_get_ph_keys();
219 $api = dfrapi_api();
220
221 try {
222 $camref = $api->getPerformanceHorizonCamrefs(
223 $merchant_id,
224 $keys['application_key'],
225 $keys['user_api_key'],
226 $keys['publisher_id']
227 );
228 } catch ( Exception $err ) {
229 $camref = 'dfrapi_unapproved_ph_merchant';
230 }
231
232 $use_cache = wp_using_ext_object_cache( false );
233 set_transient( $option_name, $camref, WEEK_IN_SECONDS );
234 wp_using_ext_object_cache( $use_cache );
235
236 dfrapi_update_transient_whitelist( $option_name );
237
238 return $camref;
239 }
240
241 /**
242 * This creates 2 options in the options table each time the option
243 * "dfrapi_all_networks" is updated with new network information from the API.
244 *
245 * - dfrapi_product_networks
246 * - dfrapi_coupon_networks
247 *
248 * These are just helper options to figure out if a network is a "product"
249 * network or a "coupon" network.
250 */
251 function dfrapi_api_set_network_types( $networks ) {
252 $product_networks = array();
253 $coupon_networks = array();
254 foreach( $networks as $network ) {
255 if ( $network['type'] == 'products' ) {
256 $product_networks[$network['_id']] = $network;
257 } elseif ( $network['type'] == 'coupons' ) {
258 $coupon_networks[$network['_id']] = $network;
259 }
260 }
261 update_option( 'dfrapi_product_networks', $product_networks );
262 update_option( 'dfrapi_coupon_networks', $coupon_networks );
263 }
264
265 /**
266 * This stores all merchants for a given source_id ($nid).
267 *
268 * It is possible to pass "all" to this function however this creates
269 * memory_limit errors when memory is set to less than 64MB.
270 */
271 function dfrapi_api_get_all_merchants( $nid ) {
272 $option_name = 'dfrapi_all_merchants_for_nid_' . $nid;
273 $use_cache = wp_using_ext_object_cache( false );
274 $merchants = get_transient( $option_name );
275 wp_using_ext_object_cache( $use_cache );
276 if ( false === $merchants || empty ( $merchants ) ) {
277 $api = dfrapi_api( dfrapi_get_transport_method() );
278 try {
279 $merchants = $api->getMerchants( array( intval( $nid ) ), TRUE );
280 dfrapi_api_update_status( $api );
281 } catch( Exception $err ) {
282 return dfrapi_api_error( $err );
283 }
284 $use_cache = wp_using_ext_object_cache( false );
285 set_transient( $option_name, $merchants, DAY_IN_SECONDS );
286 wp_using_ext_object_cache( $use_cache );
287 }
288 dfrapi_update_transient_whitelist( $option_name );
289 return $merchants;
290 }
291
292 /**
293 * This retuns merchant or merchants' information by merchant_id or
294 * an array of merchant IDs.
295 */
296 function dfrapi_api_get_merchants_by_id( $ids, $includeEmpty=FALSE ) {
297 $name = false;
298 if ( is_array( $ids ) ) {
299 sort( $ids, SORT_NUMERIC );
300 $id_string = implode( ",", $ids );
301 $name = md5( $id_string );
302 } elseif ( $ids != '' ) {
303 $name = trim( $ids );
304 }
305 if ( !$name ) { return; }
306 $name = substr( $name, 0, 20 );
307 $option_name = 'dfrapi_merchants_byid_' . $name;
308 $use_cache = wp_using_ext_object_cache( false );
309 $merchants = get_transient( $option_name );
310 wp_using_ext_object_cache( $use_cache );
311 if ( false === $merchants || empty ( $merchants ) ) {
312 $api = dfrapi_api( dfrapi_get_transport_method() );
313 try {
314 $merchants = $api->getMerchantsById( $ids, $includeEmpty );
315 dfrapi_api_update_status( $api );
316 } catch( Exception $err ) {
317 return dfrapi_api_error( $err );
318 }
319 $use_cache = wp_using_ext_object_cache( false );
320 set_transient( $option_name, $merchants, DAY_IN_SECONDS );
321 wp_using_ext_object_cache( $use_cache );
322 }
323 dfrapi_update_transient_whitelist( $option_name );
324 return $merchants;
325 }
326
327 /**
328 * Returns a $response array containing:
329 * - ids: the query passed to the function.
330 * - products: array of products.
331 * - last_status: value of $api->lastStatus().
332 * - found_count: value of $search->getFoundCount().
333 *
334 * If the API throws an exception, that will return dfrapi_api_error( $err );
335 *
336 * @param array $ids An array of product IDs.
337 * @param int $ppp The number of products to return in 1 API request. Max is dictated by API, not plugin.
338 * @param int $page The page number for returning products. This is used to figure the offset.
339 */
340 function dfrapi_api_get_products_by_id( $ids, $ppp=20, $page=1 ) {
341
342 $response = array();
343
344 // Return false if no $ids or no $postid
345 if ( empty( $ids ) ) { return $response; }
346
347 // Make sure $page is a positive integer.
348 $page = intval( abs( $page ) );
349
350 // Make sure $ppp is a positive integer.
351 $ppp = intval( abs( $ppp ) );
352
353 // Make sure $ppp is not greater than "max_length".
354 $account = (array) get_option( 'dfrapi_account' );
355 if ( $ppp > $account['max_length'] ) {
356 $ppp = $account['max_length'];
357 }
358
359 // The maximum number of results a request to the API can return.
360 // Changing this will only break your site. It's not overridable.
361 $max_total = $account['max_total'];
362
363 // Determine offset.
364 $offset = ( ( $page - 1 ) * $ppp );
365
366 // Make sure $limit doesn't go over 10,000.
367 if ( ( $offset + $ppp ) > $max_total ) {
368 $ppp = ( $max_total - $offset );
369 }
370
371 // If $ppp is negative, return empty array();
372 if ( $ppp < 1 ) {
373 return array();
374 }
375
376 // If offset is greater than 10,000 return empty array();
377 if ( $offset >= ( $max_total - $ppp ) ) {
378 return array();
379 }
380
381 try {
382
383 // Initialize API.
384 $api = dfrapi_api( dfrapi_get_transport_method() );
385 if ( ! $api ) {
386 return $response;
387 }
388
389 // Get a range of product IDs to query.
390 $id_range = array_slice( $ids, $offset, $ppp );
391
392 // Return immediately if $id_range is empty.
393 if ( empty( $id_range ) ) {
394 $response['ids'] = array();
395 $response['products'] = array();
396 $response['last_status'] = $api->lastStatus();
397 $response['found_count'] = 0;
398
399 return $response;
400 }
401
402 // Begin query
403 $search = $api->searchRequest();
404
405 // Get filters
406 $filters = dfrapi_api_query_to_filters( array() );
407 if ( isset( $filters['error'] ) ) {
408 throw new DatafeedrError( $filters['error'], 0 );
409 }
410
411 // Loop thru filters.
412 foreach ( $filters as $filter ) {
413 $search->addFilter( $filter );
414 }
415
416 $search->addFilter( 'id IN ' . implode( ",", $id_range ) );
417 $search->setLimit( $ppp );
418 $products = $search->execute();
419
420 // Keep track of IDs which were returned via the API to compare with $id_range (unreturned)
421 $included_ids = array();
422 if ( ! empty( $products ) ) {
423 foreach ( $products as $product ) {
424 $included_ids[] = $product['_id'];
425 }
426 }
427
428 // Excluded product IDs.
429 $excluded_ids = array_diff( $id_range, $included_ids );
430
431 // Add "message" values to excluded IDs if there are some.
432 $excluded_products = array();
433 if ( ! empty( $included_ids ) && ! empty( $excluded_ids ) ) {
434 foreach ( $excluded_ids as $excluded_id ) {
435
436 $wc_url = add_query_arg(
437 array(
438 's' => $excluded_id,
439 'post_status' => 'trash',
440 'post_type' => 'product',
441 ),
442 admin_url( 'edit.php' )
443 );
444
445 // Do not add a 'url' field to this array or the unavailable product WILL be imported.
446 // See /datafeedr-product-sets/classes/class-dfrps-update.php:73
447 $excluded_products[] = array(
448 '_id' => $excluded_id,
449 '_wc_url' => $wc_url,
450 'name' => $excluded_id . ' - ' . __( 'Unavailable', DFRAPI_DOMAIN ),
451 'price' => 0,
452 'finalprice' => 0,
453 'description' => __( 'This product is either temporarily or permanently unavailable.', DFRAPI_DOMAIN ),
454 'image' => DFRAPI_URL . 'images/icons/noimage.png',
455 'merchant' => 'n/a',
456 'source' => 'n/a',
457 );
458 }
459 }
460
461 // Update API status
462 dfrapi_api_update_status( $api );
463
464 // Build $response array().
465 $response['ids'] = $ids;
466 $response['products'] = array_merge( $products, $excluded_products );
467 $response['last_status'] = $api->lastStatus();
468 $response['found_count'] = count( $ids );
469 $response['params'] = $search->getParams();
470
471 // Return it!
472 return $response;
473
474 } catch( Exception $err ) {
475 return dfrapi_api_error( $err );
476 }
477 }
478
479 /**
480 * Returns a $response array containing:
481 * - query: the query passed to the function.
482 * - excluded: ids of excluded products.
483 * - products: array of products.
484 * - last_status: value of $api->lastStatus().
485 * - found_count: value of $search->getFoundCount().
486 * - params: value of $search->getParams().
487 *
488 * Example of $query array():
489 *
490 *
491 * $query[] = array(
492 * 'value' => 'shoes',
493 * 'field' => 'any',
494 * 'operator' => 'contain'
495 * );
496 *
497 * $query[] = array(
498 * 'value' => 'image',
499 * 'field' => 'duplicates',
500 * 'operator' => 'is'
501 * );
502 *
503 * $query[] = array(
504 * 'field' => 'sort',
505 * 'operator' => '+saleprice'
506 * );
507 *
508 *
509 * If the API throws an exception, that will return dfrapi_api_error( $err, $params );
510 *
511 * @param array $query The complete query to pass to the API.
512 * @param int $ppp The number of products to return in 1 API request. Max is dictated by API, not plugin.
513 * @param int $page The page number for returning products. This is used to figure the offset.
514 * @param array $excluded An array of product IDs to exclude from being returned.
515 */
516 function dfrapi_api_get_products_by_query( $query, $ppp=20, $page=1, $excluded=array() ) {
517
518 $response = array();
519
520 // Return false if no $query.
521 if ( empty( $query ) ) { return $response; }
522
523 // Make sure $page is a positive integer.
524 $page = intval( abs( $page ) );
525
526 // Make sure $ppp is a positive integer.
527 $ppp = intval( abs( $ppp ) );
528
529 // Make sure $ppp is not greater than "max_length".
530 $account = (array) get_option( 'dfrapi_account' );
531 if ( $ppp > $account['max_length'] ) {
532 $ppp = $account['max_length'];
533 }
534
535 // The maximum number of results a request to the API can return.
536 // Changing this will only break your site. It's not overridable.
537 $max_total = $account['max_total'];
538
539 // Detemine query limit (if exists).
540 $query_limit = dfrapi_api_get_query_param( $query, 'limit' );
541 $query_limit = ( $query_limit )
542 ? $query_limit['value']
543 : false;
544
545 // No query shall try to return more than 10,000 products.
546 if ( $query_limit && ( $query_limit > $max_total ) ) {
547 $query_limit = $max_total;
548 }
549
550 // Determine offset.
551 $offset = ( ( $page - 1 ) * $ppp );
552
553 // If offset is greater than 10,000 return empty array();
554 if ( $offset >= $max_total ) {
555 return array();
556 }
557
558 // Factor in query limit
559 if ( $query_limit ) {
560 if ( ( $ppp + $offset ) > $query_limit ) {
561 $ppp = ( $query_limit - $offset );
562 }
563 }
564
565 // Make sure $limit doesn't go over 10,000.
566 if ( ( $offset + $ppp ) > $max_total ) {
567 $ppp = ( $max_total - $offset );
568 }
569
570 // If $ppp is negative, return empty array();
571 if ( $ppp < 1 ) {
572 return $response;
573 }
574
575 try {
576
577 // Initialize API.
578 $api = dfrapi_api( dfrapi_get_transport_method() );
579 if ( !$api ) { return $response; }
580
581 $search = $api->searchRequest();
582
583 // Get filters
584 $filters = dfrapi_api_query_to_filters( $query );
585 if(isset($filters['error'])) {
586 throw new DatafeedrError($filters['error'], 0);
587 }
588
589 // Loop thru filters.
590 foreach ( $filters as $filter ) {
591 $search->addFilter( $filter );
592 }
593
594 // Exclude duplicates.
595 $duplicates = dfrapi_api_get_query_param( $query, 'duplicates' );
596 if ( $duplicates ) {
597 $excludes = $duplicates['value'];
598 $search->excludeDuplicates( $excludes );
599 }
600
601 // Exclude blocked products.
602 $excluded = (array) $excluded;
603 if ( !empty( $excluded ) ) {
604 $search->addFilter('id !IN ' . implode( ",", $excluded ) );
605 }
606
607 // Sort products.
608 $sort = dfrapi_api_get_query_param( $query, 'sort' );
609 if( $sort && strlen( $sort['operator'] ) ) {
610 $search->addSort( $sort['operator'] );
611 }
612
613 // Set limits and offset.
614 $search->setLimit( $ppp );
615 $search->setOffset( $offset );
616
617 // Execute query.
618 $products = $search->execute();
619
620 // Update API status
621 dfrapi_api_update_status( $api );
622
623 // Build $response array().
624 $response['query'] = $query;
625 $response['excluded'] = $excluded;
626 $response['products'] = $products;
627 $response['last_status'] = $api->lastStatus();
628 //$response['found_count'] = $search->getFoundCount(); Old, returned wrong value (#8672)
629 $response['found_count'] = $search->getResultCount();
630 $response['params'] = $search->getParams();
631
632 // Return it!
633 return $response;
634
635 } catch( Exception $err ) {
636 $params = $search->getParams();
637 return dfrapi_api_error( $err, $params );
638
639 }
640 }
641