CTX Feed – WooCommerce Product Feed Manager Plugin - Version 4.4.63

Version Description

Download this release

Release Info

Developer wahid0003
Plugin Icon 128x128 CTX Feed – WooCommerce Product Feed Manager Plugin
Version 4.4.63
Comparing to
See all releases

Code changes from version 4.4.62 to 4.4.63

README.txt CHANGED
@@ -5,7 +5,7 @@ Tags: WooCommerce Product Feed, WooCommerce, Google Shopping, Google Merchant, F
5
  Requires at least: 4.4
6
  Tested Up To: 5.9
7
  Requires PHP: 5.6
8
- Stable tag: 4.4.62
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -590,6 +590,9 @@ Using pro version:
590
 
591
  == Changelog ==
592
 
 
 
 
593
  = 4.4.62 (2022-05-25) =
594
  * Fixed: Fixing autoload, SuperGlobal, and external links
595
 
5
  Requires at least: 4.4
6
  Tested Up To: 5.9
7
  Requires PHP: 5.6
8
+ Stable tag: 4.4.63
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
590
 
591
  == Changelog ==
592
 
593
+ = 4.4.62 (2022-05-26) =
594
+ * Added: added filter to secure input-output P1
595
+
596
  = 4.4.62 (2022-05-25) =
597
  * Fixed: Fixing autoload, SuperGlobal, and external links
598
 
admin/class-woo-feed-category-list.php CHANGED
@@ -335,16 +335,19 @@ class Woo_Feed_Category_list extends Woo_Feed_List_Table {
335
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
336
  }
337
  }
338
-
 
 
 
339
  // If the delete bulk action is triggered
340
- if ( ( isset( $_POST['mapping'] ) ) && ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) || ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] ) ) {
341
  if ( 'bulk-delete' === $this->current_action() ) {
342
  if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
343
  update_option( 'wpf_message', esc_html__( 'Failed To Delete Mapping. You do not have sufficient permission to delete.', 'woo-feed' ), false );
344
  wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=error' ) );
345
  die();
346
  } else {
347
- $delete_ids = array_map( 'absint', $_POST['mapping'] );
348
  $delete_ids = array_filter( $delete_ids );
349
  // loop over the array of record IDs and delete them
350
  if ( ! empty( $delete_ids ) ) {
335
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
336
  }
337
  }
338
+ $mapping = array_map( 'sanitize_text_field', isset( $_POST['mapping'] ) && is_array($_POST['mapping']) ? $_POST['mapping'] : [] );
339
+ $action = sanitize_text_field( isset( $_POST['action'] ) ? $_POST['action'] : '' ) ;
340
+ $action2 = sanitize_text_field( isset( $_POST['action2'] ) ? $_POST['action2'] : '' );
341
+
342
  // If the delete bulk action is triggered
343
+ if ( ! empty($mapping) && ( 'bulk-delete' === $action || 'bulk-delete' === $action2 )) {
344
  if ( 'bulk-delete' === $this->current_action() ) {
345
  if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
346
  update_option( 'wpf_message', esc_html__( 'Failed To Delete Mapping. You do not have sufficient permission to delete.', 'woo-feed' ), false );
347
  wp_safe_redirect( admin_url( 'admin.php?page=webappick-feed-category-mapping&wpf_message=error' ) );
348
  die();
349
  } else {
350
+ $delete_ids = array_map( 'absint', $mapping );
351
  $delete_ids = array_filter( $delete_ids );
352
  // loop over the array of record IDs and delete them
353
  if ( ! empty( $delete_ids ) ) {
admin/class-woo-feed-manage-list.php CHANGED
@@ -424,15 +424,19 @@ class Woo_Feed_Manage_list extends Woo_Feed_List_Table {
424
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
425
  }
426
  }
427
-
 
 
 
 
428
  // If the delete bulk action is triggered
429
- if ( ( isset( $_POST['feed'] ) ) && ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) || ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] ) ) {
430
  if ( 'bulk-delete' === $this->current_action() ) {
431
  $nonce = isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash($_REQUEST['_wpnonce']) ) : '';
432
  if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
433
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
434
  } else {
435
- $delete_ids = array_map( 'absint', $_POST['feed'] );
436
  $delete_ids = array_filter( $delete_ids );
437
  // loop over the array of record IDs and delete them
438
  if ( ! empty( $delete_ids ) ) {
424
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
425
  }
426
  }
427
+
428
+ $feed = array_map( 'sanitize_text_field', isset( $_POST['feed'] ) && is_array($_POST['feed']) ? $_POST['feed'] : [] );
429
+ $action = sanitize_text_field( isset( $_POST['action'] ) ? $_POST['action'] : '' ) ;
430
+ $action2 = sanitize_text_field( isset( $_POST['action2'] ) ? $_POST['action2'] : '' );
431
+
432
  // If the delete bulk action is triggered
433
+ if ( ! empty($feed) && ( 'bulk-delete' === $action || 'bulk-delete' === $action2) ) {
434
  if ( 'bulk-delete' === $this->current_action() ) {
435
  $nonce = isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash($_REQUEST['_wpnonce']) ) : '';
436
  if ( ! wp_verify_nonce( $nonce, 'bulk-' . $this->_args['plural'] ) ) {
437
  wp_die( esc_html__( 'You do not have sufficient permission to delete!', 'woo-feed' ), 403 );
438
  } else {
439
+ $delete_ids = array_map( 'absint', $feed );
440
  $delete_ids = array_filter( $delete_ids );
441
  // loop over the array of record IDs and delete them
442
  if ( ! empty( $delete_ids ) ) {
admin/class-woo-feed-option-list.php CHANGED
@@ -337,18 +337,13 @@ class Woo_Feed_Option_list extends Woo_Feed_List_Table {
337
  }
338
  }
339
 
 
 
 
340
  // If the delete bulk action is triggered
341
  if (
342
- (
343
- isset( $_POST['option'] ) ) &&
344
- (
345
- isset( $_POST['action'] ) &&
346
- 'bulk-delete' == $_POST['action']
347
- ) ||
348
- (
349
- isset( $_POST['action2'] ) &&
350
- 'bulk-delete' == $_POST['action2']
351
- )
352
  ) {
353
  if ( 'bulk-delete' === $this->current_action() ) {
354
  $nonce = isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : '';
@@ -358,7 +353,7 @@ class Woo_Feed_Option_list extends Woo_Feed_List_Table {
358
  die();
359
  } else {
360
  // loop over the array of record IDs and delete them
361
- $delete_ids = array_map( 'absint', $_POST['option'] );
362
  $delete_ids = array_filter( $delete_ids );
363
  // loop over the array of record IDs and delete them
364
  if ( ! empty( $delete_ids ) ) {
337
  }
338
  }
339
 
340
+ $option = array_map( 'sanitize_text_field', isset( $_POST['option'] ) && is_array($_POST['option']) ? $_POST['option'] : [] );
341
+ $action = sanitize_text_field( isset( $_POST['action'] ) ? $_POST['action'] : '' ) ;
342
+ $action2 = sanitize_text_field( isset( $_POST['action2'] ) ? $_POST['action2'] : '' );
343
  // If the delete bulk action is triggered
344
  if (
345
+ ! empty( $option )
346
+ && ( 'bulk-delete' == $action || 'bulk-delete' == $action2 )
 
 
 
 
 
 
 
 
347
  ) {
348
  if ( 'bulk-delete' === $this->current_action() ) {
349
  $nonce = isset( $_REQUEST['_wpnonce'] ) && ! empty( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( $_REQUEST['_wpnonce'] ) : '';
353
  die();
354
  } else {
355
  // loop over the array of record IDs and delete them
356
+ $delete_ids = array_map( 'absint', $option );
357
  $delete_ids = array_filter( $delete_ids );
358
  // loop over the array of record IDs and delete them
359
  if ( ! empty( $delete_ids ) ) {
admin/js/woo-feed-admin.js CHANGED
@@ -1332,7 +1332,7 @@
1332
 
1333
  .on('change', '#category-mapping-form #providers', function() {
1334
  var provider = $(this).find(':selected').val(),
1335
- googleMap = ['google', 'facebook', 'pinterest', 'bing', 'bing_local_inventory', 'snapchat'];
1336
 
1337
  //add snipper element
1338
  $('.woo-feed-category-mapping-config-table').prepend('<div class="woo-feed-cat-map-spinner"><h3><span style="float:none;margin: -3px 0 0;" class="spinner is-active"></span> Loading Mapping...</h3></div>');
@@ -1358,7 +1358,7 @@
1358
  .on('click', 'span[id*="cat-map-"]', function(e) {
1359
  e.preventDefault();
1360
  var providerName = $('#category-mapping-form #providers').val(),
1361
- googleMap = ['google', 'facebook', 'pinterest', 'bing', 'bing_local_inventory', 'snapchat'],
1362
  catId = $(this).attr('id').replace(/[^\d.]/g, ''),
1363
  groupId = 'group-child-' + catId;
1364
 
@@ -1489,7 +1489,12 @@
1489
  }
1490
 
1491
  $(document).on('feedEditor.init', function(){
1492
- update_postfix();
 
 
 
 
 
1493
  });
1494
 
1495
  });
1332
 
1333
  .on('change', '#category-mapping-form #providers', function() {
1334
  var provider = $(this).find(':selected').val(),
1335
+ googleMap = ['google', 'facebook', 'pinterest', 'bing', 'bing_local_inventory', 'snapchat','tiktok'];
1336
 
1337
  //add snipper element
1338
  $('.woo-feed-category-mapping-config-table').prepend('<div class="woo-feed-cat-map-spinner"><h3><span style="float:none;margin: -3px 0 0;" class="spinner is-active"></span> Loading Mapping...</h3></div>');
1358
  .on('click', 'span[id*="cat-map-"]', function(e) {
1359
  e.preventDefault();
1360
  var providerName = $('#category-mapping-form #providers').val(),
1361
+ googleMap = ['google', 'facebook', 'pinterest', 'bing', 'bing_local_inventory', 'snapchat','tiktok'],
1362
  catId = $(this).attr('id').replace(/[^\d.]/g, ''),
1363
  groupId = 'group-child-' + catId;
1364
 
1489
  }
1490
 
1491
  $(document).on('feedEditor.init', function(){
1492
+ let provider = $(this).find(':selected').val(),
1493
+ googleMap = ['google', 'facebook', 'pinterest', 'bing', 'bing_local_inventory', 'snapchat','tiktok'];
1494
+
1495
+ if( googleMap.indexOf(provider) !== -1 ) {
1496
+ update_postfix();
1497
+ }
1498
  });
1499
 
1500
  });
admin/partials/templates/shopflix.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <MPITEMS>
3
+ <created_at>{DateTimeNow}</created_at>
4
+ <products>
5
+ {separator}
6
+ </products>
7
+ </MPITEMS>
admin/partials/woo-feed-pro-vs-free.php CHANGED
@@ -162,7 +162,7 @@ ob_start(); ?>
162
  <div class="wapk-feed-buy-now-wrapper">
163
  <div class="wapk-feed-buy-now-product-container">
164
  <div class="wapk-feed-buy-now-thumbnail">
165
- <img src="https://webappick.com/staging/wp-content/uploads/2016/10/woo-feed-icon.svg" alt="CTX Feed Pro" />
166
  </div>
167
  <div class="wapk-feed-buy-now-title">
168
  <div class="wapk-feed-buy-now-product-name"><?php esc_attr_e('CTX Feed Pro', 'woo-feed');?></div>
162
  <div class="wapk-feed-buy-now-wrapper">
163
  <div class="wapk-feed-buy-now-product-container">
164
  <div class="wapk-feed-buy-now-thumbnail">
165
+ <img src="<?php echo WOO_FEED_PRO_ADMIN_URL; ?>images/woo-feed-icon.svg" alt="CTX Feed Pro" />
166
  </div>
167
  <div class="wapk-feed-buy-now-title">
168
  <div class="wapk-feed-buy-now-product-name"><?php esc_attr_e('CTX Feed Pro', 'woo-feed');?></div>
includes/Tracker/Base.php CHANGED
@@ -61,7 +61,8 @@ abstract Class Base{
61
 
62
  if ( is_product() ) {
63
  $event = 'product_view';
64
- if ( isset( $_POST['add-to-cart'] ) ) {
 
65
  $event = 'add_to_cart';
66
  }
67
  } elseif ( is_wc_endpoint_url('order-received') ) {
61
 
62
  if ( is_product() ) {
63
  $event = 'product_view';
64
+ $add_to_cart = sanitize_text_field( $_POST['add-to-cart'] );
65
+ if ( ! empty($addToCart) ) {
66
  $event = 'add_to_cart';
67
  }
68
  } elseif ( is_wc_endpoint_url('order-received') ) {
includes/Tracker/Facebook/Pixel.php CHANGED
@@ -156,8 +156,10 @@ class Pixel extends Base{
156
  */
157
  public function product_add_to_cart_data(){
158
  $data = [];
159
- if ( isset($_POST['product_id']) ) {
160
- $product_id = intval( esc_attr( $_POST['product_id'] ) );
 
 
161
  $_product = wc_get_product( $product_id );
162
 
163
  $data = [
156
  */
157
  public function product_add_to_cart_data(){
158
  $data = [];
159
+
160
+ $product_id = sanitize_text_field( isset( $_POST['product_id'] ) ? $_POST['product_id'] : '' );
161
+ if ( ! empty($product_id) ) {
162
+ $product_id = intval( esc_attr( $product_id ) );
163
  $_product = wc_get_product( $product_id );
164
 
165
  $data = [
includes/classes/class-woo-feed-constants.php CHANGED
@@ -23,7 +23,7 @@ if( ! class_exists("Woo_Feed_Constants") ) {
23
  * @var string
24
  * @since 3.1.6
25
  */
26
- define( 'WOO_FEED_FREE_VERSION', '4.4.62' );
27
  }
28
 
29
  if ( ! defined( 'WOO_FEED_FREE_PATH' ) ) {
23
  * @var string
24
  * @since 3.1.6
25
  */
26
+ define( 'WOO_FEED_FREE_VERSION', '4.4.63' );
27
  }
28
 
29
  if ( ! defined( 'WOO_FEED_FREE_PATH' ) ) {
includes/classes/class-woo-feed-default-attributes.php CHANGED
@@ -51,6 +51,7 @@ class Woo_Feed_Default_Attributes {
51
  'upc' => array( 'gtin', true ),
52
  'identifier_exists' => array( 'identifier exists', true ),
53
  'item_group_id' => array( 'item group id', false ),
 
54
  'product_length' => array( 'product length', true ),
55
  'product_width' => array( 'product width', true ),
56
  'product_height' => array( 'product height', true ),
@@ -172,6 +173,7 @@ class Woo_Feed_Default_Attributes {
172
  'upc' => array( 'g:gtin', true ),
173
  'identifier_exists' => array( 'g:identifier_exists', true ),
174
  'item_group_id' => array( 'g:item_group_id', false ),
 
175
  'product_length' => array( 'g:product_length', true ),
176
  'product_width' => array( 'g:product_width', true ),
177
  'product_height' => array( 'g:product_height', true ),
@@ -683,6 +685,7 @@ class Woo_Feed_Default_Attributes {
683
  '---3' => '',
684
  '--4' => 'Detailed Product Attributes',
685
  'item_group_id' => 'Item Group Id[item_group_id]',
 
686
  'color' => 'Color[color]',
687
  'gender' => 'Gender[gender]',
688
  'age_group' => 'Age Group[age_group]',
51
  'upc' => array( 'gtin', true ),
52
  'identifier_exists' => array( 'identifier exists', true ),
53
  'item_group_id' => array( 'item group id', false ),
54
+ 'external_seller_id' => array( 'external seller id', false ),
55
  'product_length' => array( 'product length', true ),
56
  'product_width' => array( 'product width', true ),
57
  'product_height' => array( 'product height', true ),
173
  'upc' => array( 'g:gtin', true ),
174
  'identifier_exists' => array( 'g:identifier_exists', true ),
175
  'item_group_id' => array( 'g:item_group_id', false ),
176
+ 'external_seller_id' => array( 'g:external_seller_id', false ),
177
  'product_length' => array( 'g:product_length', true ),
178
  'product_width' => array( 'g:product_width', true ),
179
  'product_height' => array( 'g:product_height', true ),
685
  '---3' => '',
686
  '--4' => 'Detailed Product Attributes',
687
  'item_group_id' => 'Item Group Id[item_group_id]',
688
+ 'external_seller_id' => 'External seller ID[external_seller_id]',
689
  'color' => 'Color[color]',
690
  'gender' => 'Gender[gender]',
691
  'age_group' => 'Age Group[age_group]',
includes/classes/class-woo-feed-dropdown.php CHANGED
@@ -708,6 +708,14 @@ class Woo_Feed_Dropdown {
708
  $attributes['---54'] = '';
709
  }
710
 
 
 
 
 
 
 
 
 
711
  // Custom Fields & Post Metas
712
  $_meta_keys = $this->getProductMetaKeys();
713
  if ( ! empty( $_meta_keys ) && is_array( $_meta_keys ) ) {
708
  $attributes['---54'] = '';
709
  }
710
 
711
+ // ACF Plugin custom fields
712
+ $_acf_fields = woo_feed_get_acf_field_list();
713
+ if ( ! empty( $_acf_fields ) && is_array( $_acf_fields ) ) {
714
+ $attributes['--98'] = esc_html__( 'Advance Custom Fields (ACF)', 'woo-feed' );
715
+ $attributes += $_acf_fields;
716
+ $attributes['---98'] = '';
717
+ }
718
+
719
  // Custom Fields & Post Metas
720
  $_meta_keys = $this->getProductMetaKeys();
721
  if ( ! empty( $_meta_keys ) && is_array( $_meta_keys ) ) {
includes/classes/class-woo-feed-merchant.php CHANGED
@@ -425,6 +425,7 @@ class Woo_Feed_Merchant {
425
  'shopbot' => esc_html__( 'Shopbot', 'woo-feed' ),
426
  'shopmania' => esc_html__( 'Shopmania', 'woo-feed' ),
427
  'shopping' => esc_html__( 'Shopping.com', 'woo-feed' ),
 
428
  'shopzilla' => esc_html__( 'Shopzilla', 'woo-feed' ),
429
  'skinflint.co.uk' => esc_html__( 'SkinFlint.co.uk', 'woo-feed' ),
430
  'skroutz' => esc_html__( 'Skroutz.gr', 'woo-feed' ),
425
  'shopbot' => esc_html__( 'Shopbot', 'woo-feed' ),
426
  'shopmania' => esc_html__( 'Shopmania', 'woo-feed' ),
427
  'shopping' => esc_html__( 'Shopping.com', 'woo-feed' ),
428
+ 'shopflix' => esc_html__( 'Shopflix (WellComm)', 'woo-feed' ),
429
  'shopzilla' => esc_html__( 'Shopzilla', 'woo-feed' ),
430
  'skinflint.co.uk' => esc_html__( 'SkinFlint.co.uk', 'woo-feed' ),
431
  'skroutz' => esc_html__( 'Skroutz.gr', 'woo-feed' ),
includes/classes/class-woo-feed-products-v3.php CHANGED
@@ -9,8 +9,8 @@
9
 
10
  use RankMath\Helper;
11
 
12
- if ( ! defined('ABSPATH') ) {
13
- die();
14
  }
15
 
16
  /**
@@ -18,4308 +18,4471 @@ if ( ! defined('ABSPATH') ) {
18
  */
19
  class Woo_Feed_Products_v3
20
  {
21
- /**
22
- * The Increment
23
- * @var int
24
- */
25
- protected $pi = 0;
26
- /**
27
- * Feed file headers
28
- *
29
- * @var string|array
30
- */
31
- public $feedHeader;
32
- /**
33
- * Feed File Body
34
- *
35
- * @var string|array
36
- */
37
- public $feedBody;
38
- /**
39
- * Feed file footer
40
- *
41
- * @var string|array
42
- */
43
- public $feedFooter;
44
- /**
45
- * CSV|TXT column (text|word) enclosure
46
- *
47
- * @var string
48
- */
49
- protected $enclosure;
50
- /**
51
- * CSV|TXT column delimiter
52
- *
53
- * @var string
54
- */
55
- protected $delimiter;
56
- /**
57
- * Feed Rules
58
- *
59
- * @var array
60
- */
61
- protected $config;
62
- /**
63
- * Post status to query
64
- *
65
- * @var string
66
- */
67
- protected $post_status = 'publish';
68
- /**
69
- * Processed Products
70
- *
71
- * @var array
72
- */
73
- public $products = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- /**
77
- * Products IDs
78
- *
79
- * @var array
80
- */
81
- public $product_ids = [];
82
 
83
- /**
84
- * Feed Big Data
85
- *
86
- * @var array
87
- */
88
- public $data = [];
89
 
90
- /**
91
- * Processed Products
92
- *
93
- * @var array
94
- */
95
- public $product_types = [
96
- 'simple',
97
- 'variable',
98
- 'variation',
99
- 'grouped',
100
- 'external',
101
- 'composite',
102
- 'bundle',
103
- 'bundled',
104
- 'yith_bundle',
105
- 'yith-composite',
106
- 'subscription',
107
- 'variable-subscription',
108
- 'woosb',
109
- ];
110
- /**
111
- * Query Method Selector
112
- *
113
- * @var string
114
- */
115
- protected $queryType = 'wp';
116
- /**
117
- * To replace google product highlight attribute for CSV & TXT feed
118
- * @var array
119
- */
120
- protected $google_product_highlights = array(
121
- 'product highlight 1',
122
- 'product highlight 2',
123
- 'product highlight 3',
124
- 'product highlight 4',
125
- 'product highlight 5',
126
- 'product highlight 6',
127
- 'product highlight 7',
128
- 'product highlight 8',
129
- 'product highlight 9',
130
- 'product highlight 10',
131
- );
132
-
133
- /**
134
- * To replace google additional image link attribute for CSV & TXT feed
135
- * @var array
136
- */
137
- protected $google_additional_image = array(
138
- 'additional image link 1',
139
- 'additional image link 2',
140
- 'additional image link 3',
141
- 'additional image link 4',
142
- 'additional image link 5',
143
- 'additional image link 6',
144
- 'additional image link 7',
145
- 'additional image link 8',
146
- 'additional image link 9',
147
- 'additional image link 10',
148
- );
149
- /**
150
- * Google shipping tax attributes
151
- * @var array
152
- */
153
- /**
154
- * Google shipping tax attributes
155
- *
156
- * @var array
157
- */
158
- protected $google_shipping_tax = array(
159
- 'shipping_country',
160
- 'shipping_region',
161
- 'shipping_postal_code',
162
- 'shipping_service',
163
- 'shipping_price',
164
- 'min_handling_time',
165
- 'max_handling_time',
166
- 'min_transit_time',
167
- 'max_transit_time',
168
- 'tax',
169
- 'tax_country',
170
- 'tax_region',
171
- 'tax_rate',
172
- 'tax_ship',
173
- 'installment_months',
174
- 'installment_amount',
175
- 'subscription_period',
176
- 'subscription_period_length',
177
- 'subscription_amount',
178
- 'section_name',
179
- 'attribute_name',
180
- 'attribute_value',
181
- 'unit_price_value',
182
- 'unit_price_currency',
183
- 'unit_price_unit',
184
- 'additional_variant_label',
185
- 'additional_variant_value',
186
- );
187
- /**
188
- * XML Wrapper Array
189
- * Contains 'header' and 'footer' for template.
190
- * @var array
191
- */
192
- protected $xml_wrapper = [];
193
-
194
-
195
- /**
196
- * Attribute to skip in attribute loop for processing separately
197
- *
198
- * @var array
199
- */
200
- protected $skipped_merchant_attributes = array(
201
- 'google' => array(
202
- 'shipping_country',
203
- 'shipping_region',
204
- 'shipping_postal_code',
205
- 'shipping_service',
206
- 'shipping_price',
207
- 'min_handling_time',
208
- 'max_handling_time',
209
- 'min_transit_time',
210
- 'max_transit_time',
211
- 'tax_country',
212
- 'tax_region',
213
- 'tax_rate',
214
- 'tax_ship',
215
- 'installment_months',
216
- 'installment_amount',
217
- 'subscription_period',
218
- 'subscription_period_length',
219
- 'subscription_amount',
220
- 'section_name',
221
- 'attribute_name',
222
- 'attribute_value',
223
- ),
224
- 'facebook' => array(
225
- 'shipping_country',
226
- 'shipping_region',
227
- 'shipping_service',
228
- 'shipping_price',
229
- 'tax_country',
230
- 'tax_region',
231
- 'tax_rate',
232
- 'tax_ship',
233
- 'installment_months',
234
- 'installment_amount',
235
- 'subscription_period',
236
- 'subscription_period_length',
237
- 'subscription_amount',
238
- 'section_name',
239
- 'attribute_name',
240
- 'attribute_value',
241
- 'unit_price_value',
242
- 'unit_price_currency',
243
- 'unit_price_unit',
244
- 'additional_variant_label',
245
- 'additional_variant_value',
246
- ),
247
- 'bing' => array(
248
- 'shipping_country',
249
- 'shipping_service',
250
- 'shipping_price',
251
- ),
252
- 'pinterest' => array(
253
- 'shipping_country',
254
- 'shipping_service',
255
- 'shipping_price',
256
- 'shipping_region',
257
- 'shipping_postal_code',
258
- 'tax_country',
259
- 'tax_region',
260
- 'tax_rate',
261
- 'tax_ship',
262
- ),
263
- );
264
-
265
- /**
266
- * Already Processed merchant attributes by the attribute loop
267
- * this will ensure unique merchant attribute.
268
- * @see Woo_Feed_Products_v::exclude_current_attribute()
269
- * @var array
270
- */
271
- protected $processed_merchant_attributes = array();
272
-
273
-
274
- /**
275
- * Post meta prefix for dropdown item
276
- * @since 3.1.18
277
- * @var string
278
- */
279
- const POST_META_PREFIX = 'wf_cattr_';
280
-
281
- /**
282
- * Product Attribute (taxonomy & local) Prefix
283
- * @since 3.1.18
284
- * @var string
285
- */
286
- const PRODUCT_ATTRIBUTE_PREFIX = 'wf_attr_';
287
-
288
- /**
289
- * Product Taxonomy Prefix
290
- * @since 3.1.18
291
- * @var string
292
- */
293
- const PRODUCT_TAXONOMY_PREFIX = 'wf_taxo_';
294
-
295
- /**
296
- * Product Custom Field Prefix
297
- *
298
- * @since 3.1.18
299
- * @var string
300
- */
301
- const PRODUCT_CUSTOM_IDENTIFIER = 'woo_feed_';
302
-
303
- /**
304
- * Product Category Mapping Prefix
305
- * @since 3.1.18
306
- * @var string
307
- */
308
- const PRODUCT_CATEGORY_MAPPING_PREFIX = 'wf_cmapping_';
309
-
310
- /**
311
- * WordPress Option Prefix
312
- *
313
- * @since 4.3.33
314
- * @var string
315
- * @author Nazrul Islam Nayan
316
- */
317
- const WP_OPTION_PREFIX = 'wf_option_';
318
-
319
- /**
320
- * Woo_Feed_Products_v3 constructor.
321
- *
322
- * @param $config
323
- * @return void
324
- */
325
- public function __construct( $config ) {
326
- $this->config = woo_feed_parse_feed_rules($config);
327
- $this->queryType = woo_feed_get_options('product_query_type');
328
- $this->process_xml_wrapper();
329
- woo_feed_log_feed_process($this->config['filename'], sprintf('Current Query Type is %s', $this->queryType));
330
- }
331
-
332
- /**
333
- * Generate Query Args For WP/WC query class
334
- * @param string $type
335
- * @return array
336
- */
337
- protected function get_query_args( $type = 'wc' ) {
338
- $args = [];
339
-
340
- // Include Product Variations with db query if configured
341
- $variation_query = woo_feed_get_options('variation_query_type');
342
-
343
- if ( 'wc' === $type ) {
344
- $product_types = $this->product_types;
345
- if ( 'variable' === $variation_query ) {
346
- $variation = array_search('variation', $product_types, true);
347
- if ( $variation ) {
348
- unset($product_types[ $variation ]);
349
- }
350
- }
351
-
352
- $args = array(
353
- 'limit' => -1, // phpcs:ignore
354
- 'status' => $this->post_status,
355
- 'type' => $product_types,
356
- 'orderby' => 'date',
357
- 'order' => 'DESC',
358
- 'return' => 'ids',
359
- 'suppress_filters' => false,
360
- );
361
- }
362
-
363
- if ( 'wp' === $type ) {
364
-
365
- $post_type = 'product';
366
- // Include Product Variations with db query if configured
367
- $variation_query = woo_feed_get_options('variation_query_type');
368
- if ( 'individual' === $variation_query ) {
369
- $post_type = [ 'product', 'product_variation' ];
370
- }
371
-
372
- $args = array(
373
- 'posts_per_page' => -1, // phpcs:ignore
374
- 'post_type' => $post_type,
375
- 'post_status' => 'publish',
376
- 'order' => 'DESC',
377
- 'fields' => 'ids',
378
- 'cache_results' => false,
379
- 'update_post_meta_cache' => false,
380
- 'update_post_term_cache' => false,
381
- 'suppress_filters' => false,
382
- );
383
- }
384
- return $args;
385
- }
386
-
387
- /**
388
- * Get Products using WC_Product_Query
389
- *
390
- * @return array
391
- */
392
- public function get_wc_query_products() {
393
- $args = $this->get_query_args('wc');
394
- if ( woo_feed_is_debugging_enabled() ) {
395
- woo_feed_log_feed_process($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true)); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
396
- woo_feed_log($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true), 'info'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
397
- }
398
- $query = new WC_Product_Query($args);
399
- if ( woo_feed_is_debugging_enabled() ) {
400
- woo_feed_log_feed_process($this->config['filename'], sprintf('WC_Product_Query Args ::' . PHP_EOL . '%s', print_r($args, true))); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
401
- }
402
- return $query->get_products();
403
- }
404
-
405
- /**
406
- * Get Products using WP_Query
407
- *
408
- * return array
409
- */
410
- public function get_wp_query_products() {
411
- $args = $this->get_query_args('wp');
412
- $query = new WP_Query($args);
413
- if ( ! is_wp_error($query) && woo_feed_is_debugging_enabled() ) {
414
- woo_feed_log_feed_process($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true)); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
415
- woo_feed_log_feed_process($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request));
416
- woo_feed_log($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true), 'info'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
417
- woo_feed_log($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request), 'info');
418
- }
419
- return $query->get_posts();
420
- }
421
-
422
- /**
423
- * Get products
424
- *
425
- * @return array
426
- */
427
- public function query_products() {
428
- $products = [];
429
- if ( 'wc' == $this->queryType ) {
430
- $products = $this->get_wc_query_products();
431
- } elseif ( 'wp' == $this->queryType ) {
432
- $products = $this->get_wp_query_products();
433
- } elseif ( 'both' == $this->queryType ) {
434
- $wc = $this->get_wc_query_products();
435
- $wp = $this->get_wp_query_products();
436
- $products = array_unique(array_merge($wc, $wp));
437
- }
438
-
439
- //set product ids
440
- $this->product_ids = $products;
441
-
442
- return $products;
443
- }
444
-
445
- /**
446
- * Organize Feed Attribute config
447
- * @return array|bool
448
- */
449
- public function get_attribute_config() {
450
- if ( empty($this->config) ) {
451
- return false;
452
- }
453
-
454
- $attributeConfig = array();
455
- $merchantAttributes = $this->config['mattributes'];
456
- if ( ! empty($merchantAttributes) ) {
457
- $i = 0;
458
- foreach ( $merchantAttributes as $key => $value ) {
459
- $attributeConfig[ $i ]['mattributes'] = $value;
460
- $attributeConfig[ $i ]['prefix'] = $this->config['prefix'][ $key ];
461
- $attributeConfig[ $i ]['type'] = $this->config['type'][ $key ];
462
- $attributeConfig[ $i ]['attributes'] = $this->config['attributes'][ $key ];
463
- $attributeConfig[ $i ]['default'] = $this->config['default'][ $key ];
464
- $attributeConfig[ $i ]['suffix'] = $this->config['suffix'][ $key ];
465
- $attributeConfig[ $i ]['output_type'] = $this->config['output_type'][ $key ];
466
- $attributeConfig[ $i ]['limit'] = $this->config['limit'][ $key ];
467
- $i++;
468
- }
469
- }
470
-
471
- return $attributeConfig;
472
- }
473
-
474
- /**
475
- * Get Product Information according to feed config
476
- *
477
- * @param int[] $productIds
478
- *
479
- * @return array
480
- * @since 3.2.0
481
- *
482
- */
483
- public function get_products( $productIds ) {
484
-
485
- if ( empty($productIds) ) {
486
- return [];
487
- }
488
-
489
- //filter big data
490
- $this->data = apply_filters("woo_feed_feed_big_data", $this->data, $productIds, $this->config);
491
-
492
- /**
493
- * Fires before looping through request product for getting product data
494
- *
495
- * @param int[] $productIds
496
- * @param array $feedConfig
497
- *
498
- * @since 3.2.10
499
- */
500
- do_action('woo_feed_before_product_loop', $productIds, $this->config);
501
-
502
- foreach ( $productIds as $key => $pid ) {
503
- woo_feed_log_feed_process($this->config['filename'], sprintf('Loading Product Data For %d.', $pid));
504
- $product = wc_get_product($pid);
505
-
506
- if ( $this->exclude_from_loop($product) ) {
507
- continue;
508
- }
509
-
510
- if ( $this->process_variation($product) ) {
511
- continue;
512
- }
513
-
514
- if ( ! $this->filter_product($product) ) {
515
- woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Matched with filter conditions');
516
- continue;
517
- }
518
-
519
- woo_feed_log_feed_process($this->config['filename'], 'Formatting Feed Data...');
520
-
521
- // Add Single item wrapper before product info loop start
522
- if ( 'xml' == $this->config['feedType'] ) {
523
- $this->feedBody .= "\n";
524
- $this->feedBody .= '<' . $this->config['itemWrapper'] . '>';
525
- $this->feedBody .= "\n";
526
- }
527
-
528
- // reset processed attribute list before loop
529
- $this->processed_merchant_attributes = [];
530
-
531
- // Process attribute values
532
- $this->process_attributes($product);
533
-
534
- try {
535
- woo_feed_log_feed_process($this->config['filename'], 'Processing Merchant Specific Fields');
536
- // Process feed data for uncommon merchant feed like Google,Facebook,Pinterest
537
- $this->process_for_merchant($product, $this->pi);
538
- } catch ( Exception $e ) {
539
- $message = 'Error Processing Merchant Specific Fields.' . PHP_EOL . 'Caught Exception :: ' . $e->getMessage();
540
- woo_feed_log($this->config['filename'], $message, 'critical', $e, true);
541
- woo_feed_log_fatal_error($message, $e);
542
- }
543
-
544
- if ( 'xml' == $this->config['feedType'] ) {
545
- if ( empty($this->feedHeader) ) {
546
- $this->feedHeader = $this->process_xml_feed_header();
547
- $this->feedFooter = $this->process_xml_feed_footer();
548
-
549
- }
550
-
551
- $this->feedBody .= '</' . $this->config['itemWrapper'] . '>';
552
-
553
-
554
- } elseif ( 'txt' == $this->config['feedType'] ) {
555
- if ( empty($this->feedHeader) ) {
556
- $this->process_txt_feed_header();
557
- }
558
- $this->process_txt_feed_body();
559
- } elseif ( 'csv' == $this->config['feedType'] || 'xls' == $this->config['feedType'] ) {
560
- if ( empty($this->feedHeader) ) {
561
- $this->process_csv_feed_header();
562
- }
563
- $this->process_csv_feed_body();
564
- }elseif ( 'json' == $this->config['feedType'] ) {
565
- $this->process_json_feed_body();
566
- }
567
- woo_feed_log_feed_process($this->config['filename'], 'Done Formatting...');
568
- $this->pi++;
569
- }
570
-
571
- /**
572
- * Fires after looping through request product for getting product data
573
- *
574
- * @param int[] $productIds
575
- * @param array $feedConfig
576
- *
577
- * @since 3.2.10
578
- */
579
- do_action('woo_feed_after_product_loop', $productIds, $this->config);
580
-
581
- return $this->products;
582
- }
583
-
584
- /**
585
- * Process product variations
586
- * @param WC_Abstract_Legacy_Product $product
587
- *
588
- * @return bool
589
- * @since 3.3.9
590
- */
591
- protected function process_variation( $product ) {
592
- // Apply variable and variation settings
593
- if ( $product->is_type('variable') && $product->has_child() ) {
594
- $this->pi++;
595
-
596
- $variation_query = woo_feed_get_options('variation_query_type');
597
- if ( 'variable' === $variation_query ) {
598
- $variations = $product->get_visible_children();
599
- if ( is_array($variations) && (sizeof($variations) > 0) ) {
600
- if ( woo_feed_is_debugging_enabled() ) {
601
- woo_feed_log_feed_process($this->config['filename'], sprintf('Getting Variation Product(s) :: %s', implode(', ', $variations)));
602
- }
603
- $this->get_products($variations);
604
- return true;
605
- }
606
- }
607
- }
608
-
609
- return false;
610
- }
611
-
612
- /**
613
- * Process The Attributes and assign value to merchant attribute
614
- *
615
- * @param WC_Abstract_Legacy_Product $product
616
- *
617
- * @return void
618
- * @since 3.3.9
619
- */
620
- protected function process_attributes( $product ) {
621
- // Get Product Attribute values by type and assign to product array
622
- foreach ( $this->config['attributes'] as $attr_key => $attribute ) {
623
-
624
- $merchant_attribute = isset($this->config['mattributes'][ $attr_key ]) ? $this->config['mattributes'][ $attr_key ] : '';
625
-
626
- if ( $this->exclude_current_attribute($product, $merchant_attribute, $attribute) ) {
627
- continue;
628
- }
629
-
630
- // Add Prefix and Suffix into Output
631
- $prefix = $this->config['prefix'][ $attr_key ];
632
- $suffix = $this->config['suffix'][ $attr_key ];
633
- $merchant = $this->config['provider'];
634
- $feedType = $this->config['feedType'];
635
-
636
- if ( 'pattern' == $this->config['type'][ $attr_key ] ) {
637
- $attributeValue = $this->config['default'][ $attr_key ];
638
- } else { // Get Pattern value
639
- $attributeValue = $this->getAttributeValueByType($product, $attribute, $merchant_attribute);
640
- }
641
-
642
- // Format Output according to Output Type config.
643
- if ( isset($this->config['output_type'][ $attr_key ]) ) {
644
- $outputType = $this->config['output_type'][ $attr_key ];
645
- $attributeValue = $this->format_output($attributeValue, $this->config['output_type'][ $attr_key ], $product, $attribute, $merchant_attribute);
646
- }
647
-
648
- // Limit Output.
649
- if ( isset($this->config['limit'][ $attr_key ]) ) {
650
- $attributeValue = $this->crop_string($attributeValue, 0, $this->config['limit'][ $attr_key ]);
651
- }
652
-
653
- // Process prefix and suffix.
654
- $attributeValue = $this->process_prefix_suffix($attributeValue, $prefix, $suffix, $attribute);
655
-
656
- if ( 'xml' == $feedType ) {
657
-
658
- // Replace XML Nodes according to merchant requirement.
659
- $getReplacedAttribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
660
-
661
- // XML does not support space in node. So replace Space with Underscore.
662
- $getReplacedAttribute = str_replace(' ', '_', $getReplacedAttribute);
663
-
664
- // Trim XML Element text & Encode for UTF-8.
665
- if ( ! empty($attributeValue) ) {
666
- $attributeValue = trim($attributeValue);
667
-
668
- if ( 'custom' === $this->config['provider'] && strpos($attributeValue, '<![CDATA[') === false ) {
669
- $attributeValue = htmlentities($attributeValue, ENT_XML1 | ENT_QUOTES, 'UTF-8');
670
- }
671
- }
672
-
673
- // Add closing XML node if value is empty
674
- if ( '' !== $attributeValue ) {
675
- // Add CDATA wrapper for XML feed to prevent XML error.
676
- $attributeValue = woo_feed_add_cdata($merchant_attribute, $attributeValue, $merchant, $this->config['feedType']);
677
-
678
- // Strip slash from output.
679
- $attributeValue = stripslashes($attributeValue);
680
- $this->feedBody .= '<' . $getReplacedAttribute . '>' . "$attributeValue" . '</' . $getReplacedAttribute . '>';
681
- $this->feedBody .= "\n";
682
- } else {
683
- $this->feedBody .= '<' . $getReplacedAttribute . '/>';
684
- $this->feedBody .= "\n";
685
- }
686
- } elseif ( in_array($feedType, [ 'csv', 'tsv', 'xls' ], true) ) {
687
- $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
688
- $merchant_attribute = $this->processStringForCSV($merchant_attribute);
689
-
690
- if ( "shipping" === $merchant_attribute && 'bing' == $this->config['provider'] ) {
691
- $merchant_attribute = 'shipping(country:service:price)';
692
- } elseif ( "shipping" === $merchant_attribute ) {
693
- $merchant_attribute = 'shipping(country:region:service:price)';
694
- }
695
-
696
- if ( "tax" === $merchant_attribute ) {
697
- $merchant_attribute = 'tax(country:region:rate:tax_ship)';
698
- }
699
-
700
- $attributeValue = $this->processStringForCSV($attributeValue);
701
-
702
- } elseif ( 'txt' == $feedType ) {
703
- $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
704
- $merchant_attribute = $this->processStringForTXT($merchant_attribute);
705
-
706
- if ( "shipping" === $merchant_attribute && 'bing' == $this->config['provider'] ) {
707
- $merchant_attribute = 'shipping(country:service:price)';
708
- } elseif ( "shipping" === $merchant_attribute ) {
709
- $merchant_attribute = 'shipping(country:region:service:price)';
710
- }
711
-
712
- if ( "tax" === $merchant_attribute ) {
713
- $merchant_attribute = 'tax(country:region:rate:tax_ship)';
714
- }
715
-
716
- $attributeValue = $this->processStringForTXT($attributeValue);
717
- }
718
-
719
- $this->products[ $this->pi ][ $merchant_attribute ] = $attributeValue;
720
- }
721
- }
722
-
723
- /**
724
- * Process Nested Attributes
725
- *
726
- * @return array
727
- * @since 4.0.5
728
- *
729
- */
730
- protected function feed_nested_attributes() {
731
- return [
732
- 'reviewer' => [ 'reviewer', 'name' ],
733
- 'ratings' => [ 'ratings', 'overall' ],
734
- 'product_url' => [ 'products', 'product', 'product_url' ],
735
- ];
736
- }
737
-
738
- /**
739
- * Process Nested Attributes
740
- *
741
- * @param string $attribute //product feed tag
742
- * @param string $content //product feed content
743
- *
744
- * @return string
745
- * @since 4.0.5
746
- *
747
- */
748
-
749
- protected function nested_attributes_element( $attribute, $content ) {
750
- $starter = '';
751
- $finisher = '';
752
- $element = '';
753
-
754
- if ( empty($attribute) ) {
755
- return $attribute;
756
- }
757
-
758
- $attr_names = $this->feed_nested_attributes();
759
-
760
- foreach ( $attr_names as $key => $value ) {
761
- if ( $key === $attribute ) {
762
- //starter tags element
763
- foreach ( $value as $item_value ) {
764
- $starter .= '<' . strval($item_value) . '>';
765
- }
766
-
767
- //finishing tags element
768
- $rev_value = array_reverse($value);
769
- foreach ( $rev_value as $item_value ) {
770
- $finisher .= '</' . strval($item_value) . '>';
771
- }
772
- }
773
- }
774
-
775
- $element = $starter . $content . $finisher;
776
-
777
- return $element;
778
- }
779
-
780
- /**
781
- * Check if current product should be processed for feed
782
- * This should be using by Woo_Feed_Products_v3::get_products()
783
- *
784
- * @param WC_Product $product
785
- *
786
- * @return bool
787
- * @since 3.3.9
788
- *
789
- */
790
- protected function exclude_from_loop( $product ) {
791
- // Skip for invalid products
792
- if ( ! is_object($product) ) {
793
- woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product data is not a valid WC_Product object.');
794
- return true;
795
- }
796
-
797
- // For WP_Query check available product types
798
- if ( 'wp' == $this->queryType && ! in_array($product->get_type(), $this->product_types, true) ) {
799
- woo_feed_log_feed_process($this->config['filename'], sprintf('Skipping Product :: Invalid Post/Product Type : %s.', $product->get_type()));
800
- return true;
801
- }
802
-
803
- // Skip orphaned variation
804
- if ( $product->is_type('variation') && ! $product->get_parent_id() ) {
805
- woo_feed_log_feed_process($this->config['filename'], sprintf('Skipping Product :: Orphaned variation product [id: %s] skipped.', $product->get_id()));
806
- return true;
807
- }
808
-
809
- // Skip for invisible products
810
- if ( ! $product->is_visible() ) {
811
- woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product is not visible.');
812
- return true;
813
- }
814
- return false;
815
- }
816
-
817
- /**
818
- * Check if current attribute/merchant attribute should be processed for feed
819
- * This should be using by Woo_Feed_Products_v3::get_products()
820
- *
821
- * @param WC_Product $product
822
- * @param string $merchant_attribute
823
- * @param string $product_attribute
824
- * @param string $feedType
825
- *
826
- * @return bool
827
- *
828
- * @since 3.3.9
829
- *
830
- */
831
- protected function exclude_current_attribute( $product, $merchant_attribute, $product_attribute, $feedType = 'xml' ) {
832
 
833
- if ( empty($merchant_attribute) ) {
834
- return true;
835
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
836
 
837
- if (
838
- in_array($this->config['provider'], array_keys($this->skipped_merchant_attributes)) &&
839
- in_array($merchant_attribute, $this->skipped_merchant_attributes[ $this->config['provider'] ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
840
 
841
- ) {
842
- return true;
843
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
 
845
- if ( 'shopping_ads_excluded_country' !== $merchant_attribute && in_array($merchant_attribute, $this->processed_merchant_attributes) ) {
846
- return true;
847
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
848
 
849
- $this->processed_merchant_attributes[] = $merchant_attribute;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
850
 
851
- return false;
852
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
 
854
- /**
855
- * Wrapper for substr with <![CDATA[string]]> support
856
- *
857
- * @param string $string
858
- * @param int $start
859
- * @param int $limit
860
- *
861
- * @return string
862
- * @see substr
863
- *
864
- */
865
- protected function crop_string( $string, $start = 0, $limit = null ) {
866
- $limit = absint($limit);
867
- if ( $limit > 0 ) {
868
- $start = absint($start);
869
- if ( strpos($string, '<![CDATA[') !== false ) {
870
- $string = str_replace(array( '<![CDATA[', ']]>' ), array( '', '' ), $string);
871
- $string = substr($string, $start, $limit);
872
- $string = '<![CDATA[' . $string . ']]>';
873
- } else {
874
- $string = substr($string, $start, $limit);
875
- }
876
- }
877
- return $string;
878
- }
879
-
880
- /**
881
- * Process feed data according to merchant uncommon requirements like Google
882
- *
883
- * @param object $productObj WC_Product
884
- * @param int $index Product Index
885
- *
886
- * @since 3.2.0
887
- */
888
- protected function process_for_merchant( $productObj, $index ) {
889
- $product = $this->products[ $index ];
890
- $merchantAttributes = $this->config['mattributes'];
891
- $s = 0; // Shipping Index
892
- $i = 0; // Installment Index
893
- $t = 0; // Tax Index
894
- $tax = '';
895
- $shipping = '';
896
- $sub = 0;
897
- $subscription = '';
898
- $ins = 0; // Installment Index
899
- $installment = "";
900
- $product_detail = '';
901
- $unit_price = '';
902
- $additional_variant_attribute = '';
903
- $pd = 0;
904
- $up = 0; //Unit Price for facebook
905
- $av = 0; //Additional Variant Attribute for facebook
906
-
907
-
908
- // Format Shipping and Tax data for CSV and TXT feed only for google and facebook
909
-
910
- if ( 'xml' != $this->config['feedType'] && in_array($this->config['provider'], array( 'google', 'facebook', 'bing', 'snapchat', 'pinterest' )) ) {
911
- foreach ( $merchantAttributes as $key => $value ) {
912
-
913
- if ( ! in_array($value, $this->google_shipping_tax, true) ) {
914
- continue;
915
- }
916
-
917
- # Get value by attribute type with prefix & suffix
918
- $output = $this->process_for_merchant_get_value($productObj, $key);
919
-
920
- if ( 'shipping_country' == $value ) {
921
- $s++;
922
- $shipping .= $output;
923
- }
924
- if ( 'shipping_region' == $value ) {
925
- $shipping .= ':' . $output;
926
- } elseif ( 'shipping_postal_code' == $value ) {
927
- $shipping .= ':' . $output;
928
- }
929
- if ( 'shipping_service' == $value ) {
930
- $shipping .= ':' . $output;
931
- }
932
- if ( 'shipping_price' == $value ) {
933
- $shipping .= ':' . $output;
934
- }
935
-
936
- if ( 'section_name' == $value ) {
937
- $pd++;
938
- $product_detail .= $output;
939
- }
940
- if ( 'attribute_name' == $value ) {
941
- $product_detail .= ':' . $output;
942
- }
943
- if ( 'attribute_value' == $value ) {
944
- $product_detail .= ':' . $output;
945
- }
946
-
947
- //facebook nested attributes
948
- if ( isset($this->config['provider']) && "facebook" === $this->config['provider'] ) {
949
- if ( 'unit_price_value' == $value ) {
950
- $up++;
951
- $unit_price .= $output;
952
- }
953
- if ( 'unit_price_currency' == $value ) {
954
- $unit_price .= ':' . $output;
955
- }
956
- if ( 'unit_price_unit' == $value ) {
957
- $unit_price .= ':' . $output;
958
- }
959
-
960
- if ( 'additional_variant_label' == $value ) {
961
- $av++;
962
- $additional_variant_attribute .= $output;
963
- }
964
- if ( 'additional_variant_value' == $value ) {
965
- $additional_variant_attribute .= ':' . $output;
966
- }
967
-
968
- if ( 0 < $up ) {
969
- $this->products[ $this->pi ]["unit_price"] = $unit_price;
970
- }
971
-
972
- if ( 0 < $av ) {
973
- $this->products[ $this->pi ]["additional_variant_attribute"] = $additional_variant_attribute;
974
- }
975
- }
976
-
977
-
978
- if ( 'installment_months' == $value ) {
979
- $ins++;
980
- $installment .= $output;
981
- }
982
- if ( 'installment_amount' == $value ) {
983
- $installment .= ':' . $output;
984
- }
985
-
986
- if ( 'subscription_period' == $value ) {
987
- $sub++;
988
- $subscription .= $output;
989
- }
990
- if ( 'subscription_period_length' == $value ) {
991
- $subscription .= ':' . $output;
992
- }
993
- if ( 'subscription_amount' == $value ) {
994
- $subscription .= ':' . $output;
995
- }
996
- }
997
-
998
- if ( 0 < $pd ) {
999
- $this->products[ $this->pi ]["product detail"] = $product_detail;
1000
- }
1001
-
1002
- if ( 0 < $sub ) {
1003
- $this->products[ $this->pi ]["subscription cost"] = $subscription;
1004
-
1005
- }
1006
-
1007
- if ( 0 < $ins ) {
1008
- $this->products[ $this->pi ]["installment"] = $installment;
1009
- }
1010
- }
1011
-
1012
-
1013
- if ( in_array($this->config['provider'], array( 'google', 'facebook', 'snapchat', 'bing', 'pinterest' )) ) {
1014
-
1015
-
1016
- // Reformat Shipping attributes for google, facebook
1017
- if ( 'xml' == $this->config['feedType'] ) {
1018
- foreach ( $merchantAttributes as $key => $value ) {
1019
-
1020
- if ( ! in_array($value, $this->google_shipping_tax) ) {
1021
- continue;
1022
- }
1023
-
1024
-
1025
- # Get value by attribute type with prefix & suffix
1026
- $output = $this->process_for_merchant_get_value($productObj, $key);
1027
-
1028
-
1029
- if ( 'shipping_country' == $value ) {
1030
- if ( 0 == $s ) {
1031
- $shipping .= '<g:shipping>';
1032
- $s = 1;
1033
- } else {
1034
- $shipping .= '</g:shipping>' . "\n";
1035
- $shipping .= '<g:shipping>';
1036
- }
1037
- } elseif ( ! in_array('shipping_country', $merchantAttributes) && 'shipping_price' == $value ) {
1038
- if ( 0 == $s ) {
1039
- $shipping .= '<g:shipping>';
1040
- $s = 1;
1041
- } else {
1042
- $shipping .= '</g:shipping>' . "\n";
1043
- $shipping .= '<g:shipping>';
1044
- }
1045
- }
1046
-
1047
- if ( 'shipping_country' == $value ) {
1048
- $shipping .= '<g:country>' . $output . '</g:country>' . "\n";
1049
- } elseif ( 'shipping_region' == $value ) {
1050
- $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
1051
- } elseif ( 'shipping_region' == $value ) {
1052
- $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
1053
- } elseif ( 'shipping_service' == $value ) {
1054
- $shipping .= '<g:service>' . $output . '</g:service>' . "\n";
1055
- } elseif ( 'shipping_postal_code' == $value ) {
1056
- $shipping .= '<g:postal_code>' . $output . '</g:postal_code>' . "\n";
1057
- } elseif ( 'shipping_price' == $value ) {
1058
- $shipping .= '<g:price>' . $output . '</g:price>' . "\n";
1059
- } elseif ( 'tax_country' == $value ) {
1060
- if ( 0 == $t ) {
1061
- $tax .= '<g:tax>';
1062
- $t = 1;
1063
- } else {
1064
- $tax .= '</g:tax>' . "\n";
1065
- $tax .= '<g:tax>';
1066
- }
1067
- $tax .= '<g:country>' . $output . '</g:country>' . "\n";
1068
- } elseif ( 'tax_region' == $value ) {
1069
- $tax .= '<g:region>' . $output . '</g:region>' . "\n";
1070
- } elseif ( 'tax_rate' == $value ) {
1071
- $tax .= '<g:rate>' . $output . '</g:rate>' . "\n";
1072
- } elseif ( 'tax_ship' == $value ) {
1073
- $tax .= '<g:tax_ship>' . $output . '</g:tax_ship>' . "\n";
1074
- } elseif ( 'subscription_period' == $value ) {
1075
- if ( 0 == $sub ) {
1076
- $subscription .= '<g:subscription_cost>';
1077
- $sub = 1;
1078
- } else {
1079
- $subscription .= '</g:subscription_cost>' . "\n";
1080
- $subscription .= '<g:subscription_cost>';
1081
- }
1082
- $subscription .= '<g:period>' . $output . '</g:period>' . "\n";
1083
- } elseif ( 'subscription_period_length' == $value ) {
1084
- $subscription .= '<g:period_length>' . $output . '</g:period_length>' . "\n";
1085
- } elseif ( 'subscription_amount' == $value ) {
1086
- $subscription .= '<g:amount>' . $output . '</g:amount>' . "\n";
1087
- }
1088
-
1089
- if ( 'section_name' == $value ) {
1090
- if ( 0 == $pd ) {
1091
- $product_detail .= '<g:product_detail>';
1092
- $pd = 1;
1093
- } else {
1094
- $product_detail .= '</g:product_detail>' . "\n";
1095
- $product_detail .= '<g:product_detail>';
1096
- }
1097
- } elseif ( ! in_array('section_name', $merchantAttributes) && 'attribute_name' == $value ) {
1098
- if ( 0 == $pd ) {
1099
- $product_detail .= '<g:product_detail>';
1100
- $pd = 1;
1101
- } else {
1102
- $product_detail .= '</g:product_detail>' . "\n";
1103
- $product_detail .= '<g:product_detail>';
1104
- }
1105
- }
1106
-
1107
- if ( 'section_name' == $value ) {
1108
- $product_detail .= '<g:section_name>' . $output . '</g:section_name>' . "\n";
1109
- } elseif ( 'attribute_name' == $value ) {
1110
- $product_detail .= '<g:attribute_name>' . $output . '</g:attribute_name>' . "\n";
1111
- } elseif ( 'attribute_value' == $value ) {
1112
- $product_detail .= '<g:attribute_value>' . $output . '</g:attribute_value>' . "\n";
1113
- }
1114
-
1115
- if ( isset($this->config['provider']) && "facebook" === $this->config['provider'] ) {
1116
-
1117
- // unit_price configure
1118
- if ( 'unit_price_value' == $value ) {
1119
- if ( 0 == $up ) {
1120
- $unit_price .= '<unit_price>';
1121
- $up = 1;
1122
- } else {
1123
- $unit_price .= '</unit_price>' . "\n";
1124
- $unit_price .= '<unit_price>';
1125
- }
1126
- } elseif ( ! in_array('unit_price_value', $merchantAttributes) && 'unit_price_currency' == $value ) {
1127
- if ( 0 == $up ) {
1128
- $unit_price .= '<unit_price>';
1129
- $up = 1;
1130
- } else {
1131
- $unit_price .= '</unit_price>' . "\n";
1132
- $unit_price .= '<unit_price>';
1133
- }
1134
- }
1135
-
1136
- if ( 'unit_price_value' == $value ) {
1137
- $unit_price .= '<value>' . $output . '</value>' . "\n";
1138
- } elseif ( 'unit_price_currency' == $value ) {
1139
- $unit_price .= '<currency>' . $output . '</currency>' . "\n";
1140
- } elseif ( 'unit_price_unit' == $value ) {
1141
- $unit_price .= '<unit>' . $output . '</unit>' . "\n";
1142
- }
1143
-
1144
- // additional_variant_attribute configure
1145
- if ( 'additional_variant_label' == $value ) {
1146
- if ( 0 == $av ) {
1147
- $additional_variant_attribute .= '<additional_variant_attribute>';
1148
- $av = 1;
1149
- } else {
1150
- $additional_variant_attribute .= '</additional_variant_attribute>' . "\n";
1151
- $additional_variant_attribute .= '<additional_variant_attribute>';
1152
- }
1153
- } elseif ( ! in_array('additional_variant_label', $merchantAttributes) && 'additional_variant_value' == $value ) {
1154
- if ( 0 == $av ) {
1155
- $additional_variant_attribute .= '<additional_variant_attribute>';
1156
- $av = 1;
1157
- } else {
1158
- $additional_variant_attribute .= '</additional_variant_attribute>' . "\n";
1159
- $additional_variant_attribute .= '<additional_variant_attribute>';
1160
- }
1161
- }
1162
-
1163
- if ( 'additional_variant_label' == $value ) {
1164
- $additional_variant_attribute .= '<label>' . $output . '</label>' . "\n";
1165
- } elseif ( 'additional_variant_value' == $value ) {
1166
- $additional_variant_attribute .= '<value>' . $output . '</value>' . "\n";
1167
- }
1168
- }
1169
 
 
 
 
 
 
1170
 
1171
- if ( 'installment_months' === $value ) {
1172
- if ( 0 == $ins ) {
1173
- $installment .= '<g:installment>';
1174
- $ins = 1;
1175
- } else {
1176
- $installment .= '</g:installment>' . "\n";
1177
- $installment .= '<g:installment>';
1178
- }
1179
- $installment .= '<g:months>' . $output . '</g:months>' . "\n";
1180
- } elseif ( 'installment_amount' == $value ) {
1181
- $installment .= '<g:amount>' . $output . '</g:amount>' . "\n";
1182
- }
1183
- }
1184
-
1185
- if ( 1 == $pd ) {
1186
- $product_detail .= '</g:product_detail>';
1187
- }
1188
-
1189
- if ( isset($this->config['provider']) && "facebook" === $this->config['provider'] ) {
1190
- if ( 1 == $up ) {
1191
- $unit_price .= '</unit_price>';
1192
- }
1193
-
1194
- if ( 1 == $av ) {
1195
- $additional_variant_attribute .= '</additional_variant_attribute>';
1196
- }
1197
-
1198
- $this->feedBody .= $unit_price;
1199
- $this->feedBody .= $additional_variant_attribute;
1200
- }
1201
-
1202
- if ( 1 == $s ) {
1203
- $shipping .= '</g:shipping>';
1204
- }
1205
- if ( 1 == $t ) {
1206
- $tax .= '</g:tax>';
1207
- }
1208
-
1209
- if ( 1 == $sub ) {
1210
- $subscription .= '</g:subscription_cost>';
1211
- }
1212
-
1213
- if ( 1 == $ins ) {
1214
- $installment .= '</g:installment>';
1215
- }
1216
-
1217
- //$this->feedBody .= $shipping;
1218
- //$this->feedBody .= $tax;
1219
- $this->feedBody .= $product_detail;
1220
- $this->feedBody .= $installment;
1221
-
1222
- if ( $productObj->is_type('subscription') ||
1223
- $productObj->is_type('variable-subscription') ||
1224
- $productObj->is_type('subscription_variation') ) {
1225
- $this->feedBody .= $subscription;
1226
- }
1227
- }
1228
- // ADD g:identifier_exists
1229
- $identifier = array( 'brand', 'upc', 'sku', 'mpn', 'gtin' );
1230
- $countIdentifier = 0;
1231
- if ( ! in_array('identifier_exists', $merchantAttributes) ) {
1232
- if ( count(array_intersect_key(array_flip($identifier), $product)) >= 2 ) {
1233
- // Any 2 required keys exist!
1234
- // @TODO Refactor with OR
1235
- if ( array_key_exists('brand', $product) && ! empty($product['brand']) ) {
1236
- $countIdentifier++;
1237
- }
1238
- if ( array_key_exists('upc', $product) && ! empty($product['upc']) ) {
1239
- $countIdentifier++;
1240
- }
1241
- if ( array_key_exists('sku', $product) && ! empty($product['sku']) ) {
1242
- $countIdentifier++;
1243
- }
1244
- if ( array_key_exists('mpn', $product) && ! empty($product['mpn']) ) {
1245
- $countIdentifier++;
1246
- }
1247
- if ( array_key_exists('gtin', $product) && ! empty($product['gtin']) ) {
1248
- $countIdentifier++;
1249
- }
1250
- }
1251
-
1252
- if ( 'xml' == $this->config['feedType'] ) {
1253
- if ( $countIdentifier >= 2 ) {
1254
- $this->feedBody .= '<g:identifier_exists>yes</g:identifier_exists>';
1255
- } else {
1256
- $this->feedBody .= '<g:identifier_exists>no</g:identifier_exists>';
1257
- }
1258
- } else {
1259
- $identifier_exists = 'identifier exists';
1260
- if ( in_array($this->config['provider'], array( 'bing', 'pinterest' )) ) {
1261
- $identifier_exists = 'identifier_exists';
1262
- }
1263
-
1264
- if ( $countIdentifier >= 2 ) {
1265
- $this->products[ $this->pi ][ $identifier_exists ] = 'yes';
1266
- } else {
1267
- $this->products[ $this->pi ][ $identifier_exists ] = 'no';
1268
- }
1269
- }
1270
- }
1271
- }
1272
- }
1273
-
1274
- private function process_for_merchant_get_value( $productObj, $key ) {
1275
- $prefix = $this->config['prefix'][ $key ];
1276
- $suffix = $this->config['suffix'][ $key ];
1277
- $attribute = $this->config['attributes'][ $key ];
1278
- $merchant_attribute = $this->config['mattributes'][ $key ];
1279
-
1280
- if ( 'pattern' == $this->config['type'][ $key ] ) {// Get Pattern value.
1281
- $output = $this->config['default'][ $key ];
1282
- $output = $this->apply_filters_to_attribute_value($output, $productObj, $attribute, $merchant_attribute);
1283
- } else {
1284
- $output = $this->getAttributeValueByType($productObj, $attribute, $merchant_attribute);
1285
- }
1286
-
1287
- $output = $this->format_output($output, $this->config['output_type'], $productObj, $attribute, $merchant_attribute);
1288
-
1289
- $output = $this->process_prefix_suffix($output, $prefix, $suffix, $attribute = '');
1290
-
1291
- return $output;
1292
- }
1293
-
1294
- /**
1295
- * Get Query Type Settings
1296
- * @return string
1297
- */
1298
- public function get_query_type() {
1299
- return $this->queryType;
1300
- }
1301
-
1302
- public function get_product_types() {
1303
- return $this->product_types;
1304
- }
1305
-
1306
- /**
1307
- * Generate TXT Feed Header
1308
- *
1309
- * @return string
1310
- * @since 3.2.0
1311
- *
1312
- */
1313
- protected function process_txt_feed_header() {
1314
- // Set Delimiter
1315
- if ( 'tab' == $this->config['delimiter'] ) {
1316
- $this->delimiter = "\t";
1317
- } else {
1318
- $this->delimiter = $this->config['delimiter'];
1319
- }
1320
-
1321
- // Set Enclosure
1322
- if ( ! empty($this->config['enclosure']) ) {
1323
- $this->enclosure = $this->config['enclosure'];
1324
- if ( 'double' == $this->enclosure ) {
1325
- $this->enclosure = '"';
1326
- } elseif ( 'single' == $this->enclosure ) {
1327
- $this->enclosure = "'";
1328
- } else {
1329
- $this->enclosure = '';
1330
- }
1331
- } else {
1332
- $this->enclosure = '';
1333
- }
1334
-
1335
- $eol = PHP_EOL;
1336
- if ( 'trovaprezzi' === $this->config['provider'] ) {
1337
- $eol = '<endrecord>' . PHP_EOL;
1338
- }
1339
-
1340
- $product = $this->products[ $this->pi ];
1341
-
1342
- $headers = array_keys($product);
1343
-
1344
- $this->feedHeader .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $headers) . $this->enclosure . $eol;
1345
-
1346
- if ( 'google' === $this->config['provider'] ) {
1347
- $this->feedHeader = str_replace($this->google_product_highlights, 'product highlight', $this->feedHeader);
1348
- $this->feedHeader = str_replace($this->google_additional_image, 'additional image link', $this->feedHeader);
1349
- }
1350
-
1351
- return $this->feedHeader;
1352
- }
1353
-
1354
- /**
1355
- * Generate TXT Feed Body
1356
- *
1357
- * @return string
1358
- * @since 3.2.0
1359
- *
1360
- */
1361
- protected function process_txt_feed_body() {
1362
- $productInfo = array_values($this->products[ $this->pi ]);
1363
- $eol = PHP_EOL;
1364
- if ( 'trovaprezzi' === $this->config['provider'] ) {
1365
- $eol = '<endrecord>' . PHP_EOL;
1366
- }
1367
- $this->feedBody .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $productInfo) . $this->enclosure . $eol;
1368
-
1369
- return $this->feedBody;
1370
- }
1371
-
1372
- /**
1373
- * Generate CSV Feed Header
1374
- *
1375
- * @return array
1376
- * @since 3.2.0
1377
- *
1378
- */
1379
- protected function process_csv_feed_header() {
1380
- // Set Delimiter
1381
- if ( 'tab' == $this->config['delimiter'] ) {
1382
- $this->delimiter = "\t";
1383
- } else {
1384
- $this->delimiter = $this->config['delimiter'];
1385
- }
1386
-
1387
- // Set Enclosure
1388
- if ( ! empty($this->config['enclosure']) ) {
1389
- $this->enclosure = $this->config['enclosure'];
1390
- if ( 'double' == $this->enclosure ) {
1391
- $this->enclosure = '"';
1392
- } elseif ( 'single' == $this->enclosure ) {
1393
- $this->enclosure = "'";
1394
- } else {
1395
- $this->enclosure = '';
1396
- }
1397
- } else {
1398
- $this->enclosure = '';
1399
- }
1400
-
1401
- $product = $this->products[ $this->pi ];
1402
-
1403
- $this->feedHeader = array_keys($product);
1404
-
1405
- if ( 'google' === $this->config['provider'] ) {
1406
- $this->feedHeader = str_replace($this->google_product_highlights, 'product highlight', $this->feedHeader);
1407
- $this->feedHeader = str_replace($this->google_additional_image, 'additional image link', $this->feedHeader);
1408
- }
1409
-
1410
- return $this->feedHeader;
1411
- }
1412
-
1413
- /**
1414
- * Generate CSV Feed Body
1415
- * @return array
1416
- * @since 3.2.0
1417
- */
1418
- protected function process_csv_feed_body() {
1419
- $product = $this->products[ $this->pi ];
1420
- $this->feedBody[] = array_values($product);
1421
-
1422
- return $this->feedBody;
1423
- }
1424
-
1425
- protected function process_json_feed_body(){
1426
- $product = $this->products[ $this->pi ];
1427
- $this->feedBody[] = $product;
1428
-
1429
- return $this->feedBody;
1430
- }
1431
-
1432
- protected function process_xml_wrapper() {
1433
- $itemsWrapperClose = explode(' ', $this->config['itemsWrapper']);
1434
- $itemsWrapperClose = $itemsWrapperClose[0];
1435
- $this->xml_wrapper = [
1436
- 'header' => '<?xml version="1.0" encoding="UTF-8" ?>' . PHP_EOL . '<' . wp_unslash($this->config['itemsWrapper']) . '>',
1437
- 'footer' => PHP_EOL . '</' . $itemsWrapperClose . '>',
1438
- ];
1439
- $this->config['itemWrapper'] = str_replace(' ', '_', $this->config['itemWrapper']);
1440
- $this->config['itemsWrapper'] = str_replace(' ', '_', $this->config['itemsWrapper']);
1441
-
1442
- if ( file_exists(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt') ) {
1443
- $txt = file_get_contents(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt');
1444
- $txt = trim($txt);
1445
- $txt = explode('{separator}', $txt);
1446
- if ( 2 === count($txt) ) {
1447
- $this->xml_wrapper['header'] = trim($txt[0]);
1448
- $this->xml_wrapper['footer'] = "\n".trim($txt[1]);
1449
- }
1450
- }
1451
-
1452
- if ( ! empty($this->config['extraHeader']) ) {
1453
- $this->xml_wrapper['header'] .= PHP_EOL . $this->config['extraHeader'];
1454
- }
1455
-
1456
- // replace template variables.
1457
- $datetime_now = date('Y-m-d H:i:s', strtotime(current_time('mysql'))); // {DateTimeNow}
1458
- if ( 'pinterest_rss' === $this->config['provider'] ) { // DATE_RFC822 date format for pinterest rss feed
1459
- $datetime_now = date('r', strtotime(current_time('mysql'))); // {DateTimeNow}
1460
- }
1461
- $blog_name = get_bloginfo('name'); // {BlogName}
1462
- $blog_url = get_bloginfo('url'); // {BlogURL}
1463
- //$blog_desc = get_bloginfo('description'); // {BlogDescription}
1464
- $blog_desc = "CTX Feed - This product feed is generated with the CTX Feed - WooCommerce Product Feed Manager plugin by WebAppick.com. For all your support questions check out our plugin Docs on https://webappick.com/docs or e-mail to: support@webappick.com"; // {BlogDescription}
1465
- $blog_email = get_bloginfo('admin_email'); // {BlogEmail}
1466
-
1467
- $this->xml_wrapper['header'] = str_replace(
1468
- [ '{DateTimeNow}', '{BlogName}', '{BlogURL}', '{BlogDescription}', '{BlogEmail}' ],
1469
- [ $datetime_now, $blog_name, $blog_url, $blog_desc, $blog_email ],
1470
- $this->xml_wrapper['header']
1471
- );
1472
- }
1473
-
1474
- /**
1475
- * Make XML feed header
1476
- * @return string
1477
- * @since 3.2.0
1478
- */
1479
- protected function process_xml_feed_header() {
1480
- return $this->xml_wrapper['header'];
1481
- }
1482
-
1483
- /**
1484
- * Make XML feed header
1485
- * @return string
1486
- * @since 3.2.0
1487
- */
1488
- protected function process_xml_feed_footer() {
1489
- return $this->xml_wrapper['footer'];
1490
- }
1491
-
1492
- /**
1493
- * Process string for TXT CSV Feed
1494
- *
1495
- * @param $string
1496
- *
1497
- * @return mixed|string
1498
- * @since 3.2.0
1499
- *
1500
- */
1501
- protected function processStringForTXT( $string ) {
1502
- if ( ! empty($string) ) {
1503
- $string = html_entity_decode($string, ENT_HTML401 | ENT_QUOTES); // Convert any HTML entities
1504
-
1505
- if ( stristr($string, '"') ) {
1506
- $string = str_replace('"', '""', $string);
1507
- }
1508
- $string = str_replace("\n", ' ', $string);
1509
- $string = str_replace("\r", ' ', $string);
1510
- $string = str_replace("\t", ' ', $string);
1511
- $string = trim($string);
1512
- $string = stripslashes($string);
1513
-
1514
- return $string;
1515
- } elseif ( '0' == $string ) {
1516
- return '0';
1517
- } else {
1518
- return '';
1519
- }
1520
- }
1521
-
1522
- /**
1523
- * Process string for CSV
1524
- *
1525
- * @param $string
1526
- *
1527
- * @return mixed|string
1528
- * @since 3.2.0
1529
- *
1530
- */
1531
- protected function processStringForCSV( $string ) {
1532
- if ( ! empty($string) ) {
1533
- $string = str_replace("\n", ' ', $string);
1534
- $string = str_replace("\r", ' ', $string);
1535
- $string = trim($string);
1536
- $string = stripslashes($string);
1537
-
1538
- return $string;
1539
- } elseif ( '0' == $string ) {
1540
- return '0';
1541
- } else {
1542
- return '';
1543
- }
1544
- }
1545
-
1546
- /**
1547
- * Get Product Attribute Value by Type
1548
- *
1549
- * @param $product WC_Product
1550
- * @param $attribute
1551
- *
1552
- * @return mixed|string
1553
- * @since 3.2.0
1554
- *
1555
- */
1556
- public function getAttributeValueByType( $product, $attribute, $merchant_attribute = '' ) {
1557
-
1558
- if ( method_exists($this, $attribute) ) {
1559
- $output = $this->$attribute($product);
1560
- } elseif ( false !== strpos($attribute, self::PRODUCT_CUSTOM_IDENTIFIER) || woo_feed_strpos_array(array( '_identifier_gtin', '_identifier_ean', '_identifier_mpn' ), $attribute) ) {
1561
- $output = $this->getCustomField($product, $attribute);
1562
- } elseif ( false !== strpos($attribute, self::PRODUCT_ATTRIBUTE_PREFIX) ) {
1563
- $attribute = str_replace(self::PRODUCT_ATTRIBUTE_PREFIX, '', $attribute);
1564
- $output = $this->getProductAttribute($product, $attribute);
1565
- } elseif ( false !== strpos($attribute, self::POST_META_PREFIX) ) {
1566
- $attribute = str_replace(self::POST_META_PREFIX, '', $attribute);
1567
- $output = $this->getProductMeta($product, $attribute);
1568
- } elseif ( false !== strpos($attribute, self::PRODUCT_TAXONOMY_PREFIX) ) {
1569
- $attribute = str_replace(self::PRODUCT_TAXONOMY_PREFIX, '', $attribute);
1570
- $output = $this->getProductTaxonomy($product, $attribute);
1571
- } elseif ( false !== strpos($attribute, self::PRODUCT_CATEGORY_MAPPING_PREFIX) ) {
1572
- $id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
1573
- $output = woo_feed_get_category_mapping_value($attribute, $id);
1574
- } elseif ( false !== strpos($attribute, self::WP_OPTION_PREFIX) ) {
1575
- $optionName = str_replace(self::WP_OPTION_PREFIX, '', $attribute);
1576
- $output = get_option($optionName);
1577
- } elseif ( 'image_' == substr($attribute, 0, 6) ) {
1578
- // For additional image method images() will be used with extra parameter - image number
1579
- $imageKey = explode('_', $attribute);
1580
- if ( ! isset($imageKey[1]) || (isset($imageKey[1]) && (empty($imageKey[1]) || ! is_numeric($imageKey[1]))) ) {
1581
- $imageKey[1] = '';
1582
- }
1583
- $output = call_user_func_array(array( $this, 'images' ), array( $product, $imageKey[1] ));
1584
- } else {
1585
- // return the attribute so multiple attribute can be join with separator to make custom attribute.
1586
- $output = $attribute;
1587
- }
1588
-
1589
- // Json encode if value is an array
1590
- if ( is_array($output) ) {
1591
- $output = wp_json_encode($output);
1592
- }
1593
-
1594
- $output = $this->apply_filters_to_attribute_value($output, $product, $attribute, $merchant_attribute);
1595
-
1596
- return $output;
1597
- }
1598
-
1599
- /**
1600
- * Apply Filter to Attribute value
1601
- *
1602
- * @param $output
1603
- * @param $product
1604
- * @param $attribute
1605
- * @param $merchant_attribute
1606
- *
1607
- * @return mixed|void
1608
- */
1609
- protected function apply_filters_to_attribute_value( $output, $product, $attribute, $merchant_attribute ) {
1610
- /**
1611
- * Filter attribute value
1612
- *
1613
- * @param string $output the output
1614
- * @param WC_Abstract_Legacy_Product $product Product Object.
1615
- * @param array feed config/rule
1616
- *
1617
- * @since 3.4.3
1618
- *
1619
- */
1620
- $output = apply_filters('woo_feed_get_attribute', $output, $product, $this->config, $merchant_attribute);
1621
-
1622
- /**
1623
- * Filter attribute value before return based on attribute name
1624
- *
1625
- * @param string $output the output
1626
- * @param WC_Abstract_Legacy_Product $product Product Object.
1627
- * @param array feed config/rule
1628
- *
1629
- * @since 3.3.5
1630
- *
1631
- */
1632
- $output = apply_filters("woo_feed_get_{$attribute}_attribute", $output, $product, $this->config);
1633
-
1634
- /**
1635
- * Filter attribute value before return based on merchant and attribute name
1636
- *
1637
- * @param string $output the output
1638
- * @param WC_Abstract_Legacy_Product $product Product Object.
1639
- * @param array feed config/rule
1640
- *
1641
- * @since 3.3.7
1642
- *
1643
- */
1644
- $output = apply_filters("woo_feed_get_{$this->config['provider']}_{$attribute}_attribute", $output, $product, $this->config);
1645
-
1646
- return $output;
1647
- }
1648
-
1649
-
1650
- /**
1651
- * Get Product Id
1652
- *
1653
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1654
- *
1655
- * @return mixed
1656
- * @since 3.2.0
1657
- */
1658
- protected function id( $product ) {
1659
- $id = $product->get_id();
1660
 
1661
- return apply_filters('woo_feed_filter_product_id', $id, $product, $this->config);
1662
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1663
 
1664
- /**
1665
- * Get Product Title
1666
- *
1667
- * @param WC_Product $product
1668
- *
1669
- * @return mixed
1670
- * @since 3.2.0
1671
- *
1672
- */
1673
- protected function title( $product ) {
1674
- $title = woo_feed_strip_all_tags($this->remove_short_codes($product->get_name()));
1675
-
1676
- // Add all available variation attributes to variation title.
1677
- if ( $product->is_type('variation') && ! empty($product->get_attributes()) ) {
1678
- $title = $this->parent_title($product);
1679
- $attributes = [];
1680
- foreach ( $product->get_attributes() as $slug => $value ) {
1681
- $attribute = $product->get_attribute($slug);
1682
- if ( empty($attribute) ) {
1683
- continue;
1684
- }
1685
- $attributes[ $slug ] = $attribute;
1686
- }
1687
-
1688
- // set variation attributes with separator
1689
- if ( isset($this->config['provider']) && 'google' === $this->config['provider'] ) {
1690
- $variation_attributes = implode(' - ', $attributes);
1691
- } else {
1692
- $variation_attributes = implode(', ', $attributes);
1693
- }
1694
-
1695
- //get product title with variation attribute
1696
- $get_with_var_attributes = apply_filters("woo_feed_get_product_title_with_variation_attribute", true, $product, $this->config);
1697
-
1698
- if ( $get_with_var_attributes ) {
1699
- $title .= " - " . $variation_attributes;
1700
- }
1701
- }
1702
-
1703
- return apply_filters('woo_feed_filter_product_title', $title, $product, $this->config);
1704
- }
1705
-
1706
- /**
1707
- * Get Parent Product Title
1708
- *
1709
- * @param WC_Product $product Product Object.
1710
- *
1711
- * @return mixed
1712
- * @author Nazrul Islam Nayan
1713
- * @since 5.1.8
1714
- */
1715
- protected function parent_title( $product ) {
1716
- if ( $product->is_type('variation') ) {
1717
- $product = wc_get_product($product->get_parent_id());
1718
- $title = woo_feed_strip_all_tags($this->remove_short_codes($product->get_name()));
1719
- } else {
1720
- $title = $this->title($product);
1721
- }
1722
-
1723
- return apply_filters('woo_feed_filter_product_parent_title', $title, $product, $this->config);
1724
- }
1725
-
1726
- /**
1727
- * Get All in One SEO Canonical URL
1728
- *
1729
- * @param WC_Product $product
1730
- *
1731
- * @return mixed
1732
- * @since 4.4.12
1733
- */
1734
- protected function _aioseop_canonical_url( $product ) {
1735
- $aioseop_canonical_url = '';
1736
- if ( is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post') ) {
1737
- $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
1738
- $aioseop_canonical_url = $post->canonical_url;
1739
- }
1740
-
1741
- return apply_filters('woo_feed_filter_product_aioseop_canonical_url', $aioseop_canonical_url, $product, $this->config);
1742
- }
1743
-
1744
- /**
1745
- * Get Yoast Product Title
1746
- *
1747
- * @param WC_Product $product
1748
- *
1749
- * @return mixed
1750
- * @since 3.2.0
1751
- *
1752
- */
1753
- protected function yoast_wpseo_title( $product ) {
1754
- $product_id = woo_feed_parent_product_id($product);
1755
- $yoast_title = get_post_meta($product_id, '_yoast_wpseo_title', true);
1756
- if ( strpos($yoast_title, '%%') !== false ) {
1757
- $title = strstr($yoast_title, '%%', true);
1758
- if ( empty($title) ) {
1759
- $title = get_the_title($product_id);
1760
- }
1761
- $wpseo_titles = get_option('wpseo_titles');
1762
-
1763
- $sep_options = WPSEO_Option_Titles::get_instance()->get_separator_options();
1764
- if ( isset($wpseo_titles['separator']) && isset($sep_options[ $wpseo_titles['separator'] ]) ) {
1765
- $sep = $sep_options[ $wpseo_titles['separator'] ];
1766
- } else {
1767
- $sep = '-'; //setting default separator if Admin didn't set it from backed
1768
- }
1769
-
1770
- $site_title = get_bloginfo('name');
1771
-
1772
- $meta_title = $title . ' ' . $sep . ' ' . $site_title;
1773
-
1774
- if ( ! empty($meta_title) ) {
1775
- $title = $meta_title;
1776
- }
1777
- } elseif ( ! empty($yoast_title) ) {
1778
- $title = $yoast_title;
1779
- } else {
1780
- $title = $this->title($product);
1781
- }
1782
-
1783
- return apply_filters('woo_feed_filter_product_yoast_wpseo_title', $title, $product, $this->config);
1784
- }
1785
-
1786
- /**
1787
- * Get Yoast Canonical URL
1788
- *
1789
- * @param WC_Product $product
1790
- *
1791
- * @return mixed
1792
- * @since 4.3.77
1793
- */
1794
- protected function yoast_canonical_url( $product ) {
1795
- $product_id = woo_feed_parent_product_id($product);
1796
- $yoast_canonical_url = get_post_meta($product_id, '_yoast_wpseo_canonical', true);
1797
-
1798
- return apply_filters('woo_feed_filter_product_yoast_canonical_url', $yoast_canonical_url, $product, $this->config);
1799
- }
1800
-
1801
- /**
1802
- * Get Rank Math Product Title
1803
- *
1804
- * @param WC_Product $product
1805
- *
1806
- * @return mixed
1807
- * @since 5.1.3
1808
- */
1809
- protected function rank_math_title( $product ) {
1810
- $rank_title = '';
1811
- $post_title = '';
1812
- $page = '';
1813
- $sep = '';
1814
- $sitemap = '';
1815
- if ( class_exists('RankMath') ) {
1816
- $title = get_post_meta($product->get_id(), 'rank_math_title', true);
1817
- if ( empty($title) ) {
1818
- $title_format = Helper::get_settings("titles.pt_product_title");
1819
- $title_format = $title_format ? $title_format : '%title%';
1820
- $sep = Helper::get_settings('titles.title_separator');
1821
-
1822
- $rank_title = str_replace('%title%', $product->get_title(), $title_format);
1823
- $rank_title = str_replace('%sep%', $sep, $rank_title);
1824
- $rank_title = str_replace('%page%', '', $rank_title);
1825
- $rank_title = str_replace('%sitename%', get_bloginfo('name'), $rank_title);
1826
- } else {
1827
- $rank_title = $title;
1828
- }
1829
- }
1830
-
1831
- return apply_filters('woo_feed_filter_product_rank_math_title', $rank_title, $product, $this->config);
1832
- }
1833
-
1834
- /**
1835
- * Get Rank Math Product Description
1836
- *
1837
- * @param WC_Product $product
1838
- *
1839
- * @return mixed
1840
- * @since 5.1.3
1841
- */
1842
- protected function rank_math_description( $product ) {
1843
- $description = '';
1844
- if ( class_exists('RankMath') ) {
1845
- $description = get_post_meta($product->get_id(), 'rank_math_description');
1846
- $desc_format = Helper::get_settings("titles.pt_post_description");
1847
-
1848
- if ( empty($description) ) {
1849
- if ( ! empty($desc_format) && strpos( (string)$desc_format, 'excerpt') !== false ) {
1850
- $description = str_replace('%excerpt%', get_the_excerpt($product->get_id()), $desc_format);
1851
- }
1852
-
1853
- // Get Variation Description
1854
- if ( $product->is_type('variation') && empty($description) ) {
1855
- $parent = wc_get_product($product->get_parent_id());
1856
- $description = $parent->get_description();
1857
- }
1858
- }
1859
-
1860
- if ( is_array($description) ) {
1861
- $description = reset($description);
1862
- }
1863
-
1864
- $description = $this->remove_short_codes($description);
1865
-
1866
- //strip tags and spacial characters
1867
- $strip_description = woo_feed_strip_all_tags(wp_specialchars_decode($description));
1868
-
1869
- $description = ! empty(strlen($strip_description)) && 0 < strlen($strip_description) ? $strip_description : $description;
1870
- }
1871
-
1872
- return apply_filters('woo_feed_filter_product_rank_math_description', $description, $product, $this->config);
1873
- }
1874
-
1875
- /**
1876
- * Get Rank Math Canonical URL
1877
- *
1878
- * @param WC_Product $product
1879
- *
1880
- * @return mixed
1881
- * @since 5.1.6
1882
- */
1883
- protected function rank_math_canonical_url( $product ) {
1884
- $canonical_url = '';
1885
 
1886
- if ( class_exists('RankMath') ) {
1887
- $post_canonical_url = get_post_meta($product->get_id(), 'rank_math_canonical_url');
 
1888
 
1889
- if ( empty($post_canonical_url) ) {
1890
- $canonical_url = get_the_permalink($product->get_id());
1891
- } else {
1892
- $canonical_url = $post_canonical_url;
1893
- }
1894
 
1895
- if ( is_array($canonical_url) ) {
1896
- $canonical_url = reset($canonical_url);
1897
- }
1898
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1899
 
1900
- return apply_filters('woo_feed_filter_product_rank_math_canonical_url', $canonical_url, $product, $this->config);
1901
- }
1902
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1903
 
1904
- /**
1905
- * Get All In One Product Title
1906
- *
1907
- * @param WC_Product $product
1908
- *
1909
- * @return mixed
1910
- * @since 3.2.0
1911
- *
1912
- */
1913
- protected function _aioseop_title( $product ) {
1914
- $title = '';
1915
- if ( is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post') ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1916
 
1917
- $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
1918
- $title = ! empty($post->title) ? $post->title : aioseo()->meta->title->getPostTypeTitle('product');
1919
- }
 
 
 
 
 
 
 
 
 
 
1920
 
1921
- $title = ! empty($title) ? $title : $this->title($product);
 
 
 
1922
 
1923
- return apply_filters('woo_feed_filter_product_aioseop_title', $title, $product, $this->config);
1924
- }
1925
 
1926
- /**
1927
- * Get Product Description
1928
- *
1929
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1930
- *
1931
- * @return mixed|string
1932
- * @since 3.2.0
1933
- *
1934
- */
1935
- protected function description( $product ) {
1936
- $description = $product->get_description();
1937
-
1938
- // Get Variation Description
1939
- if ( $product->is_type('variation') && empty($description) ) {
1940
- $parent = wc_get_product($product->get_parent_id());
1941
-
1942
- if ( is_object($parent) ) {
1943
- $description = $parent->get_description();
1944
- } else {
1945
- $description = '';
1946
- }
1947
- }
1948
- $description = $this->remove_short_codes($description);
1949
-
1950
- // Add variations attributes after description to prevent Facebook error
1951
- if ( 'facebook' == $this->config['provider'] && $product->is_type('variation') ) {
1952
- $variationInfo = explode('-', $product->get_name());
1953
- if ( isset($variationInfo[1]) ) {
1954
- $extension = $variationInfo[1];
1955
- } else {
1956
- $extension = $product->get_id();
1957
- }
1958
- $description .= ' ' . $extension;
1959
- }
1960
-
1961
- //strip tags and spacial characters
1962
- $strip_description = woo_feed_strip_all_tags(wp_specialchars_decode($description));
1963
-
1964
- $description = ! empty(strlen($strip_description)) && 0 < strlen($strip_description) ? $strip_description : $description;
1965
-
1966
- return apply_filters('woo_feed_filter_product_description', $description, $product, $this->config);
1967
- }
1968
-
1969
- /**
1970
- * Get Product Description (with HTML)
1971
- *
1972
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1973
- *
1974
- * @return mixed|string
1975
- * @since 5.2.41
1976
- */
1977
- protected function description_with_html( $product ) {
1978
- $description = $product->get_description();
1979
-
1980
- // Get Variation Description
1981
- if ( $product->is_type('variation') && empty($description) ) {
1982
- $parent = wc_get_product($product->get_parent_id());
1983
- $description = $parent->get_description();
1984
- }
1985
- $description = $this->remove_short_codes($description);
1986
-
1987
- // Add variations attributes after description to prevent Facebook error
1988
- if ( 'facebook' === $this->config['provider'] && $product->is_type('variation') ) {
1989
- $variationInfo = explode('-', $product->get_name());
1990
- if ( isset($variationInfo[1]) ) {
1991
- $extension = $variationInfo[1];
1992
- } else {
1993
- $extension = $product->get_id();
1994
- }
1995
- $description .= ' ' . $extension;
1996
- }
1997
-
1998
- //remove spacial characters
1999
- $strip_description = wp_check_invalid_utf8(wp_specialchars_decode($description), true);
2000
-
2001
- return apply_filters('woo_feed_filter_product_description_with_html', $description, $product, $this->config);
2002
- }
2003
-
2004
- /**
2005
- * Get Yoast Product Description
2006
- *
2007
- * @param WC_Product $product
2008
- *
2009
- * @return mixed
2010
- * @since 3.2.0
2011
- *
2012
- */
2013
- protected function yoast_wpseo_metadesc( $product ) {
2014
- $product_id = woo_feed_parent_product_id($product);
2015
- $description = '';
2016
- if ( class_exists('WPSEO_Frontend') ) {
2017
- $description = wpseo_replace_vars(WPSEO_Meta::get_value('metadesc', $product_id),
2018
- get_post($product->get_id()));
2019
- } else {
2020
- $description = YoastSEO()->meta->for_post($product_id)->description;
2021
  }
2022
 
2023
- if ( empty($description) ) {
2024
- $description = $this->description($product);
2025
- }
 
 
 
 
 
 
 
 
 
 
2026
 
2027
- return apply_filters('woo_feed_filter_product_yoast_wpseo_metadesc', $description, $product, $this->config);
2028
- }
2029
 
2030
- /**
2031
- * Get All In One Product Description
2032
- *
2033
- * @param WC_Product $product
2034
- *
2035
- * @return mixed
2036
- * @since 3.2.0
2037
- *
2038
- */
2039
- protected function _aioseop_description( $product ) {
2040
- $description = '';
2041
 
2042
- if ( is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post') ) {
 
 
 
2043
 
2044
- $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
2045
- $description = ! empty($post->description) ? $post->description : aioseo()->meta->description->getPostTypeDescription('product');
2046
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2047
 
2048
- if ( empty($description) ) {
2049
- $description = $this->description($product);
2050
- }
2051
 
2052
- return apply_filters('woo_feed_filter_product_aioseop_description', $description, $product, $this->config);
2053
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2054
 
2055
- /**
2056
- * Get Product Short Description
2057
- *
2058
- * @param WC_Product $product
2059
- *
2060
- * @return mixed|string
2061
- * @since 3.2.0
2062
- *
2063
- */
2064
- protected function short_description( $product ) {
2065
- $short_description = $product->get_short_description();
2066
 
2067
- // Get Variation Short Description
2068
- if ( $product->is_type('variation') && empty($short_description) ) {
2069
- $parent = wc_get_product($product->get_parent_id());
2070
- $short_description = $parent->get_short_description();
2071
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2072
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2073
 
2074
- $short_description = $this->remove_short_codes($short_description);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2075
 
2076
- //strip tags and spacial characters
2077
- $short_description = woo_feed_strip_all_tags(wp_specialchars_decode($short_description));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2078
 
2079
- return apply_filters('woo_feed_filter_product_short_description', $short_description, $product, $this->config);
2080
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2081
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2082
 
2083
- /**
2084
- * At First convert Short Codes and then Remove failed Short Codes from String
2085
- *
2086
- * @param $content
2087
- *
2088
- * @return mixed|string
2089
- * @since 3.2.0
2090
- *
2091
- */
2092
- protected function remove_short_codes( $content ) {
2093
- if ( $content == '' ) {
2094
- return '';
2095
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2096
 
2097
- $content = do_shortcode($content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2098
 
2099
- $content = woo_feed_stripInvalidXml($content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2100
 
2101
- // Covers all kinds of shortcodes
2102
- $expression = '/\[\/*[a-zA-Z1-90_| -=\'"\{\}]*\/*\]/m';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2103
 
2104
- $content = preg_replace( $expression, '', $content );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2105
 
2106
- return strip_shortcodes($content);
2107
- }
 
2108
 
2109
- /*
2110
- * Retrieves product's parent category
2111
- *
2112
- * @param $product A Post/Product object
2113
- *
2114
- * @return WP_Term
2115
- * @since 4.4.19
2116
- * */
2117
- protected function product_parent_category_object( $product ) {
2118
- global $parent_category_memo;
2119
- if ( empty( $parent_category_memo ) ) {
2120
- $parent_category_memo = [];
2121
- }
2122
-
2123
- $id = $product->get_id();
2124
- if ( $product->is_type('variation') ) {
2125
- $id = $product->get_parent_id();
2126
- }
2127
-
2128
- $taxonomy = 'product_cat';
2129
- $categories = wp_get_post_terms( $id, $taxonomy );
2130
- $child_category = $categories[ count( $categories ) - 1 ]; // Last selected category
2131
-
2132
- $parent_category = '';
2133
-
2134
- // Memoization for faster parent retrieval
2135
- if (
2136
- isset( $parent_category_memo[ $child_category->term_id ] )
2137
- && ! empty( $parent_category_memo[ $child_category->term_id ] )
2138
- ) {
2139
- $parent_category = get_term_by( 'term_id', $parent_category_memo[ $child_category->term_id ], $taxonomy );
2140
- } else {
2141
- $parent_category = woo_feed_parent_category( $child_category, $taxonomy );
2142
- $parent_category_memo[ $child_category->term_id ] = $parent_category->term_id;
2143
- }
2144
-
2145
- // Yoast SEO primary term fetching
2146
- if ( class_exists( 'WPSEO_Primary_Term' ) ) {
2147
- $wpseo_primary_term = new WPSEO_Primary_Term( $taxonomy, $id );
2148
- $parent_category_id = $wpseo_primary_term->get_primary_term();
2149
- if ( ! empty( $parent_category_id ) ) {
2150
- $parent_category = get_term_by( 'term_id', $parent_category_id, $taxonomy );
2151
- }
2152
- }
2153
-
2154
- return $parent_category;
2155
- }
2156
-
2157
- /**
2158
- * Get Product Parent/Main Category
2159
- *
2160
- * @param WC_Product $product
2161
- *
2162
- * @return string
2163
- *
2164
- */
2165
- protected function primary_category( $product ) {
2166
- $parent_category = "";
2167
- $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2168
- $full_category = $this->product_type( $product );
2169
- if ( ! empty($full_category) ) {
2170
- $full_category_array = explode($separator,$full_category);
2171
- $parent_category = $full_category_array[0];
2172
- }
2173
-
2174
- return apply_filters('woo_feed_filter_product_primary_category', $parent_category, $product, $this->config);
2175
- }
2176
-
2177
- /**
2178
- * Get Product Parent/Main Category ID
2179
- *
2180
- * @param WC_Product $product
2181
- *
2182
- * @return string
2183
- *
2184
- */
2185
- protected function primary_category_id( $product ) {
2186
- $parent_category_id = "";
2187
- $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2188
- $full_category = $this->product_type( $product );
2189
- if ( ! empty($full_category) ) {
2190
- $full_category_array = explode($separator,$full_category);
2191
- $parent_category_obj = get_term_by( 'name', $full_category_array[0], 'product_cat' );
2192
- $parent_category_id = isset($parent_category_obj->term_id) ? $parent_category_obj->term_id : "";
2193
- }
2194
-
2195
- return apply_filters('woo_feed_filter_product_primary_category_id', $parent_category_id, $product, $this->config);
2196
- }
2197
-
2198
- /**
2199
- * Get Product Child Category
2200
- *
2201
- * @param WC_Product $product
2202
- *
2203
- * @return string
2204
- */
2205
- protected function child_category( $product ) {
2206
- $child_category = "";
2207
- $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2208
- $full_category = $this->product_type( $product );
2209
- if ( ! empty($full_category) ) {
2210
- $full_category_array = explode($separator,$full_category);
2211
- $child_category = end($full_category_array);
2212
- }
2213
-
2214
- return apply_filters('woo_feed_filter_product_child_category', $child_category, $product, $this->config);
2215
- }
2216
-
2217
- /**
2218
- * Get Product Child Category ID
2219
- *
2220
- * @param WC_Product $product
2221
- *
2222
- * @return string
2223
- */
2224
- protected function child_category_id( $product ) {
2225
- $child_category_id = "";
2226
- $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2227
- $full_category = $this->product_type( $product );
2228
- if ( ! empty($full_category) ) {
2229
- $full_category_array = explode($separator,$full_category);
2230
- $child_category_obj = get_term_by( 'name', end($full_category_array), 'product_cat' );
2231
- $child_category_id = isset($child_category_obj->term_id) ? $child_category_obj->term_id : "";
2232
- }
2233
-
2234
- return apply_filters('woo_feed_filter_product_child_category_id', $child_category_id, $product, $this->config);
2235
- }
2236
-
2237
- /**
2238
- * Get Product Categories
2239
- *
2240
- * @param WC_Product $product
2241
- *
2242
- * @return string
2243
- * @since 3.2.0
2244
- *
2245
- */
2246
- protected function product_type( $product ) {
2247
- $id = $product->get_id();
2248
- if ( $product->is_type('variation') ) {
2249
- $id = $product->get_parent_id();
2250
- }
2251
 
2252
- $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
 
 
2253
 
2254
- $product_type = woo_feed_strip_all_tags(wc_get_product_category_list($id, $separator));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2255
 
2256
- $product_categories = '';
2257
- $term_list = get_the_terms( $id, 'product_cat' );
2258
 
2259
- if ( is_array($term_list) ) {
2260
- $col = array_column( $term_list, "term_id" );
2261
- array_multisort( $col, SORT_ASC, $term_list );
2262
- $term_list = array_column( $term_list, "name" );
2263
- $product_categories = implode( $separator, $term_list );
2264
- }
2265
 
 
 
2266
 
2267
- return apply_filters('woo_feed_filter_product_local_category', $product_categories, $product, $this->config);
2268
- }
2269
 
2270
- /**
2271
- * Get Product Full Categories with unselected category parent
2272
- *
2273
- * @param WC_Product $product
2274
- *
2275
- * @return string
2276
- * @since 4.3.47
2277
- */
2278
- protected function product_full_cat( $product ) {
2279
- // $id = $product->get_id();
2280
- // if ($product->is_type('variation')) {
2281
- // $id = $product->get_parent_id();
2282
- // }
2283
- //
2284
- // $separator = apply_filters('woo_feed_product_type_separator', '>', $this->config, $product);
2285
- //
2286
- // $product_type = woo_feed_get_terms_list_hierarchical_order($id);
2287
 
2288
- $product_type = $this->product_type($product);
 
 
 
 
 
 
 
 
 
 
 
 
 
2289
 
2290
- return apply_filters('woo_feed_filter_product_local_category', $product_type, $product, $this->config);
2291
- }
2292
 
2293
- /**
2294
- * Get Product URL
2295
- *
2296
- * @param WC_Product $product
2297
- *
2298
- * @return string
2299
- * @since 3.2.0
2300
- *
2301
- */
2302
- protected function link( $product ) {
2303
 
2304
- $link = $product->get_permalink();
 
2305
 
2306
- $link = $this->add_utm_tracker( $link );
2307
 
2308
- return apply_filters('woo_feed_filter_product_link', $link, $product, $this->config);
2309
- }
2310
 
2311
- /**
2312
- * Adding UTM Tracker Query Arguments to URL
2313
- * @param string $url
 
2314
  *
2315
- * @return string $url
2316
- * @since 4.4.26
2317
- */
2318
- protected function add_utm_tracker( $url ) {
 
 
 
 
 
2319
 
2320
- $utm = $this->config['campaign_parameters'];
 
 
 
2321
 
2322
- if ( ! empty( $utm['utm_source'] ) && ! empty( $utm['utm_medium'] ) && ! empty( $utm['utm_campaign'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2323
 
2324
- $utm = [
2325
- 'utm_source' => str_replace(' ', '+', $utm['utm_source'] ),
2326
- 'utm_medium' => str_replace(' ', '+', $utm['utm_medium'] ),
2327
- 'utm_campaign' => str_replace(' ', '+', $utm['utm_campaign'] ),
2328
- 'utm_term' => str_replace(' ', '+', $utm['utm_term'] ),
2329
- 'utm_content' => str_replace(' ', '+', $utm['utm_content'] ),
2330
- ];
 
2331
 
2332
- $url = add_query_arg( array_filter( $utm ), $url );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2333
 
2334
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2335
 
2336
- return $url;
2337
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2338
 
2339
- /**
2340
- * Get Parent Product URL
2341
- *
2342
- * @param WC_Product $product
2343
- *
2344
- * @return string
2345
- * @author Nazrul Islam Nayan
2346
- * @since 5.1.8
2347
- */
2348
- protected function parent_link( $product ) {
2349
- if ( $product->is_type('variation') ) {
2350
- $product = wc_get_product($product->get_parent_id());
2351
- $link = $this->link($product);
2352
- } else {
2353
- $link = $this->link($product);
2354
- }
2355
-
2356
- return apply_filters('woo_feed_filter_product_parent_link', $link, $product, $this->config);
2357
- }
2358
-
2359
- /**
2360
- * Get Canonical Link
2361
- * @param WC_Product $product
2362
- * @return mixed
2363
- */
2364
- protected function canonical_link( $product ) {
2365
- if ( $product->is_type('variation') ) {
2366
- $product = wc_get_product($product->get_parent_id());
2367
- $canonical_link = $product->get_permalink();
2368
- } else {
2369
- $canonical_link = $product->get_permalink();
2370
- }
2371
-
2372
- return apply_filters('woo_feed_filter_product_canonical_link', $canonical_link, $product, $this->config);
2373
- }
2374
-
2375
- /**
2376
- * Get External Product URL
2377
- *
2378
- * @param WC_Product $product
2379
- *
2380
- * @return string
2381
- * @since 3.2.0
2382
- *
2383
- */
2384
- protected function ex_link( $product ) {
2385
- if ( $product->is_type('external') ) {
2386
- $utm = $this->config['campaign_parameters'];
2387
- if ( ! empty($utm['utm_source']) && ! empty($utm['utm_medium']) && ! empty($utm['utm_campaign']) ) {
2388
- $utm = [
2389
- 'utm_source' => str_replace(' ', '+', $utm['utm_source'] ),
2390
- 'utm_medium' => str_replace(' ', '+', $utm['utm_medium'] ),
2391
- 'utm_campaign' => str_replace(' ', '+', $utm['utm_campaign'] ),
2392
- 'utm_term' => str_replace(' ', '+', $utm['utm_term'] ),
2393
- 'utm_content' => str_replace(' ', '+', $utm['utm_content'] ),
2394
- ];
2395
-
2396
- return add_query_arg(array_filter($utm), $product->get_product_url());
2397
- } else {
2398
- $ex_link = $product->get_product_url();
2399
- }
2400
- } else {
2401
- $ex_link = '';
2402
- }
2403
-
2404
- return apply_filters('woo_feed_filter_product_ex_link', $ex_link, $product, $this->config);
2405
- }
2406
-
2407
- /**
2408
- * Get Product Image
2409
- *
2410
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2411
- *
2412
- * @return mixed
2413
- * @since 3.2.0
2414
- *
2415
- */
2416
- protected function image( $product ) {
2417
- $image = '';
2418
- if ( $product->is_type('variation') ) {
2419
- // Variation product type
2420
- if ( has_post_thumbnail( $product->get_id() ) ) {
2421
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ), 'single-post-thumbnail' );
2422
- $image = woo_feed_get_formatted_url($getImage[0]);
2423
- } elseif ( has_post_thumbnail( $product->get_parent_id() ) ) {
2424
- $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_parent_id()), 'single-post-thumbnail');
2425
- $image = woo_feed_get_formatted_url($getImage[0]);
2426
- }
2427
- } elseif ( has_post_thumbnail( $product->get_id() ) ) { // All product type except variation
2428
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ), 'single-post-thumbnail' );
2429
- $image = isset( $getImage[0] ) ? woo_feed_get_formatted_url( $getImage[0] ) : '';
2430
- }
2431
-
2432
- return apply_filters('woo_feed_filter_product_image', $image, $product, $this->config);
2433
- }
2434
-
2435
- /**
2436
- * Get Product Featured Image. For product variations it will return the variable product image.
2437
- *
2438
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2439
- *
2440
- * @return mixed
2441
- * @since 3.2.0
2442
- *
2443
- */
2444
- protected function feature_image( $product ) {
2445
- if ( $product->is_type('variation') ) {
2446
- $id = $product->get_parent_id();
2447
- }else {
2448
- $id = $product->get_id();
2449
- }
2450
-
2451
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $id ), 'single-post-thumbnail' );
2452
- $image = isset( $getImage[0] ) ? woo_feed_get_formatted_url( $getImage[0] ) : '';
2453
-
2454
- return apply_filters('woo_feed_filter_product_feature_image', $image, $product, $this->config);
2455
- }
2456
-
2457
- /**
2458
- * Get Comma Separated Product Images
2459
- *
2460
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2461
- * @param string $additionalImg Specific Additional Image.
2462
- *
2463
- * @return mixed
2464
- * @since 3.2.0
2465
- *
2466
- */
2467
- protected function images( $product, $additionalImg = '' ) {
2468
- $imgUrls = $this->get_product_gallery($product);
2469
- $separator = ',';
2470
-
2471
- // Return Specific Additional Image URL
2472
- if ( '' !== $additionalImg ) {
2473
- if ( array_key_exists($additionalImg, $imgUrls) ) {
2474
- $images = $imgUrls[ $additionalImg ];
2475
- } else {
2476
- $images = '';
2477
- }
2478
- } else {
2479
- if( isset($this->config['provider']) && "idealo" === $this->config['provider'] ) {
2480
- $separator = ';';
2481
- }
2482
-
2483
- $images = implode($separator, array_filter($imgUrls));
2484
- }
2485
-
2486
- return apply_filters('woo_feed_filter_product_images', $images, $product, $this->config);
2487
- }
2488
-
2489
- /**
2490
- * Get Product Gallery Items (URL) array.
2491
- * This can contains empty array values
2492
- *
2493
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product
2494
- *
2495
- * @return string[]
2496
- * @since 3.2.6
2497
- */
2498
- protected function get_product_gallery( $product ) {
2499
- $imgUrls = [];
2500
- $attachmentIds = [];
2501
-
2502
- if ( $product->is_type('variation') ) {
2503
- if ( class_exists('Woo_Variation_Gallery') ) {
2504
- /**
2505
- * Get Variation Additional Images for "Additional Variation Images Gallery for WooCommerce"
2506
- * @plugin Additional Variation Images Gallery for WooCommerce
2507
- * @link https://wordpress.org/plugins/woo-variation-gallery/
2508
- */
2509
- $attachmentIds = get_post_meta($product->get_id(), 'woo_variation_gallery_images', true);
2510
- } elseif ( class_exists('WooProductVariationGallery') ) {
2511
- /**
2512
- * Get Variation Additional Images for "Variation Images Gallery for WooCommerce"
2513
- * @plugin Variation Images Gallery for WooCommerce
2514
- * @link https://wordpress.org/plugins/woo-product-variation-gallery/
2515
- */
2516
- $attachmentIds = get_post_meta($product->get_id(), 'rtwpvg_images', true);
2517
- }
2518
- elseif ( class_exists('WC_Additional_Variation_Images') ) {
2519
- /**
2520
- * Get Variation Additional Images for "WooCommerce Additional Variation Images"
2521
- * @plugin WooCommerce Additional Variation Images
2522
- * @link https://woocommerce.com/products/woocommerce-additional-variation-images/
2523
- */
2524
- $attachmentIds = explode(',',get_post_meta($product->get_id(), '_wc_additional_variation_images', true));
2525
- }elseif ( class_exists('WOODMART_Theme') ) {
2526
- /**
2527
- * Get Variation Additional Images for "WOODMART Theme -> Variation Gallery Images Feature"
2528
- * @theme WOODMART
2529
- * @link https://themeforest.net/item/woodmart-woocommerce-wordpress-theme/20264492
2530
- */
2531
- $var_id = $product->get_id();
2532
- $parent_id = $product->get_parent_id();
2533
-
2534
- $variation_obj = get_post_meta($parent_id, 'woodmart_variation_gallery_data', true);
2535
- if ( isset($variation_obj) && isset($variation_obj[ $var_id ]) ) {
2536
- $attachmentIds = explode(',', $variation_obj[ $var_id ]);
2537
- }else {
2538
- $attachmentIds = explode(',',get_post_meta($var_id, 'wd_additional_variation_images_data', true));
2539
- }
2540
- }else {
2541
- /**
2542
- * If any Variation Gallery Image plugin not installed then get Variable Product Additional Image Ids .
2543
- */
2544
- $attachmentIds = wc_get_product($product->get_parent_id())->get_gallery_image_ids();
2545
- }
2546
- }
2547
-
2548
- /**
2549
- * Get Variable Product Gallery Image ids if Product is not a variation
2550
- * or variation does not have any gallery images
2551
- */
2552
- if ( empty($attachmentIds) ) {
2553
- $attachmentIds = $product->get_gallery_image_ids();
2554
- }
2555
-
2556
- if ( $attachmentIds && is_array($attachmentIds) ) {
2557
- $mKey = 1;
2558
- foreach ( $attachmentIds as $attachmentId ) {
2559
- $imgUrls[ $mKey ] = woo_feed_get_formatted_url(wp_get_attachment_url($attachmentId));
2560
- $mKey++;
2561
- }
2562
- }
2563
-
2564
- return $imgUrls;
2565
- }
2566
-
2567
- /**
2568
- * Get Product Condition
2569
- *
2570
- * @param WC_Product $product
2571
- *
2572
- * @return mixed
2573
- * @since 3.2.0
2574
- *
2575
- */
2576
- protected function condition( $product ) {
2577
- return apply_filters('woo_feed_product_condition', 'new', $product);
2578
- }
2579
 
2580
- /**
2581
- * Get Product Type
2582
- *
2583
- * @param WC_Product $product
2584
- *
2585
- * @return mixed
2586
- * @since 3.2.0
2587
- *
2588
- */
2589
- protected function type( $product ) {
2590
- return apply_filters('woo_feed_filter_product_type', $product->get_type(), $product, $this->config);
2591
- }
 
 
 
 
 
 
2592
 
2593
- /**
2594
- * Get Product is a bundle product or not
2595
- *
2596
- * @param WC_Product $product
2597
- *
2598
- * @return mixed
2599
- * @since 3.2.0
2600
- *
2601
- */
2602
- protected function is_bundle( $product ) {
2603
- if ( $product->is_type('bundle') || $product->is_type('yith_bundle') ) {
2604
- $is_bundle = 'yes';
2605
- } else {
2606
- $is_bundle = 'no';
2607
- }
2608
-
2609
- return apply_filters('woo_feed_filter_product_is_bundle', $is_bundle, $product, $this->config);
2610
- }
2611
-
2612
- /**
2613
- * Get Product is a multi-pack product or not
2614
- *
2615
- * @param WC_Product $product
2616
- *
2617
- * @return mixed
2618
- * @since 3.2.0
2619
- *
2620
- */
2621
- protected function multipack( $product ) {
2622
- $multi_pack = '';
2623
- if ( $product->is_type('grouped') ) {
2624
- $multi_pack = ( ! empty($product->get_children())) ? count($product->get_children()) : '';
2625
- }
2626
-
2627
- return $multi_pack;
2628
- }
2629
-
2630
- /**
2631
- * Get Product visibility status
2632
- *
2633
- * @param WC_Product $product
2634
- *
2635
- * @return mixed
2636
- * @since 3.2.0
2637
- *
2638
- */
2639
- protected function visibility( $product ) {
2640
- return apply_filters('woo_feed_filter_product_visibility', $product->get_catalog_visibility(), $product, $this->config);
2641
- }
2642
 
2643
- /**
2644
- * Get Product Total Rating
2645
- *
2646
- * @param WC_Product $product
2647
- *
2648
- * @return mixed
2649
- * @since 3.2.0
2650
- *
2651
- */
2652
- protected function rating_total( $product ) {
2653
- return apply_filters('woo_feed_filter_product_rating_total', $product->get_rating_count(), $product, $this->config);
2654
- }
2655
 
2656
- /**
2657
- * Get Product average rating
2658
- *
2659
- * @param WC_Product $product
2660
- *
2661
- * @return mixed
2662
- * @since 3.2.0
2663
- *
2664
- */
2665
- protected function rating_average( $product ) {
2666
- return apply_filters('woo_feed_filter_product_rating_average', $product->get_average_rating(), $product, $this->config);
2667
- }
2668
 
2669
- /**
2670
- * Get Product tags
2671
- *
2672
- * @param WC_Product $product
2673
- *
2674
- * @return string
2675
- * @since 3.2.0
2676
- *
2677
- */
2678
- protected function tags( $product ) {
2679
- $id = $product->get_id();
2680
- if ( $product->is_type('variation') ) {
2681
- $id = $product->get_parent_id();
2682
- }
2683
-
2684
- /**
2685
- * Separator for multiple tags
2686
- * @param string $separator
2687
- * @param array $config
2688
- * @param WC_Abstract_Legacy_Product $product
2689
- * @since 3.4.3
2690
- */
2691
- $separator = apply_filters('woo_feed_tags_separator', ',', $this->config, $product);
2692
-
2693
- $tags = woo_feed_strip_all_tags(get_the_term_list($id, 'product_tag', '', $separator, ''));
2694
-
2695
- return apply_filters('woo_feed_filter_product_tags', $tags, $product, $this->config);
2696
- }
2697
-
2698
- /**
2699
- * Get Product Parent Id
2700
- *
2701
- * @param WC_Product $product
2702
- *
2703
- * @return mixed
2704
- * @since 3.2.0
2705
- *
2706
- */
2707
- protected function item_group_id( $product ) {
2708
- $id = $product->get_id();
2709
- if ( $product->is_type('variation') ) {
2710
- $id = $product->get_parent_id();
2711
- }
2712
-
2713
- return apply_filters('woo_feed_filter_product_item_group_id', $id, $product, $this->config);
2714
- }
2715
-
2716
- /**
2717
- * Get Product SKU
2718
- *
2719
- * @param WC_Product $product
2720
- *
2721
- * @return mixed
2722
- * @since 3.2.0
2723
- *
2724
- */
2725
- protected function sku( $product ) {
2726
- return apply_filters('woo_feed_filter_product_sku', $product->get_sku(), $product, $this->config);
2727
- }
2728
 
2729
- /**
2730
- * Get Product SKU ID. It should come with after merging of sku and product id with '_' sign.
2731
- *
2732
- * @param WC_Product $product
2733
- *
2734
- * @return string
2735
- * @author Nazrul Islam Nayan
2736
- * @since 4.3.13
2737
- */
2738
- protected function sku_id( $product ) {
2739
- $sku = ! empty($product->get_sku()) ? $product->get_sku() . '_' : '';
2740
- $sku_id = $sku . $product->get_id();
2741
-
2742
- return apply_filters('woo_feed_filter_product_sku_id', $sku_id, $product, $this->config);
2743
- }
2744
-
2745
- /**
2746
- * Get Product Parent SKU
2747
- *
2748
- * @param WC_Product $product
2749
- *
2750
- * @return mixed
2751
- * @since 3.2.0
2752
- *
2753
- */
2754
- protected function parent_sku( $product ) {
2755
- if ( $product->is_type('variation') ) {
2756
- $id = $product->get_parent_id();
2757
- $parent = wc_get_product($id);
2758
-
2759
- $parent_sku = $parent->get_sku();
2760
- } else {
2761
- $parent_sku = $product->get_sku();
2762
- }
2763
-
2764
- return apply_filters('woo_feed_filter_product_parent_sku', $parent_sku, $product, $this->config);
2765
- }
2766
-
2767
- /**
2768
- * Get Product Availability Status
2769
- *
2770
- * @param WC_Product $product
2771
- *
2772
- * @return mixed
2773
- * @since 3.2.0
2774
- *
2775
- */
2776
- protected function availability( $product ) {
2777
- $status = $product->get_stock_status();
2778
- if ( 'instock' == $status ) {
2779
- $status = 'in stock';
2780
- } elseif ( 'outofstock' == $status ) {
2781
- $status = 'out of stock';
2782
- } elseif ( 'onbackorder' == $status ) {
2783
- $status = 'on backorder';
2784
- }
2785
-
2786
- // set (_) as separator for google merchant
2787
- if ( isset($this->config['provider']) && 'google' === $this->config['provider'] ) {
2788
- $status = explode(' ', $status);
2789
- $status = implode('_', $status);
2790
- }
2791
-
2792
- return apply_filters('woo_feed_filter_product_availability', $status, $product, $this->config);
2793
- }
2794
-
2795
- /**
2796
- * Get Product Availability Date
2797
- *
2798
- * @param WC_Product $product
2799
- *
2800
- * @return mixed
2801
- * @author Ohidul Islam
2802
- * @since 3.2.0
2803
- *
2804
- */
2805
- protected function availability_date( $product ) {
2806
 
2807
- $feed_settings = get_option( 'woo_feed_settings' );
 
2808
 
2809
- $availability_date_settings = isset( $feed_settings['woo_feed_identifier']['availability_date'] )
2810
- ? $feed_settings['woo_feed_identifier']['availability_date']
2811
- : 'enable' ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2812
 
2813
- if ( $product->get_stock_status() !== 'onbackorder' || $availability_date_settings === 'disable' ) {
2814
- return '';
2815
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2816
 
2817
- $meta_field_name = 'woo_feed_availability_date';
2818
 
2819
- if ( $product->is_type( 'variation' ) ) {
2820
- $meta_field_name .= '_var';
2821
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2822
 
2823
- $availability_date = get_post_meta($product->get_id(), $meta_field_name, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2824
 
2825
- if ( '' !== $availability_date && in_array($this->config['provider'], [
2826
- 'google',
2827
- 'facebook',
2828
- 'pinterest',
2829
- 'bing',
2830
- 'snapchat',
2831
- ], true) ) {
2832
- $availability_date = gmdate('c', strtotime($availability_date));
2833
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2834
 
2835
- return apply_filters('woo_feed_filter_product_availability_date', $availability_date, $product, $this->config);
2836
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2837
 
2838
- /**
2839
- * Get Product Add to Cart Link
2840
- *
2841
- * @param WC_Product $product
2842
- *
2843
- * @return string
2844
- * @author Nazrul Islam Nayan
2845
- * @since 5.1.8
2846
- */
2847
- protected function add_to_cart_link( $product ) {
2848
- $url = $this->link($product);
2849
- $suffix = 'add-to-cart=' . $product->get_id();
 
 
 
 
 
 
 
2850
 
2851
- $add_to_cart_link = woo_feed_make_url_with_parameter($url, $suffix);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2852
 
2853
- return apply_filters('woo_feed_filter_product_add_to_cart_link', $add_to_cart_link, $product, $this->config);
2854
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2855
 
2856
- /**
2857
- * Get Product Quantity
2858
- *
2859
- * @param WC_Product $product
2860
- *
2861
- * @return mixed
2862
- * @since 3.2.0
2863
- *
2864
- */
2865
- protected function quantity( $product ) {
2866
- $quantity = $product->get_stock_quantity();
2867
- $status = $product->get_stock_status();
2868
-
2869
- //when product is outofstock and it's quantity is empty, set quantity to 0
2870
- if ( 'outofstock' == $status && empty($quantity) ) {
2871
- $quantity = 0;
2872
- }
2873
-
2874
- if ( $product->is_type('variable') && $product->has_child() ) {
2875
- $visible_children = $product->get_visible_children();
2876
- $qty = array();
2877
- foreach ( $visible_children as $key => $child ) {
2878
- $childQty = get_post_meta($child, '_stock', true);
2879
- $qty[] = (int)$childQty + 0;
2880
- }
2881
-
2882
- if ( isset($this->config['variable_quantity']) ) {
2883
- $vaQty = $this->config['variable_quantity'];
2884
- if ( 'max' == $vaQty ) {
2885
- $quantity = max($qty);
2886
- } elseif ( 'min' == $vaQty ) {
2887
- $quantity = min($qty);
2888
- } elseif ( 'sum' == $vaQty ) {
2889
- $quantity = array_sum($qty);
2890
- } elseif ( 'first' == $vaQty ) {
2891
- $quantity = ( (int)$qty[0]);
2892
- }
2893
-
2894
- $quantity = array_sum($qty);
2895
- }
2896
- }
2897
-
2898
- return apply_filters('woo_feed_filter_product_quantity', $quantity, $product, $this->config);
2899
- }
2900
-
2901
- /**
2902
- * Get Product Currency
2903
- *
2904
- * @param WC_Product $product
2905
- *
2906
- * @return mixed
2907
- * @since 4.4.39
2908
- *
2909
- */
2910
- protected function currency( $product ) {
2911
- $quantity = get_option( 'woocommerce_currency' );
2912
 
2913
- return apply_filters('woo_feed_filter_product_currency', $quantity, $product, $this->config);
2914
- }
 
 
 
 
 
2915
 
2916
- /**
2917
- * Get Store currency code.
2918
- *
2919
- * @param WC_Product $product Product Object
2920
- * @return mixed|string
2921
- * @since 3.2.0
2922
- *
2923
- */
2924
- protected function store_currency( $product ) {
2925
- return get_woocommerce_currency();
2926
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2927
 
2928
- /**
2929
- * Get Product Sale Price Start Date
2930
- *
2931
- * @param WC_Product $product
2932
- *
2933
- * @return mixed
2934
- * @since 3.2.0
2935
- *
2936
- */
2937
- protected function sale_price_sdate( $product ) {
2938
- $startDate = $product->get_date_on_sale_from();
2939
- if ( is_object($startDate) ) {
2940
- $sale_price_sdate = $startDate->date_i18n();
2941
- } else {
2942
- $sale_price_sdate = '';
2943
- }
2944
-
2945
- return apply_filters('woo_feed_filter_product_sale_price_sdate', $sale_price_sdate, $product, $this->config);
2946
- }
2947
-
2948
- /**
2949
- * Get Product Sale Price End Date
2950
- *
2951
- * @param WC_Product $product
2952
- *
2953
- * @return mixed
2954
- * @since 3.2.0
2955
- *
2956
- */
2957
- protected function sale_price_edate( $product ) {
2958
- $endDate = $product->get_date_on_sale_to();
2959
- if ( is_object($endDate) ) {
2960
- $sale_price_edate = $endDate->date_i18n();
2961
- } else {
2962
- $sale_price_edate = "";
2963
- }
2964
-
2965
- return apply_filters('woo_feed_filter_product_sale_price_edate', $sale_price_edate, $product, $this->config);
2966
- }
2967
-
2968
- /**
2969
- * Get feed currency
2970
- *
2971
- * @return mixed|string
2972
- */
2973
- protected function get_feed_currency() {
2974
- $currency = get_woocommerce_currency();
2975
- if ( isset($this->config['feedCurrency']) ) {
2976
- $currency = $this->config['feedCurrency'];
2977
- }
2978
-
2979
- return $currency;
2980
- }
2981
-
2982
- /**
2983
- * Get Product Price by default WooCommerce Price Type (regular_price|price|sale_price).
2984
- *
2985
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object
2986
- * @param string $price_type Price Type (regular_price|price|sale_price)
2987
- * @param bool $tax Add tax with price (true|false)
2988
- *
2989
- * @author Ohidul Islam
2990
- * @since 4.4.14
2991
- *
2992
- * @return float|mixed|string|void
2993
- */
2994
- protected function get_price_by_price_type( $product, $price_type, $tax ) {
2995
-
2996
- if ( 'regular_price' === $price_type ) {
2997
- $price = $product->get_regular_price();
2998
- } elseif ( 'price' === $price_type ) {
2999
- $price = $product->get_price();
3000
- } else {
3001
- $price = $product->get_sale_price();
3002
- }
3003
-
3004
- // Get WooCommerce Multi language Price by Currency.
3005
- $price = apply_filters('woo_feed_wcml_price',
3006
- $price, $product->get_id(), $this->get_feed_currency(), '_' . $price_type
3007
- );
3008
-
3009
- // Get Price with tax
3010
- if ( true === $tax ) {
3011
- $price = woo_feed_get_price_with_tax($price, $product);
3012
- }
3013
-
3014
- return $price;
3015
- }
3016
-
3017
- /**
3018
- * Get Product Price by Product Type.
3019
- *
3020
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object
3021
- * @param string $price_type Price Type (regular_price|price|sale_price)
3022
- * @param bool $tax Add tax with price (true|false)
3023
- *
3024
- * @author Ohidul Islam
3025
- * @since 4.4.14
3026
- *
3027
- * @return float|int|mixed|string
3028
- */
3029
- protected function get_price_by_product_type( $product, $price_type, $tax = false ) {
3030
- if ( $product->is_type('variable') ) {
3031
- $price = $this->getVariableProductPrice($product, $price_type, $tax);
3032
- } elseif ( $product->is_type('grouped') ) {
3033
- $price = $this->getGroupProductPrice($product, $price_type, $tax);
3034
- } elseif ( $product->is_type('bundle') ) {
3035
- //TODO Diff taxation
3036
- $price = $this->getBundleProductPrice($product, $price_type, $tax);
3037
- } elseif ( $product->is_type('composite') ) {
3038
- //TODO Diff taxation
3039
- $price = $this->getCompositeProductPrice($product, $price_type, $tax);
3040
- } elseif ( $product->is_type('bundled') ) {
3041
- // iconic woocommerce product bundled plugin
3042
- $price = $this->iconic_bundle_product_price($product, $price_type, $tax);
3043
- } else {
3044
- $price = $this->get_price_by_price_type($product, $price_type, $tax);
3045
- }
3046
-
3047
- return $price > 0 ? $price : '';
3048
- }
3049
-
3050
- /**
3051
- * Get Product Regular Price
3052
- *
3053
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
3054
- *
3055
- * @return mixed
3056
- * @since 3.2.0
3057
- *
3058
- */
3059
- protected function price( $product ) {
3060
 
3061
- $regular_price = $this->get_price_by_product_type($product, 'regular_price');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3062
 
3063
- return apply_filters('woo_feed_filter_product_price', $regular_price, $product, $this->config, false);
3064
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3065
 
3066
- /**
3067
- * Get Product Price
3068
- *
3069
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3070
- *
3071
- * @return int|float|mixed
3072
- * @since 3.2.0
3073
- *
3074
- */
3075
- protected function current_price( $product ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3076
 
3077
- $price = $this->get_price_by_product_type($product, 'price');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3078
 
3079
- return apply_filters('woo_feed_filter_product_regular_price', $price, $product, $this->config, false);
3080
- }
 
 
 
3081
 
3082
- /**
3083
- * Get Product Sale Price
3084
- *
3085
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3086
- *
3087
- * @return mixed
3088
- * @since 3.2.0
3089
- *
3090
- */
3091
- protected function sale_price( $product ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3092
 
3093
- $sale_price = $this->get_price_by_product_type($product, 'sale_price');
3094
 
3095
- return apply_filters('woo_feed_filter_product_sale_price', $sale_price, $product, $this->config, false);
3096
- }
 
3097
 
3098
- /**
3099
- * Get Product Regular Price with Tax
3100
- *
3101
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
3102
- *
3103
- * @return mixed
3104
- * @since 3.2.0
3105
- *
3106
- */
3107
- protected function price_with_tax( $product ) {
3108
 
3109
- $regular_price_with_tax = $this->get_price_by_product_type($product, 'regular_price', true);
 
 
 
 
 
 
 
 
3110
 
3111
- return apply_filters('woo_feed_filter_product_price_with_tax', $regular_price_with_tax, $product, $this->config, true);
3112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3113
 
3114
- /**
3115
- * Get Product Regular Price with Tax
3116
- *
3117
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3118
- *
3119
- * @return mixed
3120
- * @since 3.2.0
3121
- *
3122
- */
3123
- protected function current_price_with_tax( $product ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
3124
 
3125
- $price_with_tax = $this->get_price_by_product_type($product, 'price', true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3126
 
3127
- return apply_filters('woo_feed_filter_product_regular_price_with_tax', $price_with_tax, $product, $this->config, true);
3128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3129
 
3130
- /**
3131
- * Get Product Regular Price with Tax
3132
- *
3133
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3134
- *
3135
- * @return mixed
3136
- * @since 3.2.0
3137
- *
3138
- */
3139
- protected function sale_price_with_tax( $product ) {
 
 
 
 
3140
 
3141
- $sale_price_with_tax = $this->get_price_by_product_type($product, 'sale_price', true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3142
 
3143
- return apply_filters('woo_feed_filter_product_sale_price_with_tax', $sale_price_with_tax, $product, $this->config, true);
3144
- }
 
 
3145
 
3146
- /**
3147
- * Get Composite Product Price
3148
- *
3149
- * @param WC_Product|WC_Product_Composite|WC_Composite_Products $product Composite Product object.
3150
- * @param string $type Price Type (regular_price|price|sale_price)
3151
- * @param bool $tax Add tax with price (true|false)
3152
- *
3153
- * @return int|float|double
3154
- * @since 3.2.6
3155
- */
3156
- protected function getCompositeProductPrice( $product, $type, $tax = false ) {
3157
- if ( class_exists('WC_Product_Composite') && class_exists('WPCleverWooco') ) {
3158
- // WPC Composite Product
3159
- return $this->get_wpc_composite_price($product, $type, $tax);
3160
- } elseif ( class_exists('WC_Composite_Products') ) {
3161
- // WooCommerce Composite Product
3162
- return $this->get_wc_composite_product_price($product, $type, $tax);
3163
- } else {
3164
- // Get Base Price for Others Composite Products.
3165
- // Note*: YITH does not auto select components. So no need to calculate component price.
3166
- return $this->get_price_by_price_type($product, $type, $tax);
3167
- }
3168
- }
3169
-
3170
- /**
3171
- * Get WooCommerce Composite Product Price
3172
- * Plugin URL: https://wordpress.org/plugins/wpc-composite-products/
3173
- * Product Type: composite
3174
- *
3175
- * @param WC_Product|WC_Product_Composite $product
3176
- * @param string $type Price Type (regular_price|price|sale_price)
3177
- * @param bool $tax Add tax with price (true|false)
3178
- * @return float|int|mixed|string|void
3179
- */
3180
- protected function get_wc_composite_product_price( $product, $type, $tax ) {
3181
- $price = 0;
3182
- // Parent Component Price
3183
- $base_price = $this->get_price_by_price_type($product, $type, $tax);
3184
- if ( isset($this->config['composite_price']) && 'all_product_price' == $this->config['composite_price'] ) {
3185
- $composite = new WC_Product_Composite($product);
3186
-
3187
- if ( 'price' === $type || 'sale_price' === $type ) {
3188
- $price = $composite->get_composite_price();
3189
- } else {
3190
- $price = $composite->get_composite_regular_price();
3191
- }
3192
-
3193
- // Get WooCommerce Multi language Price by Currency.
3194
- $price = apply_filters('woo_feed_wcml_price',
3195
- $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3196
- );
3197
-
3198
- // Get Price with tax
3199
- if ( true === $tax ) {
3200
- $price = woo_feed_get_price_with_tax($price, $composite);
3201
- }
3202
- } else {
3203
- $price = $base_price;
3204
- }
3205
-
3206
- return $price > 0 ? $price : '';
3207
- }
3208
-
3209
- /**
3210
- * Get WPC Composite Product Price.
3211
- * Plugin URL: https://wordpress.org/plugins/wpc-composite-products/
3212
- * Product Type: composite
3213
- *
3214
- * @param WC_Product|WC_Product_Composite $product
3215
- * @param string $type Price Type (regular_price|price|sale_price)
3216
- * @param bool $tax Add tax with price (true|false)
3217
- * @return float|int|mixed|string|void
3218
- */
3219
- protected function get_wpc_composite_price( $product, $type, $tax ) {
3220
- $price = 0;
3221
- // Parent Component Price
3222
- $base_price = $this->get_price_by_price_type($product, $type, $tax);
3223
- if ( isset($this->config['composite_price']) && 'all_product_price' == $this->config['composite_price'] ) {
3224
- $components_price = 0;
3225
- $components = $product->get_components();
3226
- if ( ! empty($components) && is_array($components) ) {
3227
- foreach ( $components as $component ) {
3228
- $products = explode(',', $component['products']);
3229
- foreach ( $products as $key => $product_id ) {
3230
- $default_product = wc_get_product($product_id);
3231
- if ( is_object($default_product) && $default_product->is_in_stock() ) {
3232
- $quantity = (isset($component['qty']) && $component['qty'] > 0) ? $component['qty'] : 1;
3233
- if ( 'products' == $component['type'] && empty($component['price']) ) {
3234
- $components_price += $this->get_price_by_price_type($default_product, 'price', $tax);
3235
- $components_price *= $quantity;
3236
- } elseif ( 'products' == $component['type'] && ! empty($component['price']) ) {
3237
- $clever = new WPCleverWooco();
3238
- $old_price = $this->get_price_by_price_type($default_product, 'price', $tax);
3239
- $new_price = $component['price'];
3240
- $components_price += $clever::wooco_new_price($old_price, $new_price);
3241
- $components_price *= $quantity;
3242
- }
3243
- break; // Get first in stock product from component options.
3244
- }
3245
- }
3246
- }
3247
-
3248
- // Apply discount to components price.
3249
- $discount = $product->get_discount();
3250
- if ( $discount > 0 ) {
3251
- $components_price -= (($discount / 100) * $components_price);
3252
- }
3253
- }
3254
-
3255
- if ( 'exclude' === $product->get_pricing() ) {
3256
- $price = $components_price;
3257
- } elseif ( 'include' === $product->get_pricing() ) {
3258
- $price = $components_price + $base_price;
3259
- } elseif ( 'only' === $product->get_pricing() ) {
3260
- $price = $base_price;
3261
- }
3262
- } else {
3263
- $price = $base_price;
3264
- }
3265
-
3266
- return $price > 0 ? $price : '';
3267
- }
3268
-
3269
- /**
3270
- * Get total price of grouped product
3271
- *
3272
- * @param WC_Product_Grouped $grouped Grouped Product Object
3273
- * @param string $type Price Type (regular_price|price|sale_price)
3274
- * @param bool $tax Add tax with price (true|false)
3275
- *
3276
- * @return int|string
3277
- * @since 3.2.0
3278
- *
3279
- */
3280
- protected function getGroupProductPrice( $grouped, $type, $tax = false ) {
3281
- $groupProductIds = $grouped->get_children();
3282
- $price = 0;
3283
- if ( ! empty($groupProductIds) ) {
3284
- foreach ( $groupProductIds as $id ) {
3285
- $product = wc_get_product($id);
3286
- if ( ! is_object($product) ) {
3287
- continue; // make sure that the product exists..
3288
- }
3289
-
3290
- $get_price = $this->get_price_by_product_type($product, $type, $tax);
3291
- if ( ! empty($get_price) ) {
3292
- $price += $get_price;
3293
- }
3294
- }
3295
- }
3296
-
3297
- return $price > 0 ? $price : '';
3298
- }
3299
-
3300
- /**
3301
- * Get Variable Product Price
3302
- *
3303
- * @param WC_Product_Variable $variable Variable Product Object
3304
- * @param string $type Price Type (regular_price|price|sale_price)
3305
- * @param bool $tax Add tax with price (true|false)
3306
- *
3307
- * @return int|string
3308
- * @since 3.2.0
3309
- *
3310
- */
3311
- protected function getVariableProductPrice( $variable, $type, $tax = false ) {
3312
- $min_max_first_default = apply_filters('woo_feed_variable_product_price_range', 'min');
3313
- if ( isset($this->config['variable_price']) ) {
3314
- $min_max_first_default = $this->config['variable_price'];
3315
- }
3316
-
3317
- $price = 0;
3318
- if ( 'first' == $min_max_first_default ) {
3319
- $children = $variable->get_visible_children();
3320
- if ( isset($children[0]) && ! empty($children[0]) ) {
3321
- $variation = wc_get_product($children[0]);
3322
- $price = $this->get_price_by_product_type($variation, $type, $tax);
3323
- }
3324
- } else {
3325
- if ( 'regular_price' == $type ) {
3326
- $price = $variable->get_variation_regular_price($min_max_first_default);
3327
- } elseif ( 'sale_price' == $type ) {
3328
- $price = $variable->get_variation_sale_price($min_max_first_default);
3329
- } else {
3330
- $price = $variable->get_variation_price($min_max_first_default);
3331
- }
3332
-
3333
- // Get WooCommerce Multi language Price by Currency.
3334
- $price = apply_filters('woo_feed_wcml_price',
3335
- $price, $variable->get_id(), $this->get_feed_currency(), '_' . $type
3336
- );
3337
-
3338
- // Get Price with tax
3339
- if ( true === $tax ) {
3340
- $price = woo_feed_get_price_with_tax($price, $variable);
3341
- }
3342
- }
3343
-
3344
- return $price > 0 ? $price : '';
3345
- }
3346
-
3347
- /**
3348
- * Get Bundle Product Price
3349
- *
3350
- * @param WC_Product $product Product object.
3351
- * @param string $type Price Type (regular_price|price|sale_price)
3352
- * @param bool $tax Add tax with price (true|false)
3353
- *
3354
- * @return int|float|string
3355
- * @since 4.3.24
3356
- */
3357
- protected function getBundleProductPrice( $product, $type, $tax = false ) {
3358
- if ( class_exists('WC_Product_Bundle') ) {//WC_Product_Bundle
3359
- $bundle = new WC_Product_Bundle($product);
3360
- if ( 'price' === $type || 'sale_price' === $type ) {
3361
- $price = $bundle->get_bundle_price();
3362
- } else {
3363
- $price = $bundle->get_bundle_regular_price();
3364
- }
3365
-
3366
- // Get WooCommerce Multi language Price by Currency.
3367
- $price = apply_filters('woo_feed_wcml_price',
3368
- $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3369
- );
3370
-
3371
- // Get Price with tax
3372
- if ( true === $tax ) {
3373
- $price = woo_feed_get_price_with_tax($price, $bundle);
3374
- }
3375
- } else {
3376
- // Get Default price for others bundle products.
3377
- $price = $this->get_price_by_price_type($product, $type, $tax);
3378
- }
3379
-
3380
- return $price > 0 ? $price : '';
3381
- }
3382
-
3383
- /**
3384
- * Get price for Iconic woocommerce-bundled-products
3385
- *
3386
- * @param WC_Product $product Product object
3387
- * @param string $type Price Type (regular_price|price|sale_price)
3388
- * @param bool $tax Add tax with price (true|false)
3389
- *
3390
- * @return mixed $bundle_price
3391
- */
3392
- protected function iconic_bundle_product_price( $product, $type, $tax = false ) {
3393
- if ( ! class_exists('WC_Product_Bundled') ) {
3394
- return $product->get_price();
3395
- }
3396
-
3397
- $is_discounted = false;
3398
- $price = $product->get_price();
3399
- $bundle = new WC_Product_Bundled($product->get_id());
3400
- $iconic_bundle_product_type = ( ! is_null($bundle->options['price_display'])) ? $bundle->options['price_display'] : '';
3401
- $product_ids = $bundle->options['product_ids'];
3402
-
3403
- //set discount
3404
- if ( ! empty($bundle->options['fixed_discount']) ) {
3405
- $is_discounted = true;
3406
- $discount = $bundle->options['fixed_discount'];
3407
- } else {
3408
- $is_discounted = false;
3409
- $discount = 0;
3410
- }
3411
-
3412
- // Get price
3413
- if ( is_array($product_ids) ) {
3414
- $product_prices = array_map(function ( $id ) use ( $tax, $type, $is_discounted, $discount ) {
3415
- $product = wc_get_product($id);
3416
-
3417
- return $this->get_price_by_price_type($product, $type, $tax);
3418
-
3419
- }, $product_ids);
3420
-
3421
- if ( 'range' === $iconic_bundle_product_type ) {
3422
- $price = min($product_prices);
3423
- } else {
3424
- $price = array_sum($product_prices);
3425
- }
3426
- }
3427
-
3428
- // Get sale price if discount enabled
3429
- if ( $is_discounted && ('sale_price' === $type || 'price' === $type) ) {
3430
- $price -= $discount;
3431
- }
3432
-
3433
- // Get WooCommerce Multi language Price by Currency.
3434
- $price = apply_filters('woo_feed_wcml_price',
3435
- $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3436
- );
3437
-
3438
- // Get Price with tax
3439
- if ( true === $tax ) {
3440
- $price = woo_feed_get_price_with_tax($price, $bundle);
3441
- }
3442
-
3443
- return $price > 0 ? $price : '';
3444
- }
3445
-
3446
- /**
3447
- * Get Product Weight
3448
- *
3449
- * @param WC_Product $product
3450
- *
3451
- * @return mixed
3452
- * @since 3.2.0
3453
- *
3454
- */
3455
- protected function weight( $product ) {
3456
- return apply_filters('woo_feed_filter_product_weight', $product->get_weight(), $product, $this->config);
3457
- }
3458
 
3459
- /**
3460
- * Get Product Weight Unit
3461
- *
3462
- * @param WC_Product $product
3463
- *
3464
- * @return mixed
3465
- * @since 5.2.7
3466
- *
3467
- */
3468
- protected function weight_unit( $product ) {
3469
- return apply_filters('woo_feed_filter_product_weight_unit', get_option('woocommerce_weight_unit'), $product, $this->config);
3470
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3471
 
3472
- /**
3473
- * Get Product Width
3474
- *
3475
- * @param WC_Product $product
3476
- *
3477
- * @return mixed
3478
- * @since 3.2.0
3479
- *
3480
- */
3481
- protected function width( $product ) {
3482
- return apply_filters('woo_feed_filter_product_width', $product->get_width(), $product, $this->config);
3483
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3484
 
3485
- /**
3486
- * Get Product Height
3487
- *
3488
- * @param WC_Product $product
3489
- *
3490
- * @return mixed
3491
- * @since 3.2.0
3492
- *
3493
- */
3494
- protected function height( $product ) {
3495
- return apply_filters('woo_feed_filter_product_height', $product->get_height(), $product, $this->config);
3496
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3497
 
3498
- /**
3499
- * Get Product Length
3500
- *
3501
- * @param WC_Product $product
3502
- *
3503
- * @return mixed
3504
- * @since 3.2.0
3505
- *
3506
- */
3507
- protected function length( $product ) {
3508
- return apply_filters('woo_feed_filter_product_length', $product->get_length(), $product, $this->config);
3509
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3510
 
3511
- /**
3512
- * Get Product Shipping
3513
- *
3514
- * @param WC_Product $product
3515
- *
3516
- * @return mixed
3517
- * @since 4.3.16
3518
- * @author Nazrul Islam Nayan
3519
- */
3520
- protected function shipping( $product ) {
3521
- $feedBody = '';
3522
- $data = $this->data;
 
 
 
 
 
 
 
 
3523
 
3524
- if ( isset($data['shipping_zones']) && ! empty($data['shipping_zones']) ) {
3525
- $zones = $data['shipping_zones'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3526
 
3527
- if ( in_array($this->config['provider'], [ 'google', 'facebook', 'pinterest', 'bing', 'snapchat' ]) ) {
3528
- $get_shipping = new Woo_Feed_Shipping($this->config);
3529
- $feedBody .= $get_shipping->set_product($product)->set_shipping_zone($zones)->get_google_shipping();
3530
- }
3531
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3532
 
3533
- return apply_filters('woo_feed_filter_product_shipping', $feedBody, $product, $this->config);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3534
 
3535
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
3536
 
3537
- /**
3538
- * Get Product Shipping Cost
3539
- *
3540
- * @param WC_Product $product
3541
- *
3542
- * @return mixed
3543
- * @since 5.1.20
3544
- * @author Nazrul Islam Nayan
3545
- */
3546
- protected function shipping_cost( $product ) {
3547
- $shipping_obj = new Woo_Feed_Shipping($this->config);
3548
- $shipping_obj = $shipping_obj->set_product($product);
3549
-
3550
- return apply_filters('woo_feed_filter_product_shipping_cost', $shipping_obj->get_lowest_shipping_price(), $product, $this->config);
3551
- }
3552
-
3553
- /**
3554
- * Get Product Shipping Class
3555
- *
3556
- * @param WC_Product $product
3557
- *
3558
- * @return mixed
3559
- * @since 3.2.0
3560
- *
3561
- */
3562
- protected function shipping_class( $product ) {
3563
- return apply_filters('woo_feed_filter_product_shipping_class', $product->get_shipping_class(), $product, $this->config);
3564
- }
3565
 
3566
- /**
3567
- * Get Product Author Name
3568
- *
3569
- * @param WC_Product $product
3570
- *
3571
- * @return mixed
3572
- * @since 3.2.0
3573
- *
3574
- */
3575
- protected function author_name( $product ) {
3576
- $post = get_post($product->get_id());
3577
 
3578
- return get_the_author_meta('user_login', $post->post_author);
3579
- }
3580
 
3581
- /**
3582
- * Get Product Author Email
3583
- *
3584
- * @param WC_Product $product
3585
- *
3586
- * @return mixed
3587
- * @since 3.2.0
3588
- *
3589
- */
3590
- protected function author_email( $product ) {
3591
- $post = get_post($product->get_id());
3592
 
3593
- return get_the_author_meta('user_email', $post->post_author);
3594
- }
 
 
3595
 
3596
- /**
3597
- * Get Product Created Date
3598
- *
3599
- * @param WC_Product $product
3600
- *
3601
- * @return mixed
3602
- * @since 3.2.0
3603
- *
3604
- */
3605
- protected function date_created( $product ) {
3606
- $date_created = gmdate('Y-m-d', strtotime($product->get_date_created()));
3607
 
3608
- return apply_filters('woo_feed_filter_product_date_created', $date_created, $product, $this->config);
3609
- }
 
 
3610
 
3611
- /**
3612
- * Get Product Last Updated Date
3613
- *
3614
- * @param WC_Product $product
3615
- *
3616
- * @return mixed
3617
- * @since 3.2.0
3618
- *
3619
- */
3620
- protected function date_updated( $product ) {
3621
- $date_updated = gmdate('Y-m-d', strtotime($product->get_date_modified()));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3622
 
3623
- return apply_filters('woo_feed_filter_product_date_updated', $date_updated, $product, $this->config);
3624
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3625
 
3626
- /**
3627
- * Get Product Tax
3628
- *
3629
- * @param WC_Product $product Product object.
3630
- * @return mixed
3631
- * @since 5.1.20
3632
- * @author Nazrul Islam Nayan
3633
- */
3634
- protected function tax( $product ) {
3635
- $feedBody = '';
3636
- if ( in_array($this->config['provider'], [ 'google', 'facebook', 'pinterest', 'bing', 'snapchat' ]) ) {
3637
- $shipping_obj = new Woo_Feed_Shipping($this->config);
3638
- $shipping_obj = $shipping_obj->set_product($product);
3639
- $feedBody .= $shipping_obj->get_google_tax();
3640
- }
3641
-
3642
- return apply_filters('woo_feed_filter_product_tax', $feedBody, $product, $this->config);
3643
- }
3644
-
3645
- /**
3646
- * Get Product Tax class
3647
- * @param WC_Product $product Product object.
3648
- * @return string
3649
- */
3650
- protected function tax_class( $product ) {
3651
- return apply_filters('woo_feed_filter_product_tax_class', $product->get_tax_class(), $product, $this->config);
3652
- }
3653
-
3654
- /**
3655
- * Get Product Tax Status
3656
- * @param WC_Product $product Product object.
3657
- * @return string
3658
- */
3659
- protected function tax_status( $product ) {
3660
- return apply_filters('woo_feed_filter_product_tax_status', $product->get_tax_status(), $product, $this->config);
3661
- }
3662
-
3663
- /**
3664
- * Get CTX Feed Custom Field value
3665
- *
3666
- * @param WC_Product $product Product object.
3667
- * @param string $field custom field name.
3668
- * @return string
3669
- */
3670
- protected function getCustomField( $product, $field ) {
3671
- $id = $product->get_id();
3672
- $meta = $field;
3673
- if ( $product->is_type('variation') ) {
3674
- $meta = $field . '_var';
3675
- }
3676
-
3677
- $meta = apply_filters('woo_feed_custom_field_meta', $meta, $product, $field);
3678
-
3679
- $new_meta_key = '';
3680
- $old_meta_key = '';
3681
-
3682
- if ( strpos( $meta, '_identifier' ) !== false ) {
3683
- $old_meta_key = $meta;
3684
- $new_meta_key = str_replace( '_identifier', '', $meta );
3685
- } else {
3686
- $new_meta_key = $meta;
3687
- $old_meta_key = str_replace( 'woo_feed_', 'woo_feed_identifier_', $meta );
3688
- }
3689
-
3690
- $new_meta_value = $this->getProductMeta( $product, $new_meta_key );
3691
- $old_meta_value = $this->getProductMeta( $product, $old_meta_key );
3692
-
3693
- if ( empty( $new_meta_value ) ) {
3694
- return $old_meta_value;
3695
- } else {
3696
- return $new_meta_value;
3697
- }
3698
-
3699
- }
3700
-
3701
- /**
3702
- * Get Product Sale Price Effected Date for Google Shopping
3703
- *
3704
- * @param WC_Product $product
3705
- *
3706
- * @return string
3707
- * @since 3.2.0
3708
- *
3709
- */
3710
- protected function sale_price_effective_date( $product ) {
3711
- $effective_date = '';
3712
- $from = $this->sale_price_sdate($product);
3713
- $to = $this->sale_price_edate($product);
3714
- if ( ! empty($from) && ! empty($to) ) {
3715
- $from = gmdate('c', strtotime($from));
3716
- $to = gmdate('c', strtotime($to));
3717
-
3718
- $effective_date = $from . '/' . $to;
3719
- }
3720
-
3721
- return $effective_date;
3722
- }
3723
-
3724
- /**
3725
- * Ger Product Attribute
3726
- *
3727
- * @param WC_Product $product
3728
- * @param $attr
3729
- *
3730
- * @return string
3731
- * @since 2.2.3
3732
- *
3733
- */
3734
- protected function getProductAttribute( $product, $attr ) {
3735
- $id = $product->get_id();
3736
-
3737
- if ( woo_feed_wc_version_check(3.2) ) {
3738
- if ( woo_feed_wc_version_check(3.6) ) {
3739
- $attr = str_replace('pa_', '', $attr);
3740
- }
3741
- $value = $product->get_attribute($attr);
3742
-
3743
- // if empty get attribute of parent post
3744
- if ( '' === $value && $product->is_type('variation') ) {
3745
- $product = wc_get_product($product->get_parent_id());
3746
- $value = $product->get_attribute($attr);
3747
- }
3748
-
3749
- $getproductattribute = $value;
3750
- } else {
3751
- $getproductattribute = implode(',', wc_get_product_terms($id, $attr, array( 'fields' => 'names' )));
3752
- }
3753
-
3754
- return apply_filters('woo_feed_filter_product_attribute', $getproductattribute, $product, $attr, $this->config);
3755
- }
3756
-
3757
- /**
3758
- * Get Meta
3759
- *
3760
- * @param WC_Product $product
3761
- * @param string $meta post meta key
3762
- *
3763
- * @return mixed|string
3764
- * @since 2.2.3
3765
- *
3766
- */
3767
- protected function getProductMeta( $product, $meta ) {
3768
- $value = get_post_meta($product->get_id(), $meta, true);
3769
- // if empty get meta value of parent post
3770
- if ( '' === $value && $product->is_type('variation') ) {
3771
- $value = get_post_meta($product->get_parent_id(), $meta, true);
3772
- }
3773
-
3774
- return apply_filters('woo_feed_filter_product_meta', $value, $product, $this->config);
3775
- }
3776
-
3777
- /**
3778
- * Filter Products by Conditions
3779
- *
3780
- * @param WC_Product $product
3781
- *
3782
- * @return bool|array
3783
- * @since 3.2.0
3784
- *
3785
- */
3786
- public function filter_product( $product ) {
3787
- return true;
3788
- }
3789
 
3790
- /**
3791
- * Get Taxonomy
3792
- *
3793
- * @param WC_Product $product
3794
- * @param $taxonomy
3795
- *
3796
- * @return string
3797
- * @since 2.2.3
3798
- *
3799
- */
3800
- protected function getProductTaxonomy( $product, $taxonomy ) {
3801
- $id = $product->get_id();
3802
- if ( $product->is_type('variation') ) {
3803
- $id = $product->get_parent_id();
3804
- }
3805
 
3806
- $separator = apply_filters('woo_feed_product_taxonomy_term_list_separator', ',', $this->config, $product);
 
3807
 
3808
- $term_list = get_the_term_list($id, $taxonomy, '', $separator, '');
 
 
 
 
 
 
3809
 
3810
- if ( is_object($term_list) && get_class($term_list) === 'WP_Error' ) {
3811
- $term_list = '';
3812
- }
3813
 
3814
- $getproducttaxonomy = woo_feed_strip_all_tags($term_list);
 
 
 
 
3815
 
3816
- return apply_filters('woo_feed_filter_product_taxonomy', $getproducttaxonomy, $product, $this->config);
3817
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3818
 
3819
- /**
3820
- * Format price value
3821
- *
3822
- * @param string $name Attribute Name
3823
- * @param int $conditionName condition
3824
- * @param int $result price
3825
- *
3826
- * @return mixed
3827
- * @since 3.2.0
3828
- *
3829
- */
3830
- protected function price_format( $name, $conditionName, $result ) {
3831
- $plus = '+';
3832
- $minus = '-';
3833
- $percent = '%';
3834
-
3835
- if ( strpos($name, 'price') !== false ) {
3836
- if ( strpos($result, $plus) !== false && strpos($result, $percent) !== false ) {
3837
- $result = str_replace('+', '', $result);
3838
- $result = str_replace('%', '', $result);
3839
- if ( is_numeric($result) ) {
3840
- $result = $conditionName + (($conditionName * $result) / 100);
3841
- }
3842
- } elseif ( strpos($result, $minus) !== false && strpos($result, $percent) !== false ) {
3843
- $result = str_replace('-', '', $result);
3844
- $result = str_replace('%', '', $result);
3845
- if ( is_numeric($result) ) {
3846
- $result = $conditionName - (($conditionName * $result) / 100);
3847
- }
3848
- } elseif ( strpos($result, $plus) !== false ) {
3849
- $result = str_replace('+', '', $result);
3850
- if ( is_numeric($result) ) {
3851
- $result = ($conditionName + $result);
3852
- }
3853
- } elseif ( strpos($result, $minus) !== false ) {
3854
- $result = str_replace('-', '', $result);
3855
- if ( is_numeric($result) ) {
3856
- $result = $conditionName - $result;
3857
- }
3858
- }
3859
- }
3860
-
3861
- return $result;
3862
- }
3863
-
3864
- /**
3865
- * Format output According to Output Type config
3866
- *
3867
- * @param string $output
3868
- * @param array $outputTypes
3869
- * @param WC_Product $product
3870
- * @param string $productAttribute
3871
- *
3872
- * @return float|int|string
3873
- * @since 3.2.0
3874
- *
3875
- */
3876
- protected function format_output( $output, $outputTypes, $product, $productAttribute, $merchant_attribute ) {
3877
- if ( ! empty($outputTypes) && is_array($outputTypes) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3878
 
3879
- // Format Output According to output type
3880
- if ( in_array(2, $outputTypes) ) { // Strip Tags
3881
- $output = woo_feed_strip_all_tags(html_entity_decode($output));
3882
- }
3883
 
3884
- if ( in_array(3, $outputTypes) ) { // UTF-8 Encode
3885
- $output = utf8_encode($output);
3886
- }
3887
 
3888
- if ( in_array(4, $outputTypes) ) { // htmlentities
3889
- $output = htmlentities($output, ENT_QUOTES, 'UTF-8');
3890
- }
3891
 
3892
- if ( in_array(5, $outputTypes) ) { // Integer
3893
- $output = intval($output);
3894
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3895
 
3896
- if ( in_array(6, $outputTypes) ) { // Format Price
3897
- if ( ! empty($output) && $output > 0 ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3898
  $decimals = wc_get_price_decimals();
3899
  $decimal_separator = wc_get_price_decimal_separator();
3900
  $thousand_separator = wc_get_price_thousand_separator();
3901
- $output = (float)$output;
3902
-
3903
- if( "idealo" === $this->config['provider'] ) {
3904
- $output = number_format($output, $decimals, wp_specialchars_decode(stripslashes($decimal_separator)), wp_specialchars_decode(stripslashes($thousand_separator)));
3905
- }else {
3906
- $output = number_format($output, 2, '.', '');
3907
- }
3908
-
3909
- }
3910
- }
3911
-
3912
- if ( in_array(7, $outputTypes) ) { // Rounded Price
3913
- if ( ! empty($output) && $output > 0 ) {
3914
- $output = round($output);
3915
- $output = number_format($output, 2, '.', '');
3916
- }
3917
- }
3918
-
3919
- if ( in_array(8, $outputTypes) ) { // Delete Space
3920
- $output = htmlentities($output, null, 'utf-8');
3921
- $output = str_replace("&nbsp;", " ", $output);
3922
- $output = html_entity_decode($output);
3923
- $output = preg_replace("/\\s+/", ' ', $output);
3924
- }
3925
-
3926
- if ( in_array(10, $outputTypes) ) { // Remove Invalid Character
3927
- $output = woo_feed_stripInvalidXml($output);
3928
- }
3929
-
3930
- if ( in_array(11, $outputTypes) ) { // Remove ShortCodes
3931
- $output = $this->remove_short_codes($output);
3932
- }
3933
-
3934
- if ( in_array(12, $outputTypes) ) {
3935
- $output = ucwords(strtolower($output));
3936
- }
3937
-
3938
- if ( in_array(13, $outputTypes) ) {
3939
- $output = ucfirst(strtolower($output));
3940
- }
3941
-
3942
- if ( in_array(14, $outputTypes) ) {
3943
- $output = strtoupper(strtolower($output));
3944
- }
3945
-
3946
- if ( in_array(15, $outputTypes) ) {
3947
- $output = strtolower($output);
3948
- }
3949
-
3950
- if ( in_array(16, $outputTypes) ) {
3951
- if ( 'http' == substr($output, 0, 4) ) {
3952
- $output = str_replace('http://', 'https://', $output);
3953
- }
3954
- }
3955
-
3956
- if ( in_array(17, $outputTypes) ) {
3957
- if ( 'http' == substr($output, 0, 4) ) {
3958
- $output = str_replace('https://', 'http://', $output);
3959
- }
3960
- }
3961
-
3962
- if ( in_array(18, $outputTypes) ) { // only parent
3963
- if ( $product->is_type('variation') ) {
3964
- $id = $product->get_parent_id();
3965
- $parentProduct = wc_get_product($id);
3966
- $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
3967
- }
3968
- }
3969
-
3970
- if ( in_array(19, $outputTypes) ) { // child if parent empty
3971
- if ( $product->is_type('variation') ) {
3972
- $id = $product->get_parent_id();
3973
- $parentProduct = wc_get_product($id);
3974
- $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
3975
- if ( empty($output) ) {
3976
- $output = $this->getAttributeValueByType($product, $productAttribute, $merchant_attribute);
3977
- }
3978
- }
3979
- }
3980
-
3981
- if ( in_array(20, $outputTypes) ) { // parent if child empty
3982
- if ( $product->is_type('variation') ) {
3983
- $output = $this->getAttributeValueByType($product, $productAttribute, $merchant_attribute);
3984
- if ( empty($output) ) {
3985
- $id = $product->get_parent_id();
3986
- $parentProduct = wc_get_product($id);
3987
- $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
3988
- }
3989
- }
3990
- }
3991
-
3992
- if ( in_array(9, $outputTypes) && ! empty($output) && 'xml' === $this->config['feedType'] ) { // Add CDATA
3993
- $output = '<![CDATA[' . $output . ']]>';
3994
- }
3995
- }
3996
-
3997
- return $output;
3998
- }
3999
-
4000
- /**
4001
- * Add Prefix and Suffix with attribute value
4002
- *
4003
- * @param $output
4004
- * @param $prefix
4005
- * @param $suffix
4006
- * @param $attribute
4007
- *
4008
- * @return string
4009
- * @since 3.2.0
4010
- *
4011
- */
4012
- public function process_prefix_suffix( $output, $prefix, $suffix, $attribute = '' ) {
4013
-
4014
- $cdata = false;
4015
- if ( '' === $output ) {
4016
- return $output;
4017
- }
4018
-
4019
- if ( strpos($output, '<![CDATA[') !== false ) {
4020
- $cdata = true;
4021
- $output = str_replace(array( '<![CDATA[', ']]>' ), array( '', '' ), $output);
4022
- }
4023
-
4024
- // Add Prefix before Output
4025
- if ( '' !== $prefix ) {
4026
- $output = "$prefix" . $output;
4027
- }
4028
-
4029
- // Add Suffix after Output
4030
- if ( '' !== $suffix ) {
4031
- if ( array_key_exists(trim($suffix), get_woocommerce_currencies()) ) { // Add space before suffix if attribute contain price.
4032
- $output .= ' ' . $suffix;
4033
- } elseif ( substr($output, 0, 4) === 'http' ) {
4034
- // Parse URL Parameters if available into suffix field
4035
- $output = woo_feed_make_url_with_parameter($output, $suffix);
4036
-
4037
- } else {
4038
- $output .= (string)$suffix;
4039
- }
4040
- }
4041
-
4042
- if ( $cdata ) {
4043
- $output = '<![CDATA[' . $output . ']]>';
4044
- }
4045
-
4046
- return "$output";
4047
- }
4048
-
4049
- /**
4050
- * Get Subscription period
4051
- *
4052
- * @param WC_Product $product
4053
- *
4054
- * @return mixed
4055
- * @since 3.6.3
4056
- *
4057
- */
4058
- protected function subscription_period( $product ) {
4059
- if ( class_exists('WC_Subscriptions') ) {
4060
- return $this->getProductMeta($product, '_subscription_period');
4061
- }
4062
- return '';
4063
- }
4064
-
4065
- /**
4066
- * Get Subscription period interval
4067
- *
4068
- * @param WC_Product $product
4069
- *
4070
- * @return mixed
4071
- * @since 3.6.3
4072
- *
4073
- */
4074
- protected function subscription_period_interval( $product ) {
4075
- if ( class_exists('WC_Subscriptions') ) {
4076
- return $this->getProductMeta($product, '_subscription_period_interval');
4077
- }
4078
- return '';
4079
- }
4080
-
4081
- /**
4082
- * Get Subscription period interval
4083
- *
4084
- * @param WC_Product $product
4085
- *
4086
- * @return mixed
4087
- * @since 3.6.3
4088
- *
4089
- */
4090
- protected function subscription_amount( $product ) {
4091
- return $this->price($product);
4092
- }
4093
-
4094
- /**
4095
- * Get Installment Amount
4096
- *
4097
- * @param WC_Product $product
4098
- *
4099
- * @return mixed
4100
- * @since 4.3.101
4101
- */
4102
- protected function installment_amount( $product ) {
4103
- return $this->price($product);
4104
- }
4105
-
4106
- /**
4107
- * Get Installment Months
4108
- *
4109
- * @param WC_Product $product
4110
- *
4111
- * @return mixed
4112
- * @since 4.3.101
4113
- */
4114
- protected function installment_months( $product ) {
4115
- if ( class_exists('WC_Subscriptions') ) {
4116
- return $this->getProductMeta($product, '_subscription_length');
4117
- }
4118
- return '';
4119
- }
4120
-
4121
-
4122
- /**
4123
- * Calculate unit_price_measure. If Unit custom fields by CTX feed are enabled then it will take value
4124
- * from custom fields or it will take values for WooCommerce Germanized Plugin if enabled.
4125
- *
4126
- * If variation values are empty then it will take value from variable product.
4127
- *
4128
- * @param WC_Product $product
4129
- *
4130
- * @return mixed
4131
- * @since 3.6.3
4132
- */
4133
- protected function unit_price_measure( $product ) {
4134
- $unit_price_measure = '';
4135
- $identifiers = woo_feed_get_options('woo_feed_identifier');
4136
- if ( 'enable' === $identifiers['unit_pricing_base_measure']
4137
- && 'enable' === $identifiers['unit_pricing_measure']
4138
- && 'enable' === $identifiers['unit']
4139
- ) {
4140
- $unit = $this->getCustomField($product, 'woo_feed_unit');
4141
- $unit_price_measure = $this->getCustomField($product, 'woo_feed_unit_pricing_measure');
4142
-
4143
- $unit_price_measure .= " " . $unit;
4144
- }
4145
-
4146
- if ( empty($unit_price_measure) && class_exists('WooCommerce_Germanized') ) { // For WooCommerce Germanized Plugin
4147
- $unit = $this->getProductMeta($product, '_unit');
4148
- $unit_price_measure = $this->getProductMeta($product, '_unit_product');
4149
-
4150
- $unit_price_measure .= " " . $unit;
4151
- }
4152
-
4153
- return apply_filters('woo_feed_filter_unit_price_measure', $unit_price_measure, $product, $this->config);
4154
- }
4155
-
4156
- /**
4157
- * Calculate unit_price_base_measure. If Unit custom fields by CTX feed are enabled then it will take value
4158
- * from custom fields or it will take values for WooCommerce Germanized Plugin if enabled.
4159
- *
4160
- * If variation values are empty then it will take value from variable product.
4161
- *
4162
- * @param WC_Product $product
4163
- *
4164
- * @return mixed
4165
- * @since 3.6.3
4166
- */
4167
- protected function unit_price_base_measure( $product ) {
4168
- $unit_price_base_measure = '';
4169
- $identifiers = woo_feed_get_options('woo_feed_identifier');
4170
- if ( 'enable' === $identifiers['unit_pricing_base_measure']
4171
- && 'enable' === $identifiers['unit_pricing_measure']
4172
- && 'enable' === $identifiers['unit']
4173
- ) {
4174
- $unit = $this->getCustomField($product, 'woo_feed_unit');
4175
- $unit_price_base_measure = $this->getCustomField($product, 'woo_feed_unit_pricing_base_measure');
4176
-
4177
- $unit_price_base_measure .= " " . $unit;
4178
- }
4179
-
4180
- if ( empty($unit_price_base_measure) && class_exists('WooCommerce_Germanized') ) { // For WooCommerce Germanized Plugin
4181
- $unit = $this->getProductMeta($product, '_unit');
4182
- $unit_price_base_measure = $this->getProductMeta($product, '_unit_base');
4183
-
4184
- $unit_price_base_measure .= " " . $unit;
4185
- }
4186
-
4187
- return apply_filters('woo_feed_filter_unit_price_base_measure', $unit_price_base_measure, $product, $this->config);
4188
- }
4189
-
4190
- /**
4191
- * Get GTIN value of WooCommerce Germanized Plugin
4192
- *
4193
- * @param WC_Product $product
4194
- *
4195
- * @return mixed
4196
- * @since 3.6.3
4197
- */
4198
- protected function wc_germanized_gtin( $product ) {
4199
- $wc_germanized_gtin = '';
4200
- if ( class_exists('WooCommerce_Germanized') ) { // For WooCommerce Germanized Plugin
4201
- $wc_germanized_gtin = $this->getProductMeta($product, '_ts_gtin');
4202
- }
4203
-
4204
- return apply_filters('woo_feed_filter_wc_germanized_gtin', $wc_germanized_gtin, $product, $this->config);
4205
- }
4206
-
4207
- /**
4208
- * Get MPN value of WooCommerce Germanized Plugin
4209
- *
4210
- * @param WC_Product $product
4211
- *
4212
- * @return mixed
4213
- * @since 3.6.3
4214
- */
4215
- protected function wc_germanized_mpn( $product ) {
4216
- $wc_germanized_mpn = '';
4217
- if ( class_exists('WooCommerce_Germanized') ) { // For WooCommerce Germanized Plugin
4218
- $wc_germanized_mpn = $this->getProductMeta($product, '_ts_mpn');
4219
- }
4220
 
4221
- return apply_filters('woo_feed_filter_wc_germanized_mpn', $wc_germanized_mpn, $product, $this->config);
4222
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4223
 
 
 
 
 
4224
 
4225
- /**
4226
- * Yoast Identifier attribute for gtin8
4227
- *
4228
- * @param WC_Product $product
4229
- *
4230
- * @return mixed
4231
- * @since 4.4.4
4232
- */
4233
- protected function yoast_gtin8( $product ) {
4234
- $yoast_gtin8_value = woo_feed_get_yoast_identifiers_value('gtin8', $product);
4235
 
4236
- return apply_filters('yoast_gtin8_attribute_value', $yoast_gtin8_value, $product);
4237
- }
 
 
 
 
 
 
 
 
 
4238
 
4239
- /**
4240
- * Yoast Identifier attribute for gtin12
4241
- *
4242
- * @param WC_Product $product
4243
- *
4244
- * @return mixed
4245
- * @since 4.4.4
4246
- */
4247
- protected function yoast_gtin12( $product ) {
4248
- $yoast_gtin12_value = woo_feed_get_yoast_identifiers_value('gtin12', $product);
4249
 
4250
- return apply_filters('yoast_gtin12_attribute_value', $yoast_gtin12_value, $product);
4251
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4252
 
4253
- /**
4254
- * Yoast Identifier attribute for gtin13
4255
- *
4256
- * @param WC_Product $product
4257
- *
4258
- * @return mixed
4259
- * @since 4.4.4
4260
- */
4261
- protected function yoast_gtin13( $product ) {
4262
- $yoast_gtin13_value = woo_feed_get_yoast_identifiers_value('gtin13', $product);
4263
 
4264
- return apply_filters('yoast_gtin13_attribute_value', $yoast_gtin13_value, $product);
4265
- }
4266
 
4267
- /**
4268
- * Yoast Identifier attribute for gtin12
4269
- *
4270
- * @param WC_Product $product
4271
- *
4272
- * @return mixed
4273
- * @since 4.4.4
4274
- */
4275
- protected function yoast_gtin14( $product ) {
4276
- $yoast_gtin14_value = woo_feed_get_yoast_identifiers_value('gtin14', $product);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4277
 
4278
- return apply_filters('yoast_gtin14_attribute_value', $yoast_gtin14_value, $product);
4279
- }
 
4280
 
4281
- /**
4282
- * Yoast Identifier attribute for isbn
4283
- *
4284
- * @param WC_Product $product
4285
- *
4286
- * @return mixed
4287
- * @since 4.4.4
4288
- */
4289
- protected function yoast_isbn( $product ) {
4290
- $yoast_isbn_value = woo_feed_get_yoast_identifiers_value('isbn', $product);
4291
 
4292
- return apply_filters('yoast_isbn_attribute_value', $yoast_isbn_value, $product);
4293
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4294
 
4295
- /**
4296
- * Yoast Identifier attribute for mpn
4297
- *
4298
- * @param WC_Product $product
4299
- *
4300
- * @return mixed
4301
- * @since 4.4.4
4302
- */
4303
- protected function yoast_mpn( $product ) {
4304
- $yoast_mpn_value = woo_feed_get_yoast_identifiers_value('mpn', $product);
 
 
 
 
 
 
 
4305
 
4306
- return apply_filters('yoast_mpn_attribute_value', $yoast_mpn_value, $product);
4307
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4308
 
4309
- /**
4310
- * Rank Math GTIN Identifier attribute
4311
- *
4312
- * @param WC_Product $product
4313
- *
4314
- * @return mixed
4315
- * @since 5.2.66
4316
- */
4317
- protected function rank_math_gtin( $product ) {
4318
- $product_id = woo_feed_parent_product_id($product);
4319
- $rankmath_gtin_value = get_post_meta($product_id, '_rank_math_gtin_code');
4320
- $rankmath_gtin_value = ! empty($rankmath_gtin_value) && is_array($rankmath_gtin_value) ? $rankmath_gtin_value[0] : '';
4321
-
4322
- return apply_filters('rankmath_gtin_attribute_value', $rankmath_gtin_value, $product);
4323
- }
4324
 
4325
  }
9
 
10
  use RankMath\Helper;
11
 
12
+ if (!defined('ABSPATH')) {
13
+ die();
14
  }
15
 
16
  /**
18
  */
19
  class Woo_Feed_Products_v3
20
  {
21
+ /**
22
+ * The Increment
23
+ * @var int
24
+ */
25
+ protected $pi = 0;
26
+ /**
27
+ * Feed file headers
28
+ *
29
+ * @var string|array
30
+ */
31
+ public $feedHeader;
32
+ /**
33
+ * Feed File Body
34
+ *
35
+ * @var string|array
36
+ */
37
+ public $feedBody;
38
+ /**
39
+ * Feed file footer
40
+ *
41
+ * @var string|array
42
+ */
43
+ public $feedFooter;
44
+ /**
45
+ * CSV|TXT column (text|word) enclosure
46
+ *
47
+ * @var string
48
+ */
49
+ protected $enclosure;
50
+ /**
51
+ * CSV|TXT column delimiter
52
+ *
53
+ * @var string
54
+ */
55
+ protected $delimiter;
56
+ /**
57
+ * Feed Rules
58
+ *
59
+ * @var array
60
+ */
61
+ protected $config;
62
+ /**
63
+ * Post status to query
64
+ *
65
+ * @var string
66
+ */
67
+ protected $post_status = 'publish';
68
+ /**
69
+ * Processed Products
70
+ *
71
+ * @var array
72
+ */
73
+ public $products = [];
74
+
75
+
76
+ /**
77
+ * Products IDs
78
+ *
79
+ * @var array
80
+ */
81
+ public $product_ids = [];
82
+
83
+ /**
84
+ * Feed Big Data
85
+ *
86
+ * @var array
87
+ */
88
+ public $data = [];
89
+
90
+ /**
91
+ * Processed Products
92
+ *
93
+ * @var array
94
+ */
95
+ public $product_types = [
96
+ 'simple',
97
+ 'variable',
98
+ 'variation',
99
+ 'grouped',
100
+ 'external',
101
+ 'composite',
102
+ 'bundle',
103
+ 'bundled',
104
+ 'yith_bundle',
105
+ 'yith-composite',
106
+ 'subscription',
107
+ 'variable-subscription',
108
+ 'woosb',
109
+ ];
110
+ /**
111
+ * Query Method Selector
112
+ *
113
+ * @var string
114
+ */
115
+ protected $queryType = 'wp';
116
+ /**
117
+ * To replace google product highlight attribute for CSV & TXT feed
118
+ * @var array
119
+ */
120
+ protected $google_product_highlights = array(
121
+ 'product highlight 1',
122
+ 'product highlight 2',
123
+ 'product highlight 3',
124
+ 'product highlight 4',
125
+ 'product highlight 5',
126
+ 'product highlight 6',
127
+ 'product highlight 7',
128
+ 'product highlight 8',
129
+ 'product highlight 9',
130
+ 'product highlight 10',
131
+ );
132
+
133
+ /**
134
+ * To replace google additional image link attribute for CSV & TXT feed
135
+ * @var array
136
+ */
137
+ protected $google_additional_image = array(
138
+ 'additional image link 1',
139
+ 'additional image link 2',
140
+ 'additional image link 3',
141
+ 'additional image link 4',
142
+ 'additional image link 5',
143
+ 'additional image link 6',
144
+ 'additional image link 7',
145
+ 'additional image link 8',
146
+ 'additional image link 9',
147
+ 'additional image link 10',
148
+ );
149
+ /**
150
+ * Google shipping tax attributes
151
+ * @var array
152
+ */
153
+ /**
154
+ * Google shipping tax attributes
155
+ *
156
+ * @var array
157
+ */
158
+ protected $google_shipping_tax = array(
159
+ 'shipping_country',
160
+ 'shipping_region',
161
+ 'shipping_postal_code',
162
+ 'shipping_service',
163
+ 'shipping_price',
164
+ 'min_handling_time',
165
+ 'max_handling_time',
166
+ 'min_transit_time',
167
+ 'max_transit_time',
168
+ 'tax',
169
+ 'tax_country',
170
+ 'tax_region',
171
+ 'tax_rate',
172
+ 'tax_ship',
173
+ 'installment_months',
174
+ 'installment_amount',
175
+ 'subscription_period',
176
+ 'subscription_period_length',
177
+ 'subscription_amount',
178
+ 'section_name',
179
+ 'attribute_name',
180
+ 'attribute_value',
181
+ 'unit_price_value',
182
+ 'unit_price_currency',
183
+ 'unit_price_unit',
184
+ 'additional_variant_label',
185
+ 'additional_variant_value',
186
+ );
187
+ /**
188
+ * XML Wrapper Array
189
+ * Contains 'header' and 'footer' for template.
190
+ * @var array
191
+ */
192
+ protected $xml_wrapper = [];
193
+
194
+
195
+ /**
196
+ * Attribute to skip in attribute loop for processing separately
197
+ *
198
+ * @var array
199
+ */
200
+ protected $skipped_merchant_attributes = array(
201
+ 'google' => array(
202
+ 'shipping_country',
203
+ 'shipping_region',
204
+ 'shipping_postal_code',
205
+ 'shipping_service',
206
+ 'shipping_price',
207
+ 'min_handling_time',
208
+ 'max_handling_time',
209
+ 'min_transit_time',
210
+ 'max_transit_time',
211
+ 'tax_country',
212
+ 'tax_region',
213
+ 'tax_rate',
214
+ 'tax_ship',
215
+ 'installment_months',
216
+ 'installment_amount',
217
+ 'subscription_period',
218
+ 'subscription_period_length',
219
+ 'subscription_amount',
220
+ 'section_name',
221
+ 'attribute_name',
222
+ 'attribute_value',
223
+ ),
224
+ 'facebook' => array(
225
+ 'shipping_country',
226
+ 'shipping_region',
227
+ 'shipping_service',
228
+ 'shipping_price',
229
+ 'tax_country',
230
+ 'tax_region',
231
+ 'tax_rate',
232
+ 'tax_ship',
233
+ 'installment_months',
234
+ 'installment_amount',
235
+ 'subscription_period',
236
+ 'subscription_period_length',
237
+ 'subscription_amount',
238
+ 'section_name',
239
+ 'attribute_name',
240
+ 'attribute_value',
241
+ 'unit_price_value',
242
+ 'unit_price_currency',
243
+ 'unit_price_unit',
244
+ 'additional_variant_label',
245
+ 'additional_variant_value',
246
+ ),
247
+ 'bing' => array(
248
+ 'shipping_country',
249
+ 'shipping_service',
250
+ 'shipping_price',
251
+ ),
252
+ 'pinterest' => array(
253
+ 'shipping_country',
254
+ 'shipping_service',
255
+ 'shipping_price',
256
+ 'shipping_region',
257
+ 'shipping_postal_code',
258
+ 'tax_country',
259
+ 'tax_region',
260
+ 'tax_rate',
261
+ 'tax_ship',
262
+ ),
263
+ );
264
+
265
+ /**
266
+ * Already Processed merchant attributes by the attribute loop
267
+ * this will ensure unique merchant attribute.
268
+ * @see Woo_Feed_Products_v::exclude_current_attribute()
269
+ * @var array
270
+ */
271
+ protected $processed_merchant_attributes = array();
272
+
273
+
274
+ /**
275
+ * Post meta prefix for dropdown item
276
+ * @since 3.1.18
277
+ * @var string
278
+ */
279
+ const POST_META_PREFIX = 'wf_cattr_';
280
+
281
+ /**
282
+ * Product Attribute (taxonomy & local) Prefix
283
+ * @since 3.1.18
284
+ * @var string
285
+ */
286
+ const PRODUCT_ATTRIBUTE_PREFIX = 'wf_attr_';
287
+
288
+ /**
289
+ * Product Taxonomy Prefix
290
+ * @since 3.1.18
291
+ * @var string
292
+ */
293
+ const PRODUCT_TAXONOMY_PREFIX = 'wf_taxo_';
294
+
295
+ /**
296
+ * Product Custom Field Prefix
297
+ *
298
+ * @since 3.1.18
299
+ * @var string
300
+ */
301
+ const PRODUCT_CUSTOM_IDENTIFIER = 'woo_feed_';
302
+
303
+ /**
304
+ * Product Category Mapping Prefix
305
+ * @since 3.1.18
306
+ * @var string
307
+ */
308
+ const PRODUCT_CATEGORY_MAPPING_PREFIX = 'wf_cmapping_';
309
+
310
+ /**
311
+ * WordPress Option Prefix
312
+ *
313
+ * @since 4.3.33
314
+ * @var string
315
+ * @author Nazrul Islam Nayan
316
+ */
317
+ const WP_OPTION_PREFIX = 'wf_option_';
318
+
319
+ /**
320
+ * Advance Custom Field (ACF) Prefix
321
+ *
322
+ * @since 3.1.18
323
+ * @var string
324
+ */
325
+ const PRODUCT_ACF_FIELDS = 'acf_fields_';
326
+
327
+ /**
328
+ * Woo_Feed_Products_v3 constructor.
329
+ *
330
+ * @param $config
331
+ * @return void
332
+ */
333
+ public function __construct($config)
334
+ {
335
+ $this->config = woo_feed_parse_feed_rules($config);
336
+ $this->queryType = woo_feed_get_options('product_query_type');
337
+ $this->process_xml_wrapper();
338
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Current Query Type is %s', $this->queryType));
339
+ }
340
+
341
+ /**
342
+ * Generate Query Args For WP/WC query class
343
+ * @param string $type
344
+ * @return array
345
+ */
346
+ protected function get_query_args($type = 'wc')
347
+ {
348
+ $args = [];
349
+
350
+ // Include Product Variations with db query if configured
351
+ $variation_query = woo_feed_get_options('variation_query_type');
352
+
353
+ if ('wc' === $type) {
354
+ $product_types = $this->product_types;
355
+ if ('variable' === $variation_query) {
356
+ $variation = array_search('variation', $product_types, true);
357
+ if ($variation) {
358
+ unset($product_types[$variation]);
359
+ }
360
+ }
361
+
362
+ $args = array(
363
+ 'limit' => -1, // phpcs:ignore
364
+ 'status' => $this->post_status,
365
+ 'type' => $product_types,
366
+ 'orderby' => 'date',
367
+ 'order' => 'DESC',
368
+ 'return' => 'ids',
369
+ 'suppress_filters' => false,
370
+ );
371
+ }
372
 
373
+ if ('wp' === $type) {
374
+
375
+ $post_type = 'product';
376
+ // Include Product Variations with db query if configured
377
+ $variation_query = woo_feed_get_options('variation_query_type');
378
+ if ('individual' === $variation_query) {
379
+ $post_type = ['product', 'product_variation'];
380
+ }
381
+
382
+ $args = array(
383
+ 'posts_per_page' => -1, // phpcs:ignore
384
+ 'post_type' => $post_type,
385
+ 'post_status' => 'publish',
386
+ 'order' => 'DESC',
387
+ 'fields' => 'ids',
388
+ 'cache_results' => false,
389
+ 'update_post_meta_cache' => false,
390
+ 'update_post_term_cache' => false,
391
+ 'suppress_filters' => false,
392
+ );
393
+ }
394
+ return $args;
395
+ }
396
+
397
+ /**
398
+ * Get Products using WC_Product_Query
399
+ *
400
+ * @return array
401
+ */
402
+ public function get_wc_query_products()
403
+ {
404
+ $args = $this->get_query_args('wc');
405
+ if (woo_feed_is_debugging_enabled()) {
406
+ woo_feed_log_feed_process($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true)); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
407
+ woo_feed_log($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true), 'info'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
408
+ }
409
+ $query = new WC_Product_Query($args);
410
+ if (woo_feed_is_debugging_enabled()) {
411
+ woo_feed_log_feed_process($this->config['filename'], sprintf('WC_Product_Query Args ::' . PHP_EOL . '%s', print_r($args, true))); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
412
+ }
413
+ return $query->get_products();
414
+ }
415
+
416
+ /**
417
+ * Get Products using WP_Query
418
+ *
419
+ * return array
420
+ */
421
+ public function get_wp_query_products()
422
+ {
423
+ $args = $this->get_query_args('wp');
424
+ $query = new WP_Query($args);
425
+ if (!is_wp_error($query) && woo_feed_is_debugging_enabled()) {
426
+ woo_feed_log_feed_process($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true)); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
427
+ woo_feed_log_feed_process($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request));
428
+ woo_feed_log($this->config['filename'], 'WC_Product_Query Args::' . PHP_EOL . print_r($args, true), 'info'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
429
+ woo_feed_log($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request), 'info');
430
+ }
431
+ return $query->get_posts();
432
+ }
433
+
434
+ /**
435
+ * Get products
436
+ *
437
+ * @return array
438
+ */
439
+ public function query_products()
440
+ {
441
+ $products = [];
442
+ if ('wc' == $this->queryType) {
443
+ $products = $this->get_wc_query_products();
444
+ } elseif ('wp' == $this->queryType) {
445
+ $products = $this->get_wp_query_products();
446
+ } elseif ('both' == $this->queryType) {
447
+ $wc = $this->get_wc_query_products();
448
+ $wp = $this->get_wp_query_products();
449
+ $products = array_unique(array_merge($wc, $wp));
450
+ }
451
 
452
+ //set product ids
453
+ $this->product_ids = $products;
 
 
 
 
454
 
455
+ return $products;
456
+ }
 
 
 
 
457
 
458
+ /**
459
+ * Organize Feed Attribute config
460
+ * @return array|bool
461
+ */
462
+ public function get_attribute_config()
463
+ {
464
+ if (empty($this->config)) {
465
+ return false;
466
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467
 
468
+ $attributeConfig = array();
469
+ $merchantAttributes = $this->config['mattributes'];
470
+ if (!empty($merchantAttributes)) {
471
+ $i = 0;
472
+ foreach ($merchantAttributes as $key => $value) {
473
+ $attributeConfig[$i]['mattributes'] = $value;
474
+ $attributeConfig[$i]['prefix'] = $this->config['prefix'][$key];
475
+ $attributeConfig[$i]['type'] = $this->config['type'][$key];
476
+ $attributeConfig[$i]['attributes'] = $this->config['attributes'][$key];
477
+ $attributeConfig[$i]['default'] = $this->config['default'][$key];
478
+ $attributeConfig[$i]['suffix'] = $this->config['suffix'][$key];
479
+ $attributeConfig[$i]['output_type'] = $this->config['output_type'][$key];
480
+ $attributeConfig[$i]['limit'] = $this->config['limit'][$key];
481
+ $i++;
482
+ }
483
+ }
484
 
485
+ return $attributeConfig;
486
+ }
487
+
488
+ /**
489
+ * Get Product Information according to feed config
490
+ *
491
+ * @param int[] $productIds
492
+ *
493
+ * @return array
494
+ * @since 3.2.0
495
+ *
496
+ */
497
+ public function get_products($productIds)
498
+ {
499
+
500
+ if (empty($productIds)) {
501
+ return [];
502
+ }
503
 
504
+ //filter big data
505
+ $this->data = apply_filters("woo_feed_feed_big_data", $this->data, $productIds, $this->config);
506
+
507
+ /**
508
+ * Fires before looping through request product for getting product data
509
+ *
510
+ * @param int[] $productIds
511
+ * @param array $feedConfig
512
+ *
513
+ * @since 3.2.10
514
+ */
515
+ do_action('woo_feed_before_product_loop', $productIds, $this->config);
516
+
517
+ foreach ($productIds as $key => $pid) {
518
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Loading Product Data For %d.', $pid));
519
+ $product = wc_get_product($pid);
520
+
521
+ if ($this->exclude_from_loop($product)) {
522
+ continue;
523
+ }
524
+
525
+ if ($this->process_variation($product)) {
526
+ continue;
527
+ }
528
+
529
+ if (!$this->filter_product($product)) {
530
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Matched with filter conditions');
531
+ continue;
532
+ }
533
+
534
+ woo_feed_log_feed_process($this->config['filename'], 'Formatting Feed Data...');
535
+
536
+ // Add Single item wrapper before product info loop start
537
+ if ('xml' == $this->config['feedType']) {
538
+ $this->feedBody .= "\n";
539
+ $this->feedBody .= '<' . $this->config['itemWrapper'] . '>';
540
+ $this->feedBody .= "\n";
541
+ }
542
+
543
+ // reset processed attribute list before loop
544
+ $this->processed_merchant_attributes = [];
545
+
546
+ // Process attribute values
547
+ $this->process_attributes($product);
548
+
549
+ try {
550
+ woo_feed_log_feed_process($this->config['filename'], 'Processing Merchant Specific Fields');
551
+ // Process feed data for uncommon merchant feed like Google,Facebook,Pinterest
552
+ $this->process_for_merchant($product, $this->pi);
553
+ } catch (Exception $e) {
554
+ $message = 'Error Processing Merchant Specific Fields.' . PHP_EOL . 'Caught Exception :: ' . $e->getMessage();
555
+ woo_feed_log($this->config['filename'], $message, 'critical', $e, true);
556
+ woo_feed_log_fatal_error($message, $e);
557
+ }
558
+
559
+ if ('xml' == $this->config['feedType']) {
560
+ if (empty($this->feedHeader)) {
561
+ $this->feedHeader = $this->process_xml_feed_header();
562
+ $this->feedFooter = $this->process_xml_feed_footer();
563
+
564
+ }
565
+
566
+ $this->feedBody .= '</' . $this->config['itemWrapper'] . '>';
567
+
568
+
569
+ } elseif ('txt' == $this->config['feedType']) {
570
+ if (empty($this->feedHeader)) {
571
+ $this->process_txt_feed_header();
572
+ }
573
+ $this->process_txt_feed_body();
574
+ } elseif ('csv' == $this->config['feedType'] || 'xls' == $this->config['feedType']) {
575
+ if (empty($this->feedHeader)) {
576
+ $this->process_csv_feed_header();
577
+ }
578
+ $this->process_csv_feed_body();
579
+ } elseif ('json' == $this->config['feedType']) {
580
+ $this->process_json_feed_body();
581
+ }
582
+ woo_feed_log_feed_process($this->config['filename'], 'Done Formatting...');
583
+ $this->pi++;
584
+ }
585
 
586
+ /**
587
+ * Fires after looping through request product for getting product data
588
+ *
589
+ * @param int[] $productIds
590
+ * @param array $feedConfig
591
+ *
592
+ * @since 3.2.10
593
+ */
594
+ do_action('woo_feed_after_product_loop', $productIds, $this->config);
595
+
596
+ return $this->products;
597
+ }
598
+
599
+ /**
600
+ * Process product variations
601
+ * @param WC_Abstract_Legacy_Product $product
602
+ *
603
+ * @return bool
604
+ * @since 3.3.9
605
+ */
606
+ protected function process_variation($product)
607
+ {
608
+ // Apply variable and variation settings
609
+ if ($product->is_type('variable') && $product->has_child()) {
610
+ $this->pi++;
611
+
612
+ $variation_query = woo_feed_get_options('variation_query_type');
613
+ if ('variable' === $variation_query) {
614
+ $variations = $product->get_visible_children();
615
+ if (is_array($variations) && (sizeof($variations) > 0)) {
616
+ if (woo_feed_is_debugging_enabled()) {
617
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Getting Variation Product(s) :: %s', implode(', ', $variations)));
618
+ }
619
+ $this->get_products($variations);
620
+ return true;
621
+ }
622
+ }
623
+ }
624
 
625
+ return false;
626
+ }
627
+
628
+ /**
629
+ * Process The Attributes and assign value to merchant attribute
630
+ *
631
+ * @param WC_Abstract_Legacy_Product $product
632
+ *
633
+ * @return void
634
+ * @since 3.3.9
635
+ */
636
+ protected function process_attributes($product)
637
+ {
638
+ // print_r($this->config['attributes']);
639
+ // Get Product Attribute values by type and assign to product array
640
+ foreach ($this->config['attributes'] as $attr_key => $attribute) {
641
+
642
+ $merchant_attribute = isset($this->config['mattributes'][$attr_key]) ? $this->config['mattributes'][$attr_key] : '';
643
+
644
+ if ($this->exclude_current_attribute($product, $merchant_attribute, $attribute)) {
645
+ continue;
646
+ }
647
+
648
+ // Add Prefix and Suffix into Output
649
+ $prefix = $this->config['prefix'][$attr_key];
650
+ $suffix = $this->config['suffix'][$attr_key];
651
+ $merchant = $this->config['provider'];
652
+ $feedType = $this->config['feedType'];
653
+
654
+ if ('pattern' == $this->config['type'][$attr_key]) {
655
+ $attributeValue = $this->config['default'][$attr_key];
656
+ } else { // Get Pattern value
657
+ $attributeValue = $this->getAttributeValueByType($product, $attribute, $merchant_attribute);
658
+ }
659
+
660
+ // Format Output according to Output Type config.
661
+ if (isset($this->config['output_type'][$attr_key])) {
662
+ $outputType = $this->config['output_type'][$attr_key];
663
+ $attributeValue = $this->format_output($attributeValue, $this->config['output_type'][$attr_key], $product, $attribute, $merchant_attribute);
664
+ }
665
+
666
+ // Limit Output.
667
+ if (isset($this->config['limit'][$attr_key])) {
668
+ $attributeValue = $this->crop_string($attributeValue, 0, $this->config['limit'][$attr_key]);
669
+ }
670
+
671
+ // Process prefix and suffix.
672
+ $attributeValue = $this->process_prefix_suffix($attributeValue, $prefix, $suffix, $attribute);
673
+
674
+ if ('xml' == $feedType) {
675
+
676
+ // Replace XML Nodes according to merchant requirement.
677
+ $getReplacedAttribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
678
+
679
+ // XML does not support space in node. So replace Space with Underscore.
680
+ $getReplacedAttribute = str_replace(' ', '_', $getReplacedAttribute);
681
+
682
+ // Trim XML Element text & Encode for UTF-8.
683
+ if (!empty($attributeValue)) {
684
+ $attributeValue = trim($attributeValue);
685
+
686
+ if ('custom' === $this->config['provider'] && strpos($attributeValue, '<![CDATA[') === false) {
687
+ $attributeValue = htmlentities($attributeValue, ENT_XML1 | ENT_QUOTES, 'UTF-8');
688
+ }
689
+ }
690
+
691
+ // Add closing XML node if value is empty
692
+ if ('' !== $attributeValue) {
693
+ // Add CDATA wrapper for XML feed to prevent XML error.
694
+ $attributeValue = woo_feed_add_cdata($merchant_attribute, $attributeValue, $merchant, $this->config['feedType']);
695
+ // print_r($attributeValue);echo"<br/>";
696
+ // Strip slash from output.
697
+ $attributeValue = stripslashes($attributeValue);
698
+ $this->feedBody .= '<' . $getReplacedAttribute . '>' . "$attributeValue" . '</' . $getReplacedAttribute . '>';
699
+ $this->feedBody .= "\n";
700
+ } else {
701
+ $this->feedBody .= '<' . $getReplacedAttribute . '/>';
702
+ $this->feedBody .= "\n";
703
+ }
704
+
705
+ } elseif (in_array($feedType, ['csv', 'tsv', 'xls'], true)) {
706
+ $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
707
+ $merchant_attribute = $this->processStringForCSV($merchant_attribute);
708
+
709
+ if ("shipping" === $merchant_attribute && 'bing' == $this->config['provider']) {
710
+ $merchant_attribute = 'shipping(country:service:price)';
711
+ } elseif ("shipping" === $merchant_attribute) {
712
+ $merchant_attribute = 'shipping(country:region:service:price)';
713
+ }
714
+
715
+ if ("tax" === $merchant_attribute) {
716
+ $merchant_attribute = 'tax(country:region:rate:tax_ship)';
717
+ }
718
+
719
+ $attributeValue = $this->processStringForCSV($attributeValue);
720
+
721
+ } elseif ('txt' == $feedType) {
722
+ $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
723
+ $merchant_attribute = $this->processStringForTXT($merchant_attribute);
724
+
725
+ if ("shipping" === $merchant_attribute && 'bing' == $this->config['provider']) {
726
+ $merchant_attribute = 'shipping(country:service:price)';
727
+ } elseif ("shipping" === $merchant_attribute) {
728
+ $merchant_attribute = 'shipping(country:region:service:price)';
729
+ }
730
+
731
+ if ("tax" === $merchant_attribute) {
732
+ $merchant_attribute = 'tax(country:region:rate:tax_ship)';
733
+ }
734
+
735
+ $attributeValue = $this->processStringForTXT($attributeValue);
736
+ }
737
+
738
+ $this->products[$this->pi][$merchant_attribute] = $attributeValue;
739
+ }
740
+ }
741
+
742
+ /**
743
+ * Process Nested Attributes
744
+ *
745
+ * @return array
746
+ * @since 4.0.5
747
+ *
748
+ */
749
+ protected function feed_nested_attributes()
750
+ {
751
+ return [
752
+ 'reviewer' => ['reviewer', 'name'],
753
+ 'ratings' => ['ratings', 'overall'],
754
+ 'product_url' => ['products', 'product', 'product_url'],
755
+ ];
756
+ }
757
+
758
+ /**
759
+ * Process Nested Attributes
760
+ *
761
+ * @param string $attribute //product feed tag
762
+ * @param string $content //product feed content
763
+ *
764
+ * @return string
765
+ * @since 4.0.5
766
+ *
767
+ */
768
+
769
+ protected function nested_attributes_element($attribute, $content)
770
+ {
771
+ $starter = '';
772
+ $finisher = '';
773
+ $element = '';
774
+
775
+ if (empty($attribute)) {
776
+ return $attribute;
777
+ }
778
 
779
+ $attr_names = $this->feed_nested_attributes();
780
+
781
+ foreach ($attr_names as $key => $value) {
782
+ if ($key === $attribute) {
783
+ //starter tags element
784
+ foreach ($value as $item_value) {
785
+ $starter .= '<' . strval($item_value) . '>';
786
+ }
787
+
788
+ //finishing tags element
789
+ $rev_value = array_reverse($value);
790
+ foreach ($rev_value as $item_value) {
791
+ $finisher .= '</' . strval($item_value) . '>';
792
+ }
793
+ }
794
+ }
795
 
796
+ $element = $starter . $content . $finisher;
797
+
798
+ return $element;
799
+ }
800
+
801
+ /**
802
+ * Check if current product should be processed for feed
803
+ * This should be using by Woo_Feed_Products_v3::get_products()
804
+ *
805
+ * @param WC_Product $product
806
+ *
807
+ * @return bool
808
+ * @since 3.3.9
809
+ *
810
+ */
811
+ protected function exclude_from_loop($product)
812
+ {
813
+ // Skip for invalid products
814
+ if (!is_object($product)) {
815
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product data is not a valid WC_Product object.');
816
+ return true;
817
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
 
819
+ // For WP_Query check available product types
820
+ if ('wp' == $this->queryType && !in_array($product->get_type(), $this->product_types, true)) {
821
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Skipping Product :: Invalid Post/Product Type : %s.', $product->get_type()));
822
+ return true;
823
+ }
824
 
825
+ // Skip orphaned variation
826
+ if ($product->is_type('variation') && !$product->get_parent_id()) {
827
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Skipping Product :: Orphaned variation product [id: %s] skipped.', $product->get_id()));
828
+ return true;
829
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
830
 
831
+ // Skip for invisible products
832
+ if (!$product->is_visible()) {
833
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product is not visible.');
834
+ return true;
835
+ }
836
+ return false;
837
+ }
838
+
839
+ /**
840
+ * Check if current attribute/merchant attribute should be processed for feed
841
+ * This should be using by Woo_Feed_Products_v3::get_products()
842
+ *
843
+ * @param WC_Product $product
844
+ * @param string $merchant_attribute
845
+ * @param string $product_attribute
846
+ * @param string $feedType
847
+ *
848
+ * @return bool
849
+ *
850
+ * @since 3.3.9
851
+ *
852
+ */
853
+ protected function exclude_current_attribute($product, $merchant_attribute, $product_attribute, $feedType = 'xml')
854
+ {
855
+
856
+ if (empty($merchant_attribute)) {
857
+ return true;
858
+ }
859
 
860
+ if (
861
+ in_array($this->config['provider'], array_keys($this->skipped_merchant_attributes)) &&
862
+ in_array($merchant_attribute, $this->skipped_merchant_attributes[$this->config['provider']])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
 
864
+ ) {
865
+ return true;
866
+ }
867
 
868
+ if ('shopping_ads_excluded_country' !== $merchant_attribute && in_array($merchant_attribute, $this->processed_merchant_attributes)) {
869
+ return true;
870
+ }
 
 
871
 
872
+ $this->processed_merchant_attributes[] = $merchant_attribute;
873
+
874
+ return false;
875
+ }
876
+
877
+ /**
878
+ * Wrapper for substr with <![CDATA[string]]> support
879
+ *
880
+ * @param string $string
881
+ * @param int $start
882
+ * @param int $limit
883
+ *
884
+ * @return string
885
+ * @see substr
886
+ *
887
+ */
888
+ protected function crop_string($string, $start = 0, $limit = null)
889
+ {
890
+ $limit = absint($limit);
891
+ if ($limit > 0) {
892
+ $start = absint($start);
893
+ if (strpos($string, '<![CDATA[') !== false) {
894
+ $string = str_replace(array('<![CDATA[', ']]>'), array('', ''), $string);
895
+ $string = substr($string, $start, $limit);
896
+ $string = '<![CDATA[' . $string . ']]>';
897
+ } else {
898
+ $string = substr($string, $start, $limit);
899
+ }
900
+ }
901
+ return $string;
902
+ }
903
+
904
+ /**
905
+ * Process feed data according to merchant uncommon requirements like Google
906
+ *
907
+ * @param object $productObj WC_Product
908
+ * @param int $index Product Index
909
+ *
910
+ * @since 3.2.0
911
+ */
912
+ protected function process_for_merchant($productObj, $index)
913
+ {
914
+ $product = $this->products[$index];
915
+ $merchantAttributes = $this->config['mattributes'];
916
+ $s = 0; // Shipping Index
917
+ $i = 0; // Installment Index
918
+ $t = 0; // Tax Index
919
+ $tax = '';
920
+ $shipping = '';
921
+ $sub = 0;
922
+ $subscription = '';
923
+ $ins = 0; // Installment Index
924
+ $installment = "";
925
+ $product_detail = '';
926
+ $unit_price = '';
927
+ $additional_variant_attribute = '';
928
+ $pd = 0;
929
+ $up = 0; //Unit Price for facebook
930
+ $av = 0; //Additional Variant Attribute for facebook
931
+
932
+
933
+ // Format Shipping and Tax data for CSV and TXT feed only for google and facebook
934
+
935
+ if ('xml' != $this->config['feedType'] && in_array($this->config['provider'], array('google', 'facebook', 'bing', 'snapchat', 'pinterest'))) {
936
+ foreach ($merchantAttributes as $key => $value) {
937
+
938
+ if (!in_array($value, $this->google_shipping_tax, true)) {
939
+ continue;
940
+ }
941
+
942
+ # Get value by attribute type with prefix & suffix
943
+ $output = $this->process_for_merchant_get_value($productObj, $key);
944
+
945
+ if ('shipping_country' == $value) {
946
+ $s++;
947
+ $shipping .= $output;
948
+ }
949
+ if ('shipping_region' == $value) {
950
+ $shipping .= ':' . $output;
951
+ } elseif ('shipping_postal_code' == $value) {
952
+ $shipping .= ':' . $output;
953
+ }
954
+ if ('shipping_service' == $value) {
955
+ $shipping .= ':' . $output;
956
+ }
957
+ if ('shipping_price' == $value) {
958
+ $shipping .= ':' . $output;
959
+ }
960
+
961
+ if ('section_name' == $value) {
962
+ $pd++;
963
+ $product_detail .= $output;
964
+ }
965
+ if ('attribute_name' == $value) {
966
+ $product_detail .= ':' . $output;
967
+ }
968
+ if ('attribute_value' == $value) {
969
+ $product_detail .= ':' . $output;
970
+ }
971
+
972
+ //facebook nested attributes
973
+ if (isset($this->config['provider']) && "facebook" === $this->config['provider']) {
974
+ if ('unit_price_value' == $value) {
975
+ $up++;
976
+ $unit_price .= $output;
977
+ }
978
+ if ('unit_price_currency' == $value) {
979
+ $unit_price .= ':' . $output;
980
+ }
981
+ if ('unit_price_unit' == $value) {
982
+ $unit_price .= ':' . $output;
983
+ }
984
+
985
+ if ('additional_variant_label' == $value) {
986
+ $av++;
987
+ $additional_variant_attribute .= $output;
988
+ }
989
+ if ('additional_variant_value' == $value) {
990
+ $additional_variant_attribute .= ':' . $output;
991
+ }
992
+
993
+ if (0 < $up) {
994
+ $this->products[$this->pi]["unit_price"] = $unit_price;
995
+ }
996
+
997
+ if (0 < $av) {
998
+ $this->products[$this->pi]["additional_variant_attribute"] = $additional_variant_attribute;
999
+ }
1000
+ }
1001
+
1002
+
1003
+ if ('installment_months' == $value) {
1004
+ $ins++;
1005
+ $installment .= $output;
1006
+ }
1007
+ if ('installment_amount' == $value) {
1008
+ $installment .= ':' . $output;
1009
+ }
1010
+
1011
+ if ('subscription_period' == $value) {
1012
+ $sub++;
1013
+ $subscription .= $output;
1014
+ }
1015
+ if ('subscription_period_length' == $value) {
1016
+ $subscription .= ':' . $output;
1017
+ }
1018
+ if ('subscription_amount' == $value) {
1019
+ $subscription .= ':' . $output;
1020
+ }
1021
+ }
1022
+
1023
+ if (0 < $pd) {
1024
+ $this->products[$this->pi]["product detail"] = $product_detail;
1025
+ }
1026
+
1027
+ if (0 < $sub) {
1028
+ $this->products[$this->pi]["subscription cost"] = $subscription;
1029
+
1030
+ }
1031
+
1032
+ if (0 < $ins) {
1033
+ $this->products[$this->pi]["installment"] = $installment;
1034
+ }
1035
+ }
1036
 
 
 
1037
 
1038
+ if (in_array($this->config['provider'], array('google', 'facebook', 'snapchat', 'bing', 'pinterest'))) {
1039
+
1040
+
1041
+ // Reformat Shipping attributes for google, facebook
1042
+ if ('xml' == $this->config['feedType']) {
1043
+ foreach ($merchantAttributes as $key => $value) {
1044
+
1045
+ if (!in_array($value, $this->google_shipping_tax)) {
1046
+ continue;
1047
+ }
1048
+
1049
+
1050
+ # Get value by attribute type with prefix & suffix
1051
+ $output = $this->process_for_merchant_get_value($productObj, $key);
1052
+
1053
+
1054
+ if ('shipping_country' == $value) {
1055
+ if (0 == $s) {
1056
+ $shipping .= '<g:shipping>';
1057
+ $s = 1;
1058
+ } else {
1059
+ $shipping .= '</g:shipping>' . "\n";
1060
+ $shipping .= '<g:shipping>';
1061
+ }
1062
+ } elseif (!in_array('shipping_country', $merchantAttributes) && 'shipping_price' == $value) {
1063
+ if (0 == $s) {
1064
+ $shipping .= '<g:shipping>';
1065
+ $s = 1;
1066
+ } else {
1067
+ $shipping .= '</g:shipping>' . "\n";
1068
+ $shipping .= '<g:shipping>';
1069
+ }
1070
+ }
1071
+
1072
+ if ('shipping_country' == $value) {
1073
+ $shipping .= '<g:country>' . $output . '</g:country>' . "\n";
1074
+ } elseif ('shipping_region' == $value) {
1075
+ $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
1076
+ } elseif ('shipping_region' == $value) {
1077
+ $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
1078
+ } elseif ('shipping_service' == $value) {
1079
+ $shipping .= '<g:service>' . $output . '</g:service>' . "\n";
1080
+ } elseif ('shipping_postal_code' == $value) {
1081
+ $shipping .= '<g:postal_code>' . $output . '</g:postal_code>' . "\n";
1082
+ } elseif ('shipping_price' == $value) {
1083
+ $shipping .= '<g:price>' . $output . '</g:price>' . "\n";
1084
+ } elseif ('tax_country' == $value) {
1085
+ if (0 == $t) {
1086
+ $tax .= '<g:tax>';
1087
+ $t = 1;
1088
+ } else {
1089
+ $tax .= '</g:tax>' . "\n";
1090
+ $tax .= '<g:tax>';
1091
+ }
1092
+ $tax .= '<g:country>' . $output . '</g:country>' . "\n";
1093
+ } elseif ('tax_region' == $value) {
1094
+ $tax .= '<g:region>' . $output . '</g:region>' . "\n";
1095
+ } elseif ('tax_rate' == $value) {
1096
+ $tax .= '<g:rate>' . $output . '</g:rate>' . "\n";
1097
+ } elseif ('tax_ship' == $value) {
1098
+ $tax .= '<g:tax_ship>' . $output . '</g:tax_ship>' . "\n";
1099
+ } elseif ('subscription_period' == $value) {
1100
+ if (0 == $sub) {
1101
+ $subscription .= '<g:subscription_cost>';
1102
+ $sub = 1;
1103
+ } else {
1104
+ $subscription .= '</g:subscription_cost>' . "\n";
1105
+ $subscription .= '<g:subscription_cost>';
1106
+ }
1107
+ $subscription .= '<g:period>' . $output . '</g:period>' . "\n";
1108
+ } elseif ('subscription_period_length' == $value) {
1109
+ $subscription .= '<g:period_length>' . $output . '</g:period_length>' . "\n";
1110
+ } elseif ('subscription_amount' == $value) {
1111
+ $subscription .= '<g:amount>' . $output . '</g:amount>' . "\n";
1112
+ }
1113
+
1114
+ if ('section_name' == $value) {
1115
+ if (0 == $pd) {
1116
+ $product_detail .= '<g:product_detail>';
1117
+ $pd = 1;
1118
+ } else {
1119
+ $product_detail .= '</g:product_detail>' . "\n";
1120
+ $product_detail .= '<g:product_detail>';
1121
+ }
1122
+ } elseif (!in_array('section_name', $merchantAttributes) && 'attribute_name' == $value) {
1123
+ if (0 == $pd) {
1124
+ $product_detail .= '<g:product_detail>';
1125
+ $pd = 1;
1126
+ } else {
1127
+ $product_detail .= '</g:product_detail>' . "\n";
1128
+ $product_detail .= '<g:product_detail>';
1129
+ }
1130
+ }
1131
+
1132
+ if ('section_name' == $value) {
1133
+ $product_detail .= '<g:section_name>' . $output . '</g:section_name>' . "\n";
1134
+ } elseif ('attribute_name' == $value) {
1135
+ $product_detail .= '<g:attribute_name>' . $output . '</g:attribute_name>' . "\n";
1136
+ } elseif ('attribute_value' == $value) {
1137
+ $product_detail .= '<g:attribute_value>' . $output . '</g:attribute_value>' . "\n";
1138
+ }
1139
+
1140
+ if (isset($this->config['provider']) && "facebook" === $this->config['provider']) {
1141
+
1142
+ // unit_price configure
1143
+ if ('unit_price_value' == $value) {
1144
+ if (0 == $up) {
1145
+ $unit_price .= '<unit_price>';
1146
+ $up = 1;
1147
+ } else {
1148
+ $unit_price .= '</unit_price>' . "\n";
1149
+ $unit_price .= '<unit_price>';
1150
+ }
1151
+ } elseif (!in_array('unit_price_value', $merchantAttributes) && 'unit_price_currency' == $value) {
1152
+ if (0 == $up) {
1153
+ $unit_price .= '<unit_price>';
1154
+ $up = 1;
1155
+ } else {
1156
+ $unit_price .= '</unit_price>' . "\n";
1157
+ $unit_price .= '<unit_price>';
1158
+ }
1159
+ }
1160
+
1161
+ if ('unit_price_value' == $value) {
1162
+ $unit_price .= '<value>' . $output . '</value>' . "\n";
1163
+ } elseif ('unit_price_currency' == $value) {
1164
+ $unit_price .= '<currency>' . $output . '</currency>' . "\n";
1165
+ } elseif ('unit_price_unit' == $value) {
1166
+ $unit_price .= '<unit>' . $output . '</unit>' . "\n";
1167
+ }
1168
+
1169
+ // additional_variant_attribute configure
1170
+ if ('additional_variant_label' == $value) {
1171
+ if (0 == $av) {
1172
+ $additional_variant_attribute .= '<additional_variant_attribute>';
1173
+ $av = 1;
1174
+ } else {
1175
+ $additional_variant_attribute .= '</additional_variant_attribute>' . "\n";
1176
+ $additional_variant_attribute .= '<additional_variant_attribute>';
1177
+ }
1178
+ } elseif (!in_array('additional_variant_label', $merchantAttributes) && 'additional_variant_value' == $value) {
1179
+ if (0 == $av) {
1180
+ $additional_variant_attribute .= '<additional_variant_attribute>';
1181
+ $av = 1;
1182
+ } else {
1183
+ $additional_variant_attribute .= '</additional_variant_attribute>' . "\n";
1184
+ $additional_variant_attribute .= '<additional_variant_attribute>';
1185
+ }
1186
+ }
1187
+
1188
+ if ('additional_variant_label' == $value) {
1189
+ $additional_variant_attribute .= '<label>' . $output . '</label>' . "\n";
1190
+ } elseif ('additional_variant_value' == $value) {
1191
+ $additional_variant_attribute .= '<value>' . $output . '</value>' . "\n";
1192
+ }
1193
+ }
1194
+
1195
+
1196
+ if ('installment_months' === $value) {
1197
+ if (0 == $ins) {
1198
+ $installment .= '<g:installment>';
1199
+ $ins = 1;
1200
+ } else {
1201
+ $installment .= '</g:installment>' . "\n";
1202
+ $installment .= '<g:installment>';
1203
+ }
1204
+ $installment .= '<g:months>' . $output . '</g:months>' . "\n";
1205
+ } elseif ('installment_amount' == $value) {
1206
+ $installment .= '<g:amount>' . $output . '</g:amount>' . "\n";
1207
+ }
1208
+ }
1209
+
1210
+ if (1 == $pd) {
1211
+ $product_detail .= '</g:product_detail>';
1212
+ }
1213
+
1214
+ if (isset($this->config['provider']) && "facebook" === $this->config['provider']) {
1215
+ if (1 == $up) {
1216
+ $unit_price .= '</unit_price>';
1217
+ }
1218
+
1219
+ if (1 == $av) {
1220
+ $additional_variant_attribute .= '</additional_variant_attribute>';
1221
+ }
1222
+
1223
+ $this->feedBody .= $unit_price;
1224
+ $this->feedBody .= $additional_variant_attribute;
1225
+ }
1226
+
1227
+ if (1 == $s) {
1228
+ $shipping .= '</g:shipping>';
1229
+ }
1230
+ if (1 == $t) {
1231
+ $tax .= '</g:tax>';
1232
+ }
1233
+
1234
+ if (1 == $sub) {
1235
+ $subscription .= '</g:subscription_cost>';
1236
+ }
1237
+
1238
+ if (1 == $ins) {
1239
+ $installment .= '</g:installment>';
1240
+ }
1241
+
1242
+ //$this->feedBody .= $shipping;
1243
+ //$this->feedBody .= $tax;
1244
+ $this->feedBody .= $product_detail;
1245
+ $this->feedBody .= $installment;
1246
+
1247
+ if ($productObj->is_type('subscription') ||
1248
+ $productObj->is_type('variable-subscription') ||
1249
+ $productObj->is_type('subscription_variation')) {
1250
+ $this->feedBody .= $subscription;
1251
+ }
1252
+ }
1253
+ // ADD g:identifier_exists
1254
+ $identifier = array('brand', 'upc', 'sku', 'mpn', 'gtin');
1255
+ $countIdentifier = 0;
1256
+ if (!in_array('identifier_exists', $merchantAttributes)) {
1257
+ if (count(array_intersect_key(array_flip($identifier), $product)) >= 2) {
1258
+ // Any 2 required keys exist!
1259
+ // @TODO Refactor with OR
1260
+ if (array_key_exists('brand', $product) && !empty($product['brand'])) {
1261
+ $countIdentifier++;
1262
+ }
1263
+ if (array_key_exists('upc', $product) && !empty($product['upc'])) {
1264
+ $countIdentifier++;
1265
+ }
1266
+ if (array_key_exists('sku', $product) && !empty($product['sku'])) {
1267
+ $countIdentifier++;
1268
+ }
1269
+ if (array_key_exists('mpn', $product) && !empty($product['mpn'])) {
1270
+ $countIdentifier++;
1271
+ }
1272
+ if (array_key_exists('gtin', $product) && !empty($product['gtin'])) {
1273
+ $countIdentifier++;
1274
+ }
1275
+ }
1276
+
1277
+ if ('xml' == $this->config['feedType']) {
1278
+ if ($countIdentifier >= 2) {
1279
+ $this->feedBody .= '<g:identifier_exists>yes</g:identifier_exists>';
1280
+ } else {
1281
+ $this->feedBody .= '<g:identifier_exists>no</g:identifier_exists>';
1282
+ }
1283
+ } else {
1284
+ $identifier_exists = 'identifier exists';
1285
+ if (in_array($this->config['provider'], array('bing', 'pinterest'))) {
1286
+ $identifier_exists = 'identifier_exists';
1287
+ }
1288
+
1289
+ if ($countIdentifier >= 2) {
1290
+ $this->products[$this->pi][$identifier_exists] = 'yes';
1291
+ } else {
1292
+ $this->products[$this->pi][$identifier_exists] = 'no';
1293
+ }
1294
+ }
1295
+ }
1296
+ }
1297
+ }
1298
+
1299
+ private function process_for_merchant_get_value($productObj, $key)
1300
+ {
1301
+ $prefix = $this->config['prefix'][$key];
1302
+ $suffix = $this->config['suffix'][$key];
1303
+ $attribute = $this->config['attributes'][$key];
1304
+ $merchant_attribute = $this->config['mattributes'][$key];
1305
+
1306
+ if ('pattern' == $this->config['type'][$key]) {// Get Pattern value.
1307
+ $output = $this->config['default'][$key];
1308
+ $output = $this->apply_filters_to_attribute_value($output, $productObj, $attribute, $merchant_attribute);
1309
+ } else {
1310
+ $output = $this->getAttributeValueByType($productObj, $attribute, $merchant_attribute);
1311
+ }
1312
 
1313
+ $output = $this->format_output($output, $this->config['output_type'], $productObj, $attribute, $merchant_attribute);
1314
+
1315
+ $output = $this->process_prefix_suffix($output, $prefix, $suffix, $attribute = '');
1316
+
1317
+ return $output;
1318
+ }
1319
+
1320
+ /**
1321
+ * Get Query Type Settings
1322
+ * @return string
1323
+ */
1324
+ public function get_query_type()
1325
+ {
1326
+ return $this->queryType;
1327
+ }
1328
+
1329
+ public function get_product_types()
1330
+ {
1331
+ return $this->product_types;
1332
+ }
1333
+
1334
+ /**
1335
+ * Generate TXT Feed Header
1336
+ *
1337
+ * @return string
1338
+ * @since 3.2.0
1339
+ *
1340
+ */
1341
+ protected function process_txt_feed_header()
1342
+ {
1343
+ // Set Delimiter
1344
+ if ('tab' == $this->config['delimiter']) {
1345
+ $this->delimiter = "\t";
1346
+ } else {
1347
+ $this->delimiter = $this->config['delimiter'];
1348
+ }
1349
 
1350
+ // Set Enclosure
1351
+ if (!empty($this->config['enclosure'])) {
1352
+ $this->enclosure = $this->config['enclosure'];
1353
+ if ('double' == $this->enclosure) {
1354
+ $this->enclosure = '"';
1355
+ } elseif ('single' == $this->enclosure) {
1356
+ $this->enclosure = "'";
1357
+ } else {
1358
+ $this->enclosure = '';
1359
+ }
1360
+ } else {
1361
+ $this->enclosure = '';
1362
+ }
1363
 
1364
+ $eol = PHP_EOL;
1365
+ if ('trovaprezzi' === $this->config['provider']) {
1366
+ $eol = '<endrecord>' . PHP_EOL;
1367
+ }
1368
 
1369
+ $product = $this->products[$this->pi];
 
1370
 
1371
+ $headers = array_keys($product);
1372
+
1373
+ $this->feedHeader .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $headers) . $this->enclosure . $eol;
1374
+
1375
+ if ('google' === $this->config['provider']) {
1376
+ $this->feedHeader = str_replace($this->google_product_highlights, 'product highlight', $this->feedHeader);
1377
+ $this->feedHeader = str_replace($this->google_additional_image, 'additional image link', $this->feedHeader);
1378
+ }
1379
+
1380
+ return $this->feedHeader;
1381
+ }
1382
+
1383
+ /**
1384
+ * Generate TXT Feed Body
1385
+ *
1386
+ * @return string
1387
+ * @since 3.2.0
1388
+ *
1389
+ */
1390
+ protected function process_txt_feed_body()
1391
+ {
1392
+ $productInfo = array_values($this->products[$this->pi]);
1393
+ $eol = PHP_EOL;
1394
+ if ('trovaprezzi' === $this->config['provider']) {
1395
+ $eol = '<endrecord>' . PHP_EOL;
1396
+ }
1397
+ $this->feedBody .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $productInfo) . $this->enclosure . $eol;
1398
+
1399
+ return $this->feedBody;
1400
+ }
1401
+
1402
+ /**
1403
+ * Generate CSV Feed Header
1404
+ *
1405
+ * @return array
1406
+ * @since 3.2.0
1407
+ *
1408
+ */
1409
+ protected function process_csv_feed_header()
1410
+ {
1411
+ // Set Delimiter
1412
+ if ('tab' == $this->config['delimiter']) {
1413
+ $this->delimiter = "\t";
1414
+ } else {
1415
+ $this->delimiter = $this->config['delimiter'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1416
  }
1417
 
1418
+ // Set Enclosure
1419
+ if (!empty($this->config['enclosure'])) {
1420
+ $this->enclosure = $this->config['enclosure'];
1421
+ if ('double' == $this->enclosure) {
1422
+ $this->enclosure = '"';
1423
+ } elseif ('single' == $this->enclosure) {
1424
+ $this->enclosure = "'";
1425
+ } else {
1426
+ $this->enclosure = '';
1427
+ }
1428
+ } else {
1429
+ $this->enclosure = '';
1430
+ }
1431
 
1432
+ $product = $this->products[$this->pi];
 
1433
 
1434
+ $this->feedHeader = array_keys($product);
 
 
 
 
 
 
 
 
 
 
1435
 
1436
+ if ('google' === $this->config['provider']) {
1437
+ $this->feedHeader = str_replace($this->google_product_highlights, 'product highlight', $this->feedHeader);
1438
+ $this->feedHeader = str_replace($this->google_additional_image, 'additional image link', $this->feedHeader);
1439
+ }
1440
 
1441
+ return $this->feedHeader;
1442
+ }
1443
+
1444
+ /**
1445
+ * Generate CSV Feed Body
1446
+ * @return array
1447
+ * @since 3.2.0
1448
+ */
1449
+ protected function process_csv_feed_body()
1450
+ {
1451
+ $product = $this->products[$this->pi];
1452
+ $this->feedBody[] = array_values($product);
1453
+
1454
+ return $this->feedBody;
1455
+ }
1456
+
1457
+ protected function process_json_feed_body()
1458
+ {
1459
+ $product = $this->products[$this->pi];
1460
+ $this->feedBody[] = $product;
1461
+
1462
+ return $this->feedBody;
1463
+ }
1464
+
1465
+ protected function process_xml_wrapper()
1466
+ {
1467
+ $itemsWrapperClose = explode(' ', $this->config['itemsWrapper']);
1468
+ $itemsWrapperClose = $itemsWrapperClose[0];
1469
+ $this->xml_wrapper = [
1470
+ 'header' => '<?xml version="1.0" encoding="UTF-8" ?>' . PHP_EOL . '<' . wp_unslash($this->config['itemsWrapper']) . '>',
1471
+ 'footer' => PHP_EOL . '</' . $itemsWrapperClose . '>',
1472
+ ];
1473
+ $this->config['itemWrapper'] = str_replace(' ', '_', $this->config['itemWrapper']);
1474
+ $this->config['itemsWrapper'] = str_replace(' ', '_', $this->config['itemsWrapper']);
1475
+
1476
+ if (file_exists(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt')) {
1477
+ $txt = file_get_contents(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt');
1478
+ $txt = trim($txt);
1479
+ $txt = explode('{separator}', $txt);
1480
+ if (2 === count($txt)) {
1481
+ $this->xml_wrapper['header'] = trim($txt[0]);
1482
+ $this->xml_wrapper['footer'] = "\n" . trim($txt[1]);
1483
+ }
1484
+ }
1485
 
1486
+ if (!empty($this->config['extraHeader'])) {
1487
+ $this->xml_wrapper['header'] .= PHP_EOL . $this->config['extraHeader'];
1488
+ }
1489
 
1490
+ // replace template variables.
1491
+ $datetime_now = date('Y-m-d H:i:s', strtotime(current_time('mysql'))); // {DateTimeNow}
1492
+ if ('pinterest_rss' === $this->config['provider']) { // DATE_RFC822 date format for pinterest rss feed
1493
+ $datetime_now = date('r', strtotime(current_time('mysql'))); // {DateTimeNow}
1494
+ }
1495
+ $blog_name = get_bloginfo('name'); // {BlogName}
1496
+ $blog_url = get_bloginfo('url'); // {BlogURL}
1497
+ //$blog_desc = get_bloginfo('description'); // {BlogDescription}
1498
+ $blog_desc = "CTX Feed - This product feed is generated with the CTX Feed - WooCommerce Product Feed Manager plugin by WebAppick.com. For all your support questions check out our plugin Docs on https://webappick.com/docs or e-mail to: support@webappick.com"; // {BlogDescription}
1499
+ $blog_email = get_bloginfo('admin_email'); // {BlogEmail}
1500
+
1501
+ $this->xml_wrapper['header'] = str_replace(
1502
+ ['{DateTimeNow}', '{BlogName}', '{BlogURL}', '{BlogDescription}', '{BlogEmail}'],
1503
+ [$datetime_now, $blog_name, $blog_url, $blog_desc, $blog_email],
1504
+ $this->xml_wrapper['header']
1505
+ );
1506
+ }
1507
+
1508
+ /**
1509
+ * Make XML feed header
1510
+ * @return string
1511
+ * @since 3.2.0
1512
+ */
1513
+ protected function process_xml_feed_header()
1514
+ {
1515
+ return $this->xml_wrapper['header'];
1516
+ }
1517
+
1518
+ /**
1519
+ * Make XML feed header
1520
+ * @return string
1521
+ * @since 3.2.0
1522
+ */
1523
+ protected function process_xml_feed_footer()
1524
+ {
1525
+ return $this->xml_wrapper['footer'];
1526
+ }
1527
+
1528
+ /**
1529
+ * Process string for TXT CSV Feed
1530
+ *
1531
+ * @param $string
1532
+ *
1533
+ * @return mixed|string
1534
+ * @since 3.2.0
1535
+ *
1536
+ */
1537
+ protected function processStringForTXT($string)
1538
+ {
1539
+ if (!empty($string)) {
1540
+ $string = html_entity_decode($string, ENT_HTML401 | ENT_QUOTES); // Convert any HTML entities
1541
+
1542
+ if (stristr($string, '"')) {
1543
+ $string = str_replace('"', '""', $string);
1544
+ }
1545
+ $string = str_replace("\n", ' ', $string);
1546
+ $string = str_replace("\r", ' ', $string);
1547
+ $string = str_replace("\t", ' ', $string);
1548
+ $string = trim($string);
1549
+ $string = stripslashes($string);
1550
+
1551
+ return $string;
1552
+ } elseif ('0' == $string) {
1553
+ return '0';
1554
+ } else {
1555
+ return '';
1556
+ }
1557
+ }
1558
+
1559
+ /**
1560
+ * Process string for CSV
1561
+ *
1562
+ * @param $string
1563
+ *
1564
+ * @return mixed|string
1565
+ * @since 3.2.0
1566
+ *
1567
+ */
1568
+ protected function processStringForCSV($string)
1569
+ {
1570
+ if (!empty($string)) {
1571
+ $string = str_replace("\n", ' ', $string);
1572
+ $string = str_replace("\r", ' ', $string);
1573
+ $string = trim($string);
1574
+ $string = stripslashes($string);
1575
+
1576
+ return $string;
1577
+ } elseif ('0' == $string) {
1578
+ return '0';
1579
+ } else {
1580
+ return '';
1581
+ }
1582
+ }
1583
+
1584
+ /**
1585
+ * Get Product Attribute Value by Type
1586
+ *
1587
+ * @param $product WC_Product
1588
+ * @param $attribute
1589
+ *
1590
+ * @return mixed|string
1591
+ * @since 3.2.0
1592
+ *
1593
+ */
1594
+ public function getAttributeValueByType($product, $attribute, $merchant_attribute = '')
1595
+ {
1596
+
1597
+ if (method_exists($this, $attribute)) {
1598
+ $output = $this->$attribute($product);
1599
+ } elseif ( false !== strpos( $attribute, self::PRODUCT_ACF_FIELDS ) ) {
1600
+ $output = $this->getACFField( $product, $attribute );
1601
+ } elseif (false !== strpos($attribute, self::PRODUCT_CUSTOM_IDENTIFIER) || woo_feed_strpos_array(array('_identifier_gtin', '_identifier_ean', '_identifier_mpn'), $attribute)) {
1602
+ $output = $this->getCustomField($product, $attribute);
1603
+ } elseif (false !== strpos($attribute, self::PRODUCT_ATTRIBUTE_PREFIX)) {
1604
+ $attribute = str_replace(self::PRODUCT_ATTRIBUTE_PREFIX, '', $attribute);
1605
+ $output = $this->getProductAttribute($product, $attribute);
1606
+ } elseif (false !== strpos($attribute, self::POST_META_PREFIX)) {
1607
+ $attribute = str_replace(self::POST_META_PREFIX, '', $attribute);
1608
+ $output = $this->getProductMeta($product, $attribute);
1609
+ } elseif (false !== strpos($attribute, self::PRODUCT_TAXONOMY_PREFIX)) {
1610
+ $attribute = str_replace(self::PRODUCT_TAXONOMY_PREFIX, '', $attribute);
1611
+ $output = $this->getProductTaxonomy($product, $attribute);
1612
+ } elseif (false !== strpos($attribute, self::PRODUCT_CATEGORY_MAPPING_PREFIX)) {
1613
+ $id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
1614
+ $output = woo_feed_get_category_mapping_value($attribute, $id);
1615
+ } elseif (false !== strpos($attribute, self::WP_OPTION_PREFIX)) {
1616
+ $optionName = str_replace(self::WP_OPTION_PREFIX, '', $attribute);
1617
+ $output = get_option($optionName);
1618
+ } elseif ('image_' == substr($attribute, 0, 6)) {
1619
+ // For additional image method images() will be used with extra parameter - image number
1620
+ $imageKey = explode('_', $attribute);
1621
+ if (!isset($imageKey[1]) || (isset($imageKey[1]) && (empty($imageKey[1]) || !is_numeric($imageKey[1])))) {
1622
+ $imageKey[1] = '';
1623
+ }
1624
+ $output = call_user_func_array(array($this, 'images'), array($product, $imageKey[1]));
1625
+ } else {
1626
+ // return the attribute so multiple attribute can be join with separator to make custom attribute.
1627
+ $output = $attribute;
1628
+ }
1629
 
1630
+ // Json encode if value is an array
1631
+ if (is_array($output)) {
1632
+ $output = wp_json_encode($output);
1633
+ }
 
 
 
 
 
 
 
1634
 
1635
+ $output = $this->apply_filters_to_attribute_value($output, $product, $attribute, $merchant_attribute);
1636
+
1637
+ return $output;
1638
+ }
1639
+
1640
+ /**
1641
+ * Apply Filter to Attribute value
1642
+ *
1643
+ * @param $output
1644
+ * @param $product
1645
+ * @param $attribute
1646
+ * @param $merchant_attribute
1647
+ *
1648
+ * @return mixed|void
1649
+ */
1650
+ protected function apply_filters_to_attribute_value($output, $product, $attribute, $merchant_attribute)
1651
+ {
1652
+ /**
1653
+ * Filter attribute value
1654
+ *
1655
+ * @param string $output the output
1656
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1657
+ * @param array feed config/rule
1658
+ *
1659
+ * @since 3.4.3
1660
+ *
1661
+ */
1662
+ $output = apply_filters('woo_feed_get_attribute', $output, $product, $this->config, $merchant_attribute);
1663
+
1664
+ /**
1665
+ * Filter attribute value before return based on attribute name
1666
+ *
1667
+ * @param string $output the output
1668
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1669
+ * @param array feed config/rule
1670
+ *
1671
+ * @since 3.3.5
1672
+ *
1673
+ */
1674
+ $output = apply_filters("woo_feed_get_{$attribute}_attribute", $output, $product, $this->config);
1675
+
1676
+ /**
1677
+ * Filter attribute value before return based on merchant and attribute name
1678
+ *
1679
+ * @param string $output the output
1680
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1681
+ * @param array feed config/rule
1682
+ *
1683
+ * @since 3.3.7
1684
+ *
1685
+ */
1686
+ $output = apply_filters("woo_feed_get_{$this->config['provider']}_{$attribute}_attribute", $output, $product, $this->config);
1687
+
1688
+ return $output;
1689
+ }
1690
+
1691
+
1692
+ /**
1693
+ * Get Product Id
1694
+ *
1695
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1696
+ *
1697
+ * @return mixed
1698
+ * @since 3.2.0
1699
+ */
1700
+ protected function id($product)
1701
+ {
1702
+ $id = $product->get_id();
1703
+
1704
+ return apply_filters('woo_feed_filter_product_id', $id, $product, $this->config);
1705
+ }
1706
+
1707
+ /**
1708
+ * Get Product Title
1709
+ *
1710
+ * @param WC_Product $product
1711
+ *
1712
+ * @return mixed
1713
+ * @since 3.2.0
1714
+ *
1715
+ */
1716
+ protected function title($product)
1717
+ {
1718
+ $title = woo_feed_strip_all_tags($this->remove_short_codes($product->get_name()));
1719
+
1720
+ // Add all available variation attributes to variation title.
1721
+ if ($product->is_type('variation') && !empty($product->get_attributes())) {
1722
+ $title = $this->parent_title($product);
1723
+ $attributes = [];
1724
+ foreach ($product->get_attributes() as $slug => $value) {
1725
+ $attribute = $product->get_attribute($slug);
1726
+ if (empty($attribute)) {
1727
+ continue;
1728
+ }
1729
+ $attributes[$slug] = $attribute;
1730
+ }
1731
+
1732
+ // set variation attributes with separator
1733
+ if (isset($this->config['provider']) && 'google' === $this->config['provider']) {
1734
+ $variation_attributes = implode(' - ', $attributes);
1735
+ } else {
1736
+ $variation_attributes = implode(', ', $attributes);
1737
+ }
1738
+
1739
+ //get product title with variation attribute
1740
+ $get_with_var_attributes = apply_filters("woo_feed_get_product_title_with_variation_attribute", true, $product, $this->config);
1741
+
1742
+ if ($get_with_var_attributes) {
1743
+ $title .= " - " . $variation_attributes;
1744
+ }
1745
+ }
1746
 
1747
+ return apply_filters('woo_feed_filter_product_title', $title, $product, $this->config);
1748
+ }
1749
+
1750
+ /**
1751
+ * Get Parent Product Title
1752
+ *
1753
+ * @param WC_Product $product Product Object.
1754
+ *
1755
+ * @return mixed
1756
+ * @author Nazrul Islam Nayan
1757
+ * @since 5.1.8
1758
+ */
1759
+ protected function parent_title($product)
1760
+ {
1761
+ if ($product->is_type('variation')) {
1762
+ $product = wc_get_product($product->get_parent_id());
1763
+ $title = woo_feed_strip_all_tags($this->remove_short_codes($product->get_name()));
1764
+ } else {
1765
+ $title = $this->title($product);
1766
+ }
1767
 
1768
+ return apply_filters('woo_feed_filter_product_parent_title', $title, $product, $this->config);
1769
+ }
1770
+
1771
+ /**
1772
+ * Get All in One SEO Canonical URL
1773
+ *
1774
+ * @param WC_Product $product
1775
+ *
1776
+ * @return mixed
1777
+ * @since 4.4.12
1778
+ */
1779
+ protected function _aioseop_canonical_url($product)
1780
+ {
1781
+ $aioseop_canonical_url = '';
1782
+ if (is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post')) {
1783
+ $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
1784
+ $aioseop_canonical_url = $post->canonical_url;
1785
+ }
1786
 
1787
+ return apply_filters('woo_feed_filter_product_aioseop_canonical_url', $aioseop_canonical_url, $product, $this->config);
1788
+ }
1789
+
1790
+ /**
1791
+ * Get Yoast Product Title
1792
+ *
1793
+ * @param WC_Product $product
1794
+ *
1795
+ * @return mixed
1796
+ * @since 3.2.0
1797
+ *
1798
+ */
1799
+ protected function yoast_wpseo_title($product)
1800
+ {
1801
+ $product_id = woo_feed_parent_product_id($product);
1802
+ $yoast_title = get_post_meta($product_id, '_yoast_wpseo_title', true);
1803
+ if (strpos($yoast_title, '%%') !== false) {
1804
+ $title = strstr($yoast_title, '%%', true);
1805
+ if (empty($title)) {
1806
+ $title = get_the_title($product_id);
1807
+ }
1808
+ $wpseo_titles = get_option('wpseo_titles');
1809
+
1810
+ $sep_options = WPSEO_Option_Titles::get_instance()->get_separator_options();
1811
+ if (isset($wpseo_titles['separator']) && isset($sep_options[$wpseo_titles['separator']])) {
1812
+ $sep = $sep_options[$wpseo_titles['separator']];
1813
+ } else {
1814
+ $sep = '-'; //setting default separator if Admin didn't set it from backed
1815
+ }
1816
+
1817
+ $site_title = get_bloginfo('name');
1818
+
1819
+ $meta_title = $title . ' ' . $sep . ' ' . $site_title;
1820
+
1821
+ if (!empty($meta_title)) {
1822
+ $title = $meta_title;
1823
+ }
1824
+ } elseif (!empty($yoast_title)) {
1825
+ $title = $yoast_title;
1826
+ } else {
1827
+ $title = $this->title($product);
1828
+ }
1829
 
1830
+ return apply_filters('woo_feed_filter_product_yoast_wpseo_title', $title, $product, $this->config);
1831
+ }
1832
+
1833
+ /**
1834
+ * Get Yoast Canonical URL
1835
+ *
1836
+ * @param WC_Product $product
1837
+ *
1838
+ * @return mixed
1839
+ * @since 4.3.77
1840
+ */
1841
+ protected function yoast_canonical_url($product)
1842
+ {
1843
+ $product_id = woo_feed_parent_product_id($product);
1844
+ $yoast_canonical_url = get_post_meta($product_id, '_yoast_wpseo_canonical', true);
1845
+
1846
+ return apply_filters('woo_feed_filter_product_yoast_canonical_url', $yoast_canonical_url, $product, $this->config);
1847
+ }
1848
+
1849
+ /**
1850
+ * Get Rank Math Product Title
1851
+ *
1852
+ * @param WC_Product $product
1853
+ *
1854
+ * @return mixed
1855
+ * @since 5.1.3
1856
+ */
1857
+ protected function rank_math_title($product)
1858
+ {
1859
+ $rank_title = '';
1860
+ $post_title = '';
1861
+ $page = '';
1862
+ $sep = '';
1863
+ $sitemap = '';
1864
+ if (class_exists('RankMath')) {
1865
+ $title = get_post_meta($product->get_id(), 'rank_math_title', true);
1866
+ if (empty($title)) {
1867
+ $title_format = Helper::get_settings("titles.pt_product_title");
1868
+ $title_format = $title_format ? $title_format : '%title%';
1869
+ $sep = Helper::get_settings('titles.title_separator');
1870
+
1871
+ $rank_title = str_replace('%title%', $product->get_title(), $title_format);
1872
+ $rank_title = str_replace('%sep%', $sep, $rank_title);
1873
+ $rank_title = str_replace('%page%', '', $rank_title);
1874
+ $rank_title = str_replace('%sitename%', get_bloginfo('name'), $rank_title);
1875
+ } else {
1876
+ $rank_title = $title;
1877
+ }
1878
+ }
1879
 
1880
+ return apply_filters('woo_feed_filter_product_rank_math_title', $rank_title, $product, $this->config);
1881
+ }
1882
+
1883
+ /**
1884
+ * Get Rank Math Product Description
1885
+ *
1886
+ * @param WC_Product $product
1887
+ *
1888
+ * @return mixed
1889
+ * @since 5.1.3
1890
+ */
1891
+ protected function rank_math_description($product)
1892
+ {
1893
+ $description = '';
1894
+ if (class_exists('RankMath')) {
1895
+ $description = get_post_meta($product->get_id(), 'rank_math_description');
1896
+ $desc_format = Helper::get_settings("titles.pt_post_description");
1897
+
1898
+ if (empty($description)) {
1899
+ if (!empty($desc_format) && strpos((string)$desc_format, 'excerpt') !== false) {
1900
+ $description = str_replace('%excerpt%', get_the_excerpt($product->get_id()), $desc_format);
1901
+ }
1902
+
1903
+ // Get Variation Description
1904
+ if ($product->is_type('variation') && empty($description)) {
1905
+ $parent = wc_get_product($product->get_parent_id());
1906
+ $description = $parent->get_description();
1907
+ }
1908
+ }
1909
+
1910
+ if (is_array($description)) {
1911
+ $description = reset($description);
1912
+ }
1913
+
1914
+ $description = $this->remove_short_codes($description);
1915
+
1916
+ //strip tags and spacial characters
1917
+ $strip_description = woo_feed_strip_all_tags(wp_specialchars_decode($description));
1918
+
1919
+ $description = !empty(strlen($strip_description)) && 0 < strlen($strip_description) ? $strip_description : $description;
1920
+ }
1921
 
1922
+ return apply_filters('woo_feed_filter_product_rank_math_description', $description, $product, $this->config);
1923
+ }
1924
+
1925
+ /**
1926
+ * Get Rank Math Canonical URL
1927
+ *
1928
+ * @param WC_Product $product
1929
+ *
1930
+ * @return mixed
1931
+ * @since 5.1.6
1932
+ */
1933
+ protected function rank_math_canonical_url($product)
1934
+ {
1935
+ $canonical_url = '';
1936
+
1937
+ if (class_exists('RankMath')) {
1938
+ $post_canonical_url = get_post_meta($product->get_id(), 'rank_math_canonical_url');
1939
+
1940
+ if (empty($post_canonical_url)) {
1941
+ $canonical_url = get_the_permalink($product->get_id());
1942
+ } else {
1943
+ $canonical_url = $post_canonical_url;
1944
+ }
1945
+
1946
+ if (is_array($canonical_url)) {
1947
+ $canonical_url = reset($canonical_url);
1948
+ }
1949
+ }
1950
 
1951
+ return apply_filters('woo_feed_filter_product_rank_math_canonical_url', $canonical_url, $product, $this->config);
1952
+ }
1953
+
1954
+
1955
+ /**
1956
+ * Get All In One Product Title
1957
+ *
1958
+ * @param WC_Product $product
1959
+ *
1960
+ * @return mixed
1961
+ * @since 3.2.0
1962
+ *
1963
+ */
1964
+ protected function _aioseop_title($product)
1965
+ {
1966
+ $title = '';
1967
+ if (is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post')) {
1968
+
1969
+ $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
1970
+ $title = !empty($post->title) ? $post->title : aioseo()->meta->title->getPostTypeTitle('product');
1971
+ }
1972
 
1973
+ $title = !empty($title) ? $title : $this->title($product);
1974
+
1975
+ return apply_filters('woo_feed_filter_product_aioseop_title', $title, $product, $this->config);
1976
+ }
1977
+
1978
+ /**
1979
+ * Get Product Description
1980
+ *
1981
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1982
+ *
1983
+ * @return mixed|string
1984
+ * @since 3.2.0
1985
+ *
1986
+ */
1987
+ protected function description($product)
1988
+ {
1989
+ $description = $product->get_description();
1990
+
1991
+ // Get Variation Description
1992
+ if ($product->is_type('variation') && empty($description)) {
1993
+ $parent = wc_get_product($product->get_parent_id());
1994
+
1995
+ if (is_object($parent)) {
1996
+ $description = $parent->get_description();
1997
+ } else {
1998
+ $description = '';
1999
+ }
2000
+ }
2001
+ $description = $this->remove_short_codes($description);
2002
+
2003
+ // Add variations attributes after description to prevent Facebook error
2004
+ if ('facebook' == $this->config['provider'] && $product->is_type('variation')) {
2005
+ $variationInfo = explode('-', $product->get_name());
2006
+ if (isset($variationInfo[1])) {
2007
+ $extension = $variationInfo[1];
2008
+ } else {
2009
+ $extension = $product->get_id();
2010
+ }
2011
+ $description .= ' ' . $extension;
2012
+ }
2013
 
2014
+ //strip tags and spacial characters
2015
+ $strip_description = woo_feed_strip_all_tags(wp_specialchars_decode($description));
2016
+
2017
+ $description = !empty(strlen($strip_description)) && 0 < strlen($strip_description) ? $strip_description : $description;
2018
+
2019
+ return apply_filters('woo_feed_filter_product_description', $description, $product, $this->config);
2020
+ }
2021
+
2022
+ /**
2023
+ * Get Product Description (with HTML)
2024
+ *
2025
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2026
+ *
2027
+ * @return mixed|string
2028
+ * @since 5.2.41
2029
+ */
2030
+ protected function description_with_html($product)
2031
+ {
2032
+ $description = $product->get_description();
2033
+
2034
+ // Get Variation Description
2035
+ if ($product->is_type('variation') && empty($description)) {
2036
+ $parent = wc_get_product($product->get_parent_id());
2037
+ $description = $parent->get_description();
2038
+ }
2039
+ $description = $this->remove_short_codes($description);
2040
+
2041
+ // Add variations attributes after description to prevent Facebook error
2042
+ if ('facebook' === $this->config['provider'] && $product->is_type('variation')) {
2043
+ $variationInfo = explode('-', $product->get_name());
2044
+ if (isset($variationInfo[1])) {
2045
+ $extension = $variationInfo[1];
2046
+ } else {
2047
+ $extension = $product->get_id();
2048
+ }
2049
+ $description .= ' ' . $extension;
2050
+ }
2051
 
2052
+ //remove spacial characters
2053
+ $strip_description = wp_check_invalid_utf8(wp_specialchars_decode($description), true);
2054
+
2055
+ return apply_filters('woo_feed_filter_product_description_with_html', $description, $product, $this->config);
2056
+ }
2057
+
2058
+ /**
2059
+ * Get Yoast Product Description
2060
+ *
2061
+ * @param WC_Product $product
2062
+ *
2063
+ * @return mixed
2064
+ * @since 3.2.0
2065
+ *
2066
+ */
2067
+ protected function yoast_wpseo_metadesc($product)
2068
+ {
2069
+ $product_id = woo_feed_parent_product_id($product);
2070
+ $description = '';
2071
+ if (class_exists('WPSEO_Frontend')) {
2072
+ $description = wpseo_replace_vars(WPSEO_Meta::get_value('metadesc', $product_id),
2073
+ get_post($product->get_id()));
2074
+ } else {
2075
+ $description = YoastSEO()->meta->for_post($product_id)->description;
2076
+ }
2077
 
2078
+ if (empty($description)) {
2079
+ $description = $this->description($product);
2080
+ }
2081
 
2082
+ return apply_filters('woo_feed_filter_product_yoast_wpseo_metadesc', $description, $product, $this->config);
2083
+ }
2084
+
2085
+ /**
2086
+ * Get All In One Product Description
2087
+ *
2088
+ * @param WC_Product $product
2089
+ *
2090
+ * @return mixed
2091
+ * @since 3.2.0
2092
+ *
2093
+ */
2094
+ protected function _aioseop_description($product)
2095
+ {
2096
+ $description = '';
2097
+
2098
+ if (is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php') && class_exists('AIOSEO\Plugin\Common\Models\Post')) {
2099
+
2100
+ $post = AIOSEO\Plugin\Common\Models\Post::getPost($product->get_id());
2101
+ $description = !empty($post->description) ? $post->description : aioseo()->meta->description->getPostTypeDescription('product');
2102
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2103
 
2104
+ if (empty($description)) {
2105
+ $description = $this->description($product);
2106
+ }
2107
 
2108
+ return apply_filters('woo_feed_filter_product_aioseop_description', $description, $product, $this->config);
2109
+ }
2110
+
2111
+ /**
2112
+ * Get Product Short Description
2113
+ *
2114
+ * @param WC_Product $product
2115
+ *
2116
+ * @return mixed|string
2117
+ * @since 3.2.0
2118
+ *
2119
+ */
2120
+ protected function short_description($product)
2121
+ {
2122
+ $short_description = $product->get_short_description();
2123
+
2124
+ // Get Variation Short Description
2125
+ if ($product->is_type('variation') && empty($short_description)) {
2126
+ $parent = wc_get_product($product->get_parent_id());
2127
+ $short_description = $parent->get_short_description();
2128
+ }
2129
 
 
 
2130
 
2131
+ $short_description = $this->remove_short_codes($short_description);
 
 
 
 
 
2132
 
2133
+ //strip tags and spacial characters
2134
+ $short_description = woo_feed_strip_all_tags(wp_specialchars_decode($short_description));
2135
 
2136
+ return apply_filters('woo_feed_filter_product_short_description', $short_description, $product, $this->config);
2137
+ }
2138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2139
 
2140
+ /**
2141
+ * At First convert Short Codes and then Remove failed Short Codes from String
2142
+ *
2143
+ * @param $content
2144
+ *
2145
+ * @return mixed|string
2146
+ * @since 3.2.0
2147
+ *
2148
+ */
2149
+ protected function remove_short_codes($content)
2150
+ {
2151
+ if ($content == '') {
2152
+ return '';
2153
+ }
2154
 
2155
+ $content = do_shortcode($content);
 
2156
 
2157
+ $content = woo_feed_stripInvalidXml($content);
 
 
 
 
 
 
 
 
 
2158
 
2159
+ // Covers all kinds of shortcodes
2160
+ $expression = '/\[\/*[a-zA-Z1-90_| -=\'"\{\}]*\/*\]/m';
2161
 
2162
+ $content = preg_replace($expression, '', $content);
2163
 
2164
+ return strip_shortcodes($content);
2165
+ }
2166
 
2167
+ /*
2168
+ * Retrieves product's parent category
2169
+ *
2170
+ * @param $product A Post/Product object
2171
  *
2172
+ * @return WP_Term
2173
+ * @since 4.4.19
2174
+ * */
2175
+ protected function product_parent_category_object($product)
2176
+ {
2177
+ global $parent_category_memo;
2178
+ if (empty($parent_category_memo)) {
2179
+ $parent_category_memo = [];
2180
+ }
2181
 
2182
+ $id = $product->get_id();
2183
+ if ($product->is_type('variation')) {
2184
+ $id = $product->get_parent_id();
2185
+ }
2186
 
2187
+ $taxonomy = 'product_cat';
2188
+ $categories = wp_get_post_terms($id, $taxonomy);
2189
+ $child_category = $categories[count($categories) - 1]; // Last selected category
2190
+
2191
+ $parent_category = '';
2192
+
2193
+ // Memoization for faster parent retrieval
2194
+ if (
2195
+ isset($parent_category_memo[$child_category->term_id])
2196
+ && !empty($parent_category_memo[$child_category->term_id])
2197
+ ) {
2198
+ $parent_category = get_term_by('term_id', $parent_category_memo[$child_category->term_id], $taxonomy);
2199
+ } else {
2200
+ $parent_category = woo_feed_parent_category($child_category, $taxonomy);
2201
+ $parent_category_memo[$child_category->term_id] = $parent_category->term_id;
2202
+ }
2203
 
2204
+ // Yoast SEO primary term fetching
2205
+ if (class_exists('WPSEO_Primary_Term')) {
2206
+ $wpseo_primary_term = new WPSEO_Primary_Term($taxonomy, $id);
2207
+ $parent_category_id = $wpseo_primary_term->get_primary_term();
2208
+ if (!empty($parent_category_id)) {
2209
+ $parent_category = get_term_by('term_id', $parent_category_id, $taxonomy);
2210
+ }
2211
+ }
2212
 
2213
+ return $parent_category;
2214
+ }
2215
+
2216
+ /**
2217
+ * Get Product Parent/Main Category
2218
+ *
2219
+ * @param WC_Product $product
2220
+ *
2221
+ * @return string
2222
+ *
2223
+ */
2224
+ protected function primary_category($product)
2225
+ {
2226
+ $parent_category = "";
2227
+ $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2228
+ $full_category = $this->product_type($product);
2229
+ if (!empty($full_category)) {
2230
+ $full_category_array = explode($separator, $full_category);
2231
+ $parent_category = $full_category_array[0];
2232
+ }
2233
 
2234
+ return apply_filters('woo_feed_filter_product_primary_category', $parent_category, $product, $this->config);
2235
+ }
2236
+
2237
+ /**
2238
+ * Get Product Parent/Main Category ID
2239
+ *
2240
+ * @param WC_Product $product
2241
+ *
2242
+ * @return string
2243
+ *
2244
+ */
2245
+ protected function primary_category_id($product)
2246
+ {
2247
+ $parent_category_id = "";
2248
+ $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2249
+ $full_category = $this->product_type($product);
2250
+ if (!empty($full_category)) {
2251
+ $full_category_array = explode($separator, $full_category);
2252
+ $parent_category_obj = get_term_by('name', $full_category_array[0], 'product_cat');
2253
+ $parent_category_id = isset($parent_category_obj->term_id) ? $parent_category_obj->term_id : "";
2254
+ }
2255
 
2256
+ return apply_filters('woo_feed_filter_product_primary_category_id', $parent_category_id, $product, $this->config);
2257
+ }
2258
+
2259
+ /**
2260
+ * Get Product Child Category
2261
+ *
2262
+ * @param WC_Product $product
2263
+ *
2264
+ * @return string
2265
+ */
2266
+ protected function child_category($product)
2267
+ {
2268
+ $child_category = "";
2269
+ $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2270
+ $full_category = $this->product_type($product);
2271
+ if (!empty($full_category)) {
2272
+ $full_category_array = explode($separator, $full_category);
2273
+ $child_category = end($full_category_array);
2274
+ }
2275
 
2276
+ return apply_filters('woo_feed_filter_product_child_category', $child_category, $product, $this->config);
2277
+ }
2278
+
2279
+ /**
2280
+ * Get Product Child Category ID
2281
+ *
2282
+ * @param WC_Product $product
2283
+ *
2284
+ * @return string
2285
+ */
2286
+ protected function child_category_id($product)
2287
+ {
2288
+ $child_category_id = "";
2289
+ $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
2290
+ $full_category = $this->product_type($product);
2291
+ if (!empty($full_category)) {
2292
+ $full_category_array = explode($separator, $full_category);
2293
+ $child_category_obj = get_term_by('name', end($full_category_array), 'product_cat');
2294
+ $child_category_id = isset($child_category_obj->term_id) ? $child_category_obj->term_id : "";
2295
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2296
 
2297
+ return apply_filters('woo_feed_filter_product_child_category_id', $child_category_id, $product, $this->config);
2298
+ }
2299
+
2300
+ /**
2301
+ * Get Product Categories
2302
+ *
2303
+ * @param WC_Product $product
2304
+ *
2305
+ * @return string
2306
+ * @since 3.2.0
2307
+ *
2308
+ */
2309
+ protected function product_type($product)
2310
+ {
2311
+ $id = $product->get_id();
2312
+ if ($product->is_type('variation')) {
2313
+ $id = $product->get_parent_id();
2314
+ }
2315
 
2316
+ $separator = apply_filters('woo_feed_product_type_separator', ' > ', $this->config, $product);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2317
 
2318
+ $product_type = woo_feed_strip_all_tags(wc_get_product_category_list($id, $separator));
 
 
 
 
 
 
 
 
 
 
 
2319
 
2320
+ $product_categories = '';
2321
+ $term_list = get_the_terms($id, 'product_cat');
 
 
 
 
 
 
 
 
 
 
2322
 
2323
+ if (is_array($term_list)) {
2324
+ $col = array_column($term_list, "term_id");
2325
+ array_multisort($col, SORT_ASC, $term_list);
2326
+ $term_list = array_column($term_list, "name");
2327
+ $product_categories = implode($separator, $term_list);
2328
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2330
 
2331
+ return apply_filters('woo_feed_filter_product_local_category', $product_categories, $product, $this->config);
2332
+ }
2333
 
2334
+ /**
2335
+ * Get Product Full Categories with unselected category parent
2336
+ *
2337
+ * @param WC_Product $product
2338
+ *
2339
+ * @return string
2340
+ * @since 4.3.47
2341
+ */
2342
+ protected function product_full_cat($product)
2343
+ {
2344
+ // $id = $product->get_id();
2345
+ // if ($product->is_type('variation')) {
2346
+ // $id = $product->get_parent_id();
2347
+ // }
2348
+ //
2349
+ // $separator = apply_filters('woo_feed_product_type_separator', '>', $this->config, $product);
2350
+ //
2351
+ // $product_type = woo_feed_get_terms_list_hierarchical_order($id);
2352
 
2353
+ $product_type = $this->product_type($product);
2354
+
2355
+ return apply_filters('woo_feed_filter_product_local_category', $product_type, $product, $this->config);
2356
+ }
2357
+
2358
+ /**
2359
+ * Get Product URL
2360
+ *
2361
+ * @param WC_Product|WC_Product_Variation $product
2362
+ *
2363
+ * @return string
2364
+ * @since 3.2.0
2365
+ *
2366
+ */
2367
+ protected function link($product)
2368
+ {
2369
+
2370
+ $link = $product->get_permalink();
2371
+
2372
+ $link = $this->add_utm_tracker($link);
2373
+ return apply_filters('woo_feed_filter_product_link', $link, $product, $this->config);
2374
+ }
2375
+
2376
+ /**
2377
+ * Adding UTM Tracker Query Arguments to URL
2378
+ * @param string $url
2379
+ *
2380
+ * @return string $url
2381
+ * @since 4.4.26
2382
+ */
2383
+ protected function add_utm_tracker($url)
2384
+ {
2385
+
2386
+ $utm = $this->config['campaign_parameters'];
2387
+
2388
+ if (!empty($utm['utm_source']) && !empty($utm['utm_medium']) && !empty($utm['utm_campaign'])) {
2389
+
2390
+ $utm = [
2391
+ 'utm_source' => str_replace(' ', '+', $utm['utm_source']),
2392
+ 'utm_medium' => str_replace(' ', '+', $utm['utm_medium']),
2393
+ 'utm_campaign' => str_replace(' ', '+', $utm['utm_campaign']),
2394
+ 'utm_term' => str_replace(' ', '+', $utm['utm_term']),
2395
+ 'utm_content' => str_replace(' ', '+', $utm['utm_content']),
2396
+ ];
2397
+
2398
+ $url = add_query_arg(array_filter($utm), $url);
2399
 
2400
+ }
2401
 
2402
+ return $url;
2403
+ }
2404
+
2405
+ /**
2406
+ * Get Parent Product URL
2407
+ *
2408
+ * @param WC_Product $product
2409
+ *
2410
+ * @return string
2411
+ * @author Nazrul Islam Nayan
2412
+ * @since 5.1.8
2413
+ */
2414
+ protected function parent_link($product)
2415
+ {
2416
+ if ($product->is_type('variation')) {
2417
+ $product = wc_get_product($product->get_parent_id());
2418
+ $link = $this->link($product);
2419
+ } else {
2420
+ $link = $this->link($product);
2421
+ }
2422
 
2423
+ return apply_filters('woo_feed_filter_product_parent_link', $link, $product, $this->config);
2424
+ }
2425
+
2426
+ /**
2427
+ * Get Canonical Link
2428
+ * @param WC_Product $product
2429
+ * @return mixed
2430
+ */
2431
+ protected function canonical_link($product)
2432
+ {
2433
+ if ($product->is_type('variation')) {
2434
+ $product = wc_get_product($product->get_parent_id());
2435
+ $canonical_link = $product->get_permalink();
2436
+ } else {
2437
+ $canonical_link = $product->get_permalink();
2438
+ }
2439
 
2440
+ return apply_filters('woo_feed_filter_product_canonical_link', $canonical_link, $product, $this->config);
2441
+ }
2442
+
2443
+ /**
2444
+ * Get External Product URL
2445
+ *
2446
+ * @param WC_Product $product
2447
+ *
2448
+ * @return string
2449
+ * @since 3.2.0
2450
+ *
2451
+ */
2452
+ protected function ex_link($product)
2453
+ {
2454
+ if ($product->is_type('external')) {
2455
+ $utm = $this->config['campaign_parameters'];
2456
+ if (!empty($utm['utm_source']) && !empty($utm['utm_medium']) && !empty($utm['utm_campaign'])) {
2457
+ $utm = [
2458
+ 'utm_source' => str_replace(' ', '+', $utm['utm_source']),
2459
+ 'utm_medium' => str_replace(' ', '+', $utm['utm_medium']),
2460
+ 'utm_campaign' => str_replace(' ', '+', $utm['utm_campaign']),
2461
+ 'utm_term' => str_replace(' ', '+', $utm['utm_term']),
2462
+ 'utm_content' => str_replace(' ', '+', $utm['utm_content']),
2463
+ ];
2464
+
2465
+ return add_query_arg(array_filter($utm), $product->get_product_url());
2466
+ } else {
2467
+ $ex_link = $product->get_product_url();
2468
+ }
2469
+ } else {
2470
+ $ex_link = '';
2471
+ }
2472
 
2473
+ return apply_filters('woo_feed_filter_product_ex_link', $ex_link, $product, $this->config);
2474
+ }
2475
+
2476
+ /**
2477
+ * Get Product Image
2478
+ *
2479
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2480
+ *
2481
+ * @return mixed
2482
+ * @since 3.2.0
2483
+ *
2484
+ */
2485
+ protected function image($product)
2486
+ {
2487
+ $image = '';
2488
+ if ($product->is_type('variation')) {
2489
+ // Variation product type
2490
+ if (has_post_thumbnail($product->get_id())) {
2491
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_id()), 'single-post-thumbnail');
2492
+ $image = woo_feed_get_formatted_url($getImage[0]);
2493
+ } elseif (has_post_thumbnail($product->get_parent_id())) {
2494
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_parent_id()), 'single-post-thumbnail');
2495
+ $image = woo_feed_get_formatted_url($getImage[0]);
2496
+ }
2497
+ } elseif (has_post_thumbnail($product->get_id())) { // All product type except variation
2498
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_id()), 'single-post-thumbnail');
2499
+ $image = isset($getImage[0]) ? woo_feed_get_formatted_url($getImage[0]) : '';
2500
+ }
2501
 
2502
+ return apply_filters('woo_feed_filter_product_image', $image, $product, $this->config);
2503
+ }
2504
+
2505
+ /**
2506
+ * Get Product Featured Image. For product variations it will return the variable product image.
2507
+ *
2508
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2509
+ *
2510
+ * @return mixed
2511
+ * @since 3.2.0
2512
+ *
2513
+ */
2514
+ protected function feature_image($product)
2515
+ {
2516
+ if ($product->is_type('variation')) {
2517
+ $id = $product->get_parent_id();
2518
+ } else {
2519
+ $id = $product->get_id();
2520
+ }
2521
 
2522
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($id), 'single-post-thumbnail');
2523
+ $image = isset($getImage[0]) ? woo_feed_get_formatted_url($getImage[0]) : '';
2524
+
2525
+ return apply_filters('woo_feed_filter_product_feature_image', $image, $product, $this->config);
2526
+ }
2527
+
2528
+ /**
2529
+ * Get Comma Separated Product Images
2530
+ *
2531
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
2532
+ * @param string $additionalImg Specific Additional Image.
2533
+ *
2534
+ * @return mixed
2535
+ * @since 3.2.0
2536
+ *
2537
+ */
2538
+ protected function images($product, $additionalImg = '')
2539
+ {
2540
+ $imgUrls = $this->get_product_gallery($product);
2541
+ $separator = ',';
2542
+
2543
+ // Return Specific Additional Image URL
2544
+ if ('' !== $additionalImg) {
2545
+ if (array_key_exists($additionalImg, $imgUrls)) {
2546
+ $images = $imgUrls[$additionalImg];
2547
+ } else {
2548
+ $images = '';
2549
+ }
2550
+ } else {
2551
+ if (isset($this->config['provider']) && "idealo" === $this->config['provider']) {
2552
+ $separator = ';';
2553
+ }
2554
+
2555
+ $images = implode($separator, array_filter($imgUrls));
2556
+ }
2557
 
2558
+ return apply_filters('woo_feed_filter_product_images', $images, $product, $this->config);
2559
+ }
2560
+
2561
+ /**
2562
+ * Get Product Gallery Items (URL) array.
2563
+ * This can contains empty array values
2564
+ *
2565
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product
2566
+ *
2567
+ * @return string[]
2568
+ * @since 3.2.6
2569
+ */
2570
+ protected function get_product_gallery($product)
2571
+ {
2572
+ $imgUrls = [];
2573
+ $attachmentIds = [];
2574
+
2575
+ if ($product->is_type('variation')) {
2576
+ if (class_exists('Woo_Variation_Gallery')) {
2577
+ /**
2578
+ * Get Variation Additional Images for "Additional Variation Images Gallery for WooCommerce"
2579
+ * @plugin Additional Variation Images Gallery for WooCommerce
2580
+ * @link https://wordpress.org/plugins/woo-variation-gallery/
2581
+ */
2582
+ $attachmentIds = get_post_meta($product->get_id(), 'woo_variation_gallery_images', true);
2583
+ } elseif (class_exists('WooProductVariationGallery')) {
2584
+ /**
2585
+ * Get Variation Additional Images for "Variation Images Gallery for WooCommerce"
2586
+ * @plugin Variation Images Gallery for WooCommerce
2587
+ * @link https://wordpress.org/plugins/woo-product-variation-gallery/
2588
+ */
2589
+ $attachmentIds = get_post_meta($product->get_id(), 'rtwpvg_images', true);
2590
+ } elseif (class_exists('WC_Additional_Variation_Images')) {
2591
+ /**
2592
+ * Get Variation Additional Images for "WooCommerce Additional Variation Images"
2593
+ * @plugin WooCommerce Additional Variation Images
2594
+ * @link https://woocommerce.com/products/woocommerce-additional-variation-images/
2595
+ */
2596
+ $attachmentIds = explode(',', get_post_meta($product->get_id(), '_wc_additional_variation_images', true));
2597
+ } elseif (class_exists('WOODMART_Theme')) {
2598
+ /**
2599
+ * Get Variation Additional Images for "WOODMART Theme -> Variation Gallery Images Feature"
2600
+ * @theme WOODMART
2601
+ * @link https://themeforest.net/item/woodmart-woocommerce-wordpress-theme/20264492
2602
+ */
2603
+ $var_id = $product->get_id();
2604
+ $parent_id = $product->get_parent_id();
2605
+
2606
+ $variation_obj = get_post_meta($parent_id, 'woodmart_variation_gallery_data', true);
2607
+ if (isset($variation_obj) && isset($variation_obj[$var_id])) {
2608
+ $attachmentIds = explode(',', $variation_obj[$var_id]);
2609
+ } else {
2610
+ $attachmentIds = explode(',', get_post_meta($var_id, 'wd_additional_variation_images_data', true));
2611
+ }
2612
+ } else {
2613
+ /**
2614
+ * If any Variation Gallery Image plugin not installed then get Variable Product Additional Image Ids .
2615
+ */
2616
+ $attachmentIds = wc_get_product($product->get_parent_id())->get_gallery_image_ids();
2617
+ }
2618
+ }
2619
 
2620
+ /**
2621
+ * Get Variable Product Gallery Image ids if Product is not a variation
2622
+ * or variation does not have any gallery images
2623
+ */
2624
+ if (empty($attachmentIds)) {
2625
+ $attachmentIds = $product->get_gallery_image_ids();
2626
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2627
 
2628
+ if ($attachmentIds && is_array($attachmentIds)) {
2629
+ $mKey = 1;
2630
+ foreach ($attachmentIds as $attachmentId) {
2631
+ $imgUrls[$mKey] = woo_feed_get_formatted_url(wp_get_attachment_url($attachmentId));
2632
+ $mKey++;
2633
+ }
2634
+ }
2635
 
2636
+ return $imgUrls;
2637
+ }
2638
+
2639
+ /**
2640
+ * Get Product Condition
2641
+ *
2642
+ * @param WC_Product $product
2643
+ *
2644
+ * @return mixed
2645
+ * @since 3.2.0
2646
+ *
2647
+ */
2648
+ protected function condition($product)
2649
+ {
2650
+ return apply_filters('woo_feed_product_condition', 'new', $product);
2651
+ }
2652
+
2653
+ /**
2654
+ * Get Product Type
2655
+ *
2656
+ * @param WC_Product $product
2657
+ *
2658
+ * @return mixed
2659
+ * @since 3.2.0
2660
+ *
2661
+ */
2662
+ protected function type($product)
2663
+ {
2664
+ return apply_filters('woo_feed_filter_product_type', $product->get_type(), $product, $this->config);
2665
+ }
2666
+
2667
+ /**
2668
+ * Get Product is a bundle product or not
2669
+ *
2670
+ * @param WC_Product $product
2671
+ *
2672
+ * @return mixed
2673
+ * @since 3.2.0
2674
+ *
2675
+ */
2676
+ protected function is_bundle($product)
2677
+ {
2678
+ if ($product->is_type('bundle') || $product->is_type('yith_bundle')) {
2679
+ $is_bundle = 'yes';
2680
+ } else {
2681
+ $is_bundle = 'no';
2682
+ }
2683
 
2684
+ return apply_filters('woo_feed_filter_product_is_bundle', $is_bundle, $product, $this->config);
2685
+ }
2686
+
2687
+ /**
2688
+ * Get Product is a multi-pack product or not
2689
+ *
2690
+ * @param WC_Product $product
2691
+ *
2692
+ * @return mixed
2693
+ * @since 3.2.0
2694
+ *
2695
+ */
2696
+ protected function multipack($product)
2697
+ {
2698
+ $multi_pack = '';
2699
+ if ($product->is_type('grouped')) {
2700
+ $multi_pack = (!empty($product->get_children())) ? count($product->get_children()) : '';
2701
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2702
 
2703
+ return $multi_pack;
2704
+ }
2705
+
2706
+ /**
2707
+ * Get Product visibility status
2708
+ *
2709
+ * @param WC_Product $product
2710
+ *
2711
+ * @return mixed
2712
+ * @since 3.2.0
2713
+ *
2714
+ */
2715
+ protected function visibility($product)
2716
+ {
2717
+ return apply_filters('woo_feed_filter_product_visibility', $product->get_catalog_visibility(), $product, $this->config);
2718
+ }
2719
+
2720
+ /**
2721
+ * Get Product Total Rating
2722
+ *
2723
+ * @param WC_Product $product
2724
+ *
2725
+ * @return mixed
2726
+ * @since 3.2.0
2727
+ *
2728
+ */
2729
+ protected function rating_total($product)
2730
+ {
2731
+ return apply_filters('woo_feed_filter_product_rating_total', $product->get_rating_count(), $product, $this->config);
2732
+ }
2733
+
2734
+ /**
2735
+ * Get Product average rating
2736
+ *
2737
+ * @param WC_Product $product
2738
+ *
2739
+ * @return mixed
2740
+ * @since 3.2.0
2741
+ *
2742
+ */
2743
+ protected function rating_average($product)
2744
+ {
2745
+ return apply_filters('woo_feed_filter_product_rating_average', $product->get_average_rating(), $product, $this->config);
2746
+ }
2747
+
2748
+ /**
2749
+ * Get Product tags
2750
+ *
2751
+ * @param WC_Product $product
2752
+ *
2753
+ * @return string
2754
+ * @since 3.2.0
2755
+ *
2756
+ */
2757
+ protected function tags($product)
2758
+ {
2759
+ $id = $product->get_id();
2760
+ if ($product->is_type('variation')) {
2761
+ $id = $product->get_parent_id();
2762
+ }
2763
 
2764
+ /**
2765
+ * Separator for multiple tags
2766
+ * @param string $separator
2767
+ * @param array $config
2768
+ * @param WC_Abstract_Legacy_Product $product
2769
+ * @since 3.4.3
2770
+ */
2771
+ $separator = apply_filters('woo_feed_tags_separator', ',', $this->config, $product);
2772
+
2773
+ $tags = woo_feed_strip_all_tags(get_the_term_list($id, 'product_tag', '', $separator, ''));
2774
+
2775
+ return apply_filters('woo_feed_filter_product_tags', $tags, $product, $this->config);
2776
+ }
2777
+
2778
+ /**
2779
+ * Get Product Parent Id
2780
+ *
2781
+ * @param WC_Product $product
2782
+ *
2783
+ * @return mixed
2784
+ * @since 3.2.0
2785
+ *
2786
+ */
2787
+ protected function item_group_id($product)
2788
+ {
2789
+ $id = $product->get_id();
2790
+ if ($product->is_type('variation')) {
2791
+ $id = $product->get_parent_id();
2792
+ }
2793
 
2794
+ return apply_filters('woo_feed_filter_product_item_group_id', $id, $product, $this->config);
2795
+ }
2796
+
2797
+ /**
2798
+ * Get Product SKU
2799
+ *
2800
+ * @param WC_Product $product
2801
+ *
2802
+ * @return mixed
2803
+ * @since 3.2.0
2804
+ *
2805
+ */
2806
+ protected function sku($product)
2807
+ {
2808
+ return apply_filters('woo_feed_filter_product_sku', $product->get_sku(), $product, $this->config);
2809
+ }
2810
+
2811
+ /**
2812
+ * Get Product SKU ID. It should come with after merging of sku and product id with '_' sign.
2813
+ *
2814
+ * @param WC_Product $product
2815
+ *
2816
+ * @return string
2817
+ * @author Nazrul Islam Nayan
2818
+ * @since 4.3.13
2819
+ */
2820
+ protected function sku_id($product)
2821
+ {
2822
+ $sku = !empty($product->get_sku()) ? $product->get_sku() . '_' : '';
2823
+ $sku_id = $sku . $product->get_id();
2824
+
2825
+ return apply_filters('woo_feed_filter_product_sku_id', $sku_id, $product, $this->config);
2826
+ }
2827
+
2828
+ /**
2829
+ * Get Product Parent SKU
2830
+ *
2831
+ * @param WC_Product $product
2832
+ *
2833
+ * @return mixed
2834
+ * @since 3.2.0
2835
+ *
2836
+ */
2837
+ protected function parent_sku($product)
2838
+ {
2839
+ if ($product->is_type('variation')) {
2840
+ $id = $product->get_parent_id();
2841
+ $parent = wc_get_product($id);
2842
+
2843
+ $parent_sku = $parent->get_sku();
2844
+ } else {
2845
+ $parent_sku = $product->get_sku();
2846
+ }
2847
 
2848
+ return apply_filters('woo_feed_filter_product_parent_sku', $parent_sku, $product, $this->config);
2849
+ }
2850
+
2851
+ /**
2852
+ * Get Product Availability Status
2853
+ *
2854
+ * @param WC_Product $product
2855
+ *
2856
+ * @return mixed
2857
+ * @since 3.2.0
2858
+ *
2859
+ */
2860
+ protected function availability($product)
2861
+ {
2862
+ $status = $product->get_stock_status();
2863
+ if ('instock' == $status) {
2864
+ $status = 'in stock';
2865
+ } elseif ('outofstock' == $status) {
2866
+ $status = 'out of stock';
2867
+ } elseif ('onbackorder' == $status) {
2868
+ $status = 'on backorder';
2869
+ }
2870
 
2871
+ // set (_) as separator for google merchant
2872
+ if (isset($this->config['provider']) && 'google' === $this->config['provider']) {
2873
+ $status = explode(' ', $status);
2874
+ $status = implode('_', $status);
2875
+ }
2876
 
2877
+ return apply_filters('woo_feed_filter_product_availability', $status, $product, $this->config);
2878
+ }
2879
+
2880
+ /**
2881
+ * Get Product Availability Date
2882
+ *
2883
+ * @param WC_Product $product
2884
+ *
2885
+ * @return mixed
2886
+ * @author Ohidul Islam
2887
+ * @since 3.2.0
2888
+ *
2889
+ */
2890
+ protected function availability_date($product)
2891
+ {
2892
+
2893
+ $feed_settings = get_option('woo_feed_settings');
2894
+
2895
+ $availability_date_settings = isset($feed_settings['woo_feed_identifier']['availability_date'])
2896
+ ? $feed_settings['woo_feed_identifier']['availability_date']
2897
+ : 'enable';
2898
+
2899
+ if ($product->get_stock_status() !== 'onbackorder' || $availability_date_settings === 'disable') {
2900
+ return '';
2901
+ }
2902
 
2903
+ $meta_field_name = 'woo_feed_availability_date';
2904
 
2905
+ if ($product->is_type('variation')) {
2906
+ $meta_field_name .= '_var';
2907
+ }
2908
 
2909
+ $availability_date = get_post_meta($product->get_id(), $meta_field_name, true);
 
 
 
 
 
 
 
 
 
2910
 
2911
+ if ('' !== $availability_date && in_array($this->config['provider'], [
2912
+ 'google',
2913
+ 'facebook',
2914
+ 'pinterest',
2915
+ 'bing',
2916
+ 'snapchat',
2917
+ ], true)) {
2918
+ $availability_date = gmdate('c', strtotime($availability_date));
2919
+ }
2920
 
2921
+ return apply_filters('woo_feed_filter_product_availability_date', $availability_date, $product, $this->config);
2922
+ }
2923
+
2924
+ /**
2925
+ * Get Product Add to Cart Link
2926
+ *
2927
+ * @param WC_Product $product
2928
+ *
2929
+ * @return string
2930
+ * @author Nazrul Islam Nayan
2931
+ * @since 5.1.8
2932
+ */
2933
+ protected function add_to_cart_link($product)
2934
+ {
2935
+ $url = $this->link($product);
2936
+ $suffix = 'add-to-cart=' . $product->get_id();
2937
+
2938
+ $add_to_cart_link = woo_feed_make_url_with_parameter($url, $suffix);
2939
+
2940
+ return apply_filters('woo_feed_filter_product_add_to_cart_link', $add_to_cart_link, $product, $this->config);
2941
+ }
2942
+
2943
+ /**
2944
+ * Get Product Quantity
2945
+ *
2946
+ * @param WC_Product $product
2947
+ *
2948
+ * @return mixed
2949
+ * @since 3.2.0
2950
+ *
2951
+ */
2952
+ protected function quantity($product)
2953
+ {
2954
+ $quantity = $product->get_stock_quantity();
2955
+ $status = $product->get_stock_status();
2956
+
2957
+ //when product is outofstock and it's quantity is empty, set quantity to 0
2958
+ if ('outofstock' == $status && empty($quantity)) {
2959
+ $quantity = 0;
2960
+ }
2961
 
2962
+ if ($product->is_type('variable') && $product->has_child()) {
2963
+ $visible_children = $product->get_visible_children();
2964
+ $qty = array();
2965
+ foreach ($visible_children as $key => $child) {
2966
+ $childQty = get_post_meta($child, '_stock', true);
2967
+ $qty[] = (int)$childQty + 0;
2968
+ }
2969
+
2970
+ if (isset($this->config['variable_quantity'])) {
2971
+ $vaQty = $this->config['variable_quantity'];
2972
+ if ('max' == $vaQty) {
2973
+ $quantity = max($qty);
2974
+ } elseif ('min' == $vaQty) {
2975
+ $quantity = min($qty);
2976
+ } elseif ('sum' == $vaQty) {
2977
+ $quantity = array_sum($qty);
2978
+ } elseif ('first' == $vaQty) {
2979
+ $quantity = ((int)$qty[0]);
2980
+ }
2981
+
2982
+ $quantity = array_sum($qty);
2983
+ }
2984
+ }
2985
 
2986
+ return apply_filters('woo_feed_filter_product_quantity', $quantity, $product, $this->config);
2987
+ }
2988
+
2989
+ /**
2990
+ * Get Product Currency
2991
+ *
2992
+ * @param WC_Product $product
2993
+ *
2994
+ * @return mixed
2995
+ * @since 4.4.39
2996
+ *
2997
+ */
2998
+ protected function currency($product)
2999
+ {
3000
+ $quantity = get_option('woocommerce_currency');
3001
+
3002
+ return apply_filters('woo_feed_filter_product_currency', $quantity, $product, $this->config);
3003
+ }
3004
+
3005
+ /**
3006
+ * Get Store currency code.
3007
+ *
3008
+ * @param WC_Product $product Product Object
3009
+ * @return mixed|string
3010
+ * @since 3.2.0
3011
+ *
3012
+ */
3013
+ protected function store_currency($product)
3014
+ {
3015
+ return get_woocommerce_currency();
3016
+ }
3017
+
3018
+ /**
3019
+ * Get Product Sale Price Start Date
3020
+ *
3021
+ * @param WC_Product $product
3022
+ *
3023
+ * @return mixed
3024
+ * @since 3.2.0
3025
+ *
3026
+ */
3027
+ protected function sale_price_sdate($product)
3028
+ {
3029
+ $startDate = $product->get_date_on_sale_from();
3030
+ if (is_object($startDate)) {
3031
+ $sale_price_sdate = $startDate->date_i18n();
3032
+ } else {
3033
+ $sale_price_sdate = '';
3034
+ }
3035
 
3036
+ return apply_filters('woo_feed_filter_product_sale_price_sdate', $sale_price_sdate, $product, $this->config);
3037
+ }
3038
+
3039
+ /**
3040
+ * Get Product Sale Price End Date
3041
+ *
3042
+ * @param WC_Product $product
3043
+ *
3044
+ * @return mixed
3045
+ * @since 3.2.0
3046
+ *
3047
+ */
3048
+ protected function sale_price_edate($product)
3049
+ {
3050
+ $endDate = $product->get_date_on_sale_to();
3051
+ if (is_object($endDate)) {
3052
+ $sale_price_edate = $endDate->date_i18n();
3053
+ } else {
3054
+ $sale_price_edate = "";
3055
+ }
3056
 
3057
+ return apply_filters('woo_feed_filter_product_sale_price_edate', $sale_price_edate, $product, $this->config);
3058
+ }
3059
+
3060
+ /**
3061
+ * Get feed currency
3062
+ *
3063
+ * @return mixed|string
3064
+ */
3065
+ protected function get_feed_currency()
3066
+ {
3067
+ $currency = get_woocommerce_currency();
3068
+ if (isset($this->config['feedCurrency'])) {
3069
+ $currency = $this->config['feedCurrency'];
3070
+ }
3071
 
3072
+ return $currency;
3073
+ }
3074
+
3075
+ /**
3076
+ * Get Product Price by default WooCommerce Price Type (regular_price|price|sale_price).
3077
+ *
3078
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object
3079
+ * @param string $price_type Price Type (regular_price|price|sale_price)
3080
+ * @param bool $tax Add tax with price (true|false)
3081
+ *
3082
+ * @return float|mixed|string|void
3083
+ * @since 4.4.14
3084
+ *
3085
+ * @author Ohidul Islam
3086
+ */
3087
+ protected function get_price_by_price_type($product, $price_type, $tax)
3088
+ {
3089
+
3090
+ if ('regular_price' === $price_type) {
3091
+ $price = $product->get_regular_price();
3092
+ } elseif ('price' === $price_type) {
3093
+ $price = $product->get_price();
3094
+ } else {
3095
+ $price = $product->get_sale_price();
3096
+ }
3097
 
3098
+ // Get WooCommerce Multi language Price by Currency.
3099
+ $price = apply_filters('woo_feed_wcml_price',
3100
+ $price, $product->get_id(), $this->get_feed_currency(), '_' . $price_type
3101
+ );
3102
 
3103
+ // Get Price with tax
3104
+ if (true === $tax) {
3105
+ $price = woo_feed_get_price_with_tax($price, $product);
3106
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3107
 
3108
+ return $price;
3109
+ }
3110
+
3111
+ /**
3112
+ * Get Product Price by Product Type.
3113
+ *
3114
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object
3115
+ * @param string $price_type Price Type (regular_price|price|sale_price)
3116
+ * @param bool $tax Add tax with price (true|false)
3117
+ *
3118
+ * @return float|int|mixed|string
3119
+ * @since 4.4.14
3120
+ *
3121
+ * @author Ohidul Islam
3122
+ */
3123
+ protected function get_price_by_product_type($product, $price_type, $tax = false)
3124
+ {
3125
+ if ($product->is_type('variable')) {
3126
+ $price = $this->getVariableProductPrice($product, $price_type, $tax);
3127
+ } elseif ($product->is_type('grouped')) {
3128
+ $price = $this->getGroupProductPrice($product, $price_type, $tax);
3129
+ } elseif ($product->is_type('bundle')) {
3130
+ //TODO Diff taxation
3131
+ $price = $this->getBundleProductPrice($product, $price_type, $tax);
3132
+ } elseif ($product->is_type('composite')) {
3133
+ //TODO Diff taxation
3134
+ $price = $this->getCompositeProductPrice($product, $price_type, $tax);
3135
+ } elseif ($product->is_type('bundled')) {
3136
+ // iconic woocommerce product bundled plugin
3137
+ $price = $this->iconic_bundle_product_price($product, $price_type, $tax);
3138
+ } else {
3139
+ $price = $this->get_price_by_price_type($product, $price_type, $tax);
3140
+ }
3141
 
3142
+ return $price > 0 ? $price : '';
3143
+ }
3144
+
3145
+ /**
3146
+ * Get Product Regular Price
3147
+ *
3148
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
3149
+ *
3150
+ * @return mixed
3151
+ * @since 3.2.0
3152
+ *
3153
+ */
3154
+ protected function price($product)
3155
+ {
3156
+
3157
+ $regular_price = $this->get_price_by_product_type($product, 'regular_price');
3158
+
3159
+ return apply_filters('woo_feed_filter_product_price', $regular_price, $product, $this->config, false);
3160
+ }
3161
+
3162
+ /**
3163
+ * Get Product Price
3164
+ *
3165
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3166
+ *
3167
+ * @return int|float|mixed
3168
+ * @since 3.2.0
3169
+ *
3170
+ */
3171
+ protected function current_price($product)
3172
+ {
3173
+
3174
+ $price = $this->get_price_by_product_type($product, 'price');
3175
+
3176
+ return apply_filters('woo_feed_filter_product_regular_price', $price, $product, $this->config, false);
3177
+ }
3178
+
3179
+ /**
3180
+ * Get Product Sale Price
3181
+ *
3182
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3183
+ *
3184
+ * @return mixed
3185
+ * @since 3.2.0
3186
+ *
3187
+ */
3188
+ protected function sale_price($product)
3189
+ {
3190
+
3191
+ $sale_price = $this->get_price_by_product_type($product, 'sale_price');
3192
+
3193
+ return apply_filters('woo_feed_filter_product_sale_price', $sale_price, $product, $this->config, false);
3194
+ }
3195
+
3196
+ /**
3197
+ * Get Product Regular Price with Tax
3198
+ *
3199
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
3200
+ *
3201
+ * @return mixed
3202
+ * @since 3.2.0
3203
+ *
3204
+ */
3205
+ protected function price_with_tax($product)
3206
+ {
3207
+
3208
+ $regular_price_with_tax = $this->get_price_by_product_type($product, 'regular_price', true);
3209
+
3210
+ return apply_filters('woo_feed_filter_product_price_with_tax', $regular_price_with_tax, $product, $this->config, true);
3211
+ }
3212
+
3213
+ /**
3214
+ * Get Product Regular Price with Tax
3215
+ *
3216
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3217
+ *
3218
+ * @return mixed
3219
+ * @since 3.2.0
3220
+ *
3221
+ */
3222
+ protected function current_price_with_tax($product)
3223
+ {
3224
+
3225
+ $price_with_tax = $this->get_price_by_product_type($product, 'price', true);
3226
+
3227
+ return apply_filters('woo_feed_filter_product_regular_price_with_tax', $price_with_tax, $product, $this->config, true);
3228
+ }
3229
+
3230
+ /**
3231
+ * Get Product Regular Price with Tax
3232
+ *
3233
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product object.
3234
+ *
3235
+ * @return mixed
3236
+ * @since 3.2.0
3237
+ *
3238
+ */
3239
+ protected function sale_price_with_tax($product)
3240
+ {
3241
+
3242
+ $sale_price_with_tax = $this->get_price_by_product_type($product, 'sale_price', true);
3243
+
3244
+ return apply_filters('woo_feed_filter_product_sale_price_with_tax', $sale_price_with_tax, $product, $this->config, true);
3245
+ }
3246
+
3247
+ /**
3248
+ * Get Composite Product Price
3249
+ *
3250
+ * @param WC_Product|WC_Product_Composite|WC_Composite_Products $product Composite Product object.
3251
+ * @param string $type Price Type (regular_price|price|sale_price)
3252
+ * @param bool $tax Add tax with price (true|false)
3253
+ *
3254
+ * @return int|float|double
3255
+ * @since 3.2.6
3256
+ */
3257
+ protected function getCompositeProductPrice($product, $type, $tax = false)
3258
+ {
3259
+ if (class_exists('WC_Product_Composite') && class_exists('WPCleverWooco')) {
3260
+ // WPC Composite Product
3261
+ return $this->get_wpc_composite_price($product, $type, $tax);
3262
+ } elseif (class_exists('WC_Composite_Products')) {
3263
+ // WooCommerce Composite Product
3264
+ return $this->get_wc_composite_product_price($product, $type, $tax);
3265
+ } else {
3266
+ // Get Base Price for Others Composite Products.
3267
+ // Note*: YITH does not auto select components. So no need to calculate component price.
3268
+ return $this->get_price_by_price_type($product, $type, $tax);
3269
+ }
3270
+ }
3271
+
3272
+ /**
3273
+ * Get WooCommerce Composite Product Price
3274
+ * Plugin URL: https://wordpress.org/plugins/wpc-composite-products/
3275
+ * Product Type: composite
3276
+ *
3277
+ * @param WC_Product|WC_Product_Composite $product
3278
+ * @param string $type Price Type (regular_price|price|sale_price)
3279
+ * @param bool $tax Add tax with price (true|false)
3280
+ * @return float|int|mixed|string|void
3281
+ */
3282
+ protected function get_wc_composite_product_price($product, $type, $tax)
3283
+ {
3284
+ $price = 0;
3285
+ // Parent Component Price
3286
+ $base_price = $this->get_price_by_price_type($product, $type, $tax);
3287
+ if (isset($this->config['composite_price']) && 'all_product_price' == $this->config['composite_price']) {
3288
+ $composite = new WC_Product_Composite($product);
3289
+
3290
+ if ('price' === $type || 'sale_price' === $type) {
3291
+ $price = $composite->get_composite_price();
3292
+ } else {
3293
+ $price = $composite->get_composite_regular_price();
3294
+ }
3295
+
3296
+ // Get WooCommerce Multi language Price by Currency.
3297
+ $price = apply_filters('woo_feed_wcml_price',
3298
+ $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3299
+ );
3300
+
3301
+ // Get Price with tax
3302
+ if (true === $tax) {
3303
+ $price = woo_feed_get_price_with_tax($price, $composite);
3304
+ }
3305
+ } else {
3306
+ $price = $base_price;
3307
+ }
3308
 
3309
+ return $price > 0 ? $price : '';
3310
+ }
3311
+
3312
+ /**
3313
+ * Get WPC Composite Product Price.
3314
+ * Plugin URL: https://wordpress.org/plugins/wpc-composite-products/
3315
+ * Product Type: composite
3316
+ *
3317
+ * @param WC_Product|WC_Product_Composite $product
3318
+ * @param string $type Price Type (regular_price|price|sale_price)
3319
+ * @param bool $tax Add tax with price (true|false)
3320
+ * @return float|int|mixed|string|void
3321
+ */
3322
+ protected function get_wpc_composite_price($product, $type, $tax)
3323
+ {
3324
+ $price = 0;
3325
+ // Parent Component Price
3326
+ $base_price = $this->get_price_by_price_type($product, $type, $tax);
3327
+ if (isset($this->config['composite_price']) && 'all_product_price' == $this->config['composite_price']) {
3328
+ $components_price = 0;
3329
+ $components = $product->get_components();
3330
+ if (!empty($components) && is_array($components)) {
3331
+ foreach ($components as $component) {
3332
+ $products = explode(',', $component['products']);
3333
+ foreach ($products as $key => $product_id) {
3334
+ $default_product = wc_get_product($product_id);
3335
+ if (is_object($default_product) && $default_product->is_in_stock()) {
3336
+ $quantity = (isset($component['qty']) && $component['qty'] > 0) ? $component['qty'] : 1;
3337
+ if ('products' == $component['type'] && empty($component['price'])) {
3338
+ $components_price += $this->get_price_by_price_type($default_product, 'price', $tax);
3339
+ $components_price *= $quantity;
3340
+ } elseif ('products' == $component['type'] && !empty($component['price'])) {
3341
+ $clever = new WPCleverWooco();
3342
+ $old_price = $this->get_price_by_price_type($default_product, 'price', $tax);
3343
+ $new_price = $component['price'];
3344
+ $components_price += $clever::wooco_new_price($old_price, $new_price);
3345
+ $components_price *= $quantity;
3346
+ }
3347
+ break; // Get first in stock product from component options.
3348
+ }
3349
+ }
3350
+ }
3351
+
3352
+ // Apply discount to components price.
3353
+ $discount = $product->get_discount();
3354
+ if ($discount > 0) {
3355
+ $components_price -= (($discount / 100) * $components_price);
3356
+ }
3357
+ }
3358
+
3359
+ if ('exclude' === $product->get_pricing()) {
3360
+ $price = $components_price;
3361
+ } elseif ('include' === $product->get_pricing()) {
3362
+ $price = $components_price + $base_price;
3363
+ } elseif ('only' === $product->get_pricing()) {
3364
+ $price = $base_price;
3365
+ }
3366
+ } else {
3367
+ $price = $base_price;
3368
+ }
3369
 
3370
+ return $price > 0 ? $price : '';
3371
+ }
3372
+
3373
+ /**
3374
+ * Get total price of grouped product
3375
+ *
3376
+ * @param WC_Product_Grouped $grouped Grouped Product Object
3377
+ * @param string $type Price Type (regular_price|price|sale_price)
3378
+ * @param bool $tax Add tax with price (true|false)
3379
+ *
3380
+ * @return int|string
3381
+ * @since 3.2.0
3382
+ *
3383
+ */
3384
+ protected function getGroupProductPrice($grouped, $type, $tax = false)
3385
+ {
3386
+ $groupProductIds = $grouped->get_children();
3387
+ $price = 0;
3388
+ if (!empty($groupProductIds)) {
3389
+ foreach ($groupProductIds as $id) {
3390
+ $product = wc_get_product($id);
3391
+ if (!is_object($product)) {
3392
+ continue; // make sure that the product exists..
3393
+ }
3394
+
3395
+ $get_price = $this->get_price_by_product_type($product, $type, $tax);
3396
+ if (!empty($get_price)) {
3397
+ $price += $get_price;
3398
+ }
3399
+ }
3400
+ }
3401
 
3402
+ return $price > 0 ? $price : '';
3403
+ }
3404
+
3405
+ /**
3406
+ * Get Variable Product Price
3407
+ *
3408
+ * @param WC_Product_Variable $variable Variable Product Object
3409
+ * @param string $type Price Type (regular_price|price|sale_price)
3410
+ * @param bool $tax Add tax with price (true|false)
3411
+ *
3412
+ * @return int|string
3413
+ * @since 3.2.0
3414
+ *
3415
+ */
3416
+ protected function getVariableProductPrice($variable, $type, $tax = false)
3417
+ {
3418
+ $min_max_first_default = apply_filters('woo_feed_variable_product_price_range', 'min');
3419
+ if (isset($this->config['variable_price'])) {
3420
+ $min_max_first_default = $this->config['variable_price'];
3421
+ }
3422
 
3423
+ $price = 0;
3424
+ if ('first' == $min_max_first_default) {
3425
+ $children = $variable->get_visible_children();
3426
+ if (isset($children[0]) && !empty($children[0])) {
3427
+ $variation = wc_get_product($children[0]);
3428
+ $price = $this->get_price_by_product_type($variation, $type, $tax);
3429
+ }
3430
+ } else {
3431
+ if ('regular_price' == $type) {
3432
+ $price = $variable->get_variation_regular_price($min_max_first_default);
3433
+ } elseif ('sale_price' == $type) {
3434
+ $price = $variable->get_variation_sale_price($min_max_first_default);
3435
+ } else {
3436
+ $price = $variable->get_variation_price($min_max_first_default);
3437
+ }
3438
+
3439
+ // Get WooCommerce Multi language Price by Currency.
3440
+ $price = apply_filters('woo_feed_wcml_price',
3441
+ $price, $variable->get_id(), $this->get_feed_currency(), '_' . $type
3442
+ );
3443
+
3444
+ // Get Price with tax
3445
+ if (true === $tax) {
3446
+ $price = woo_feed_get_price_with_tax($price, $variable);
3447
+ }
3448
+ }
3449
 
3450
+ return $price > 0 ? $price : '';
3451
+ }
3452
+
3453
+ /**
3454
+ * Get Bundle Product Price
3455
+ *
3456
+ * @param WC_Product $product Product object.
3457
+ * @param string $type Price Type (regular_price|price|sale_price)
3458
+ * @param bool $tax Add tax with price (true|false)
3459
+ *
3460
+ * @return int|float|string
3461
+ * @since 4.3.24
3462
+ */
3463
+ protected function getBundleProductPrice($product, $type, $tax = false)
3464
+ {
3465
+ if (class_exists('WC_Product_Bundle')) {//WC_Product_Bundle
3466
+ $bundle = new WC_Product_Bundle($product);
3467
+ if ('price' === $type || 'sale_price' === $type) {
3468
+ $price = $bundle->get_bundle_price();
3469
+ } else {
3470
+ $price = $bundle->get_bundle_regular_price();
3471
+ }
3472
+
3473
+ // Get WooCommerce Multi language Price by Currency.
3474
+ $price = apply_filters('woo_feed_wcml_price',
3475
+ $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3476
+ );
3477
+
3478
+ // Get Price with tax
3479
+ if (true === $tax) {
3480
+ $price = woo_feed_get_price_with_tax($price, $bundle);
3481
+ }
3482
+ } else {
3483
+ // Get Default price for others bundle products.
3484
+ $price = $this->get_price_by_price_type($product, $type, $tax);
3485
+ }
3486
 
3487
+ return $price > 0 ? $price : '';
3488
+ }
3489
+
3490
+ /**
3491
+ * Get price for Iconic woocommerce-bundled-products
3492
+ *
3493
+ * @param WC_Product $product Product object
3494
+ * @param string $type Price Type (regular_price|price|sale_price)
3495
+ * @param bool $tax Add tax with price (true|false)
3496
+ *
3497
+ * @return mixed $bundle_price
3498
+ */
3499
+ protected function iconic_bundle_product_price($product, $type, $tax = false)
3500
+ {
3501
+ if (!class_exists('WC_Product_Bundled')) {
3502
+ return $product->get_price();
3503
+ }
3504
 
3505
+ $is_discounted = false;
3506
+ $price = $product->get_price();
3507
+ $bundle = new WC_Product_Bundled($product->get_id());
3508
+ $iconic_bundle_product_type = (!is_null($bundle->options['price_display'])) ? $bundle->options['price_display'] : '';
3509
+ $product_ids = $bundle->options['product_ids'];
3510
+
3511
+ //set discount
3512
+ if (!empty($bundle->options['fixed_discount'])) {
3513
+ $is_discounted = true;
3514
+ $discount = $bundle->options['fixed_discount'];
3515
+ } else {
3516
+ $is_discounted = false;
3517
+ $discount = 0;
3518
+ }
3519
 
3520
+ // Get price
3521
+ if (is_array($product_ids)) {
3522
+ $product_prices = array_map(function ($id) use ($tax, $type, $is_discounted, $discount) {
3523
+ $product = wc_get_product($id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3524
 
3525
+ return $this->get_price_by_price_type($product, $type, $tax);
 
 
 
 
 
 
 
 
 
 
3526
 
3527
+ }, $product_ids);
 
3528
 
3529
+ if ('range' === $iconic_bundle_product_type) {
3530
+ $price = min($product_prices);
3531
+ } else {
3532
+ $price = array_sum($product_prices);
3533
+ }
3534
+ }
 
 
 
 
 
3535
 
3536
+ // Get sale price if discount enabled
3537
+ if ($is_discounted && ('sale_price' === $type || 'price' === $type)) {
3538
+ $price -= $discount;
3539
+ }
3540
 
3541
+ // Get WooCommerce Multi language Price by Currency.
3542
+ $price = apply_filters('woo_feed_wcml_price',
3543
+ $price, $product->get_id(), $this->get_feed_currency(), '_' . $type
3544
+ );
 
 
 
 
 
 
 
3545
 
3546
+ // Get Price with tax
3547
+ if (true === $tax) {
3548
+ $price = woo_feed_get_price_with_tax($price, $bundle);
3549
+ }
3550
 
3551
+ return $price > 0 ? $price : '';
3552
+ }
3553
+
3554
+ /**
3555
+ * Get Product Weight
3556
+ *
3557
+ * @param WC_Product $product
3558
+ *
3559
+ * @return mixed
3560
+ * @since 3.2.0
3561
+ *
3562
+ */
3563
+ protected function weight($product)
3564
+ {
3565
+ return apply_filters('woo_feed_filter_product_weight', $product->get_weight(), $product, $this->config);
3566
+ }
3567
+
3568
+ /**
3569
+ * Get Product Weight Unit
3570
+ *
3571
+ * @param WC_Product $product
3572
+ *
3573
+ * @return mixed
3574
+ * @since 5.2.7
3575
+ *
3576
+ */
3577
+ protected function weight_unit($product)
3578
+ {
3579
+ return apply_filters('woo_feed_filter_product_weight_unit', get_option('woocommerce_weight_unit'), $product, $this->config);
3580
+ }
3581
+
3582
+ /**
3583
+ * Get Product Width
3584
+ *
3585
+ * @param WC_Product $product
3586
+ *
3587
+ * @return mixed
3588
+ * @since 3.2.0
3589
+ *
3590
+ */
3591
+ protected function width($product)
3592
+ {
3593
+ return apply_filters('woo_feed_filter_product_width', $product->get_width(), $product, $this->config);
3594
+ }
3595
+
3596
+ /**
3597
+ * Get Product Height
3598
+ *
3599
+ * @param WC_Product $product
3600
+ *
3601
+ * @return mixed
3602
+ * @since 3.2.0
3603
+ *
3604
+ */
3605
+ protected function height($product)
3606
+ {
3607
+ return apply_filters('woo_feed_filter_product_height', $product->get_height(), $product, $this->config);
3608
+ }
3609
+
3610
+ /**
3611
+ * Get Product Length
3612
+ *
3613
+ * @param WC_Product $product
3614
+ *
3615
+ * @return mixed
3616
+ * @since 3.2.0
3617
+ *
3618
+ */
3619
+ protected function length($product)
3620
+ {
3621
+ return apply_filters('woo_feed_filter_product_length', $product->get_length(), $product, $this->config);
3622
+ }
3623
+
3624
+ /**
3625
+ * Get Product Shipping
3626
+ *
3627
+ * @param WC_Product $product
3628
+ *
3629
+ * @return mixed
3630
+ * @since 4.3.16
3631
+ * @author Nazrul Islam Nayan
3632
+ */
3633
+ protected function shipping($product)
3634
+ {
3635
+ $feedBody = '';
3636
+ $data = $this->data;
3637
+
3638
+ if (isset($data['shipping_zones']) && !empty($data['shipping_zones'])) {
3639
+ $zones = $data['shipping_zones'];
3640
+
3641
+ if (in_array($this->config['provider'], ['google', 'facebook', 'pinterest', 'bing', 'snapchat'])) {
3642
+ $get_shipping = new Woo_Feed_Shipping($this->config);
3643
+ $feedBody .= $get_shipping->set_product($product)->set_shipping_zone($zones)->get_google_shipping();
3644
+ }
3645
+ }
3646
 
3647
+ return apply_filters('woo_feed_filter_product_shipping', $feedBody, $product, $this->config);
3648
+
3649
+ }
3650
+
3651
+ /**
3652
+ * Get Product Shipping Cost
3653
+ *
3654
+ * @param WC_Product $product
3655
+ *
3656
+ * @return mixed
3657
+ * @since 5.1.20
3658
+ * @author Nazrul Islam Nayan
3659
+ */
3660
+ protected function shipping_cost($product)
3661
+ {
3662
+ $shipping_obj = new Woo_Feed_Shipping($this->config);
3663
+ $shipping_obj = $shipping_obj->set_product($product);
3664
+
3665
+ return apply_filters('woo_feed_filter_product_shipping_cost', $shipping_obj->get_lowest_shipping_price(), $product, $this->config);
3666
+ }
3667
+
3668
+ /**
3669
+ * Get Product Shipping Class
3670
+ *
3671
+ * @param WC_Product $product
3672
+ *
3673
+ * @return mixed
3674
+ * @since 3.2.0
3675
+ *
3676
+ */
3677
+ protected function shipping_class($product)
3678
+ {
3679
+ return apply_filters('woo_feed_filter_product_shipping_class', $product->get_shipping_class(), $product, $this->config);
3680
+ }
3681
+
3682
+ /**
3683
+ * Get Product Author Name
3684
+ *
3685
+ * @param WC_Product $product
3686
+ *
3687
+ * @return mixed
3688
+ * @since 3.2.0
3689
+ *
3690
+ */
3691
+ protected function author_name($product)
3692
+ {
3693
+ $post = get_post($product->get_id());
3694
+
3695
+ return get_the_author_meta('user_login', $post->post_author);
3696
+ }
3697
+
3698
+ /**
3699
+ * Get Product Author Email
3700
+ *
3701
+ * @param WC_Product $product
3702
+ *
3703
+ * @return mixed
3704
+ * @since 3.2.0
3705
+ *
3706
+ */
3707
+ protected function author_email($product)
3708
+ {
3709
+ $post = get_post($product->get_id());
3710
+
3711
+ return get_the_author_meta('user_email', $post->post_author);
3712
+ }
3713
+
3714
+ /**
3715
+ * Get Product Created Date
3716
+ *
3717
+ * @param WC_Product $product
3718
+ *
3719
+ * @return mixed
3720
+ * @since 3.2.0
3721
+ *
3722
+ */
3723
+ protected function date_created($product)
3724
+ {
3725
+ $date_created = gmdate('Y-m-d', strtotime($product->get_date_created()));
3726
+
3727
+ return apply_filters('woo_feed_filter_product_date_created', $date_created, $product, $this->config);
3728
+ }
3729
+
3730
+ /**
3731
+ * Get Product Last Updated Date
3732
+ *
3733
+ * @param WC_Product $product
3734
+ *
3735
+ * @return mixed
3736
+ * @since 3.2.0
3737
+ *
3738
+ */
3739
+ protected function date_updated($product)
3740
+ {
3741
+ $date_updated = gmdate('Y-m-d', strtotime($product->get_date_modified()));
3742
+
3743
+ return apply_filters('woo_feed_filter_product_date_updated', $date_updated, $product, $this->config);
3744
+ }
3745
+
3746
+ /**
3747
+ * Get Product Tax
3748
+ *
3749
+ * @param WC_Product $product Product object.
3750
+ * @return mixed
3751
+ * @since 5.1.20
3752
+ * @author Nazrul Islam Nayan
3753
+ */
3754
+ protected function tax($product)
3755
+ {
3756
+ $feedBody = '';
3757
+ if (in_array($this->config['provider'], ['google', 'facebook', 'pinterest', 'bing', 'snapchat'])) {
3758
+ $shipping_obj = new Woo_Feed_Shipping($this->config);
3759
+ $shipping_obj = $shipping_obj->set_product($product);
3760
+ $feedBody .= $shipping_obj->get_google_tax();
3761
+ }
3762
 
3763
+ return apply_filters('woo_feed_filter_product_tax', $feedBody, $product, $this->config);
3764
+ }
3765
+
3766
+ /**
3767
+ * Get Product Tax class
3768
+ * @param WC_Product $product Product object.
3769
+ * @return string
3770
+ */
3771
+ protected function tax_class($product)
3772
+ {
3773
+ return apply_filters('woo_feed_filter_product_tax_class', $product->get_tax_class(), $product, $this->config);
3774
+ }
3775
+
3776
+ /**
3777
+ * Get Product Tax Status
3778
+ * @param WC_Product $product Product object.
3779
+ * @return string
3780
+ */
3781
+ protected function tax_status($product)
3782
+ {
3783
+ return apply_filters('woo_feed_filter_product_tax_status', $product->get_tax_status(), $product, $this->config);
3784
+ }
3785
+
3786
+ /**
3787
+ * Get CTX Feed Custom Field value
3788
+ *
3789
+ * @param WC_Product $product Product object.
3790
+ * @param string $field custom field name.
3791
+ * @return string
3792
+ */
3793
+ protected function getCustomField($product, $field)
3794
+ {
3795
+ $id = $product->get_id();
3796
+ $meta = $field;
3797
+ if ($product->is_type('variation')) {
3798
+ $meta = $field . '_var';
3799
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3800
 
3801
+ $meta = apply_filters('woo_feed_custom_field_meta', $meta, $product, $field);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3802
 
3803
+ $new_meta_key = '';
3804
+ $old_meta_key = '';
3805
 
3806
+ if (strpos($meta, '_identifier') !== false) {
3807
+ $old_meta_key = $meta;
3808
+ $new_meta_key = str_replace('_identifier', '', $meta);
3809
+ } else {
3810
+ $new_meta_key = $meta;
3811
+ $old_meta_key = str_replace('woo_feed_', 'woo_feed_identifier_', $meta);
3812
+ }
3813
 
3814
+ $new_meta_value = $this->getProductMeta($product, $new_meta_key);
3815
+ $old_meta_value = $this->getProductMeta($product, $old_meta_key);
 
3816
 
3817
+ if (empty($new_meta_value)) {
3818
+ return $old_meta_value;
3819
+ } else {
3820
+ return $new_meta_value;
3821
+ }
3822
 
3823
+ }
3824
+
3825
+ /**
3826
+ * Get Product Sale Price Effected Date for Google Shopping
3827
+ *
3828
+ * @param WC_Product $product
3829
+ *
3830
+ * @return string
3831
+ * @since 3.2.0
3832
+ *
3833
+ */
3834
+ protected function sale_price_effective_date($product)
3835
+ {
3836
+ $effective_date = '';
3837
+ $from = $this->sale_price_sdate($product);
3838
+ $to = $this->sale_price_edate($product);
3839
+ if (!empty($from) && !empty($to)) {
3840
+ $from = gmdate('c', strtotime($from));
3841
+ $to = gmdate('c', strtotime($to));
3842
+
3843
+ $effective_date = $from . '/' . $to;
3844
+ }
3845
 
3846
+ return $effective_date;
3847
+ }
3848
+
3849
+ /**
3850
+ * Ger Product Attribute
3851
+ *
3852
+ * @param WC_Product $product
3853
+ * @param $attr
3854
+ *
3855
+ * @return string
3856
+ * @since 2.2.3
3857
+ *
3858
+ */
3859
+ protected function getProductAttribute($product, $attr)
3860
+ {
3861
+ $id = $product->get_id();
3862
+
3863
+ if (woo_feed_wc_version_check(3.2)) {
3864
+ if (woo_feed_wc_version_check(3.6)) {
3865
+ $attr = str_replace('pa_', '', $attr);
3866
+ }
3867
+ $value = $product->get_attribute($attr);
3868
+
3869
+ // if empty get attribute of parent post
3870
+ if ('' === $value && $product->is_type('variation')) {
3871
+ $product = wc_get_product($product->get_parent_id());
3872
+ $value = $product->get_attribute($attr);
3873
+ }
3874
+
3875
+ $getproductattribute = $value;
3876
+ } else {
3877
+ $getproductattribute = implode(',', wc_get_product_terms($id, $attr, array('fields' => 'names')));
3878
+ }
3879
+
3880
+ return apply_filters('woo_feed_filter_product_attribute', $getproductattribute, $product, $attr, $this->config);
3881
+ }
3882
+
3883
+ /**
3884
+ * Get Meta
3885
+ *
3886
+ * @param WC_Product $product
3887
+ * @param string $meta post meta key
3888
+ *
3889
+ * @return mixed|string
3890
+ * @since 2.2.3
3891
+ *
3892
+ */
3893
+ protected function getProductMeta($product, $meta)
3894
+ {
3895
+ $value = get_post_meta($product->get_id(), $meta, true);
3896
+ // if empty get meta value of parent post
3897
+ if ('' === $value && $product->is_type('variation')) {
3898
+ $value = get_post_meta($product->get_parent_id(), $meta, true);
3899
+ }
3900
+
3901
+ return apply_filters('woo_feed_filter_product_meta', $value, $product, $this->config);
3902
+ }
3903
+
3904
+ /**
3905
+ * Filter Products by Conditions
3906
+ *
3907
+ * @param WC_Product $product
3908
+ *
3909
+ * @return bool|array
3910
+ * @since 3.2.0
3911
+ *
3912
+ */
3913
+ public function filter_product($product)
3914
+ {
3915
+ return true;
3916
+ }
3917
+
3918
+ /**
3919
+ * Get Taxonomy
3920
+ *
3921
+ * @param WC_Product $product
3922
+ * @param $taxonomy
3923
+ *
3924
+ * @return string
3925
+ * @since 2.2.3
3926
+ *
3927
+ */
3928
+ protected function getProductTaxonomy($product, $taxonomy)
3929
+ {
3930
+ $id = $product->get_id();
3931
+ if ($product->is_type('variation')) {
3932
+ $id = $product->get_parent_id();
3933
+ }
3934
 
3935
+ $separator = apply_filters('woo_feed_product_taxonomy_term_list_separator', ',', $this->config, $product);
 
 
 
3936
 
3937
+ $term_list = get_the_term_list($id, $taxonomy, '', $separator, '');
 
 
3938
 
3939
+ if (is_object($term_list) && get_class($term_list) === 'WP_Error') {
3940
+ $term_list = '';
3941
+ }
3942
 
3943
+ $getproducttaxonomy = woo_feed_strip_all_tags($term_list);
3944
+
3945
+ return apply_filters('woo_feed_filter_product_taxonomy', $getproducttaxonomy, $product, $this->config);
3946
+ }
3947
+
3948
+ /**
3949
+ * Format price value
3950
+ *
3951
+ * @param string $name Attribute Name
3952
+ * @param int $conditionName condition
3953
+ * @param int $result price
3954
+ *
3955
+ * @return mixed
3956
+ * @since 3.2.0
3957
+ *
3958
+ */
3959
+ protected function price_format($name, $conditionName, $result)
3960
+ {
3961
+ $plus = '+';
3962
+ $minus = '-';
3963
+ $percent = '%';
3964
+
3965
+ if (strpos($name, 'price') !== false) {
3966
+ if (strpos($result, $plus) !== false && strpos($result, $percent) !== false) {
3967
+ $result = str_replace('+', '', $result);
3968
+ $result = str_replace('%', '', $result);
3969
+ if (is_numeric($result)) {
3970
+ $result = $conditionName + (($conditionName * $result) / 100);
3971
+ }
3972
+ } elseif (strpos($result, $minus) !== false && strpos($result, $percent) !== false) {
3973
+ $result = str_replace('-', '', $result);
3974
+ $result = str_replace('%', '', $result);
3975
+ if (is_numeric($result)) {
3976
+ $result = $conditionName - (($conditionName * $result) / 100);
3977
+ }
3978
+ } elseif (strpos($result, $plus) !== false) {
3979
+ $result = str_replace('+', '', $result);
3980
+ if (is_numeric($result)) {
3981
+ $result = ($conditionName + $result);
3982
+ }
3983
+ } elseif (strpos($result, $minus) !== false) {
3984
+ $result = str_replace('-', '', $result);
3985
+ if (is_numeric($result)) {
3986
+ $result = $conditionName - $result;
3987
+ }
3988
+ }
3989
+ }
3990
 
3991
+ return $result;
3992
+ }
3993
+
3994
+ /**
3995
+ * Format output According to Output Type config
3996
+ *
3997
+ * @param string $output
3998
+ * @param array $outputTypes
3999
+ * @param WC_Product $product
4000
+ * @param string $productAttribute
4001
+ *
4002
+ * @return float|int|string
4003
+ * @since 3.2.0
4004
+ *
4005
+ */
4006
+ protected function format_output($output, $outputTypes, $product, $productAttribute, $merchant_attribute)
4007
+ {
4008
+ if (!empty($outputTypes) && is_array($outputTypes)) {
4009
+
4010
+ // Format Output According to output type
4011
+ if (in_array(2, $outputTypes)) { // Strip Tags
4012
+ $output = woo_feed_strip_all_tags(html_entity_decode($output));
4013
+ }
4014
+
4015
+ if (in_array(3, $outputTypes)) { // UTF-8 Encode
4016
+ $output = utf8_encode($output);
4017
+ }
4018
+
4019
+ if (in_array(4, $outputTypes)) { // htmlentities
4020
+ $output = htmlentities($output, ENT_QUOTES, 'UTF-8');
4021
+ }
4022
+
4023
+ if (in_array(5, $outputTypes)) { // Integer
4024
+ $output = intval($output);
4025
+ }
4026
+
4027
+ if (in_array(6, $outputTypes)) { // Format Price
4028
+ if (!empty($output) && $output > 0) {
4029
  $decimals = wc_get_price_decimals();
4030
  $decimal_separator = wc_get_price_decimal_separator();
4031
  $thousand_separator = wc_get_price_thousand_separator();
4032
+ $output = (float)$output;
4033
+
4034
+ if ("idealo" === $this->config['provider']) {
4035
+ $output = number_format($output, $decimals, wp_specialchars_decode(stripslashes($decimal_separator)), wp_specialchars_decode(stripslashes($thousand_separator)));
4036
+ } else {
4037
+ $output = number_format($output, 2, '.', '');
4038
+ }
4039
+
4040
+ }
4041
+ }
4042
+
4043
+ if (in_array(7, $outputTypes)) { // Rounded Price
4044
+ if (!empty($output) && $output > 0) {
4045
+ $output = round($output);
4046
+ $output = number_format($output, 2, '.', '');
4047
+ }
4048
+ }
4049
+
4050
+ if (in_array(8, $outputTypes)) { // Delete Space
4051
+ $output = htmlentities($output, null, 'utf-8');
4052
+ $output = str_replace("&nbsp;", " ", $output);
4053
+ $output = html_entity_decode($output);
4054
+ $output = preg_replace("/\\s+/", ' ', $output);
4055
+ }
4056
+
4057
+ if (in_array(10, $outputTypes)) { // Remove Invalid Character
4058
+ $output = woo_feed_stripInvalidXml($output);
4059
+ }
4060
+
4061
+ if (in_array(11, $outputTypes)) { // Remove ShortCodes
4062
+ $output = $this->remove_short_codes($output);
4063
+ }
4064
+
4065
+ if (in_array(12, $outputTypes)) {
4066
+ $output = ucwords(strtolower($output));
4067
+ }
4068
+
4069
+ if (in_array(13, $outputTypes)) {
4070
+ $output = ucfirst(strtolower($output));
4071
+ }
4072
+
4073
+ if (in_array(14, $outputTypes)) {
4074
+ $output = strtoupper(strtolower($output));
4075
+ }
4076
+
4077
+ if (in_array(15, $outputTypes)) {
4078
+ $output = strtolower($output);
4079
+ }
4080
+
4081
+ if (in_array(16, $outputTypes)) {
4082
+ if ('http' == substr($output, 0, 4)) {
4083
+ $output = str_replace('http://', 'https://', $output);
4084
+ }
4085
+ }
4086
+
4087
+ if (in_array(17, $outputTypes)) {
4088
+ if ('http' == substr($output, 0, 4)) {
4089
+ $output = str_replace('https://', 'http://', $output);
4090
+ }
4091
+ }
4092
+
4093
+ if (in_array(18, $outputTypes)) { // only parent
4094
+ if ($product->is_type('variation')) {
4095
+ $id = $product->get_parent_id();
4096
+ $parentProduct = wc_get_product($id);
4097
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
4098
+ }
4099
+ }
4100
+
4101
+ if (in_array(19, $outputTypes)) { // child if parent empty
4102
+ if ($product->is_type('variation')) {
4103
+ $id = $product->get_parent_id();
4104
+ $parentProduct = wc_get_product($id);
4105
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
4106
+ if (empty($output)) {
4107
+ $output = $this->getAttributeValueByType($product, $productAttribute, $merchant_attribute);
4108
+ }
4109
+ }
4110
+ }
4111
+
4112
+ if (in_array(20, $outputTypes)) { // parent if child empty
4113
+ if ($product->is_type('variation')) {
4114
+ $output = $this->getAttributeValueByType($product, $productAttribute, $merchant_attribute);
4115
+ if (empty($output)) {
4116
+ $id = $product->get_parent_id();
4117
+ $parentProduct = wc_get_product($id);
4118
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute, $merchant_attribute);
4119
+ }
4120
+ }
4121
+ }
4122
+
4123
+ if (in_array(9, $outputTypes) && !empty($output) && 'xml' === $this->config['feedType']) { // Add CDATA
4124
+ $output = '<![CDATA[' . $output . ']]>';
4125
+ }
4126
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4127
 
4128
+ return $output;
4129
+ }
4130
+
4131
+ /**
4132
+ * Add Prefix and Suffix with attribute value
4133
+ *
4134
+ * @param $output
4135
+ * @param $prefix
4136
+ * @param $suffix
4137
+ * @param $attribute
4138
+ *
4139
+ * @return string
4140
+ * @since 3.2.0
4141
+ *
4142
+ */
4143
+ public function process_prefix_suffix($output, $prefix, $suffix, $attribute = '')
4144
+ {
4145
+ $cdata = false;
4146
+ if ('' === $output) {
4147
+ return $output;
4148
+ }
4149
 
4150
+ if (strpos($output, '<![CDATA[') !== false) {
4151
+ $cdata = true;
4152
+ $output = str_replace(array('<![CDATA[', ']]>'), array('', ''), $output);
4153
+ }
4154
 
4155
+ // Add Prefix before Output
4156
+ if ('' !== $prefix) {
4157
+ $output = "$prefix" . $output;
4158
+ }
 
 
 
 
 
 
4159
 
4160
+ // Add Suffix after Output
4161
+ if ('' !== $suffix) {
4162
+ if (array_key_exists(trim($suffix), get_woocommerce_currencies())) { // Add space before suffix if attribute contain price.
4163
+ $output .= ' ' . $suffix;
4164
+ } elseif (substr($output, 0, 4) === 'http') {
4165
+ // Parse URL Parameters if available into suffix field
4166
+ $output = woo_feed_make_url_with_parameter($output, $suffix);
4167
+ } else {
4168
+ $output .= (string)$suffix;
4169
+ }
4170
+ }
4171
 
4172
+ if ($cdata) {
4173
+ $output = '<![CDATA[' . $output . ']]>';
4174
+ }
 
 
 
 
 
 
 
4175
 
4176
+ return "$output";
4177
+ }
4178
+
4179
+ /**
4180
+ * Get Subscription period
4181
+ *
4182
+ * @param WC_Product $product
4183
+ *
4184
+ * @return mixed
4185
+ * @since 3.6.3
4186
+ *
4187
+ */
4188
+ protected function subscription_period($product)
4189
+ {
4190
+ if (class_exists('WC_Subscriptions')) {
4191
+ return $this->getProductMeta($product, '_subscription_period');
4192
+ }
4193
+ return '';
4194
+ }
4195
+
4196
+ /**
4197
+ * Get Subscription period interval
4198
+ *
4199
+ * @param WC_Product $product
4200
+ *
4201
+ * @return mixed
4202
+ * @since 3.6.3
4203
+ *
4204
+ */
4205
+ protected function subscription_period_interval($product)
4206
+ {
4207
+ if (class_exists('WC_Subscriptions')) {
4208
+ return $this->getProductMeta($product, '_subscription_period_interval');
4209
+ }
4210
+ return '';
4211
+ }
4212
+
4213
+ /**
4214
+ * Get Subscription period interval
4215
+ *
4216
+ * @param WC_Product $product
4217
+ *
4218
+ * @return mixed
4219
+ * @since 3.6.3
4220
+ *
4221
+ */
4222
+ protected function subscription_amount($product)
4223
+ {
4224
+ return $this->price($product);
4225
+ }
4226
+
4227
+ /**
4228
+ * Get Installment Amount
4229
+ *
4230
+ * @param WC_Product $product
4231
+ *
4232
+ * @return mixed
4233
+ * @since 4.3.101
4234
+ */
4235
+ protected function installment_amount($product)
4236
+ {
4237
+ return $this->price($product);
4238
+ }
4239
+
4240
+ /**
4241
+ * Get Installment Months
4242
+ *
4243
+ * @param WC_Product $product
4244
+ *
4245
+ * @return mixed
4246
+ * @since 4.3.101
4247
+ */
4248
+ protected function installment_months($product)
4249
+ {
4250
+ if (class_exists('WC_Subscriptions')) {
4251
+ return $this->getProductMeta($product, '_subscription_length');
4252
+ }
4253
+ return '';
4254
+ }
4255
+
4256
+
4257
+ /**
4258
+ * Calculate unit_price_measure. If Unit custom fields by CTX feed are enabled then it will take value
4259
+ * from custom fields or it will take values for WooCommerce Germanized Plugin if enabled.
4260
+ *
4261
+ * If variation values are empty then it will take value from variable product.
4262
+ *
4263
+ * @param WC_Product $product
4264
+ *
4265
+ * @return mixed
4266
+ * @since 3.6.3
4267
+ */
4268
+ protected function unit_price_measure($product)
4269
+ {
4270
+ $unit_price_measure = '';
4271
+ $identifiers = woo_feed_get_options('woo_feed_identifier');
4272
+ if ('enable' === $identifiers['unit_pricing_base_measure']
4273
+ && 'enable' === $identifiers['unit_pricing_measure']
4274
+ && 'enable' === $identifiers['unit']
4275
+ ) {
4276
+ $unit = $this->getCustomField($product, 'woo_feed_unit');
4277
+ $unit_price_measure = $this->getCustomField($product, 'woo_feed_unit_pricing_measure');
4278
+
4279
+ $unit_price_measure .= " " . $unit;
4280
+ }
4281
 
4282
+ if (empty($unit_price_measure) && class_exists('WooCommerce_Germanized')) { // For WooCommerce Germanized Plugin
4283
+ $unit = $this->getProductMeta($product, '_unit');
4284
+ $unit_price_measure = $this->getProductMeta($product, '_unit_product');
 
 
 
 
 
 
 
4285
 
4286
+ $unit_price_measure .= " " . $unit;
4287
+ }
4288
 
4289
+ return apply_filters('woo_feed_filter_unit_price_measure', $unit_price_measure, $product, $this->config);
4290
+ }
4291
+
4292
+ /**
4293
+ * Calculate unit_price_base_measure. If Unit custom fields by CTX feed are enabled then it will take value
4294
+ * from custom fields or it will take values for WooCommerce Germanized Plugin if enabled.
4295
+ *
4296
+ * If variation values are empty then it will take value from variable product.
4297
+ *
4298
+ * @param WC_Product $product
4299
+ *
4300
+ * @return mixed
4301
+ * @since 3.6.3
4302
+ */
4303
+ protected function unit_price_base_measure($product)
4304
+ {
4305
+ $unit_price_base_measure = '';
4306
+ $identifiers = woo_feed_get_options('woo_feed_identifier');
4307
+ if ('enable' === $identifiers['unit_pricing_base_measure']
4308
+ && 'enable' === $identifiers['unit_pricing_measure']
4309
+ && 'enable' === $identifiers['unit']
4310
+ ) {
4311
+ $unit = $this->getCustomField($product, 'woo_feed_unit');
4312
+ $unit_price_base_measure = $this->getCustomField($product, 'woo_feed_unit_pricing_base_measure');
4313
+
4314
+ $unit_price_base_measure .= " " . $unit;
4315
+ }
4316
 
4317
+ if (empty($unit_price_base_measure) && class_exists('WooCommerce_Germanized')) { // For WooCommerce Germanized Plugin
4318
+ $unit = $this->getProductMeta($product, '_unit');
4319
+ $unit_price_base_measure = $this->getProductMeta($product, '_unit_base');
4320
 
4321
+ $unit_price_base_measure .= " " . $unit;
4322
+ }
 
 
 
 
 
 
 
 
4323
 
4324
+ return apply_filters('woo_feed_filter_unit_price_base_measure', $unit_price_base_measure, $product, $this->config);
4325
+ }
4326
+
4327
+ /**
4328
+ * Get GTIN value of WooCommerce Germanized Plugin
4329
+ *
4330
+ * @param WC_Product $product
4331
+ *
4332
+ * @return mixed
4333
+ * @since 3.6.3
4334
+ */
4335
+ protected function wc_germanized_gtin($product)
4336
+ {
4337
+ $wc_germanized_gtin = '';
4338
+ if (class_exists('WooCommerce_Germanized')) { // For WooCommerce Germanized Plugin
4339
+ $wc_germanized_gtin = $this->getProductMeta($product, '_ts_gtin');
4340
+ }
4341
 
4342
+ return apply_filters('woo_feed_filter_wc_germanized_gtin', $wc_germanized_gtin, $product, $this->config);
4343
+ }
4344
+
4345
+ /**
4346
+ * Get MPN value of WooCommerce Germanized Plugin
4347
+ *
4348
+ * @param WC_Product $product
4349
+ *
4350
+ * @return mixed
4351
+ * @since 3.6.3
4352
+ */
4353
+ protected function wc_germanized_mpn($product)
4354
+ {
4355
+ $wc_germanized_mpn = '';
4356
+ if (class_exists('WooCommerce_Germanized')) { // For WooCommerce Germanized Plugin
4357
+ $wc_germanized_mpn = $this->getProductMeta($product, '_ts_mpn');
4358
+ }
4359
 
4360
+ return apply_filters('woo_feed_filter_wc_germanized_mpn', $wc_germanized_mpn, $product, $this->config);
4361
+ }
4362
+
4363
+
4364
+ /**
4365
+ * Yoast Identifier attribute for gtin8
4366
+ *
4367
+ * @param WC_Product $product
4368
+ *
4369
+ * @return mixed
4370
+ * @since 4.4.4
4371
+ */
4372
+ protected function yoast_gtin8($product)
4373
+ {
4374
+ $yoast_gtin8_value = woo_feed_get_yoast_identifiers_value('gtin8', $product);
4375
+
4376
+ return apply_filters('yoast_gtin8_attribute_value', $yoast_gtin8_value, $product);
4377
+ }
4378
+
4379
+ /**
4380
+ * Yoast Identifier attribute for gtin12
4381
+ *
4382
+ * @param WC_Product $product
4383
+ *
4384
+ * @return mixed
4385
+ * @since 4.4.4
4386
+ */
4387
+ protected function yoast_gtin12($product)
4388
+ {
4389
+ $yoast_gtin12_value = woo_feed_get_yoast_identifiers_value('gtin12', $product);
4390
+
4391
+ return apply_filters('yoast_gtin12_attribute_value', $yoast_gtin12_value, $product);
4392
+ }
4393
+
4394
+ /**
4395
+ * Yoast Identifier attribute for gtin13
4396
+ *
4397
+ * @param WC_Product $product
4398
+ *
4399
+ * @return mixed
4400
+ * @since 4.4.4
4401
+ */
4402
+ protected function yoast_gtin13($product)
4403
+ {
4404
+ $yoast_gtin13_value = woo_feed_get_yoast_identifiers_value('gtin13', $product);
4405
+
4406
+ return apply_filters('yoast_gtin13_attribute_value', $yoast_gtin13_value, $product);
4407
+ }
4408
+
4409
+ /**
4410
+ * Yoast Identifier attribute for gtin12
4411
+ *
4412
+ * @param WC_Product $product
4413
+ *
4414
+ * @return mixed
4415
+ * @since 4.4.4
4416
+ */
4417
+ protected function yoast_gtin14($product)
4418
+ {
4419
+ $yoast_gtin14_value = woo_feed_get_yoast_identifiers_value('gtin14', $product);
4420
+
4421
+ return apply_filters('yoast_gtin14_attribute_value', $yoast_gtin14_value, $product);
4422
+ }
4423
+
4424
+ /**
4425
+ * Yoast Identifier attribute for isbn
4426
+ *
4427
+ * @param WC_Product $product
4428
+ *
4429
+ * @return mixed
4430
+ * @since 4.4.4
4431
+ */
4432
+ protected function yoast_isbn($product)
4433
+ {
4434
+ $yoast_isbn_value = woo_feed_get_yoast_identifiers_value('isbn', $product);
4435
+
4436
+ return apply_filters('yoast_isbn_attribute_value', $yoast_isbn_value, $product);
4437
+ }
4438
+
4439
+ /**
4440
+ * Yoast Identifier attribute for mpn
4441
+ *
4442
+ * @param WC_Product $product
4443
+ *
4444
+ * @return mixed
4445
+ * @since 4.4.4
4446
+ */
4447
+ protected function yoast_mpn($product)
4448
+ {
4449
+ $yoast_mpn_value = woo_feed_get_yoast_identifiers_value('mpn', $product);
4450
+
4451
+ return apply_filters('yoast_mpn_attribute_value', $yoast_mpn_value, $product);
4452
+ }
4453
+
4454
+ /**
4455
+ * Rank Math GTIN Identifier attribute
4456
+ *
4457
+ * @param WC_Product $product
4458
+ *
4459
+ * @return mixed
4460
+ * @since 5.2.66
4461
+ */
4462
+ protected function rank_math_gtin($product)
4463
+ {
4464
+ $product_id = woo_feed_parent_product_id($product);
4465
+ $rankmath_gtin_value = get_post_meta($product_id, '_rank_math_gtin_code');
4466
+ $rankmath_gtin_value = !empty($rankmath_gtin_value) && is_array($rankmath_gtin_value) ? $rankmath_gtin_value[0] : '';
4467
+
4468
+ return apply_filters('rankmath_gtin_attribute_value', $rankmath_gtin_value, $product);
4469
+ }
4470
+
4471
+ /**
4472
+ * Get ACF Field values
4473
+ *
4474
+ * @param WC_Product $product
4475
+ * @param string $field_key ACF Filed Key with prefix "acf_fields_"
4476
+ *
4477
+ * @return mixed|string
4478
+ */
4479
+ private function getACFField( $product, $field_key ) {
4480
+ $field = str_replace( 'acf_fields_', '', $field_key );
4481
+ if ( class_exists( 'ACF' ) ) {
4482
+ return get_field( $field, $product->get_id() );
4483
+ }
4484
 
4485
+ return '';
4486
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
4487
 
4488
  }
includes/classes/class-woo-feed-webappick-api.php CHANGED
@@ -391,26 +391,27 @@ if ( ! class_exists( 'WooFeedWebAppickAPI' ) ) {
391
  public function woo_feed_save_review_notice() {
392
  $user_id = get_current_user_id();
393
 
 
 
 
 
 
 
394
  //submit review notice dismissal
395
- if ( isset($_POST['woo_feed_review_notice_submit']) ) {
396
  add_user_meta( $user_id, 'woo_feed_review_notice_dismissed', true, true );
397
  update_option( 'woo_feed_review_notice_next_show_time', time() + ( DAY_IN_SECONDS * 30 ) );
398
  }
399
 
400
  //submit review notice form data
401
- if ( isset( $_POST['woo_feed_review_notice_btn_given'] ) ) {
402
  wp_redirect('https://wordpress.org/support/plugin/webappick-product-feed-for-woocommerce/reviews/?rate=5#new-post');
403
  exit();
404
- } elseif ( isset( $_POST['woo_feed_review_notice_btn_never'] ) || isset( $_POST['woo_feed_review_notice_btn_done'] ) ) {
405
- if ( isset( $_POST['woo_feed_review_notice_btn_never'] ) ) {
406
- $notice = $_POST['woo_feed_review_notice_btn_never'];
407
- }else {
408
- $notice = $_POST['woo_feed_review_notice_btn_done'];
409
- }
410
-
411
  add_user_meta( $user_id, 'woo_feed_review_notice_dismissed', true, true );
412
- } elseif ( isset( $_POST['woo_feed_review_notice_btn_later'] ) ) {
413
- $notice = $_POST['woo_feed_review_notice_btn_later'];
414
  update_option( 'woo_feed_review_notice_next_show_time', time() + ( DAY_IN_SECONDS * 30 ) );
415
  }
416
 
391
  public function woo_feed_save_review_notice() {
392
  $user_id = get_current_user_id();
393
 
394
+ $woo_feed_review_notice_submit = sanitize_text_field( isset( $_POST['woo_feed_review_notice_submit'] ) ? $_POST['woo_feed_review_notice_submit'] : '' ) ;
395
+ $woo_feed_review_notice_btn_given = sanitize_text_field( isset( $_POST['woo_feed_review_notice_btn_given'] ) ? $_POST['woo_feed_review_notice_btn_given'] : '' ) ;
396
+ $woo_feed_review_notice_btn_never = sanitize_text_field( isset( $_POST['woo_feed_review_notice_btn_never'] ) ? $_POST['woo_feed_review_notice_btn_never'] : '' ) ;
397
+ $woo_feed_review_notice_btn_done = sanitize_text_field( isset( $_POST['woo_feed_review_notice_btn_done'] ) ? $_POST['woo_feed_review_notice_btn_done'] : '' ) ;
398
+ $woo_feed_review_notice_btn_later = sanitize_text_field( isset( $_POST['woo_feed_review_notice_btn_later'] ) ? $_POST['woo_feed_review_notice_btn_later'] : '' ) ;
399
+
400
  //submit review notice dismissal
401
+ if ( $woo_feed_review_notice_submit ) {
402
  add_user_meta( $user_id, 'woo_feed_review_notice_dismissed', true, true );
403
  update_option( 'woo_feed_review_notice_next_show_time', time() + ( DAY_IN_SECONDS * 30 ) );
404
  }
405
 
406
  //submit review notice form data
407
+ if ( $woo_feed_review_notice_btn_given ) {
408
  wp_redirect('https://wordpress.org/support/plugin/webappick-product-feed-for-woocommerce/reviews/?rate=5#new-post');
409
  exit();
410
+ } elseif ( $woo_feed_review_notice_btn_never || $woo_feed_review_notice_btn_done ) {
411
+ $notice = $woo_feed_review_notice_btn_never ? $woo_feed_review_notice_btn_never : $woo_feed_review_notice_btn_done;
 
 
 
 
 
412
  add_user_meta( $user_id, 'woo_feed_review_notice_dismissed', true, true );
413
+ } elseif ( $woo_feed_review_notice_btn_later ) {
414
+ $notice = $woo_feed_review_notice_btn_later;
415
  update_option( 'woo_feed_review_notice_next_show_time', time() + ( DAY_IN_SECONDS * 30 ) );
416
  }
417
 
includes/feeds/class-woo-feed-review.php CHANGED
@@ -81,140 +81,16 @@ class Woo_Feed_Review {
81
 
82
  // When update via cron job then set productIds.
83
  if ( ! isset( $feedRule['productIds'] ) ) {
84
-
85
  $feedRule['productIds'] = $this->products->query_products();
86
-
87
- // $feedRule['productIds'] = $this->get_products_with_reviews();
88
-
89
  }
90
 
91
-
92
  $products = $this->products->get_products( $feedRule['productIds'] );
93
 
94
- $product_names = [];
95
-
96
- foreach ( $products as $product ) {
97
- $product_names[] = $product['product_name'];
98
- }
99
-
100
- $product_ids = [];
101
-
102
- foreach ( $product_names as $product_name ) {
103
- $product_by_title = get_page_by_title($product_name, OBJECT, 'product');
104
- if ( is_object( $product_by_title) ) {
105
- $product_ids[] = $product_by_title->ID;
106
- }
107
- }
108
-
109
- if ( ! empty($product_ids) ) {
110
- $this->ids = array_filter($product_ids, 'strlen');
111
- } else {
112
- $this->ids = array_filter($feedRule['productIds'], 'strlen');
113
- }
114
 
115
  $this->rules = $feedRule;
116
 
117
  $this->data = $this->processReviewsData($feedRule);
118
-
119
- }
120
-
121
-
122
- /**
123
- * Return Feed
124
- *
125
- * @return array|bool|string
126
- */
127
- public function returnFinalProduct() {
128
- if ( ! empty( $this->products ) ) {
129
-
130
- if ( 'xml' == $this->rules['feedType'] ) {
131
- // return $this->get_feed($this->products);
132
- $feed = array(
133
- 'header' => $this->get_xml_feed_header(),
134
- 'body' => $this->get_xml_feed_body(),
135
- 'footer' => $this->get_xml_feed_footer(),
136
- );
137
-
138
- return $feed;
139
- }
140
- }
141
-
142
- $feed = array(
143
- 'body' => '',
144
- 'header' => '',
145
- 'footer' => '',
146
- );
147
-
148
- return $feed;
149
- }
150
-
151
- /**
152
- * Get products having reviews
153
- *
154
- * @return array $ids product ids
155
- */
156
- public function get_products_with_reviews() {
157
- $args = array(
158
- 'post_type' => 'product',
159
- 'fields' => 'ids',
160
- 'status' => 'approve',
161
- 'comment_count' => array(
162
- 'value' => 0,
163
- 'compare' => '>',
164
- ),
165
- );
166
-
167
- $ids = get_posts($args);
168
-
169
- return $ids ? $ids : array();
170
- }
171
-
172
- public function sampleData() {
173
- $data = array(
174
- 'filetype' => 'xml',
175
- 'reviews' => array(
176
- array(
177
- 'review' => array(
178
- 'review_id' => '1',
179
- 'reviewer' => array(
180
- 'reviewer_id' => '11',
181
- 'name' => 'Anamul Haque 2',
182
- ),
183
- 'reviewer-link' => 'anamulhaque@gmail.com',
184
- 'products' => array(
185
- 'product' => array(
186
- array(
187
- 'product-id' => '50',
188
- 'product-name' => 'Hoodie with logo',
189
- 'product-link' => 'http://www.chaldal.com/hoodie',
190
- ),
191
- ),
192
- ),
193
- ),
194
- ),
195
- array(
196
- 'review' => array(
197
- 'review_id' => '2',
198
- 'reviewer' => array(
199
- 'reviewer_id' => '12',
200
- 'name' => 'Tanvir Hayder',
201
- ),
202
- 'reviewer-link' => 'tanvirhayder@gmail.com',
203
- 'products' => array(
204
- 'product' => array(
205
- array(
206
- 'product-id' => '10',
207
- 'product-name' => 'Beanie',
208
- 'product-link' => 'http://www.chaldal.com/beanie',
209
- ),
210
- ),
211
- ),
212
- ),
213
- ),
214
- ),
215
- );
216
-
217
- return $data;
218
  }
219
 
220
  /**
@@ -223,97 +99,96 @@ class Woo_Feed_Review {
223
  * @param mixed $config feed configuration
224
  *
225
  */
226
- public function processReviewsData( $config ) {
227
  $ids = $this->ids;
228
-
229
  $feed = array();
230
  $feed['version'] = '2.3';
231
  $feed['aggregator']['name'] = 'review';
232
  $feed['publisher']['name'] = 'CTX Feed – WooCommerce Product Feed Generator by Webappick';
233
  $feed['reviews'] = array();
234
 
235
- if ( $ids && is_array($ids) ) {
236
- foreach ( $ids as $id ) {
237
- $product = wc_get_product($id);
238
-
239
- $reviews = get_comments(
240
- array(
241
- 'post_id' => $id,
242
- 'post_type' => 'product',
243
- 'parent' => 0,
244
- )
245
- );
246
-
247
- $review = array();
248
-
249
- if ( $reviews && is_array($reviews) ) {
250
- foreach ( $reviews as $single_review ) {
251
- $review_time = "";
252
- $review_content = $single_review->comment_content;
253
- $rating = get_comment_meta( $single_review->comment_ID, 'rating', true);
254
- $review_content = woo_feed_strip_all_tags(wp_specialchars_decode($review_content));
255
- $review_content = preg_replace('/[^A-Za-z0-9-]/', ' ', $review_content);
256
- $review_content = ! empty($review_content) ? woo_feed_strip_all_tags(wp_specialchars_decode($review_content)) : "";
257
- $review_product_url = ! empty($product->get_permalink()) ? "<![CDATA[" . $product->get_permalink() . "]]>" : "";
258
- $review_id = ! empty($single_review->comment_ID) ? $single_review->comment_ID : "";
259
- $review_author = ! empty($single_review->comment_author) ? $single_review->comment_author : "";
260
- $review_user_id = ! empty($single_review->user_id) ? $single_review->user_id : "";
261
-
262
- if( ! empty($single_review->comment_date_gmt) ) {
263
- $review_time = $single_review->comment_date_gmt;
264
- $review_time = explode(' ', $review_time);
265
- $review_time = implode('T', $review_time)."Z";
266
- }
267
 
268
- $review['review']['review_id'] = $review_id;
269
- $review['review']['reviewer']['name'] = $review_author;
270
- $review['review']['reviewer']['reviewer_id'] = $review_user_id;
271
- $review['review']['content'] = $review_content;
272
- $review['review']['review_timestamp'] = $review_time;
273
- $review['review']['review_url'] = $review_product_url;
274
- $review['review']['ratings']["overall"] = $rating;
275
- $review['review']['products'] = array();
276
- $review['review']['products']['product'] = array();
277
-
278
- // Get Product Attribute values by type and assign to product array
279
- foreach ( $config['attributes'] as $attr_key => $attribute ) {
280
- $merchant_attribute = isset($config['mattributes'][ $attr_key ]) ? $config['mattributes'][ $attr_key ] : '';
281
-
282
- // Add Prefix and Suffix into Output
283
- $prefix = $config['prefix'][ $attr_key ];
284
- $suffix = $config['suffix'][ $attr_key ];
285
- $merchant = $config['provider'];
286
- $feedType = $config['feedType'];
287
-
288
- if ( 'pattern' == $config['type'][ $attr_key ] ) {
289
- $attributeValue = $config['default'][ $attr_key ];
290
- } else {
291
- $attributeValue = $this->products->getAttributeValueByType($product, $attribute, $merchant_attribute);
292
- }
293
-
294
- //add prefix - suffix to attribute value
295
- $attributeValue = $prefix . $attributeValue . $suffix;
296
- $attributeValue = ! empty($attributeValue) ? "<![CDATA[" . $attributeValue . "]]>" : "";
297
-
298
- if ( "review_temp_gtin" === $merchant_attribute ) {
299
- $review['review']['products']['product']['product_ids']['gtins']['gtin'] = $attributeValue;
300
- } elseif ( "review_temp_mpn" === $merchant_attribute ) {
301
- $review['review']['products']['product']['product_ids']['mpns']['mpn'] = $attributeValue;
302
- } elseif ( "review_temp_sku" === $merchant_attribute ) {
303
- $review['review']['products']['product']['product_ids']['skus']['sku'] = $attributeValue;
304
- } elseif ( "review_temp_brand" === $merchant_attribute ) {
305
- $review['review']['products']['product']['product_ids']['brands']['brand'] = $attributeValue;
306
- } else {
307
- $review['review']['products']['product'][ $merchant_attribute ] = $attributeValue;
308
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  }
310
 
311
- array_push($feed['reviews'], $review);
 
 
 
 
 
 
 
 
 
 
 
 
312
  }
 
 
 
313
  }
314
  }
315
- }
316
 
 
317
  return $feed;
318
  }
319
 
@@ -338,7 +213,10 @@ class Woo_Feed_Review {
338
  $rating = $xml->addChild($key,"$value");
339
  $rating->addAttribute('min','1');
340
  $rating->addAttribute('max','5');
341
- } else {
 
 
 
342
  $value = htmlspecialchars($value);
343
  $xml->addChild("$key","$value");
344
  }
@@ -354,7 +232,7 @@ class Woo_Feed_Review {
354
  public function make_review_xml_feed() {
355
  // create simpleXML object
356
  $xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><feed xmlns:vc=\"http://www.w3.org/2007/XMLSchema-versioning\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.google.com/shopping/reviews/schema/product/2.3/product_reviews.xsd\"></feed>");
357
- $this->woo_feed_array_to_xml($this->data, $xml);
358
  $feedBody = $xml->asXML();
359
 
360
  $data = new DOMDocument();
@@ -365,188 +243,4 @@ class Woo_Feed_Review {
365
 
366
  return $feedBody;
367
  }
368
-
369
- /**
370
- * Make xml node
371
- *
372
- * @param string $attribute Attribute Name
373
- * @param string $value Attribute Value
374
- * @param bool $cdata
375
- * @param string $space
376
- *
377
- * @return string
378
- */
379
- function formatXMLLine( $attribute, $value, $cdata, $space = '' ) {
380
- // Make single XML node
381
- if ( ! empty( $value ) ) {
382
- $value = trim( $value );
383
- }
384
- if ( gettype( $value ) == 'array' ) {
385
- $value = wp_json_encode( $value );
386
- }
387
- if ( false === strpos( $value, '<![CDATA[' ) && 'http' === substr( trim( $value ), 0, 4 ) ) {
388
- $value = "<![CDATA[$value]]>";
389
- } elseif ( false === strpos( $value, '<![CDATA[' ) && true === $cdata && ! empty( $value ) ) {
390
- $value = "<![CDATA[$value]]>";
391
- } elseif ( $cdata ) {
392
- if ( ! empty( $value ) ) {
393
- $value = "<![CDATA[$value]]>";
394
- }
395
- }
396
-
397
- if ( 'g:additional_image_link' == substr( $attribute, 0, 23 ) ) {
398
- $attribute = 'g:additional_image_link';
399
- }
400
-
401
- return "$space<$attribute>$value</$attribute>";
402
- }
403
-
404
- /**
405
- * Make XML Feed Body
406
- * @param array $data review product array
407
- *
408
- * @return string
409
- */
410
- public function create_xml_lines( $data ) {
411
- $output = '';
412
-
413
- if ( ! empty($data) && is_array($data) ) {
414
- foreach ( $data as $data_item_key => $data_item ) {
415
- $chunk_data = array_chunk($data_item, 1, true);
416
- $output .= '<review>';
417
- foreach ( $chunk_data as $key => $value ) {
418
- foreach ( $value as $item_key => $item_value ) {
419
- if ( is_array($item_value) ) {
420
- if ( is_int($item_key) ) {
421
- $output .= '</'. key($value) .'>';
422
- $output .= '<'. key($value) .'>';
423
- }else {
424
- $output .= '<'. $item_key .'>';
425
- }
426
- }else {
427
- $output .= '<'. $item_key .'>';
428
- }
429
- if ( is_array($item_value) ) {
430
- foreach ( $item_value as $item_value2_key => $item_value2 ) {
431
- if ( is_array($item_value2) ) {
432
- if ( is_int($item_value2_key) ) {
433
- $output .= '</'. key($item_value) .'>';
434
- $output .= '<'. key($item_value) .'>';
435
- }else {
436
- $output .= '<'. $item_value2_key .'>';
437
- }
438
- }else {
439
- $output .= '<'. $item_value2_key .'>';
440
- }
441
- if ( is_array($item_value2) ) {
442
-
443
- foreach ( $item_value2 as $item_value3_key => $item_value3_value ) {
444
- if ( is_array($item_value3_value) ) {
445
- if ( is_int($item_value3_key) ) {
446
- $output .= '</'. key($item_value2) .'>';
447
- $output .= '<'. key($item_value2) .'>';
448
- }else {
449
- $output .= '<'. $item_value3_key .'>';
450
- }
451
- }else {
452
- $output .= '<'. $item_value3_key .'>';
453
- }
454
- if ( is_array($item_value3_value) ) {
455
- foreach ( $item_value3_value as $item_value4_key => $item_value4_value ) {
456
- if ( is_array($item_value4_value) ) {
457
- if ( is_int($item_value4_key) ) {
458
- $output .= '</'. key($item_value2) .'>';
459
- $output .= '<'. key($item_value2) .'>';
460
- }else {
461
- $output .= '<'. $item_value4_key .'>';
462
- }
463
- }else {
464
- $output .= '<'. $item_value4_key .'>';
465
- }
466
-
467
- if ( is_array($item_value4_value) ) {
468
- foreach ( $item_value4_value as $item_value5_key => $item_value5_value ) {
469
- if ( is_array($item_value5_value) ) {
470
- if ( is_int($item_value5_key) ) {
471
- $output .= '</'. key($item_value3_value) .'>';
472
- $output .= '<'. key($item_value3_value) .'>';
473
- }else {
474
- $output .= '<'. $item_value5_key .'>';
475
- }
476
- }else {
477
- $output .= '<'. $item_value5_key .'>';
478
- }
479
-
480
- //test end
481
- if ( is_array($item_value5_value) ) {
482
- if ( is_int($item_value5_key) ) {
483
- $output .= '</'. key($item_value3_value) .'>';
484
- }else {
485
- $output .= '</'. $item_value5_key .'>';
486
- }
487
- }else {
488
- $output .= '</'. $item_value5_key .'>';
489
- }
490
- }
491
- }else {
492
- $output .= $item_value4_value;
493
- }
494
-
495
- if ( is_array($item_value4_value) ) {
496
- if ( is_int($item_value4_key) ) {
497
- $output .= '</'. key($item_value2) .'>';
498
- }else {
499
- $output .= '</'. $item_value4_key .'>';
500
- }
501
- }else {
502
- $output .= '</'. $item_value4_key .'>';
503
- }
504
- }
505
- }else {
506
- $output .= $item_value3_value;
507
- }
508
- if ( is_array($item_value3_value) ) {
509
- if ( is_int($item_value3_key) ) {
510
- $output .= '</'. key($item_value2) .'>';
511
- }else {
512
- $output .= '</'. $item_value3_key .'>';
513
- }
514
- }else {
515
- $output .= '</'. $item_value3_key .'>';
516
- }
517
- }
518
- }else {
519
- $output .= $item_value2;
520
- }
521
- if ( is_array($item_value2) ) {
522
- if ( is_int($item_value2_key) ) {
523
- $output .= '</'. key($item_value) .'>';
524
- }else {
525
- $output .= '</'. $item_value2_key .'>';
526
- }
527
- }else {
528
- $output .= '</'. $item_value2_key .'>';
529
- }
530
- }
531
- }else {
532
- $output .= $item_value;
533
- }
534
- if ( is_array($item_value) ) {
535
- if ( is_int($item_key) ) {
536
- $output .= '</'. key($value) .'>';
537
- }else {
538
- $output .= '</'. $item_key .'>';
539
- }
540
- }else {
541
- $output .= '</'. $item_key .'>';
542
- }
543
- }
544
- }
545
- $output .= '</review>';
546
- }
547
- }
548
-
549
- return $output;
550
- }
551
-
552
  }
81
 
82
  // When update via cron job then set productIds.
83
  if ( ! isset( $feedRule['productIds'] ) ) {
 
84
  $feedRule['productIds'] = $this->products->query_products();
 
 
 
85
  }
86
 
 
87
  $products = $this->products->get_products( $feedRule['productIds'] );
88
 
89
+ $this->ids = $feedRule['productIds'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  $this->rules = $feedRule;
92
 
93
  $this->data = $this->processReviewsData($feedRule);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
 
96
  /**
99
  * @param mixed $config feed configuration
100
  *
101
  */
102
+ private function processReviewsData($config ) {
103
  $ids = $this->ids;
 
104
  $feed = array();
105
  $feed['version'] = '2.3';
106
  $feed['aggregator']['name'] = 'review';
107
  $feed['publisher']['name'] = 'CTX Feed – WooCommerce Product Feed Generator by Webappick';
108
  $feed['reviews'] = array();
109
 
110
+ foreach ( $ids as $id ) {
111
+ $product = wc_get_product($id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
+ $reviews = get_comments(
114
+ array(
115
+ 'post_id' => $id,
116
+ 'status' => 'approve',
117
+ 'post_status' => 'publish',
118
+ 'post_type' => 'product'
119
+ )
120
+ );
121
+
122
+ // echo "<pre>";
123
+ // print_r($reviews);
124
+
125
+ $review = array();
126
+ $i=0;
127
+ if ( $reviews && is_array($reviews) ) {
128
+ foreach ( $reviews as $single_review ) {
129
+ $review_time = ! empty($single_review->comment_date_gmt)?gmdate('c', strtotime($single_review->comment_date_gmt)):"";
130
+ $review_content = $single_review->comment_content;
131
+ $rating = get_comment_meta( $single_review->comment_ID, 'rating', true);
132
+
133
+ //Review Content
134
+ //strip tags and spacial characters
135
+ $strip_review_content = woo_feed_strip_all_tags(wp_specialchars_decode($review_content));
136
+ $review_content = !empty(strlen($strip_review_content)) && 0 < strlen($strip_review_content) ? $strip_review_content : $review_content;
137
+
138
+ $review_product_url = ! empty($product->get_permalink()) ? $product->get_permalink() : "";
139
+
140
+ $review_id = ! empty($single_review->comment_ID) ? $single_review->comment_ID : "";
141
+ $review_author = ! empty($single_review->comment_author) ? $single_review->comment_author : "";
142
+ $review_user_id = ! empty($single_review->user_id) ? $single_review->user_id : "";
143
+
144
+ $review['review']['review_id'] = $review_id;
145
+ $review['review']['reviewer']['name'] = $review_author;
146
+ $review['review']['reviewer']['reviewer_id'] = $review_user_id;
147
+ $review['review']['content'] = $review_content;
148
+ $review['review']['review_timestamp'] = $review_time;
149
+ $review['review']['review_url'] = $review_product_url;
150
+ $review['review']['ratings']["overall"] = $rating;
151
+ $review['review']['products'] = array();
152
+ $review['review']['products']['product'] = array();
153
+
154
+ $review['review']['products']['product']['product_name'] = ! empty($product->get_name()) ? $product->get_name() : "";
155
+ $review['review']['products']['product']['product_url'] = $review_product_url;
156
+
157
+ // Get Product Attribute values by type and assign to product array
158
+ foreach ( $config['attributes'] as $attr_key => $attribute ) {
159
+ $merchant_attribute = isset($config['mattributes'][ $attr_key ]) ? $config['mattributes'][ $attr_key ] : '';
160
+
161
+ // Add Prefix and Suffix into Output
162
+ $prefix = $config['prefix'][ $attr_key ];
163
+ $suffix = $config['suffix'][ $attr_key ];
164
+
165
+ if ( 'pattern' === $config['type'][ $attr_key ] ) {
166
+ $attributeValue = $config['default'][ $attr_key ];
167
+ } else {
168
+ $attributeValue = $this->products->getAttributeValueByType($product, $attribute, $merchant_attribute);
169
  }
170
 
171
+ //add prefix - suffix to attribute value
172
+ $attributeValue = $prefix . $attributeValue . $suffix;
173
+ $attributeValue = ! empty($attributeValue) ? $attributeValue : "";
174
+
175
+ if ( "review_temp_gtin" === $merchant_attribute && !empty($attributeValue)) {
176
+ $review['review']['products']['product']['product_ids']['gtins']['gtin'] = $attributeValue;
177
+ } elseif ( "review_temp_mpn" === $merchant_attribute && !empty($attributeValue)) {
178
+ $review['review']['products']['product']['product_ids']['mpns']['mpn'] = $attributeValue;
179
+ } elseif ( "review_temp_sku" === $merchant_attribute && !empty($attributeValue)) {
180
+ $review['review']['products']['product']['product_ids']['skus']['sku'] = $attributeValue;
181
+ } elseif ( "review_temp_brand" === $merchant_attribute && !empty($attributeValue)) {
182
+ $review['review']['products']['product']['product_ids']['brands']['brand'] = $attributeValue;
183
+ }
184
  }
185
+
186
+ array_push($feed['reviews'], $review);
187
+ $i++;
188
  }
189
  }
 
190
 
191
+ }
192
  return $feed;
193
  }
194
 
213
  $rating = $xml->addChild($key,"$value");
214
  $rating->addAttribute('min','1');
215
  $rating->addAttribute('max','5');
216
+ } elseif("review_url" === $key){
217
+ $rating = $xml->addChild($key,"$value");
218
+ $rating->addAttribute('type','group');
219
+ }else {
220
  $value = htmlspecialchars($value);
221
  $xml->addChild("$key","$value");
222
  }
232
  public function make_review_xml_feed() {
233
  // create simpleXML object
234
  $xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\"?><feed xmlns:vc=\"http://www.w3.org/2007/XMLSchema-versioning\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://www.google.com/shopping/reviews/schema/product/2.3/product_reviews.xsd\"></feed>");
235
+ $this->woo_feed_array_to_xml($this->data,$xml);
236
  $feedBody = $xml->asXML();
237
 
238
  $data = new DOMDocument();
243
 
244
  return $feedBody;
245
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
includes/filters/filters.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Aa single function that includes a filter(s) for filtering POST/GET/REQUEST/FILE (securing-input) (securing-output) (securing-input-output)
4
+ *
5
+ *
6
+ * @since 4.4.64
7
+ * @package CTXFeed
8
+ * @subpackage CTXFeed/filters
9
+ * @author Anwar <anwar.webappick@gmail.com>
10
+ * @link https://webappick.com
11
+ */
12
+ // If this file is called directly, abort.
13
+ if (!defined('ABSPATH')) {
14
+ exit;
15
+ }
16
+
17
+ function CTXFEED_filter_securing_input_cb($meth = "POST", $inpu = '', $type = "text" ) {
18
+ $outp = '';
19
+ switch ( $type ) {
20
+ case "email":
21
+ $outp = sanitize_text_email($inpu);
22
+ break;
23
+
24
+ case "text":
25
+ $outp = sanitize_text_field($inpu);
26
+ break;
27
+
28
+ case "textarea":
29
+ $outp = sanitize_textarea_field($inpu);
30
+ break;
31
+
32
+ case "file_name":
33
+ $outp = sanitize_file_name($inpu);
34
+ break;
35
+ }
36
+ return $outp;
37
+
38
+ }
39
+
40
+ add_filter( 'CTXFEED_filter_securing_input', 'CTXFEED_filter_securing_input_cb', 10, 4 );
includes/helper.php CHANGED
@@ -565,13 +565,15 @@ if ( ! function_exists('woo_feed_merchant_require_google_category') ) {
565
  'google_local',
566
  'google_local_inventory',
567
  'facebook',
 
 
568
  'adroll',
569
  'smartly.io',
570
  'pinterest',
571
  'rakuten.de',
572
  ],
573
  'fb_product_category' => [ 'facebook' ],
574
- 'google_product_category' => [ 'rakuten.de' ],
575
  'google_category_id' => [ 'daisycon', 'daisycon_automotive', 'daisycon_books', 'daisycon_cosmetics', 'daisycon_daily_offers', 'daisycon_electronics', 'daisycon_food_drinks', 'daisycon_home_garden', 'daisycon_housing', 'daisycon_fashion', 'daisycon_studies_trainings', 'daisycon_telecom_accessories', 'daisycon_telecom_all_in_one', 'daisycon_telecom_gsm_subscription', 'daisycon_telecom_gsm', 'daisycon_telecom_sim', 'daisycon_magazines', 'daisycon_holidays_accommodations', 'daisycon_holidays_accommodations_and_transport', 'daisycon_holidays_trips', 'daisycon_work_jobs' ],
576
  ];
577
  if ( null !== $merchant && null !== $attribute ) {
@@ -1712,18 +1714,20 @@ if ( ! function_exists('woo_feed_import_config') ) {
1712
  */
1713
  function woo_feed_import_config() {
1714
  check_admin_referer('wpf_import');
 
 
 
 
1715
 
1716
  if (
1717
- isset(
1718
- $_FILES['wpf_import_file'],
1719
- $_POST['wpf_import_feed_name'],
1720
- $_FILES['wpf_import_file']['name'],
1721
- $_FILES['wpf_import_file']['tmp_name']
1722
- ) &&
1723
- 'wpf' === pathinfo(wp_unslash($_FILES['wpf_import_file']['name']), PATHINFO_EXTENSION) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1724
  ) {
1725
- $file_name = sanitize_text_field(wp_unslash($_FILES['wpf_import_file']['name']));
1726
- $data = file_get_contents(sanitize_text_field(wp_unslash($_FILES['wpf_import_file']['tmp_name'])));
1727
  if ( empty($data) ) {
1728
  wp_die(
1729
  esc_html__('Empty File Uploaded. Try again.', 'woo-feed'),
@@ -2281,11 +2285,13 @@ if ( ! function_exists('woo_feed_add_cdata') ) {
2281
  return "$attributeValue";
2282
  }
2283
  } else {
2284
- return "<![CDATA[$attributeValue]]>";
 
2285
  }
2286
  } else {
2287
  return "$attributeValue";
2288
  }
 
2289
  }
2290
  }
2291
 
@@ -5565,6 +5571,46 @@ if ( ! function_exists('woo_feed_filter_shipping_info_callback') ) {
5565
  add_filter('woo_feed_filter_shipping_info', 'woo_feed_filter_shipping_info_callback', 10, 4);
5566
  }
5567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5568
  #==== MERCHANT TEMPLATE OVERRIDE END ================#
5569
 
5570
  // Including pluggable functions file
565
  'google_local',
566
  'google_local_inventory',
567
  'facebook',
568
+ 'tiktok',
569
+ 'snapchat',
570
  'adroll',
571
  'smartly.io',
572
  'pinterest',
573
  'rakuten.de',
574
  ],
575
  'fb_product_category' => [ 'facebook' ],
576
+ 'google_product_category' => [ 'rakuten.de','tiktok','snapchat' ],
577
  'google_category_id' => [ 'daisycon', 'daisycon_automotive', 'daisycon_books', 'daisycon_cosmetics', 'daisycon_daily_offers', 'daisycon_electronics', 'daisycon_food_drinks', 'daisycon_home_garden', 'daisycon_housing', 'daisycon_fashion', 'daisycon_studies_trainings', 'daisycon_telecom_accessories', 'daisycon_telecom_all_in_one', 'daisycon_telecom_gsm_subscription', 'daisycon_telecom_gsm', 'daisycon_telecom_sim', 'daisycon_magazines', 'daisycon_holidays_accommodations', 'daisycon_holidays_accommodations_and_transport', 'daisycon_holidays_trips', 'daisycon_work_jobs' ],
578
  ];
579
  if ( null !== $merchant && null !== $attribute ) {
1714
  */
1715
  function woo_feed_import_config() {
1716
  check_admin_referer('wpf_import');
1717
+ $wpf_import_file = isset($_FILES['wpf_import_file']) ? $_FILES['wpf_import_file'] : '';
1718
+ $wpf_import_feed_name = isset($_FILES['wpf_import_feed_name']) ? $_FILES['wpf_import_feed_name'] : '';
1719
+ $wpf_import_file_name = isset( $_FILES['wpf_import_file']['name']) ? $_FILES['wpf_import_file']['name'] : '';
1720
+ $wpf_import_file_tmp_name = isset( $_FILES['wpf_import_file']['tmp_name']) ? $_FILES['wpf_import_file']['tmp_name'] : '';
1721
 
1722
  if (
1723
+ $wpf_import_file &&
1724
+ $wpf_import_feed_name &&
1725
+ $wpf_import_file_name &&
1726
+ $wpf_import_file_tmp_name &&
1727
+ 'wpf' === pathinfo(wp_unslash($wpf_import_file_name), PATHINFO_EXTENSION) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
 
 
1728
  ) {
1729
+ $file_name = sanitize_file_name( sanitize_text_field(wp_unslash( $wpf_import_file_name )));
1730
+ $data = file_get_contents(sanitize_text_field(wp_unslash( $wpf_import_file_tmp_name)));
1731
  if ( empty($data) ) {
1732
  wp_die(
1733
  esc_html__('Empty File Uploaded. Try again.', 'woo-feed'),
2285
  return "$attributeValue";
2286
  }
2287
  } else {
2288
+ return "<![CDATA[ $attributeValue ]]>";
2289
+ // return "$attributeValue";
2290
  }
2291
  } else {
2292
  return "$attributeValue";
2293
  }
2294
+ return "$attributeValue";
2295
  }
2296
  }
2297
 
5571
  add_filter('woo_feed_filter_shipping_info', 'woo_feed_filter_shipping_info_callback', 10, 4);
5572
  }
5573
 
5574
+ #=============== ACF ===============================================
5575
+ if ( ! function_exists( 'woo_feed_get_acf_field_list' ) ) {
5576
+ /**
5577
+ * Get Advance Custom Field (ACF) field list
5578
+ *
5579
+ *
5580
+ * @return Array
5581
+ */
5582
+ function woo_feed_get_acf_field_list() {
5583
+ $options = [];
5584
+ if ( class_exists( 'ACF' ) ) {
5585
+ $acf_fields = woo_feed_get_cached_data( 'acf_field_list' );
5586
+ if ( false === $acf_fields ) {
5587
+ $field_groups = acf_get_field_groups();
5588
+ foreach ( $field_groups as $group ) {
5589
+ // DO NOT USE here: $fields = acf_get_fields($group['key']);
5590
+ // because it causes repeater field bugs and returns "trashed" fields
5591
+ $fields = get_posts( array(
5592
+ 'posts_per_page' => - 1,
5593
+ 'post_type' => 'acf-field',
5594
+ 'orderby' => 'menu_order',
5595
+ 'order' => 'ASC',
5596
+ 'suppress_filters' => true, // DO NOT allow WPML to modify the query
5597
+ 'post_parent' => $group['ID'],
5598
+ 'post_status' => 'any',
5599
+ 'update_post_meta_cache' => false,
5600
+ ) );
5601
+ foreach ( $fields as $field ) {
5602
+ $options[ 'acf_fields_'.$field->post_name ] = $field->post_title;
5603
+ }
5604
+ }
5605
+
5606
+ woo_feed_set_cache_data( 'acf_field_list', $options );
5607
+ }
5608
+ }
5609
+
5610
+ return $options;
5611
+ }
5612
+ }
5613
+
5614
  #==== MERCHANT TEMPLATE OVERRIDE END ================#
5615
 
5616
  // Including pluggable functions file
includes/template-configs.php CHANGED
@@ -3116,9 +3116,9 @@ return array(
3116
  'googlereview' => array(
3117
  'mattributes' => array( 'product_name', 'product_url', 'review_temp_gtin', 'review_temp_mpn', 'review_temp_sku', 'review_temp_brand' ),
3118
  'prefix' => array( '', '', '', '', '', '' ),
3119
- 'type' => array( 'attribute', 'attribute', 'pattern', 'pattern', 'pattern', 'pattern' ),
3120
- 'attributes' => array( 'title', 'link', '', '', '', '' ),
3121
- 'default' => array( '', '', '', '', '', '' ),
3122
  'suffix' => array( '', '', '', '', '', '' ),
3123
  'output_type' => array( '1', '1', '1', '1', '1', '1' ),
3124
  'limit' => array( '', '', '', '', '', '' ),
@@ -7343,15 +7343,25 @@ return array(
7343
  'output_type' => array( '1', '1', '1', '1', '1', '1', '6', '1', '1', '6', '1', '1' ),
7344
  'limit' => array( '', '', '', '', '', '', '', '', '', '', '', '' ),
7345
  ),
7346
- 'tiktok' => array(
7347
- 'mattributes' => array( 'sku_id', 'title', 'description', 'availability', 'link', 'image_link', 'price', 'brand', 'condition' ),
7348
- 'prefix' => array( '', '', '', '', '', '', '', '', '' ),
7349
- 'type' => array( 'attribute', 'attribute', 'attribute', 'attribute', 'attribute', 'attribute', 'attribute', 'pattern', 'pattern' ),
7350
- 'attributes' => array( 'sku_id', 'title', 'description', 'availability', 'link', 'image', 'price', '', '' ),
7351
- 'default' => array( '', '', '', '', '', '', '', '', '' ),
7352
- 'suffix' => array( '', '', '', '', '', '', '', '', '' ),
7353
- 'output_type' => array( '1', '1', '1', '1', '1', '1', '6', '1', '1' ),
7354
- 'limit' => array( '', '', '', '', '', '', '', '', '' ),
 
 
 
 
 
 
 
 
 
 
7355
  ),
7356
  );
7357
  // End of file merchant_templates.php
3116
  'googlereview' => array(
3117
  'mattributes' => array( 'product_name', 'product_url', 'review_temp_gtin', 'review_temp_mpn', 'review_temp_sku', 'review_temp_brand' ),
3118
  'prefix' => array( '', '', '', '', '', '' ),
3119
+ 'type' => array( 'attribute', 'attribute', 'pattern', 'pattern', 'attribute', 'pattern' ),
3120
+ 'attributes' => array( 'title', 'link', '', '', 'sku', '' ),
3121
+ 'default' => array( '', '', '', '', '', $this->brand_pattern ),
3122
  'suffix' => array( '', '', '', '', '', '' ),
3123
  'output_type' => array( '1', '1', '1', '1', '1', '1' ),
3124
  'limit' => array( '', '', '', '', '', '' ),
7343
  'output_type' => array( '1', '1', '1', '1', '1', '1', '6', '1', '1', '6', '1', '1' ),
7344
  'limit' => array( '', '', '', '', '', '', '', '', '', '', '', '' ),
7345
  ),
7346
+ 'tiktok' => array(
7347
+ 'mattributes' => array('sku_id','title','description','availability','link','image_link','price','brand','condition','google_product_category','item_group_id','product_type',),
7348
+ 'prefix' => array('','','','','','','','','','','','',),
7349
+ 'type' => array('attribute','attribute','attribute','attribute','attribute','attribute','attribute','pattern','pattern','pattern','attribute','attribute',),
7350
+ 'attributes' => array('sku_id','title','description','availability','link','image','price','','','','item_group_id','product_type',),
7351
+ 'default' => array('','','','','','','',$this->brand_pattern,'new','','','',),
7352
+ 'suffix' => array('','','','','','',$this->currency,'','','','','',),
7353
+ 'output_type' => array('1','1','1','1','1','1','6','1','1','1','1','1',),
7354
+ 'limit' => array('','','','','','','','','','','','',),
7355
+ ),
7356
+ 'shopflix' => array(
7357
+ 'mattributes' => array('sku','name','description','ean','manufacturer','weight','color','price','quantity','shipping_lead_time',),
7358
+ 'prefix' => array('','','','','','','','','','',),
7359
+ 'type' => array('attribute','attribute','attribute','attribute','pattern','attribute','attribute','attribute','attribute','pattern',),
7360
+ 'attributes' => array('sku','title','description','','','','','price','quantity','',),
7361
+ 'default' => array('','','','',$this->brand_pattern,'','','','','1',),
7362
+ 'suffix' => array('','','','','','','','','','',),
7363
+ 'output_type' => array('1','1','1','1','1','1','1','6','1','1',),
7364
+ 'limit' => array('','','','','','','','','','',),
7365
  ),
7366
  );
7367
  // End of file merchant_templates.php
includes/template-infos.php CHANGED
@@ -434,7 +434,10 @@ return array(
434
  ),
435
  'tiktok' => array(
436
  'link' => 'https://ads.tiktok.com/help/article?aid=10001006',
437
- 'feed_file_type' => array( 'XML', 'CSV' ),
 
 
 
438
  ),
439
  );
440
  // End of file merchant_infos.php
434
  ),
435
  'tiktok' => array(
436
  'link' => 'https://ads.tiktok.com/help/article?aid=10001006',
437
+ 'feed_file_type' => array('CSV' ),
438
+ ),
439
+ 'shopflix' => array(
440
+ 'feed_file_type' => array('XML' ),
441
  ),
442
  );
443
  // End of file merchant_infos.php
languages/woo-feed.pot CHANGED
@@ -16,7 +16,7 @@ msgstr ""
16
  msgid "Unauthorized Action."
17
  msgstr ""
18
 
19
- #: woo-feed.php:141, woo-feed.php:260, includes/helper.php:823, includes/helper.php:1843, includes/helper.php:2867, includes/helper.php:2895, includes/helper.php:3288, includes/helper.php:3479, includes/helper.php:3506, includes/helper.php:4736, includes/helper.php:5226
20
  msgid "Invalid Request."
21
  msgstr ""
22
 
@@ -709,31 +709,31 @@ msgstr ""
709
  msgid "Choose from the most used"
710
  msgstr ""
711
 
712
- #: includes/helper.php:4433
713
  msgid "Option Successfully Added."
714
  msgstr ""
715
 
716
- #: includes/helper.php:4424
717
  msgid "Option Already Added."
718
  msgstr ""
719
 
720
- #: includes/helper.php:5133
721
  msgid "Delivery up to 30 days"
722
  msgstr ""
723
 
724
- #: includes/helper.php:5131
725
  msgid "Delivery 1 to 3 days"
726
  msgstr ""
727
 
728
- #: includes/helper.php:5234
729
  msgid "Feed data is empty. Can't duplicate feed."
730
  msgstr ""
731
 
732
- #: includes/helper.php:5250
733
  msgid "Unable to save the duplicate feed data."
734
  msgstr ""
735
 
736
- #: includes/helper.php:5260
737
  msgid "Feed Successfully Duplicated, but unable to generate the data file. Please click the \"Regenerate Button\""
738
  msgstr ""
739
 
16
  msgid "Unauthorized Action."
17
  msgstr ""
18
 
19
+ #: woo-feed.php:141, woo-feed.php:260, includes/helper.php:823, includes/helper.php:1843, includes/helper.php:2867, includes/helper.php:2895, includes/helper.php:3288, includes/helper.php:3479, includes/helper.php:3506, includes/helper.php:4737, includes/helper.php:5227
20
  msgid "Invalid Request."
21
  msgstr ""
22
 
709
  msgid "Choose from the most used"
710
  msgstr ""
711
 
712
+ #: includes/helper.php:4434
713
  msgid "Option Successfully Added."
714
  msgstr ""
715
 
716
+ #: includes/helper.php:4425
717
  msgid "Option Already Added."
718
  msgstr ""
719
 
720
+ #: includes/helper.php:5134
721
  msgid "Delivery up to 30 days"
722
  msgstr ""
723
 
724
+ #: includes/helper.php:5132
725
  msgid "Delivery 1 to 3 days"
726
  msgstr ""
727
 
728
+ #: includes/helper.php:5235
729
  msgid "Feed data is empty. Can't duplicate feed."
730
  msgstr ""
731
 
732
+ #: includes/helper.php:5251
733
  msgid "Unable to save the duplicate feed data."
734
  msgstr ""
735
 
736
+ #: includes/helper.php:5261
737
  msgid "Feed Successfully Duplicated, but unable to generate the data file. Please click the \"Regenerate Button\""
738
  msgstr ""
739
 
libs/WebAppick/Attributes/AvailabilityDate.php CHANGED
@@ -94,10 +94,10 @@ class AvailabilityDate implements AttributeInterface {
94
  * @return void
95
  * @since 4.4.14
96
  */
97
- public function admin_simple_save( $post_id ){
98
-
99
- if( isset( $_POST['woo_feed_availability_date'] ) && !empty( $_POST['woo_feed_availability_date'] ) ) {
100
- update_post_meta($post_id, 'woo_feed_availability_date', esc_attr($_POST['woo_feed_availability_date']));
101
  }
102
  }
103
 
@@ -110,10 +110,10 @@ class AvailabilityDate implements AttributeInterface {
110
  * @return void
111
  * @since 4.4.14
112
  */
113
- public function admin_variable_save( $post_id, $loop ){
114
-
115
- if( isset( $_POST['woo_feed_availability_date_var'][$loop] ) && !empty( $_POST['woo_feed_availability_date_var'][$loop] ) ) {
116
- update_post_meta($post_id, 'woo_feed_availability_date_var', esc_attr($_POST['woo_feed_availability_date_var'][$loop]));
117
  }
118
  }
119
 
94
  * @return void
95
  * @since 4.4.14
96
  */
97
+ public function admin_simple_save( $post_id ) {
98
+ $woo_feed_availability_date = !empty( $_POST['woo_feed_availability_date'] ) ? $_POST['woo_feed_availability_date'] : '';
99
+ if( $woo_feed_availability_date ) {
100
+ update_post_meta($post_id, 'woo_feed_availability_date', esc_attr( $woo_feed_availability_date ));
101
  }
102
  }
103
 
110
  * @return void
111
  * @since 4.4.14
112
  */
113
+ public function admin_variable_save( $post_id, $loop ) {
114
+ $var = !empty($_POST['woo_feed_availability_date_var'][$loop]) ? $_POST['woo_feed_availability_date_var'][$loop] : '';
115
+ if( $var) {
116
+ update_post_meta($post_id, 'woo_feed_availability_date_var', esc_attr( $var ));
117
  }
118
  }
119
 
woo-feed.php CHANGED
@@ -10,7 +10,7 @@
10
  * Plugin Name: CTX Feed
11
  * Plugin URI: https://webappick.com/
12
  * Description: Easily generate woocommerce product feed for any marketing channel like Google Shopping(Merchant), Facebook Remarketing, Bing, eBay & more. Support 100+ Merchants.
13
- * Version: 4.4.62
14
  * Author: WebAppick
15
  * Author URI: https://webappick.com/
16
  * License: GPL v2
@@ -76,6 +76,11 @@ require_once WOO_FEED_FREE_PATH . 'includes/log-helper.php';
76
  require_once WOO_FEED_FREE_PATH . 'includes/helper.php';
77
  require_once WOO_FEED_FREE_PATH . 'includes/cron-helper.php';
78
 
 
 
 
 
 
79
  /**
80
  * Installer
81
  */
@@ -158,23 +163,24 @@ if ( ! function_exists( 'woo_feed_get_product_information' ) ) {
158
  }
159
  try {
160
  do_action( 'before_woo_feed_get_product_information', $getConfig );
161
- if ( isset($getConfig['provider']) && 'googlereview' === $getConfig['provider'] ) {
162
- $args = array(
163
- 'post_type' => 'product',
164
- 'fields' => 'ids',
165
- 'comment_count' => array(
166
- 'value' => 0,
167
- 'compare' => '>',
168
- ),
169
- );
170
-
171
- $ids = get_posts($args);
172
-
173
- }else {
174
- $products = new Woo_Feed_Products_v3( $getConfig );
175
- $ids = $products->query_products();
176
- }
177
 
 
 
178
 
179
  do_action( 'after_woo_feed_get_product_information', $getConfig );
180
  woo_feed_log_feed_process( $getConfig['filename'], sprintf( 'Total %d product found', is_array( $ids ) && ! empty( $ids ) ? count( $ids ) : 0 ) );
@@ -537,6 +543,7 @@ if ( ! function_exists( 'woo_feed_generate_new_feed' ) ) {
537
  * Generate Feed
538
  */
539
  function woo_feed_generate_new_feed() {
 
540
  if ( isset( $_POST['provider'], $_POST['_wpnonce'], $_POST['filename'], $_POST['feedType'] ) ) {
541
  // Verify Nonce.
542
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'woo_feed_form_nonce' ) ) {
@@ -571,25 +578,36 @@ if ( ! function_exists( 'woo_feed_manage_feed' ) ) {
571
  */
572
  function woo_feed_manage_feed() {
573
 
 
 
 
 
 
 
 
 
 
574
  // @TODO use admin_post_ action for form handling.
575
  // Manage action for category mapping.
576
- if ( isset( $_GET['action'] ) && 'edit-feed' === $_GET['action'] ) {
577
  if ( ! defined( 'WOO_FEED_EDIT_CONFIG' ) ) {
578
  define( 'WOO_FEED_EDIT_CONFIG', true );
579
  }
580
- if ( count( $_POST ) && isset( $_POST['provider'], $_POST['feed_id'], $_POST['feed_option_name'], $_POST['filename'], $_POST['feedType'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
 
581
  $nonce = isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : '';
582
  if ( ! wp_verify_nonce( $nonce, 'wf_edit_feed' ) ) {
583
  wp_die( esc_html__( 'Failed security check', 'woo-feed' ), 403 );
584
  }
585
  // Check feed type (file ext)
586
- if ( ! woo_feed_check_valid_extension( sanitize_text_field( wp_unslash( $_POST['feedType'] ) ) ) ) {
587
  wp_die( esc_html__( 'Invalid Feed Type!', 'woo-feed' ), 400 );
588
  }
589
 
590
  // check if name is changed... save as new, rename feed isn't implemented ... it can be...
591
  // delete old feed save data as new feed.
592
- $feed_option_name = ( isset( $_POST['feed_option_name'] ) && ! empty( $_POST['feed_option_name'] ) ) ? sanitize_text_field( wp_unslash( $_POST['feed_option_name'] ) ) : null;
 
593
  // if ( $_POST['filename'] !== $_POST['feed_option_name'] ) {
594
  // $feed_option_name = ( isset( $_POST['filename'] ) && ! empty( $_POST['filename'] ) ) ? sanitize_text_field( $_POST['filename'] ) : null;
595
  // Delete old feed info & file
@@ -622,9 +640,9 @@ if ( ! function_exists( 'woo_feed_manage_feed' ) ) {
622
  );
623
  die();
624
  }
625
- if ( isset( $_GET['feed'] ) && ! empty( $_GET['feed'] ) ) {
626
  global $wpdb, $feedRules, $feedName, $feedId, $provider;
627
- $feedName = sanitize_text_field( wp_unslash( $_GET['feed'] ) );
628
  $feedInfo = maybe_unserialize( get_option( $feedName ) );
629
  if ( false !== $feedInfo ) {
630
  $query = $wpdb->prepare( "SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT 1", $feedName );
@@ -645,11 +663,12 @@ if ( ! function_exists( 'woo_feed_manage_feed' ) ) {
645
  }
646
  } else {
647
  // Update Interval.
648
- if ( isset( $_POST['wf_schedule'] ) ) {
 
649
  if ( isset( $_POST['wf_schedule_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wf_schedule_nonce'] ) ), 'wf_schedule' ) ) {
650
- $interval = absint( $_POST['wf_schedule'] );
651
  if ( $interval >= woo_feed_get_minimum_interval_option() ) {
652
- if ( update_option( 'wf_schedule', sanitize_text_field( wp_unslash( $_POST['wf_schedule'] ) ), false ) ) {
653
  wp_clear_scheduled_hook( 'woo_feed_update' );
654
  add_filter( 'cron_schedules', 'Woo_Feed_installer::cron_schedules' ); // phpcs:ignore
655
  // wp_schedule_event( time(), 'woo_feed_corn', 'woo_feed_update' );
10
  * Plugin Name: CTX Feed
11
  * Plugin URI: https://webappick.com/
12
  * Description: Easily generate woocommerce product feed for any marketing channel like Google Shopping(Merchant), Facebook Remarketing, Bing, eBay & more. Support 100+ Merchants.
13
+ * Version: 4.4.63
14
  * Author: WebAppick
15
  * Author URI: https://webappick.com/
16
  * License: GPL v2
76
  require_once WOO_FEED_FREE_PATH . 'includes/helper.php';
77
  require_once WOO_FEED_FREE_PATH . 'includes/cron-helper.php';
78
 
79
+ /**
80
+ * Load filter, sanitizer
81
+ */
82
+ require_once WOO_FEED_FREE_PATH . 'includes/filters/filters.php';
83
+
84
  /**
85
  * Installer
86
  */
163
  }
164
  try {
165
  do_action( 'before_woo_feed_get_product_information', $getConfig );
166
+ // if ( isset($getConfig['provider']) && 'googlereview' === $getConfig['provider'] ) {
167
+ // $args = array(
168
+ // 'post_type' => 'product',
169
+ // 'fields' => 'ids',
170
+ // 'comment_count' => array(
171
+ // 'value' => 0,
172
+ // 'compare' => '>',
173
+ // ),
174
+ // );
175
+ //
176
+ // $ids = get_posts($args);
177
+ //
178
+ // }else {
179
+ //
180
+ // }
 
181
 
182
+ $products = new Woo_Feed_Products_v3( $getConfig );
183
+ $ids = $products->query_products();
184
 
185
  do_action( 'after_woo_feed_get_product_information', $getConfig );
186
  woo_feed_log_feed_process( $getConfig['filename'], sprintf( 'Total %d product found', is_array( $ids ) && ! empty( $ids ) ? count( $ids ) : 0 ) );
543
  * Generate Feed
544
  */
545
  function woo_feed_generate_new_feed() {
546
+
547
  if ( isset( $_POST['provider'], $_POST['_wpnonce'], $_POST['filename'], $_POST['feedType'] ) ) {
548
  // Verify Nonce.
549
  if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'woo_feed_form_nonce' ) ) {
578
  */
579
  function woo_feed_manage_feed() {
580
 
581
+ $provider = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['provider'], "text");
582
+ $feed_id = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['feed_id'], "text");
583
+ $feed_option_name = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['feed_option_name'], "text");
584
+ $filename = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['filename'], "file_name");
585
+ $feedType = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['feedType'], "text");
586
+
587
+ $getaction = apply_filters('CTXFEED_filter_securing_input', "GET", @$_GET['action'], "text");
588
+ $getfeed = apply_filters('CTXFEED_filter_securing_input', "GET", @$_GET['feed'], "text");
589
+
590
  // @TODO use admin_post_ action for form handling.
591
  // Manage action for category mapping.
592
+ if ( 'edit-feed' === $getaction ) {
593
  if ( ! defined( 'WOO_FEED_EDIT_CONFIG' ) ) {
594
  define( 'WOO_FEED_EDIT_CONFIG', true );
595
  }
596
+
597
+ if ( count( $_POST ) && $provider && $feed_id && $feed_option_name && $filename && $feedType ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
598
  $nonce = isset( $_POST['_wpnonce'] ) && ! empty( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : '';
599
  if ( ! wp_verify_nonce( $nonce, 'wf_edit_feed' ) ) {
600
  wp_die( esc_html__( 'Failed security check', 'woo-feed' ), 403 );
601
  }
602
  // Check feed type (file ext)
603
+ if ( ! woo_feed_check_valid_extension( wp_unslash( $_POST['feedType'] ) ) ) {
604
  wp_die( esc_html__( 'Invalid Feed Type!', 'woo-feed' ), 400 );
605
  }
606
 
607
  // check if name is changed... save as new, rename feed isn't implemented ... it can be...
608
  // delete old feed save data as new feed.
609
+ $feed_option_name = wp_unslash( $feed_option_name ) ;
610
+
611
  // if ( $_POST['filename'] !== $_POST['feed_option_name'] ) {
612
  // $feed_option_name = ( isset( $_POST['filename'] ) && ! empty( $_POST['filename'] ) ) ? sanitize_text_field( $_POST['filename'] ) : null;
613
  // Delete old feed info & file
640
  );
641
  die();
642
  }
643
+ if ( $getfeed ) {
644
  global $wpdb, $feedRules, $feedName, $feedId, $provider;
645
+ $feedName = wp_unslash( $getfeed ) ;
646
  $feedInfo = maybe_unserialize( get_option( $feedName ) );
647
  if ( false !== $feedInfo ) {
648
  $query = $wpdb->prepare( "SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT 1", $feedName );
663
  }
664
  } else {
665
  // Update Interval.
666
+ $wf_schedule = apply_filters('CTXFEED_filter_securing_input', "POST", @$_POST['wf_schedule'], "text");
667
+ if ( $wf_schedule ) {
668
  if ( isset( $_POST['wf_schedule_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wf_schedule_nonce'] ) ), 'wf_schedule' ) ) {
669
+ $interval = absint( $wf_schedule );
670
  if ( $interval >= woo_feed_get_minimum_interval_option() ) {
671
+ if ( update_option( 'wf_schedule', wp_unslash( $wf_schedule ) , false ) ) {
672
  wp_clear_scheduled_hook( 'woo_feed_update' );
673
  add_filter( 'cron_schedules', 'Woo_Feed_installer::cron_schedules' ); // phpcs:ignore
674
  // wp_schedule_event( time(), 'woo_feed_corn', 'woo_feed_update' );