CTX Feed – WooCommerce Product Feed Manager Plugin - Version 3.6.4

Version Description

(2020-06-03) = * Fixed: Yoast SEO Title (manually added title) issue fixed.

Download this release

Release Info

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

Code changes from version 3.6.3 to 3.6.4

README.txt CHANGED
@@ -5,7 +5,7 @@ Tags:product feed,woocommerce product feed,google shopping feed,google shopping,
5
  Requires at least: 3.6
6
  Tested Up To: 5.4
7
  Requires PHP: 5.6
8
- Stable tag: 3.6.3
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -305,6 +305,9 @@ Using pro version:
305
 
306
  == Changelog ==
307
 
 
 
 
308
  = 3.6.3 (2020-06-02) =
309
  * Fixed: Yoast SEO Title issue fixed.
310
 
5
  Requires at least: 3.6
6
  Tested Up To: 5.4
7
  Requires PHP: 5.6
8
+ Stable tag: 3.6.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
305
 
306
  == Changelog ==
307
 
308
+ = 3.6.4 (2020-06-03) =
309
+ * Fixed: Yoast SEO Title (manually added title) issue fixed.
310
+
311
  = 3.6.3 (2020-06-02) =
312
  * Fixed: Yoast SEO Title issue fixed.
313
 
includes/classes/class-woo-feed-products-v3.php CHANGED
@@ -7,143 +7,144 @@
7
  * Time: 5:10 PM
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- die();
12
  }
13
 
14
  /**
15
  * Class Woo_Feed_Products_v3
16
  */
17
- class Woo_Feed_Products_v3 {
18
- /**
19
- * The Increment
20
- * @var int
21
- */
22
- protected $pi = 0;
23
- /**
24
- * Feed file headers
25
- *
26
- * @var string|array
27
- */
28
- public $feedHeader;
29
- /**
30
- * Feed File Body
31
- *
32
- * @var string|array
33
- */
34
- public $feedBody;
35
- /**
36
- * Feed file footer
37
- *
38
- * @var string|array
39
- */
40
- public $feedFooter;
41
- /**
42
- * CSV|TXT column (text|word) enclosure
43
- *
44
- * @var string
45
- */
46
- protected $enclosure;
47
- /**
48
- * CSV|TXT column delimiter
49
- *
50
- * @var string
51
- */
52
- protected $delimiter;
53
- /**
54
- * Feed Rules
55
- *
56
- * @var array
57
- */
58
- protected $config;
59
- /**
60
- * Post status to query
61
- *
62
- * @var string
63
- */
64
- protected $post_status = 'publish';
65
- /**
66
- * Processed Products
67
- *
68
- * @var array
69
- */
70
- public $products = [];
71
- /**
72
- * Query Method Selector
73
- *
74
- * @var string
75
- */
76
- protected $queryType = 'wp';
77
- /**
78
- * Google shipping tax attributes
79
- * @var array
80
- */
81
- protected $google_shipping_tax = array(
82
- 'shipping_country',
83
- 'shipping_region',
84
- 'shipping_service',
85
- 'shipping_price',
86
- 'tax_country',
87
- 'tax_region',
88
- 'tax_rate',
89
- 'tax_ship',
90
- 'installment_months',
91
- 'installment_amount',
92
- 'subscription_period',
93
- 'subscription_period_length',
94
- 'subscription_amount',
95
- );
96
- /**
97
- * XML Wrapper Array
98
- * Contains 'header' and 'footer' for template.
99
- * @var array
100
- */
101
- protected $xml_wrapper = [];
102
-
103
- /**
104
- * Attribute to skip in attribute loop for processing separately
105
- * @var array
106
- */
107
- protected $skipped_merchant_attributes = array(
108
- 'google' => array(
109
- 'shipping_country',
110
- 'shipping_region',
111
- 'shipping_service',
112
- 'shipping_price',
113
- 'tax_country',
114
- 'tax_region',
115
- 'tax_rate',
116
- 'tax_ship',
117
- 'installment_months',
118
- 'installment_amount',
119
- 'subscription_period',
120
- 'subscription_period_length',
121
- 'subscription_amount',
122
- ),
123
- 'facebook' => array(
124
- 'shipping_country',
125
- 'shipping_region',
126
- 'shipping_service',
127
- 'shipping_price',
128
- 'tax_country',
129
- 'tax_region',
130
- 'tax_rate',
131
- 'tax_ship',
132
- 'installment_months',
133
- 'installment_amount',
134
- 'subscription_period',
135
- 'subscription_period_length',
136
- 'subscription_amount',
137
- ),
138
- );
139
-
140
- /**
141
- * Already Processed merchant attributes by the attribute loop
142
- * this will ensure unique merchant attribute.
143
- * @see Woo_Feed_Products_v3::exclude_current_attribute()
144
- * @var array
145
- */
146
- protected $processed_merchant_attributes = array();
 
147
 
148
  /**
149
  * Product types Supported for query
@@ -156,2334 +157,2421 @@ class Woo_Feed_Products_v3 {
156
  'grouped',
157
  'external',
158
  );
159
- /**
160
- * Post meta prefix for dropdown item
161
- * @since 3.1.18
162
- * @var string
163
- */
164
- const POST_META_PREFIX = 'wf_cattr_';
165
- /**
166
- * Product Attribute (taxonomy & local) Prefix
167
- * @since 3.1.18
168
- * @var string
169
- */
170
- const PRODUCT_ATTRIBUTE_PREFIX = 'wf_attr_';
171
- /**
172
- * Product Taxonomy Prefix
173
- * @since 3.1.18
174
- * @var string
175
- */
176
- const PRODUCT_TAXONOMY_PREFIX = 'wf_taxo_';
177
-
178
- public function __construct( $config ) {
179
- $this->config = woo_feed_parse_feed_rules( $config );
180
- $this->queryType = woo_feed_get_options( 'product_query_type' );
181
- $this->process_xml_wrapper();
182
- woo_feed_log_feed_process( $this->config['filename'], sprintf( 'Current Query Type is %s', $this->queryType ) );
183
- }
184
-
185
- /**
186
- * Generate Query Args For WP/WC query class
187
- * @param string $type
188
- * @return array
189
- */
190
- protected function get_query_args( $type = 'wc' ) {
191
- $args = [];
192
- if ( 'wc' === $type ) {
193
- $args = array(
194
- 'limit' => 2e3, // phpcs:ignore
195
- 'status' => $this->post_status,
196
- 'type' => [ 'simple', 'variable', 'grouped', 'external' ],
197
- 'orderby' => 'date',
198
- 'order' => 'DESC',
199
- 'return' => 'ids',
200
- 'suppress_filters' => false,
201
- );
202
- }
203
- if ( 'wp' === $type ) {
204
- $args = array(
205
- 'posts_per_page' => 2e3, // phpcs:ignore
206
- 'post_type' => 'product',
207
- 'post_status' => 'publish',
208
- 'order' => 'DESC',
209
- 'fields' => 'ids',
210
- 'cache_results' => false,
211
- 'update_post_meta_cache' => false,
212
- 'update_post_term_cache' => false,
213
- 'suppress_filters' => false,
214
- );
215
- }
216
- return $args;
217
- }
218
-
219
- /**
220
- * Get Products using WC_Product_Query
221
- *
222
- * @return array
223
- */
224
- public function get_wc_query_products() {
225
- $args = $this->get_query_args( 'wc' );
226
- if ( woo_feed_is_debugging_enabled() ) {
227
- 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
228
- 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
229
- }
230
- $query = new WC_Product_Query( $args );
231
- if ( woo_feed_is_debugging_enabled() ) {
232
- 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
233
- }
234
- return $query->get_products();
235
- }
236
-
237
- /**
238
- * Get Products using WP_Query
239
- *
240
- * @return array
241
- */
242
- public function get_wp_query_products() {
243
- $args = $this->get_query_args( 'wp' );
244
- $query = new WP_Query( $args );
245
- if ( woo_feed_is_debugging_enabled() ) {
246
- 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
247
- woo_feed_log_feed_process( $this->config['filename'], sprintf( 'WP_Query Request ::' . PHP_EOL . '%s', $query->request ) );
248
- 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
249
- woo_feed_log( $this->config['filename'], sprintf( 'WP_Query Request ::' . PHP_EOL . '%s', $query->request ), 'info' );
250
- }
251
- return $query->get_posts();
252
- }
253
-
254
- /**
255
- * Get products
256
- *
257
- * @return array
258
- */
259
- public function query_products() {
260
- $products = [];
261
- if ( 'wc' == $this->queryType ) {
262
- $products = $this->get_wc_query_products();
263
- } elseif ( 'wp' == $this->queryType ) {
264
- $products = $this->get_wp_query_products();
265
- } elseif ( 'both' == $this->queryType ) {
266
- $wc = $this->get_wc_query_products();
267
- $wp = $this->get_wp_query_products();
268
- $products = array_unique( array_merge( $wc, $wp ) );
269
- }
270
-
271
- return $products;
272
- }
273
-
274
- /**
275
- * Organize Feed Attribute config
276
- * @return array|bool
277
- */
278
- public function get_attribute_config() {
279
- if ( empty( $this->config ) ) {
280
- return false;
281
- }
282
-
283
- $attributeConfig = array();
284
- $merchantAttributes = $this->config['mattributes'];
285
- if ( ! empty( $merchantAttributes ) ) {
286
- $i = 0;
287
- foreach ( $merchantAttributes as $key => $value ) {
288
- $attributeConfig[ $i ]['mattributes'] = $value;
289
- $attributeConfig[ $i ]['prefix'] = $this->config['prefix'][ $key ];
290
- $attributeConfig[ $i ]['type'] = $this->config['type'][ $key ];
291
- $attributeConfig[ $i ]['attributes'] = $this->config['attributes'][ $key ];
292
- $attributeConfig[ $i ]['default'] = $this->config['default'][ $key ];
293
- $attributeConfig[ $i ]['suffix'] = $this->config['suffix'][ $key ];
294
- $attributeConfig[ $i ]['output_type'] = $this->config['output_type'][ $key ];
295
- $attributeConfig[ $i ]['limit'] = $this->config['limit'][ $key ];
296
- $i ++;
297
- }
298
- }
299
-
300
- return $attributeConfig;
301
- }
302
-
303
- /**
304
- * Get Product Information according to feed config
305
- *
306
- * @param int[] $productIds
307
- *
308
- * @return array
309
- * @since 3.2.0
310
- *
311
- */
312
- public function get_products( $productIds ) {
313
-
314
- if ( empty( $productIds ) ) {
315
- return [];
316
- }
317
-
318
- /**
319
- * Fires before looping through request product for getting product data
320
- *
321
- * @param int[] $productIds
322
- * @param array $feedConfig
323
- *
324
- * @since 3.2.10
325
- */
326
- do_action( 'woo_feed_before_product_loop', $productIds, $this->config );
327
-
328
- foreach ( $productIds as $key => $pid ) {
329
- woo_feed_log_feed_process( $this->config['filename'], sprintf( 'Loading Product Data For %d.', $pid ) );
330
- $product = wc_get_product( $pid );
331
-
332
- if ( $this->exclude_from_loop( $product ) ) {
333
- continue;
334
- }
335
-
336
- if ( $this->process_variation( $product ) ) {
337
- continue;
338
- }
339
-
340
- if ( ! $this->filter_product( $product ) ) {
341
- woo_feed_log_feed_process( $this->config['filename'], 'Skipping Product :: Matched with filter conditions' );
342
- continue;
343
- }
344
-
345
- woo_feed_log_feed_process( $this->config['filename'], 'Formatting Feed Data...' );
346
-
347
- // Add Single item wrapper before product info loop start
348
- if ( 'xml' == $this->config['feedType'] ) {
349
- $this->feedBody .= "\n";
350
- $this->feedBody .= '<' . $this->config['itemWrapper'] . '>';
351
- $this->feedBody .= "\n";
352
- }
353
-
354
- // reset processed attribute list before loop
355
- $this->processed_merchant_attributes = [];
356
- // Process attribute values
357
- $this->process_attributes( $product );
358
-
359
- try {
360
- woo_feed_log_feed_process( $this->config['filename'], 'Processing Merchant Specific Fields' );
361
- // Process feed data for uncommon merchant feed like Google,Facebook,Pinterest
362
- $this->process_for_merchant( $product, $this->pi );
363
- } catch ( Exception $e ) {
364
- $message = 'Error Processing Merchant Specific Fields.' . PHP_EOL . 'Caught Exception :: ' . $e->getMessage();
365
- woo_feed_log( $this->config['filename'], $message, 'critical', $e, true );
366
- woo_feed_log_fatal_error( $message, $e );
367
- }
368
-
369
- if ( 'xml' == $this->config['feedType'] ) {
370
- if ( empty( $this->feedHeader ) ) {
371
- $this->feedHeader = $this->process_xml_feed_header();
372
- $this->feedFooter = $this->process_xml_feed_footer();
373
-
374
- }
375
-
376
- $this->feedBody .= '</' . $this->config['itemWrapper'] . '>';
377
-
378
-
379
- } elseif ( 'txt' == $this->config['feedType'] ) {
380
- if ( empty( $this->feedHeader ) ) {
381
- $this->process_txt_feed_header();
382
- }
383
- $this->process_txt_feed_body();
384
- } else {
385
- if ( empty( $this->feedHeader ) ) {
386
- $this->process_csv_feed_header();
387
- }
388
- $this->process_csv_feed_body();
389
- }
390
- woo_feed_log_feed_process( $this->config['filename'], 'Done Formatting...' );
391
- $this->pi ++;
392
- }
393
-
394
- /**
395
- * Fires after looping through request product for getting product data
396
- *
397
- * @param int[] $productIds
398
- * @param array $feedConfig
399
- *
400
- * @since 3.2.10
401
- */
402
- do_action( 'woo_feed_after_product_loop', $productIds, $this->config );
403
-
404
- return $this->products;
405
- }
406
-
407
- /**
408
- * Process product variations
409
- * @param WC_Abstract_Legacy_Product $product
410
- *
411
- * @return bool
412
- * @since 3.3.9
413
- */
414
- protected function process_variation( $product ) {
415
- // Apply variable and variation settings
416
- if ( $product->is_type( 'variable' ) && $product->has_child() ) {
417
- $this->pi ++;
418
- $variations = $product->get_visible_children();
419
- if ( is_array( $variations ) && ( sizeof( $variations ) > 0 ) ) {
420
- if ( woo_feed_is_debugging_enabled() ) {
421
- woo_feed_log_feed_process( $this->config['filename'], sprintf( 'Getting Variation Product(s) :: %s', implode( ', ', $variations ) ) );
422
- }
423
- $this->get_products( $variations );
424
- return false;
425
- }
426
- }
427
- return false;
428
- }
429
-
430
- /**
431
- * Process The Attributes and assign value to merchant attribute
432
- *
433
- * @param WC_Abstract_Legacy_Product $product
434
- *
435
- * @return void
436
- * @since 3.3.9
437
- */
438
- protected function process_attributes( $product ) {
439
- // Get Product Attribute values by type and assign to product array
440
- foreach ( $this->config['attributes'] as $attr_key => $attribute ) {
441
-
442
- $merchant_attribute = $this->config['mattributes'][ $attr_key ];
443
-
444
- if ( $this->exclude_current_attribute( $product, $merchant_attribute, $attribute ) ) {
445
- continue;
446
- }
447
-
448
- // Add Prefix and Suffix into Output
449
- $prefix = $this->config['prefix'][ $attr_key ];
450
- $suffix = $this->config['suffix'][ $attr_key ];
451
- $merchant = $this->config['provider'];
452
- $feedType = $this->config['feedType'];
453
-
454
- if ( 'pattern' == $this->config['type'][ $attr_key ] ) {
455
- $attributeValue = $this->config['default'][ $attr_key ];
456
- } else { // Get Pattern value
457
- $attributeValue = $this->getAttributeValueByType( $product, $attribute );
458
- }
459
-
460
- // Format Output according to Output Type config.
461
- if ( isset($this->config['output_type'][ $attr_key ]) ) {
462
- $outputType = $this->config['output_type'][ $attr_key ];
463
- $attributeValue = $this->format_output( $attributeValue, $this->config['output_type'][ $attr_key ], $product, $attribute );
464
- }
465
 
466
- // Limit Output.
467
- if ( isset($this->config['limit'][ $attr_key ]) ) {
468
- $attributeValue = $this->crop_string($attributeValue, 0, $this->config['limit'][ $attr_key ]);
469
- }
 
 
 
470
 
471
- // Process prefix and suffix.
472
- $attributeValue = $this->process_prefix_suffix( $attributeValue, $prefix, $suffix, $attribute );
473
-
474
- if ( 'xml' == $feedType ) {
475
-
476
- // Replace XML Nodes according to merchant requirement.
477
- $getReplacedAttribute = woo_feed_replace_to_merchant_attribute( $merchant_attribute, $merchant, $feedType );
478
-
479
- // XML does not support space in node. So replace Space with Underscore.
480
- $getReplacedAttribute = str_replace( ' ', '_', $getReplacedAttribute );
481
-
482
- if ( ! empty( $attributeValue ) ) {
483
- $attributeValue = trim( $attributeValue );
484
- }
485
-
486
- // Add closing XML node if value is empty
487
- if ( '' != $attributeValue ) {
488
- // Add CDATA wrapper for XML feed to prevent XML error.
489
- $attributeValue = woo_feed_add_cdata( $merchant_attribute, $attributeValue, $merchant );
490
-
491
- // TODO Move to proper place
492
- // Replace Google Color attribute value according to requirements
493
- if ( 'g:color' == $getReplacedAttribute ) {
494
- $attributeValue = str_replace( ', ', '/', $attributeValue );
495
- }
496
-
497
- // Strip slash from output
498
- $attributeValue = stripslashes( $attributeValue );
499
-
500
- $this->feedBody .= '<' . $getReplacedAttribute . '>' . "$attributeValue" . '</' . $getReplacedAttribute . '>';
501
- $this->feedBody .= "\n";
502
-
503
- } else {
504
- $this->feedBody .= '<' . $getReplacedAttribute . '/>';
505
- $this->feedBody .= "\n";
506
- }
507
- } elseif ( 'csv' == $feedType ) {
508
- $merchant_attribute = woo_feed_replace_to_merchant_attribute( $merchant_attribute, $merchant, $feedType );
509
- $merchant_attribute = $this->processStringForCSV( $merchant_attribute );
510
- $attributeValue = $this->processStringForCSV( $attributeValue );
511
- } elseif ( 'txt' == $feedType ) {
512
- $merchant_attribute = woo_feed_replace_to_merchant_attribute( $merchant_attribute, $merchant, $feedType );
513
- $merchant_attribute = $this->processStringForTXT( $merchant_attribute );
514
- $attributeValue = $this->processStringForTXT( $attributeValue );
515
- }
516
-
517
- $this->products[ $this->pi ][ $merchant_attribute ] = $attributeValue;
518
- }
519
- }
520
-
521
- /**
522
- * Check if current product should be processed for feed
523
- * This should be using by Woo_Feed_Products_v3::get_products()
524
- *
525
- * @param WC_Product $product
526
- *
527
- * @return bool
528
- * @since 3.3.9
529
- *
530
- */
531
- protected function exclude_from_loop( $product ) {
532
- // For WP_Query check available product types
533
- if ( 'wp' == $this->queryType && ! in_array( $product->get_type(), $this->product_types ) ) {
534
- woo_feed_log_feed_process( $this->config['filename'], sprintf( 'Skipping Product :: Invalid Post/Product Type : %s.', $product->get_type() ) );
535
- return true;
536
- }
537
-
538
- // Skip for invalid products
539
- if ( ! is_object( $product ) ) {
540
- woo_feed_log_feed_process( $this->config['filename'], 'Skipping Product :: Product data is not a valid WC_Product object.' );
541
- return true;
542
- }
543
-
544
- // Skip for invisible products
545
- if ( ! $product->is_visible() ) {
546
- woo_feed_log_feed_process( $this->config['filename'], 'Skipping Product :: Product is not visible.' );
547
- return true;
548
- }
549
- return false;
550
- }
551
-
552
- /**
553
- * Check if current attribute/merchant attribute should be processed for feed
554
- * This should be using by Woo_Feed_Products_v3::get_products()
555
- *
556
- * @param WC_Product $product
557
- * @param string $merchant_attribute
558
- * @param string $product_attribute
559
- * @param string $feedType
560
- *
561
- * @return bool
562
- *
563
- * @since 3.3.9
564
- *
565
- */
566
- protected function exclude_current_attribute( $product, $merchant_attribute, $product_attribute, $feedType = 'xml' ) {
567
- if (
568
- $feedType == $this->config['feedType'] &&
569
- in_array( $this->config['provider'], array_keys( $this->skipped_merchant_attributes ) ) &&
570
- in_array( $merchant_attribute, $this->skipped_merchant_attributes[ $this->config['provider'] ] )
571
-
572
- ) {
573
- return true;
574
- }
575
-
576
- if ( in_array( $merchant_attribute, $this->processed_merchant_attributes ) ) {
577
- return true;
578
- }
579
-
580
- $this->processed_merchant_attributes[] = $merchant_attribute;
581
-
582
- return false;
583
- }
584
-
585
- /**
586
- * Wrapper for substr with <![CDATA[string]]> support
587
- *
588
- * @see substr
589
- *
590
- * @param string $string
591
- * @param int $start
592
- * @param int $limit
593
- *
594
- * @return string
595
- */
596
- protected function crop_string( $string, $start = 0, $limit = null ) {
597
- $limit = absint( $limit );
598
- if ( $limit > 0 ) {
599
- $start = absint( $start );
600
- if ( strpos( $string, '<![CDATA[' ) !== false ) {
601
- $string = str_replace( array( '<![CDATA[', ']]>' ), array( '', '' ), $string );
602
- $string = substr( $string, $start, $limit );
603
- $string = '<![CDATA[' . $string . ']]>';
604
- } else {
605
- $string = substr( $string, $start, $limit );
606
- }
607
- }
608
- return $string;
609
- }
610
-
611
- /**
612
- * Process feed data according to merchant uncommon requirements like Google
613
- *
614
- * @param $productObj WC_Product
615
- * @param $index | Product Index
616
- *
617
- * @since 3.2.0
618
- *
619
- */
620
- protected function process_for_merchant( $productObj, $index ) {
621
- $product = $this->products[ $index ];
622
- $merchantAttributes = $this->config['mattributes'];
623
-
624
- // Format Shipping and Tax data for CSV and TXT feed only for google and facebook
625
- if ( 'xml' != $this->config['feedType'] && in_array( $this->config['provider'], [ 'google', 'facebook' ] ) ) {
626
-
627
- $shipping = array();
628
- $tax = array();
629
- $installment = array();
630
- $s = 0; // Shipping Index
631
- $t = 0; // Tax Index
632
- $i = 0; // Installment Index
633
- $shippingAttr = array(
634
- 'shipping_country',
635
- 'shipping_service',
636
- 'shipping_price',
637
- 'shipping_region',
638
- 'tax_country',
639
- 'tax_region',
640
- 'tax_rate',
641
- 'tax_ship',
642
- );
643
- foreach ( $this->products[ $this->pi ] as $attribute => $value ) {
644
- if ( in_array( $attribute, $shippingAttr ) ) {
645
-
646
- if ( 'tax_country' == $attribute ) {
647
- $t ++;
648
- $tax[ $t ] .= $value . ':';
649
- } elseif ( 'tax_region' == $attribute ) {
650
- $tax[ $t ] .= $value . ':';
651
- } elseif ( 'tax_rate' == $attribute ) {
652
- $tax[ $t ] .= $value . ':';
653
- } elseif ( 'tax_ship' == $attribute ) {
654
- $tax[ $t ] .= $value . ':';
655
- }
656
-
657
- if ( 'shipping_country' == $attribute ) {
658
- $s ++;
659
- $shipping[ $s ] .= $value . ':';
660
- } elseif ( 'shipping_service' == $attribute ) {
661
- $shipping[ $s ] .= $value . ':';
662
- } elseif ( 'shipping_price' == $attribute ) {
663
- $shipping[ $s ] .= $value . ':';
664
- } elseif ( 'shipping_region' == $attribute ) {
665
- $shipping[ $s ] .= $value . ':';
666
- }
667
-
668
- unset( $this->products[ $this->pi ][ $attribute ] );
669
- }
670
- }
671
-
672
- foreach ( $shipping as $key => $val ) {
673
- $this->products[ $this->pi ]['shipping(country:region:service:price)'] = $val;
674
- }
675
-
676
- foreach ( $tax as $key => $val ) {
677
- $this->products[ $this->pi ]['tax(country:region:rate:tax_ship)'] = $val;
678
- }
679
- }
680
-
681
- if ( 'google' == $this->config['provider'] ) {
682
-
683
- // Reformat Shipping attributes for google, facebook
684
- $s = 0;
685
- $t = 0;
686
- $tax = '';
687
- $shipping = '';
688
- if ( 'xml' == $this->config['feedType'] ) {
689
- foreach ( $merchantAttributes as $key => $value ) {
690
-
691
- if ( ! in_array( $value, $this->google_shipping_tax ) ) {
692
- continue;
693
- }
694
-
695
- $prefix = $this->config['prefix'][ $key ];
696
- $suffix = $this->config['suffix'][ $key ];
697
-
698
- if ( 'pattern' == $this->config['type'][ $key ] ) {
699
- $output = $this->config['default'][ $key ];
700
- } else { // Get Pattern value.
701
- $attribute = $this->config['attributes'][ $key ];
702
- $output = $this->getAttributeValueByType( $productObj, $attribute );
703
- }
704
-
705
- if ( false !== strpos( $value, 'price' ) || false !== strpos( $value, 'rate' ) ) {
706
- $suffix = '' . $suffix;
707
- }
708
-
709
-
710
- $output = $prefix . $output . $suffix;
711
-
712
- if ( 'shipping_country' == $value ) {
713
- if ( 0 == $s ) {
714
- $shipping .= '<g:shipping>';
715
- $s = 1;
716
- } else {
717
- $shipping .= '</g:shipping>' . "\n";
718
- $shipping .= '<g:shipping>';
719
- }
720
- } elseif ( ! in_array( 'shipping_country', $merchantAttributes ) && 'shipping_price' == $value ) {
721
- if ( 0 == $s ) {
722
- $shipping .= '<g:shipping>';
723
- $s = 1;
724
- } else {
725
- $shipping .= '</g:shipping>' . "\n";
726
- $shipping .= '<g:shipping>';
727
- }
728
- }
729
-
730
- if ( 'shipping_country' == $value ) {
731
- $shipping .= '<g:country>' . $output . '</g:country>' . "\n";
732
- } elseif ( 'shipping_region' == $value ) {
733
- $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
734
- } elseif ( 'shipping_service' == $value ) {
735
- $shipping .= '<g:service>' . $output . '</g:service>' . "\n";
736
- } elseif ( 'shipping_price' == $value ) {
737
- $shipping .= '<g:price>' . $output . '</g:price>' . "\n";
738
- } elseif ( 'tax_country' == $value ) {
739
- if ( 0 == $t ) {
740
- $tax .= '<g:tax>';
741
- $t = 1;
742
- } else {
743
- $tax .= '</g:tax>' . "\n";
744
- $tax .= '<g:tax>';
745
- }
746
- $tax .= '<g:country>' . $output . '</g:country>' . "\n";
747
- } elseif ( 'tax_region' == $value ) {
748
- $tax .= '<g:region>' . $output . '</g:region>' . "\n";
749
- } elseif ( 'tax_rate' == $value ) {
750
- $tax .= '<g:rate>' . $output . '</g:rate>' . "\n";
751
- } elseif ( 'tax_ship' == $value ) {
752
- $tax .= '<g:tax_ship>' . $output . '</g:tax_ship>' . "\n";
753
- }
754
- }
755
-
756
- if ( 1 == $s ) {
757
- $shipping .= '</g:shipping>';
758
- }
759
- if ( 1 == $t ) {
760
- $tax .= '</g:tax>';
761
- }
762
-
763
- $this->feedBody .= $shipping;
764
- $this->feedBody .= $tax;
765
- }
766
- // ADD g:identifier_exists
767
- $identifier = array( 'brand', 'upc', 'sku', 'mpn', 'gtin' );
768
- $countIdentifier = 0;
769
- if ( ! in_array( 'identifier_exists', $merchantAttributes ) ) {
770
- if ( count( array_intersect_key( array_flip( $identifier ), $product ) ) >= 2 ) {
771
- // Any 2 required keys exist!
772
- // @TODO Refactor with OR
773
- if ( array_key_exists( 'brand', $product ) && ! empty( $product['brand'] ) ) {
774
- $countIdentifier ++;
775
- }
776
- if ( array_key_exists( 'upc', $product ) && ! empty( $product['upc'] ) ) {
777
- $countIdentifier ++;
778
- }
779
- if ( array_key_exists( 'sku', $product ) && ! empty( $product['sku'] ) ) {
780
- $countIdentifier ++;
781
- }
782
- if ( array_key_exists( 'mpn', $product ) && ! empty( $product['mpn'] ) ) {
783
- $countIdentifier ++;
784
- }
785
- if ( array_key_exists( 'gtin', $product ) && ! empty( $product['gtin'] ) ) {
786
- $countIdentifier ++;
787
- }
788
- }
789
-
790
- if ( 'xml' == $this->config['feedType'] ) {
791
- if ( $countIdentifier >= 2 ) {
792
- $this->feedBody .= '<g:identifier_exists>yes</g:identifier_exists>';
793
- } else {
794
- $this->feedBody .= '<g:identifier_exists>no</g:identifier_exists>';
795
- }
796
- } else {
797
- if ( $countIdentifier >= 2 ) {
798
- $this->products[ $this->pi ]['identifier exists'] = 'yes';
799
- } else {
800
- $this->products[ $this->pi ]['identifier exists'] = 'no';
801
- }
802
- }
803
- }
804
- }
805
- }
806
-
807
- /**
808
- * Get Query Type Settings
809
- * @return string
810
- */
811
- public function get_query_type() {
812
- return $this->queryType;
813
- }
814
-
815
- public function get_product_types() {
816
- return $this->product_types;
817
- }
818
- /**
819
- * Generate TXT Feed Header
820
- *
821
- * @return string
822
- * @since 3.2.0
823
- *
824
- */
825
- protected function process_txt_feed_header() {
826
- // Set Delimiter
827
- if ( 'tab' == $this->config['delimiter'] ) {
828
- $this->delimiter = "\t";
829
- } else {
830
- $this->delimiter = $this->config['delimiter'];
831
- }
832
-
833
- // Set Enclosure
834
- if ( ! empty( $this->config['enclosure'] ) ) {
835
- $this->enclosure = $this->config['enclosure'];
836
- if ( 'double' == $this->enclosure ) {
837
- $this->enclosure = '"';
838
- } elseif ( 'single' == $this->enclosure ) {
839
- $this->enclosure = "'";
840
- } else {
841
- $this->enclosure = '';
842
- }
843
- } else {
844
- $this->enclosure = '';
845
- }
846
-
847
- $eol = PHP_EOL;
848
- if ( 'trovaprezzi' === $this->config['provider'] ) {
849
- $eol = '<endrecord>' . PHP_EOL;
850
- }
851
-
852
- $product = $this->products[ $this->pi ];
853
- $headers = array_keys( $product );
854
- $this->feedHeader .= $this->enclosure . implode( "$this->enclosure$this->delimiter$this->enclosure", $headers ) . $this->enclosure . $eol;
855
-
856
- return $this->feedHeader;
857
- }
858
-
859
- /**
860
- * Generate TXT Feed Body
861
- *
862
- * @return string
863
- * @since 3.2.0
864
- *
865
- */
866
- protected function process_txt_feed_body() {
867
- $productInfo = array_values( $this->products[ $this->pi ] );
868
- $eol = PHP_EOL;
869
- if ( 'trovaprezzi' === $this->config['provider'] ) {
870
- $eol = '<endrecord>' . PHP_EOL;
871
- }
872
- $this->feedBody .= $this->enclosure . implode( "$this->enclosure$this->delimiter$this->enclosure", $productInfo ) . $this->enclosure . $eol;
873
-
874
- return $this->feedBody;
875
- }
876
-
877
- /**
878
- * Generate CSV Feed Header
879
- *
880
- * @return array
881
- * @since 3.2.0
882
- *
883
- */
884
- protected function process_csv_feed_header() {
885
- // Set Delimiter
886
- if ( 'tab' == $this->config['delimiter'] ) {
887
- $this->delimiter = "\t";
888
- } else {
889
- $this->delimiter = $this->config['delimiter'];
890
- }
891
-
892
- // Set Enclosure
893
- if ( ! empty( $this->config['enclosure'] ) ) {
894
- $this->enclosure = $this->config['enclosure'];
895
- if ( 'double' == $this->enclosure ) {
896
- $this->enclosure = '"';
897
- } elseif ( 'single' == $this->enclosure ) {
898
- $this->enclosure = "'";
899
- } else {
900
- $this->enclosure = '';
901
- }
902
- } else {
903
- $this->enclosure = '';
904
- }
905
-
906
- $product = $this->products[ $this->pi ];
907
- $this->feedHeader = array_keys( $product );
908
-
909
- return $this->feedHeader;
910
- }
911
-
912
- /**
913
- * Generate CSV Feed Body
914
- * @return array
915
- * @since 3.2.0
916
- */
917
- protected function process_csv_feed_body() {
918
- $product = $this->products[ $this->pi ];
919
- $this->feedBody[] = array_values( $product );
920
-
921
- return $this->feedBody;
922
- }
923
-
924
- protected function process_xml_wrapper() {
925
-
926
- $this->xml_wrapper = [
927
- 'header' => '<?xml version="1.0" encoding="UTF-8" ?>' . PHP_EOL . '<' . $this->config['itemsWrapper'] . '>',
928
- 'footer' => PHP_EOL . '</' . $this->config['itemsWrapper'] . '>',
929
- ];
930
- $this->config['itemWrapper'] = str_replace( ' ', '_', $this->config['itemWrapper'] );
931
- $this->config['itemsWrapper'] = str_replace( ' ', '_', $this->config['itemsWrapper'] );
932
-
933
- if ( file_exists( WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt' ) ) {
934
- $txt = file_get_contents( WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt' );
935
- $txt = trim( $txt );
936
- $txt = explode( '{separator}', $txt );
937
- if ( 2 === count( $txt ) ) {
938
- $this->xml_wrapper['header'] = trim( $txt[0] );
939
- $this->xml_wrapper['footer'] = trim( $txt[1] );
940
- }
941
- }
942
-
943
- if ( ! empty( $this->config['extraHeader'] ) ) {
944
- $this->xml_wrapper['header'] .= PHP_EOL . $this->config['extraHeader'];
945
- }
946
-
947
- // replace template variables.
948
- $datetime_now = gmdate( 'Y-m-d H:i:s' ); // {DateTimeNow}
949
- $blog_name = get_bloginfo( 'name' ); // {BlogName}
950
- $blog_url = get_bloginfo( 'url' ); // {BlogURL}
951
- $blog_desc = get_bloginfo( 'description' ); // {BlogDescription}
952
- $blog_email = get_bloginfo( 'admin_email' ); // {BlogEmail}
953
-
954
- $this->xml_wrapper['header'] = str_replace(
955
- [ '{DateTimeNow}', '{BlogName}', '{BlogURL}', '{BlogDescription}', '{BlogEmail}' ],
956
- [ $datetime_now, $blog_name, $blog_url, $blog_desc, $blog_email ],
957
- $this->xml_wrapper['header']
958
- );
959
- }
960
-
961
- /**
962
- * Make XML feed header
963
- * @return string
964
- * @since 3.2.0
965
- */
966
- protected function process_xml_feed_header() {
967
- return $this->xml_wrapper['header'];
968
- }
969
-
970
- /**
971
- * Make XML feed header
972
- * @return string
973
- * @since 3.2.0
974
- */
975
- protected function process_xml_feed_footer() {
976
- return $this->xml_wrapper['footer'];
977
- }
978
-
979
- /**
980
- * Process string for TXT CSV Feed
981
- *
982
- * @param $string
983
- *
984
- * @return mixed|string
985
- * @since 3.2.0
986
- *
987
- */
988
- protected function processStringForTXT( $string ) {
989
- if ( ! empty( $string ) ) {
990
- $string = html_entity_decode( $string, ENT_HTML401 | ENT_QUOTES ); // Convert any HTML entities
991
-
992
- if ( stristr( $string, '"' ) ) {
993
- $string = str_replace( '"', '""', $string );
994
- }
995
- $string = str_replace( "\n", ' ', $string );
996
- $string = str_replace( "\r", ' ', $string );
997
- $string = str_replace( "\t", ' ', $string );
998
- $string = trim( $string );
999
- $string = stripslashes( $string );
1000
-
1001
- return $string;
1002
- } elseif ( '0' == $string ) {
1003
- return '0';
1004
- } else {
1005
- return '';
1006
- }
1007
- }
1008
-
1009
- /**
1010
- * Process string for CSV
1011
- *
1012
- * @param $string
1013
- *
1014
- * @return mixed|string
1015
- * @since 3.2.0
1016
- *
1017
- */
1018
- protected function processStringForCSV( $string ) {
1019
- if ( ! empty( $string ) ) {
1020
- $string = str_replace( "\n", ' ', $string );
1021
- $string = str_replace( "\r", ' ', $string );
1022
- $string = trim( $string );
1023
- $string = stripslashes( $string );
1024
-
1025
- return $string;
1026
- } elseif ( '0' == $string ) {
1027
- return '0';
1028
- } else {
1029
- return '';
1030
- }
1031
- }
1032
-
1033
- /**
1034
- * Get Product Attribute Value by Type
1035
- *
1036
- * @param $product WC_Product
1037
- * @param $attribute
1038
- *
1039
- * @return mixed|string
1040
- * @since 3.2.0
1041
- *
1042
- */
1043
- protected function getAttributeValueByType( $product, $attribute ) {
1044
-
1045
- if ( method_exists( $this, $attribute ) ) {
1046
- $output = call_user_func_array( array( $this, $attribute ), array( $product ) );
1047
- } elseif ( false !== strpos( $attribute, self::PRODUCT_ATTRIBUTE_PREFIX ) ) {
1048
- $attribute = str_replace( self::PRODUCT_ATTRIBUTE_PREFIX, '', $attribute );
1049
- $output = $this->getProductAttribute( $product, $attribute );
1050
- } elseif ( false !== strpos( $attribute, self::POST_META_PREFIX ) ) {
1051
- $attribute = str_replace( self::POST_META_PREFIX, '', $attribute );
1052
- $output = $this->getProductMeta( $product, $attribute );
1053
- } elseif ( false !== strpos( $attribute, self::PRODUCT_TAXONOMY_PREFIX ) ) {
1054
- $attribute = str_replace( self::PRODUCT_TAXONOMY_PREFIX, '', $attribute );
1055
- $output = $this->getProductTaxonomy( $product, $attribute );
1056
- } elseif ( 'image_' == substr( $attribute, 0, 6 ) ) {
1057
- // For additional image method images() will be used with extra parameter - image number
1058
- $imageKey = explode( '_', $attribute );
1059
- if ( ! isset( $imageKey[1] ) || ( isset( $imageKey[1] ) && ( empty( $imageKey[1] ) || ! is_numeric( $imageKey[1] ) ) ) ) {
1060
- $imageKey[1] = '';
1061
- }
1062
- $output = call_user_func_array( array( $this, 'images' ), array( $product, $imageKey[1] ) );
1063
- } else {
1064
- // return the attribute so multiple attribute can be join with separator to make custom attribute.
1065
- $output = $attribute;
1066
- }
1067
-
1068
- // Json encode if value is an array
1069
- if ( is_array( $output ) ) {
1070
- $output = wp_json_encode( $output );
1071
- }
1072
-
1073
- /**
1074
- * Filter attribute value
1075
- *
1076
- * @param string $output the output
1077
- * @param WC_Abstract_Legacy_Product $product Product Object.
1078
- * @param array feed config/rule
1079
- *
1080
- * @since 3.4.3
1081
- *
1082
- */
1083
- $output = apply_filters( 'woo_feed_get_attribute', $output, $product, $this->config );
1084
-
1085
- /**
1086
- * Filter attribute value before return based on attribute name
1087
- *
1088
- * @param string $output the output
1089
- * @param WC_Abstract_Legacy_Product $product Product Object.
1090
- * @param array feed config/rule
1091
- *
1092
- * @since 3.3.5
1093
- *
1094
- */
1095
- $output = apply_filters( "woo_feed_get_{$attribute}_attribute", $output, $product, $this->config );
1096
-
1097
- /**
1098
- * Filter attribute value before return based on merchant and attribute name
1099
- *
1100
- * @param string $output the output
1101
- * @param WC_Abstract_Legacy_Product $product Product Object.
1102
- * @param array feed config/rule
1103
- *
1104
- * @since 3.3.7
1105
- *
1106
- */
1107
- $output = apply_filters( "woo_feed_get_{$this->config['provider']}_{$attribute}_attribute", $output, $product, $this->config );
1108
-
1109
- return $output;
1110
- }
1111
-
1112
- /**
1113
- * Get Product Id
1114
- *
1115
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1116
- *
1117
- * @return mixed
1118
- * @since 3.2.0
1119
- */
1120
- protected function id( $product ) {
1121
- return $product->get_id();
1122
- }
1123
-
1124
- /**
1125
- * Get Product Title
1126
- *
1127
- * @param WC_Product $product
1128
- *
1129
- * @return mixed
1130
- * @since 3.2.0
1131
- *
1132
- */
1133
- protected function title( $product ) {
1134
- return $product->get_name();
1135
- }
1136
-
1137
- /**
1138
- * Get Yoast Product Title
1139
- *
1140
- * @param WC_Product $product
1141
- *
1142
- * @return mixed
1143
- * @since 3.2.0
1144
- *
1145
- */
1146
- protected function yoast_wpseo_title( $product ) {
1147
 
1148
- $yoast_title = get_post_meta($product->get_id(), '_yoast_wpseo_title', true);
1149
- $title = strstr($yoast_title, '%%', true);
1150
- if (empty($title)) {
1151
- $title = get_the_title($product->get_id());
 
 
 
 
 
 
 
 
 
 
 
1152
  }
1153
- $wpseo_titles = get_option('wpseo_titles');
 
1154
 
1155
- $sep_options = WPSEO_Option_Titles::get_instance()->get_separator_options();
1156
- if (isset($wpseo_titles['separator']) && isset($sep_options[$wpseo_titles['separator']])) {
1157
- $sep = $sep_options[$wpseo_titles['separator']];
1158
- } else {
1159
- $sep = '-'; //setting default separator if Admin didn't set it from backed
 
 
 
 
 
 
 
 
 
1160
  }
 
 
1161
 
1162
- $site_title = get_bloginfo('name');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1163
 
1164
- $meta_title = $title . ' ' . $sep . ' ' . $site_title;
 
1165
 
1166
- if ( ! empty( $meta_title ) ) {
1167
- return $meta_title;
1168
- }
 
 
 
 
 
 
1169
 
1170
- // $title = '';
1171
- // if ( class_exists( 'WPSEO_Frontend' ) ) {
1172
- // $title = WPSEO_Frontend::get_instance()->get_seo_title( get_post( $product->get_id() ) );
1173
- // }
1174
- // if ( ! empty( $title ) ) {
1175
- // return $title;
1176
- // }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1177
 
1178
- return $this->title( $product );
1179
- }
1180
-
1181
- /**
1182
- * Get All In One Product Title
1183
- *
1184
- * @param WC_Product $product
1185
- *
1186
- * @return mixed
1187
- * @since 3.2.0
1188
- *
1189
- */
1190
- protected function _aioseop_title( $product ) {
1191
- $title = '';
1192
- if ( class_exists( 'All_in_One_SEO_Pack' ) ) {
1193
- global $aioseop_options, $aiosp;
1194
- if ( ! is_array( $aioseop_options ) ) {
1195
- $aioseop_options = get_option( 'aioseop_options' );
1196
- }
1197
- if ( ! ( $aiosp instanceof All_in_One_SEO_Pack ) ) {
1198
- $aiosp = new All_in_One_SEO_Pack();
1199
- }
1200
-
1201
- if ( in_array( 'product', $aioseop_options['aiosp_cpostactive'], true ) ) {
1202
- if ( ! empty( $aioseop_options['aiosp_rewrite_titles'] ) ) {
1203
- $title = $aiosp->get_aioseop_title( get_post( $product->get_id() ) );
1204
- $title = $aiosp->apply_cf_fields( $title );
1205
- }
1206
- $title = apply_filters( 'aioseop_title', $title );
1207
- }
1208
- }
1209
- if ( ! empty( $title ) ) {
1210
- return $title;
1211
- }
1212
-
1213
- return $this->title( $product );
1214
- }
1215
-
1216
- /**
1217
- * Get Product Description
1218
- *
1219
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1220
- *
1221
- * @return mixed|string
1222
- * @since 3.2.0
1223
- *
1224
- */
1225
- protected function description( $product ) {
1226
-
1227
- $description = $product->get_description();
1228
-
1229
- // Get Variation Description
1230
- if ( $product->is_type( 'variation' ) && empty( $description ) ) {
1231
- $parent = wc_get_product( $product->get_parent_id() );
1232
- $description = $parent->get_description();
1233
- }
1234
- $description = $this->remove_short_codes( $description );
1235
-
1236
- // Add variations attributes after description to prevent Facebook error
1237
- if ( 'facebook' == $this->config['provider'] ) {
1238
- $variationInfo = explode( '-', $product->get_name() );
1239
- if ( isset( $variationInfo[1] ) ) {
1240
- $extension = $variationInfo[1];
1241
- } else {
1242
- $extension = $product->get_id();
1243
- }
1244
- $description .= ' ' . $extension;
1245
- }
1246
-
1247
- return $description;
1248
- }
1249
-
1250
- /**
1251
- * Get Yoast Product Description
1252
- *
1253
- * @param WC_Product $product
1254
- *
1255
- * @return mixed
1256
- * @since 3.2.0
1257
- *
1258
- */
1259
- protected function yoast_wpseo_metadesc( $product ) {
1260
- $description = '';
1261
- if ( class_exists( 'WPSEO_Frontend' ) ) {
1262
- $description = wpseo_replace_vars( WPSEO_Meta::get_value( 'metadesc', $product->get_id() ),
1263
- get_post( $product->get_id() ) );
1264
- }
1265
- if ( ! empty( $description ) ) {
1266
- return $description;
1267
- }
1268
-
1269
- return $this->description( $product );
1270
- }
1271
-
1272
- /**
1273
- * Get All In One Product Description
1274
- *
1275
- * @param WC_Product $product
1276
- *
1277
- * @return mixed
1278
- * @since 3.2.0
1279
- *
1280
- */
1281
- protected function _aioseop_description( $product ) {
1282
- $description = '';
1283
- if ( class_exists( 'All_in_One_SEO_Pack' ) ) {
1284
- global $aioseop_options, $aiosp;
1285
- if ( ! is_array( $aioseop_options ) ) {
1286
- $aioseop_options = get_option( 'aioseop_options' );
1287
- }
1288
- if ( ! ( $aiosp instanceof All_in_One_SEO_Pack ) ) {
1289
- $aiosp = new All_in_One_SEO_Pack();
1290
- }
1291
- if ( in_array( 'product', $aioseop_options['aiosp_cpostactive'], true ) ) {
1292
- $description = $aiosp->get_main_description( get_post( $product->get_id() ) ); // Get the description.
1293
- $description = $aiosp->trim_description( $description );
1294
- $description = apply_filters( 'aioseop_description_full',
1295
- $aiosp->apply_description_format( $description, get_post( $product->get_id() ) ) );
1296
- }
1297
- }
1298
- if ( ! empty( $description ) ) {
1299
- return $description;
1300
- }
1301
-
1302
- return $this->description( $product );
1303
- }
1304
-
1305
- /**
1306
- * Get Product Short Description
1307
- *
1308
- * @param WC_Product $product
1309
- *
1310
- * @return mixed|string
1311
- * @since 3.2.0
1312
- *
1313
- */
1314
- protected function short_description( $product ) {
1315
-
1316
- $short_description = $product->get_short_description();
1317
-
1318
- // Get Variation Short Description
1319
- if ( $product->is_type( 'variation' ) && empty( $short_description ) ) {
1320
- $parent = wc_get_product( $product->get_parent_id() );
1321
- $short_description = $parent->get_short_description();
1322
- }
1323
-
1324
-
1325
- $short_description = $this->remove_short_codes( $short_description );
1326
-
1327
- return $short_description;
1328
- }
1329
-
1330
-
1331
- /**
1332
- * At First convert Short Codes and then Remove failed Short Codes from String
1333
- *
1334
- * @param $content
1335
- *
1336
- * @return mixed|string
1337
- * @since 3.2.0
1338
- *
1339
- */
1340
- protected function remove_short_codes( $content ) {
1341
- if ( empty( $content ) ) {
1342
- return '';
1343
- }
1344
-
1345
- // Remove DIVI Builder Short Codes
1346
- if ( class_exists( 'ET_Builder_Module' ) || defined( 'ET_BUILDER_PLUGIN_VERSION' ) ) {
1347
- /** @noinspection RegExpRedundantEscape */
1348
- $content = preg_replace( '/\[\/?et_pb.*?\]/', '', $content );
1349
- }
1350
-
1351
- $content = do_shortcode( $content );
1352
-
1353
- $content = woo_feed_stripInvalidXml( $content );
1354
-
1355
- return strip_shortcodes( $content );
1356
- }
1357
-
1358
- /**
1359
- * Get Product Main Category
1360
- *
1361
- * @param WC_Product $product
1362
- *
1363
- * @return string
1364
- *
1365
- */
1366
- protected function primary_category( $product ) {
1367
- $id = $product->get_id();
1368
- if ( $product->is_type( 'variation' ) ) {
1369
- $id = $product->get_parent_id();
1370
- }
1371
- $wpseo_primary_term = false;
1372
- $main_category = '';
1373
- if ( class_exists( 'WPSEO_Primary_Term' ) ) {
1374
- $wpseo_primary_term = new WPSEO_Primary_Term( 'product_cat', $id );
1375
- $main_category = $wpseo_primary_term->get_primary_term();
1376
- $main_category = get_term( $main_category, 'product_cat' );
1377
- }
1378
- if ( ! ( $wpseo_primary_term instanceof WPSEO_Primary_Term ) || empty( $main_category ) ) {
1379
- $term = wp_get_post_terms( $id, 'product_cat' );
1380
- if ( ! is_wp_error( $term ) && ! empty( $term ) ) {
1381
- $main_category = $term[0];
1382
- }
1383
- }
1384
-
1385
- return $main_category instanceof WP_Term ? $main_category->name : '';
1386
- }
1387
-
1388
- /**
1389
- * Get Product Categories
1390
- *
1391
- * @param WC_Product $product
1392
- *
1393
- * @return string
1394
- * @since 3.2.0
1395
- *
1396
- */
1397
- protected function product_type( $product ) {
1398
- $id = $product->get_id();
1399
- if ( $product->is_type( 'variation' ) ) {
1400
- $id = $product->get_parent_id();
1401
- }
1402
-
1403
- $separator = apply_filters( 'woo_feed_product_type_separator', '>', $this->config, $product );
1404
-
1405
- return wp_strip_all_tags( wc_get_product_category_list( $id, $separator, '' ) );
1406
- }
1407
-
1408
- /**
1409
- * Get Product URL
1410
- *
1411
- * @param WC_Product $product
1412
- *
1413
- * @return string
1414
- * @since 3.2.0
1415
- *
1416
- */
1417
- protected function link( $product ) {
1418
- $utm = $this->config['campaign_parameters'];
1419
- if ( ! empty( $utm['utm_source'] ) && ! empty( $utm['utm_medium'] ) && ! empty( $utm['utm_campaign'] ) ) {
1420
- $utm = [
1421
- 'utm_source' => $utm['utm_source'],
1422
- 'utm_medium' => $utm['utm_medium'],
1423
- 'utm_campaign' => $utm['utm_campaign'],
1424
- 'utm_term' => $utm['utm_term'],
1425
- 'utm_content' => $utm['utm_content'],
1426
- ];
1427
-
1428
- return add_query_arg( array_filter( $utm ), $product->get_permalink() );
1429
- }
1430
-
1431
- return $product->get_permalink();
1432
- }
1433
-
1434
- /**
1435
- * Get External Product URL
1436
- *
1437
- * @param WC_Product $product
1438
- *
1439
- * @return string
1440
- * @since 3.2.0
1441
- *
1442
- */
1443
- protected function ex_link( $product ) {
1444
- if ( $product->is_type( 'external' ) ) {
1445
- return $product->get_product_url();
1446
- }
1447
-
1448
- return '';
1449
- }
1450
-
1451
- /**
1452
- * Get Product Image
1453
- *
1454
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1455
- *
1456
- * @return mixed
1457
- * @since 3.2.0
1458
- *
1459
- */
1460
- protected function image( $product ) {
1461
- if ( $product->is_type( 'variation' ) ) {
1462
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ),
1463
- 'single-post-thumbnail' );
1464
- if ( has_post_thumbnail( $product->get_id() ) && ! empty( $getImage[0] ) ) :
1465
- $image = woo_feed_get_formatted_url( $getImage[0] );
1466
- else :
1467
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_parent_id() ),
1468
- 'single-post-thumbnail' );
1469
- $image = woo_feed_get_formatted_url( $getImage[0] );
1470
- endif;
1471
- } else {
1472
- if ( has_post_thumbnail( $product->get_id() ) ) :
1473
- $getImage = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ),
1474
- 'single-post-thumbnail' );
1475
- $image = woo_feed_get_formatted_url( $getImage[0] );
1476
- else :
1477
- $image = woo_feed_get_formatted_url( wp_get_attachment_url( $product->get_id() ) );
1478
- endif;
1479
- }
1480
-
1481
- return $image;
1482
- }
1483
-
1484
- /**
1485
- * Get Product Featured Image
1486
- *
1487
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1488
- *
1489
- * @return mixed
1490
- * @since 3.2.0
1491
- *
1492
- */
1493
- protected function feature_image( $product ) {
1494
- return $this->image( $product );
1495
- }
1496
-
1497
- /**
1498
- * Get Comma Separated Product Images
1499
- *
1500
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1501
- * @param string $additionalImg Specific Additional Image.
1502
- *
1503
- * @return mixed
1504
- * @since 3.2.0
1505
- *
1506
- */
1507
- protected function images( $product, $additionalImg = '' ) {
1508
- if ( $product->is_type( 'variation' ) ) {
1509
- // TODO Test Variation Images
1510
- $imgUrls = $this->get_product_gallery( wc_get_product( $product->get_parent_id() ) );
1511
- } else {
1512
- $imgUrls = $this->get_product_gallery( $product );
1513
- }
1514
-
1515
- // Return Specific Additional Image URL
1516
- if ( '' != $additionalImg ) {
1517
- if ( array_key_exists( $additionalImg, $imgUrls ) ) {
1518
- return $imgUrls[ $additionalImg ];
1519
- } else {
1520
- return '';
1521
- }
1522
- }
1523
-
1524
- return implode( ',', array_filter( $imgUrls ) );
1525
- }
1526
-
1527
- /**
1528
- * Get Product Gallery Items (URL) array.
1529
- * This can contains empty array values
1530
- *
1531
- * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product
1532
- *
1533
- * @return string[]
1534
- * @since 3.2.6
1535
- */
1536
- protected function get_product_gallery( $product ) {
1537
- $attachmentIds = $product->get_gallery_image_ids();
1538
- $imgUrls = array();
1539
- if ( $attachmentIds && is_array( $attachmentIds ) ) {
1540
- $mKey = 1;
1541
- foreach ( $attachmentIds as $attachmentId ) {
1542
- $imgUrls[ $mKey ] = woo_feed_get_formatted_url( wp_get_attachment_url( $attachmentId ) );
1543
- $mKey ++;
1544
- }
1545
- }
1546
-
1547
- return $imgUrls;
1548
- }
1549
-
1550
- /**
1551
- * Get Product Condition
1552
- *
1553
- * @param WC_Product $product
1554
- *
1555
- * @return mixed
1556
- * @since 3.2.0
1557
- *
1558
- */
1559
- protected function condition( $product ) {
1560
- return apply_filters( 'woo_feed_product_condition', 'new', $product );
1561
- }
1562
-
1563
- /**
1564
- * Get Product Type
1565
- *
1566
- * @param WC_Product $product
1567
- *
1568
- * @return mixed
1569
- * @since 3.2.0
1570
- *
1571
- */
1572
- protected function type( $product ) {
1573
- return $product->get_type();
1574
- }
1575
-
1576
- /**
1577
- * Get Product is a bundle product or not
1578
- *
1579
- * @param WC_Product $product
1580
- *
1581
- * @return mixed
1582
- * @since 3.2.0
1583
- *
1584
- */
1585
- protected function is_bundle( $product ) {
1586
- if ( $product->is_type( 'bundle' ) || $product->is_type( 'yith_bundle' ) ) {
1587
- return 'yes';
1588
- }
1589
-
1590
- return 'no';
1591
- }
1592
-
1593
- /**
1594
- * Get Product is a multi-pack product or not
1595
- *
1596
- * @param WC_Product $product
1597
- *
1598
- * @return mixed
1599
- * @since 3.2.0
1600
- *
1601
- */
1602
- protected function multipack( $product ) {
1603
- $multi_pack = '';
1604
- if ( $product->is_type( 'grouped' ) ) {
1605
- $multi_pack = ( ! empty( $product->get_children() ) ) ? count( $product->get_children() ) : '';
1606
- }
1607
-
1608
- return $multi_pack;
1609
- }
1610
-
1611
- /**
1612
- * Get Product visibility status
1613
- *
1614
- * @param WC_Product $product
1615
- *
1616
- * @return mixed
1617
- * @since 3.2.0
1618
- *
1619
- */
1620
- protected function visibility( $product ) {
1621
- return $product->get_catalog_visibility();
1622
- }
1623
-
1624
- /**
1625
- * Get Product Total Rating
1626
- *
1627
- * @param WC_Product $product
1628
- *
1629
- * @return mixed
1630
- * @since 3.2.0
1631
- *
1632
- */
1633
- protected function rating_total( $product ) {
1634
- return $product->get_rating_count();
1635
- }
1636
-
1637
- /**
1638
- * Get Product average rating
1639
- *
1640
- * @param WC_Product $product
1641
- *
1642
- * @return mixed
1643
- * @since 3.2.0
1644
- *
1645
- */
1646
- protected function rating_average( $product ) {
1647
- return $product->get_average_rating();
1648
- }
1649
-
1650
- /**
1651
- * Get Product tags
1652
- *
1653
- * @param WC_Product $product
1654
- *
1655
- * @return string
1656
- * @since 3.2.0
1657
- *
1658
- */
1659
- protected function tags( $product ) {
1660
- $id = $product->get_id();
1661
- if ( $product->is_type( 'variation' ) ) {
1662
- $id = $product->get_parent_id();
1663
- }
1664
-
1665
- /**
1666
- * Separator for multiple tags
1667
- * @param string $separator
1668
- * @param array $config
1669
- * @param WC_Abstract_Legacy_Product $product
1670
- * @since 3.4.3
1671
- */
1672
- $separator = apply_filters( 'woo_feed_tags_separator', ',', $this->config, $product );
1673
-
1674
- return wp_strip_all_tags( get_the_term_list( $id, 'product_tag', '', $separator, '' ) );
1675
- }
1676
-
1677
- /**
1678
- * Get Product Parent Id
1679
- *
1680
- * @param WC_Product $product
1681
- *
1682
- * @return mixed
1683
- * @since 3.2.0
1684
- *
1685
- */
1686
- protected function item_group_id( $product ) {
1687
- $id = $product->get_id();
1688
- if ( $product->is_type( 'variation' ) ) {
1689
- $id = $product->get_parent_id();
1690
- }
1691
-
1692
- return $id;
1693
- }
1694
-
1695
- /**
1696
- * Get Product SKU
1697
- *
1698
- * @param WC_Product $product
1699
- *
1700
- * @return mixed
1701
- * @since 3.2.0
1702
- *
1703
- */
1704
- protected function sku( $product ) {
1705
- return $product->get_sku();
1706
- }
1707
-
1708
- /**
1709
- * Get Product Parent SKU
1710
- *
1711
- * @param WC_Product $product
1712
- *
1713
- * @return mixed
1714
- * @since 3.2.0
1715
- *
1716
- */
1717
- protected function parent_sku( $product ) {
1718
- if ( $product->is_type( 'variation' ) ) {
1719
- $id = $product->get_parent_id();
1720
- $parent = wc_get_product( $id );
1721
-
1722
- return $parent->get_sku();
1723
- }
1724
-
1725
- return $product->get_sku();
1726
- }
1727
-
1728
- /**
1729
- * Get Product Availability Status
1730
- *
1731
- * @param WC_Product $product
1732
- *
1733
- * @return mixed
1734
- * @since 3.2.0
1735
- *
1736
- */
1737
- protected function availability( $product ) {
1738
- $status = $product->get_stock_status();
1739
- if ( 'instock' == $status ) {
1740
- return 'in stock';
1741
- } elseif ( 'outofstock' == $status ) {
1742
- return 'out of stock';
1743
- } elseif ( 'onbackorder' == $status ) {
1744
- return 'on backorder';
1745
- } else {
1746
- return 'in stock';
1747
- }
1748
- }
1749
-
1750
- /**
1751
- * Get Product Quantity
1752
- *
1753
- * @param WC_Product $product
1754
- *
1755
- * @return mixed
1756
- * @since 3.2.0
1757
- *
1758
- */
1759
- protected function quantity( $product ) {
1760
- if ( $product->is_type( 'variable' ) && $product->has_child() ) {
1761
- $visible_children = $product->get_visible_children();
1762
- $qty = array();
1763
- foreach ( $visible_children as $key => $child ) {
1764
- $childQty = get_post_meta( $child, '_stock', true );
1765
- $qty[] = (int) $childQty + 0;
1766
- }
1767
-
1768
- if ( isset( $this->config['variable_quantity'] ) ) {
1769
- $vaQty = $this->config['variable_quantity'];
1770
- if ( 'max' == $vaQty ) {
1771
- return max( $qty );
1772
- } elseif ( 'min' == $vaQty ) {
1773
- return min( $qty );
1774
- } elseif ( 'sum' == $vaQty ) {
1775
- return array_sum( $qty );
1776
- } elseif ( 'first' == $vaQty ) {
1777
- return ( (int) $qty[0] );
1778
- }
1779
-
1780
- return array_sum( $qty );
1781
- }
1782
- }
1783
-
1784
- return $product->get_stock_quantity();
1785
- }
1786
-
1787
- /**
1788
- * Get Product Sale Price Start Date
1789
- *
1790
- * @param WC_Product $product
1791
- *
1792
- * @return mixed
1793
- * @since 3.2.0
1794
- *
1795
- */
1796
- protected function sale_price_sdate( $product ) {
1797
- $startDate = $product->get_date_on_sale_from();
1798
- if ( is_object( $startDate ) ) {
1799
- return $startDate->date_i18n();
1800
- }
1801
-
1802
- return '';
1803
- }
1804
-
1805
- /**
1806
- * Get Product Sale Price End Date
1807
- *
1808
- * @param WC_Product $product
1809
- *
1810
- * @return mixed
1811
- * @since 3.2.0
1812
- *
1813
- */
1814
- protected function sale_price_edate( $product ) {
1815
- $endDate = $product->get_date_on_sale_to();
1816
- if ( is_object( $endDate ) ) {
1817
- return $endDate->date_i18n();
1818
- }
1819
-
1820
- return '';
1821
- }
1822
-
1823
- /**
1824
- * Get Product Regular Price
1825
- *
1826
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
1827
- *
1828
- * @return mixed
1829
- * @since 3.2.0
1830
- *
1831
- */
1832
- protected function price( $product ) {
1833
- if ( $product->is_type( 'variable' ) ) {
1834
- return $this->getVariableProductPrice( $product, 'regular_price' );
1835
- } elseif ( $product->is_type( 'grouped' ) ) {
1836
- return $this->getGroupProductPrice( $product,
1837
- 'regular' ); // this calls self::price() so no need to use self::getWPMLPrice()
1838
- } else {
1839
- return $product->get_regular_price();
1840
- }
1841
- }
1842
-
1843
- /**
1844
- * Get Product Price
1845
- *
1846
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1847
- *
1848
- * @return int|float|double|mixed
1849
- * @since 3.2.0
1850
- *
1851
- */
1852
- protected function current_price( $product ) {
1853
- if ( $product->is_type( 'variable' ) ) {
1854
- return $this->getVariableProductPrice( $product, 'price' );
1855
- } elseif ( $product->is_type( 'grouped' ) ) {
1856
- return $this->getGroupProductPrice( $product, 'current' );
1857
- } else {
1858
- return $product->get_price();
1859
- }
1860
- }
1861
-
1862
- /**
1863
- * Get Product Sale Price
1864
- *
1865
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1866
- *
1867
- * @return mixed
1868
- * @since 3.2.0
1869
- *
1870
- */
1871
- protected function sale_price( $product ) {
1872
- if ( $product->is_type( 'variable' ) ) {
1873
- return $this->getVariableProductPrice( $product, 'sale_price' );
1874
- } elseif ( $product->is_type( 'grouped' ) ) {
1875
- return $this->getGroupProductPrice( $product, 'sale' );
1876
- } else {
1877
- $price = $product->get_sale_price();
1878
-
1879
- return $price > 0 ? $price : '';
1880
- }
1881
- }
1882
-
1883
- /**
1884
- * Get Product Regular Price with Tax
1885
- *
1886
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
1887
- *
1888
- * @return mixed
1889
- * @since 3.2.0
1890
- *
1891
- */
1892
- protected function price_with_tax( $product ) {
1893
- if ( $product->is_type( 'variable' ) ) {
1894
- return $this->getVariableProductPrice( $product, 'regular_price', true );
1895
- } elseif ( $product->is_type( 'grouped' ) ) {
1896
- return $this->getGroupProductPrice( $product, 'regular', true );
1897
- } else {
1898
- $price = $this->price( $product );
1899
-
1900
- // Get price with tax.
1901
- return ( $product->is_taxable() && ! empty( $price ) ) ? $this->get_price_with_tax( $product,
1902
- $price ) : $price;
1903
- }
1904
- }
1905
-
1906
- /**
1907
- * Get Product Regular Price with Tax
1908
- *
1909
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1910
- *
1911
- * @return mixed
1912
- * @since 3.2.0
1913
- *
1914
- */
1915
- protected function current_price_with_tax( $product ) {
1916
- if ( $product->is_type( 'variable' ) ) {
1917
- return $this->getVariableProductPrice( $product, 'current_price', true );
1918
- } elseif ( $product->is_type( 'grouped' ) ) {
1919
- return $this->getGroupProductPrice( $product, 'current', true );
1920
- } else {
1921
- $price = $this->current_price( $product );
1922
-
1923
- // Get price with tax
1924
- return ( $product->is_taxable() && ! empty( $price ) ) ? $this->get_price_with_tax( $product,
1925
- $price ) : $price;
1926
- }
1927
- }
1928
-
1929
- /**
1930
- * Get Product Regular Price with Tax
1931
- *
1932
- * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1933
- *
1934
- * @return mixed
1935
- * @since 3.2.0
1936
- *
1937
- */
1938
- protected function sale_price_with_tax( $product ) {
1939
- if ( $product->is_type( 'variable' ) ) {
1940
- return $this->getVariableProductPrice( $product, 'sale_price', true );
1941
- } elseif ( $product->is_type( 'grouped' ) ) {
1942
- return $this->getGroupProductPrice( $product, 'sale', true );
1943
- } else {
1944
- $price = $this->sale_price( $product );
1945
- if ( $product->is_taxable() && ! empty( $price ) ) {
1946
- $price = $this->get_price_with_tax( $product, $price );
1947
- }
1948
-
1949
- return $price > 0 ? $price : '';
1950
- }
1951
- }
1952
-
1953
- /**
1954
- * Get total price of grouped product
1955
- *
1956
- * @param WC_Product_Grouped $grouped
1957
- * @param string $type
1958
- * @param bool $tax
1959
- *
1960
- * @return int|string
1961
- * @since 3.2.0
1962
- *
1963
- */
1964
- protected function getGroupProductPrice( $grouped, $type, $tax = false ) {
1965
- $groupProductIds = $grouped->get_children();
1966
- $sum = 0;
1967
- if ( ! empty( $groupProductIds ) ) {
1968
- foreach ( $groupProductIds as $id ) {
1969
- $product = wc_get_product( $id );
1970
-
1971
- if ( ! is_object( $product ) ) {
1972
- continue; // make sure that the product exists..
1973
- }
1974
-
1975
- if ( $tax ) {
1976
- if ( 'regular' == $type ) {
1977
- $regularPrice = $this->price_with_tax( $product );
1978
- $sum += (float) $regularPrice;
1979
- } elseif ( 'current' == $type ) {
1980
- $currentPrice = $this->current_price_with_tax( $product );
1981
- $sum += (float) $currentPrice;
1982
- } else {
1983
- $salePrice = $this->sale_price_with_tax( $product );
1984
- $sum += (float) $salePrice;
1985
- }
1986
- } else {
1987
- if ( 'regular' == $type ) {
1988
- $regularPrice = $this->price( $product );
1989
- $sum += (float) $regularPrice;
1990
- } elseif ( 'current' == $type ) {
1991
- $currentPrice = $this->current_price( $product );
1992
- $sum += (float) $currentPrice;
1993
- } else {
1994
- $salePrice = $this->sale_price( $product );
1995
- $sum += (float) $salePrice;
1996
- }
1997
- }
1998
- }
1999
- }
2000
-
2001
- if ( 'sale' == $type ) {
2002
- $sum = $sum > 0 ? $sum : '';
2003
- }
2004
-
2005
- return $sum;
2006
- }
2007
-
2008
- /**
2009
- * Get total price of variable product
2010
- *
2011
- * @param WC_Product_Variable $variable
2012
- * @param string $type regular_price, sale_price & current_price
2013
- * @param bool $tax calculate tax
2014
- *
2015
- * @return int|string
2016
- * @since 3.2.0
2017
- *
2018
- */
2019
- protected function getVariableProductPrice( $variable, $type, $tax = false ) {
2020
- $price = 0;
2021
- if ( 'regular_price' == $type ) {
2022
- $price = $variable->get_variation_regular_price();
2023
- } elseif ( 'sale_price' == $type ) {
2024
- $price = $variable->get_variation_sale_price();
2025
- } else {
2026
- $price = $variable->get_variation_price();
2027
- }
2028
- if ( true === $tax && $variable->is_taxable() ) {
2029
- $price = $this->get_price_with_tax( $variable, $price );
2030
- }
2031
- if ( 'sale_price' != $type ) {
2032
- $price = $price > 0 ? $price : '';
2033
- }
2034
-
2035
- return $price;
2036
- }
2037
-
2038
- /**
2039
- * Return product price with tax
2040
- *
2041
- * @param WC_Product $product Product.
2042
- * @param float $price Price.
2043
- *
2044
- * @return float|string
2045
- * @since 3.2.0
2046
- *
2047
- */
2048
- protected function get_price_with_tax( $product, $price ) {
2049
- if ( woo_feed_wc_version_check( 3.0 ) ) {
2050
- return wc_get_price_including_tax( $product, array( 'price' => $price ) );
2051
- } else {
2052
- return $product->get_price_including_tax( 1, $price );
2053
- }
2054
- }
2055
-
2056
- /**
2057
- * Get Product Weight
2058
- *
2059
- * @param WC_Product $product
2060
- *
2061
- * @return mixed
2062
- * @since 3.2.0
2063
- *
2064
- */
2065
- protected function weight( $product ) {
2066
- return $product->get_weight();
2067
- }
2068
-
2069
- /**
2070
- * Get Product Width
2071
- *
2072
- * @param WC_Product $product
2073
- *
2074
- * @return mixed
2075
- * @since 3.2.0
2076
- *
2077
- */
2078
- protected function width( $product ) {
2079
- return $product->get_width();
2080
- }
2081
-
2082
- /**
2083
- * Get Product Height
2084
- *
2085
- * @param WC_Product $product
2086
- *
2087
- * @return mixed
2088
- * @since 3.2.0
2089
- *
2090
- */
2091
- protected function height( $product ) {
2092
- return $product->get_height();
2093
- }
2094
-
2095
- /**
2096
- * Get Product Length
2097
- *
2098
- * @param WC_Product $product
2099
- *
2100
- * @return mixed
2101
- * @since 3.2.0
2102
- *
2103
- */
2104
- protected function length( $product ) {
2105
- return $product->get_length();
2106
- }
2107
-
2108
- /**
2109
- * Get Product Shipping Class
2110
- *
2111
- * @param WC_Product $product
2112
- *
2113
- * @return mixed
2114
- * @since 3.2.0
2115
- *
2116
- */
2117
- protected function shipping_class( $product ) {
2118
- return $product->get_shipping_class();
2119
- }
2120
-
2121
- /**
2122
- * Get Product Author Name
2123
- *
2124
- * @param WC_Product $product
2125
- *
2126
- * @return mixed
2127
- * @since 3.2.0
2128
- *
2129
- */
2130
- protected function author_name( $product ) {
2131
- $post = get_post( $product->get_id() );
2132
-
2133
- return get_the_author_meta( 'user_login', $post->post_author );
2134
- }
2135
-
2136
- /**
2137
- * Get Product Author Email
2138
- *
2139
- * @param WC_Product $product
2140
- *
2141
- * @return mixed
2142
- * @since 3.2.0
2143
- *
2144
- */
2145
- protected function author_email( $product ) {
2146
- $post = get_post( $product->get_id() );
2147
-
2148
- return get_the_author_meta( 'user_email', $post->post_author );
2149
- }
2150
-
2151
- /**
2152
- * Get Product Created Date
2153
- *
2154
- * @param WC_Product $product
2155
- *
2156
- * @return mixed
2157
- * @since 3.2.0
2158
- *
2159
- */
2160
- protected function date_created( $product ) {
2161
- return gmdate( 'Y-m-d', strtotime( $product->get_date_created() ) );
2162
- }
2163
-
2164
- /**
2165
- * Get Product Last Updated Date
2166
- *
2167
- * @param WC_Product $product
2168
- *
2169
- * @return mixed
2170
- * @since 3.2.0
2171
- *
2172
- */
2173
- protected function date_updated( $product ) {
2174
- return gmdate( 'Y-m-d', strtotime( $product->get_date_modified() ) );
2175
- }
2176
-
2177
- /**
2178
- * Get Product Sale Price Effected Date for Google Shopping
2179
- *
2180
- * @param WC_Product $product
2181
- *
2182
- * @return string
2183
- * @since 3.2.0
2184
- *
2185
- */
2186
- protected function sale_price_effective_date( $product ) {
2187
- $effective_date = '';
2188
- $from = $this->sale_price_sdate( $product );
2189
- $to = $this->sale_price_edate( $product );
2190
- if ( ! empty( $from ) && ! empty( $to ) ) {
2191
- $from = gmdate( 'c', strtotime( $from ) );
2192
- $to = gmdate( 'c', strtotime( $to ) );
2193
-
2194
- $effective_date = $from . '/' . $to;
2195
- }
2196
-
2197
- return $effective_date;
2198
- }
2199
-
2200
- /**
2201
- * Ger Product Attribute
2202
- *
2203
- * @param WC_Product $product
2204
- * @param $attr
2205
- *
2206
- * @return string
2207
- * @since 2.2.3
2208
- *
2209
- */
2210
- protected function getProductAttribute( $product, $attr ) {
2211
- $id = $product->get_id();
2212
-
2213
- if ( woo_feed_wc_version_check( 3.2 ) ) {
2214
- if ( woo_feed_wc_version_check( 3.6 ) ) {
2215
- $attr = str_replace( 'pa_', '', $attr );
2216
- }
2217
- $value = $product->get_attribute( $attr );
2218
-
2219
- return $value;
2220
- } else {
2221
- return implode( ',', wc_get_product_terms( $id, $attr, array( 'fields' => 'names' ) ) );
2222
- }
2223
- }
2224
-
2225
- /**
2226
- * Get Meta
2227
- *
2228
- * @param WC_Product $product
2229
- * @param string $meta post meta key
2230
- *
2231
- * @return mixed|string
2232
- * @since 2.2.3
2233
- *
2234
- */
2235
- protected function getProductMeta( $product, $meta ) {
2236
- $value = get_post_meta( $product->get_id(), $meta, true );
2237
- // if empty get meta value of parent post
2238
- if ( '' == $value && $product->get_parent_id() ) {
2239
- $value = get_post_meta( $product->get_parent_id(), $meta, true );
2240
- }
2241
-
2242
- return $value;
2243
- }
2244
-
2245
- /**
2246
- * Filter Products by Conditions
2247
- *
2248
- * @param WC_Product $product
2249
- *
2250
- * @return bool|array
2251
- * @since 3.2.0
2252
- *
2253
- */
2254
- public function filter_product( $product ) {
2255
- return true;
2256
- }
2257
-
2258
- /**
2259
- * Get Taxonomy
2260
- *
2261
- * @param WC_Product $product
2262
- * @param $taxonomy
2263
- *
2264
- * @return string
2265
- * @since 2.2.3
2266
- *
2267
- */
2268
- protected function getProductTaxonomy( $product, $taxonomy ) {
2269
- $id = $product->get_id();
2270
- if ( $product->is_type( 'variation' ) ) {
2271
- $id = $product->get_parent_id();
2272
- }
2273
-
2274
- $separator = apply_filters( 'woo_feed_product_taxonomy_term_list_separator', ',', $this->config, $product );
2275
-
2276
- return wp_strip_all_tags( get_the_term_list( $id, $taxonomy, '', $separator, '' ) );
2277
- }
2278
-
2279
- /**
2280
- * Format price value
2281
- *
2282
- * @param string $name Attribute Name
2283
- * @param int $conditionName condition
2284
- * @param int $result price
2285
- *
2286
- * @return mixed
2287
- * @since 3.2.0
2288
- *
2289
- */
2290
- protected function price_format( $name, $conditionName, $result ) {
2291
- $plus = '+';
2292
- $minus = '-';
2293
- $percent = '%';
2294
-
2295
- if ( strpos( $name, 'price' ) !== false ) {
2296
- if ( strpos( $result, $plus ) !== false && strpos( $result, $percent ) !== false ) {
2297
- $result = str_replace( '+', '', $result );
2298
- $result = str_replace( '%', '', $result );
2299
- if ( is_numeric( $result ) ) {
2300
- $result = $conditionName + ( ( $conditionName * $result ) / 100 );
2301
- }
2302
- } elseif ( strpos( $result, $minus ) !== false && strpos( $result, $percent ) !== false ) {
2303
- $result = str_replace( '-', '', $result );
2304
- $result = str_replace( '%', '', $result );
2305
- if ( is_numeric( $result ) ) {
2306
- $result = $conditionName - ( ( $conditionName * $result ) / 100 );
2307
- }
2308
- } elseif ( strpos( $result, $plus ) !== false ) {
2309
- $result = str_replace( '+', '', $result );
2310
- if ( is_numeric( $result ) ) {
2311
- $result = ( $conditionName + $result );
2312
- }
2313
- } elseif ( strpos( $result, $minus ) !== false ) {
2314
- $result = str_replace( '-', '', $result );
2315
- if ( is_numeric( $result ) ) {
2316
- $result = $conditionName - $result;
2317
- }
2318
- }
2319
- }
2320
-
2321
- return $result;
2322
- }
2323
-
2324
- /**
2325
- * Format output According to Output Type config
2326
- *
2327
- * @param string $output
2328
- * @param array $outputTypes
2329
- * @param WC_Product $product
2330
- * @param string $productAttribute
2331
- *
2332
- * @return float|int|string
2333
- * @since 3.2.0
2334
- *
2335
- */
2336
- protected function format_output( $output, $outputTypes, $product, $productAttribute ) {
2337
- if ( ! empty( $outputTypes ) && is_array( $outputTypes ) ) {
2338
-
2339
- // Format Output According to output type
2340
- if ( in_array( 2, $outputTypes ) ) { // Strip Tags
2341
- $output = wp_strip_all_tags( html_entity_decode( $output ) );
2342
- }
2343
-
2344
- if ( in_array( 3, $outputTypes ) ) { // UTF-8 Encode
2345
- $output = utf8_encode( $output );
2346
- }
2347
-
2348
- if ( in_array( 4, $outputTypes ) ) { // htmlentities
2349
- $output = htmlentities( $output, ENT_QUOTES, 'UTF-8' );
2350
- }
2351
-
2352
- if ( in_array( 5, $outputTypes ) ) { // Integer
2353
- $output = intval( $output );
2354
- }
2355
-
2356
- if ( in_array( 6, $outputTypes ) ) { // Format Price
2357
- if ( ! empty( $output ) && $output > 0 ) {
2358
- $output = (float) $output;
2359
- $output = number_format( $output, 2, '.', '' );
2360
- }
2361
- }
2362
-
2363
- if ( in_array( 7, $outputTypes ) ) { // Delete Space
2364
- $output = trim( $output );
2365
- $output = preg_replace( '!\s+!', ' ', $output );
2366
- }
2367
-
2368
- if ( in_array( 9, $outputTypes ) ) { // Remove Invalid Character
2369
- $output = woo_feed_stripInvalidXml( $output );
2370
- }
2371
-
2372
- if ( in_array( 10, $outputTypes ) ) { // Remove ShortCodes
2373
- $output = $this->remove_short_codes( $output );
2374
- }
2375
-
2376
- if ( in_array( 11, $outputTypes ) ) {
2377
- $output = ucwords( strtolower( $output ) );
2378
  }
2379
 
2380
- if ( in_array( 12, $outputTypes ) ) {
2381
- $output = ucfirst( strtolower( $output ) );
 
 
 
 
 
2382
  }
2383
 
2384
- if ( in_array( 13, $outputTypes ) ) {
2385
- $output = strtoupper( strtolower( $output ) );
 
 
 
 
 
 
 
 
 
 
 
2386
  }
2387
 
2388
- if ( in_array( 14, $outputTypes ) ) {
2389
- $output = strtolower( $output );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2390
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2391
 
2392
- if ( in_array( 15, $outputTypes ) ) {
2393
- if ( 'http' == substr( $output, 0, 4 ) ) {
2394
- $output = str_replace( 'http://', 'https://', $output );
 
 
 
 
 
 
 
 
 
 
 
 
 
2395
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2396
  }
2397
 
2398
- if ( in_array( 16, $outputTypes ) ) {
2399
- if ( 'http' == substr( $output, 0, 4 ) ) {
2400
- $output = str_replace( 'https://', 'http://', $output );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2401
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2403
 
2404
- if ( in_array( 17, $outputTypes ) ) { // only parent
2405
- if ( $product->is_type( 'variation' ) ) {
2406
- $id = $product->get_parent_id();
2407
- $parentProduct = wc_get_product( $id );
2408
- $output = $this->getAttributeValueByType( $parentProduct, $productAttribute );
2409
  }
2410
  }
2411
 
2412
- if ( in_array( 18, $outputTypes ) ) { // child if parent empty
2413
- if ( $product->is_type( 'variation' ) ) {
2414
- $id = $product->get_parent_id();
2415
- $parentProduct = wc_get_product( $id );
2416
- $output = $this->getAttributeValueByType( $parentProduct, $productAttribute );
2417
- if ( empty( $output ) ) {
2418
- $output = $this->getAttributeValueByType( $product, $productAttribute );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2419
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2420
  }
 
 
 
2421
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2422
 
2423
- if ( in_array( 19, $outputTypes ) ) { // parent if child empty
2424
- if ( $product->is_type( 'variation' ) ) {
2425
- $output = $this->getAttributeValueByType( $product, $productAttribute );
2426
- if ( empty( $output ) ) {
2427
- $id = $product->get_parent_id();
2428
- $parentProduct = wc_get_product( $id );
2429
- $output = $this->getAttributeValueByType( $parentProduct, $productAttribute );
 
 
 
 
2430
  }
2431
  }
2432
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2433
 
2434
- if ( in_array( 8, $outputTypes ) && ! empty( $output ) ) { // Add CDATA
2435
- $output = '<![CDATA[' . $output . ']]>';
2436
- }
2437
- }
2438
-
2439
- return $output;
2440
- }
2441
-
2442
- /**
2443
- * Add Prefix and Suffix with attribute value
2444
- *
2445
- * @param $output
2446
- * @param $prefix
2447
- * @param $suffix
2448
- * @param $attribute
2449
- *
2450
- * @return string
2451
- * @since 3.2.0
2452
- *
2453
- */
2454
- public function process_prefix_suffix( $output, $prefix, $suffix, $attribute = '' ) {
2455
-
2456
- if ( '' == $output ) {
2457
- return $output;
2458
- }
2459
-
2460
- // Add Prefix before Output
2461
- if ( '' != $prefix ) {
2462
- $output = "$prefix" . $output;
2463
- }
2464
-
2465
- // Add Suffix after Output
2466
- if ( '' !== $suffix ) {
2467
- if (
2468
- 'price' == $attribute
2469
- || 'sale_price' == $attribute
2470
- || 'current_price' == $attribute
2471
- || 'price_with_tax' == $attribute
2472
- || 'current_price_with_tax' == $attribute
2473
- || 'sale_price_with_tax' == $attribute
2474
- || 'shipping_price' == $attribute
2475
- || 'tax_rate' == $attribute
2476
- ) { // Add space before suffix if attribute contain price.
2477
- $output = $output . ' ' . $suffix;
2478
- } elseif ( substr( $output, 0, 4 ) === 'http' ) {
2479
- // Parse URL Parameters if available into suffix field
2480
- $output = woo_feed_make_url_with_parameter( $output, $suffix );
2481
-
2482
- } else {
2483
- $output = $output . "$suffix";
2484
- }
2485
- }
2486
-
2487
- return "$output";
2488
- }
2489
  }
7
  * Time: 5:10 PM
8
  */
9
 
10
+ if (!defined('ABSPATH')) {
11
+ die();
12
  }
13
 
14
  /**
15
  * Class Woo_Feed_Products_v3
16
  */
17
+ class Woo_Feed_Products_v3
18
+ {
19
+ /**
20
+ * The Increment
21
+ * @var int
22
+ */
23
+ protected $pi = 0;
24
+ /**
25
+ * Feed file headers
26
+ *
27
+ * @var string|array
28
+ */
29
+ public $feedHeader;
30
+ /**
31
+ * Feed File Body
32
+ *
33
+ * @var string|array
34
+ */
35
+ public $feedBody;
36
+ /**
37
+ * Feed file footer
38
+ *
39
+ * @var string|array
40
+ */
41
+ public $feedFooter;
42
+ /**
43
+ * CSV|TXT column (text|word) enclosure
44
+ *
45
+ * @var string
46
+ */
47
+ protected $enclosure;
48
+ /**
49
+ * CSV|TXT column delimiter
50
+ *
51
+ * @var string
52
+ */
53
+ protected $delimiter;
54
+ /**
55
+ * Feed Rules
56
+ *
57
+ * @var array
58
+ */
59
+ protected $config;
60
+ /**
61
+ * Post status to query
62
+ *
63
+ * @var string
64
+ */
65
+ protected $post_status = 'publish';
66
+ /**
67
+ * Processed Products
68
+ *
69
+ * @var array
70
+ */
71
+ public $products = [];
72
+ /**
73
+ * Query Method Selector
74
+ *
75
+ * @var string
76
+ */
77
+ protected $queryType = 'wp';
78
+ /**
79
+ * Google shipping tax attributes
80
+ * @var array
81
+ */
82
+ protected $google_shipping_tax = array(
83
+ 'shipping_country',
84
+ 'shipping_region',
85
+ 'shipping_service',
86
+ 'shipping_price',
87
+ 'tax_country',
88
+ 'tax_region',
89
+ 'tax_rate',
90
+ 'tax_ship',
91
+ 'installment_months',
92
+ 'installment_amount',
93
+ 'subscription_period',
94
+ 'subscription_period_length',
95
+ 'subscription_amount',
96
+ );
97
+ /**
98
+ * XML Wrapper Array
99
+ * Contains 'header' and 'footer' for template.
100
+ * @var array
101
+ */
102
+ protected $xml_wrapper = [];
103
+
104
+ /**
105
+ * Attribute to skip in attribute loop for processing separately
106
+ * @var array
107
+ */
108
+ protected $skipped_merchant_attributes = array(
109
+ 'google' => array(
110
+ 'shipping_country',
111
+ 'shipping_region',
112
+ 'shipping_service',
113
+ 'shipping_price',
114
+ 'tax_country',
115
+ 'tax_region',
116
+ 'tax_rate',
117
+ 'tax_ship',
118
+ 'installment_months',
119
+ 'installment_amount',
120
+ 'subscription_period',
121
+ 'subscription_period_length',
122
+ 'subscription_amount',
123
+ ),
124
+ 'facebook' => array(
125
+ 'shipping_country',
126
+ 'shipping_region',
127
+ 'shipping_service',
128
+ 'shipping_price',
129
+ 'tax_country',
130
+ 'tax_region',
131
+ 'tax_rate',
132
+ 'tax_ship',
133
+ 'installment_months',
134
+ 'installment_amount',
135
+ 'subscription_period',
136
+ 'subscription_period_length',
137
+ 'subscription_amount',
138
+ ),
139
+ );
140
+
141
+ /**
142
+ * Already Processed merchant attributes by the attribute loop
143
+ * this will ensure unique merchant attribute.
144
+ * @see Woo_Feed_Products_v3::exclude_current_attribute()
145
+ * @var array
146
+ */
147
+ protected $processed_merchant_attributes = array();
148
 
149
  /**
150
  * Product types Supported for query
157
  'grouped',
158
  'external',
159
  );
160
+ /**
161
+ * Post meta prefix for dropdown item
162
+ * @since 3.1.18
163
+ * @var string
164
+ */
165
+ const POST_META_PREFIX = 'wf_cattr_';
166
+ /**
167
+ * Product Attribute (taxonomy & local) Prefix
168
+ * @since 3.1.18
169
+ * @var string
170
+ */
171
+ const PRODUCT_ATTRIBUTE_PREFIX = 'wf_attr_';
172
+ /**
173
+ * Product Taxonomy Prefix
174
+ * @since 3.1.18
175
+ * @var string
176
+ */
177
+ const PRODUCT_TAXONOMY_PREFIX = 'wf_taxo_';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
+ public function __construct($config)
180
+ {
181
+ $this->config = woo_feed_parse_feed_rules($config);
182
+ $this->queryType = woo_feed_get_options('product_query_type');
183
+ $this->process_xml_wrapper();
184
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Current Query Type is %s', $this->queryType));
185
+ }
186
 
187
+ /**
188
+ * Generate Query Args For WP/WC query class
189
+ * @param string $type
190
+ * @return array
191
+ */
192
+ protected function get_query_args($type = 'wc')
193
+ {
194
+ $args = [];
195
+ if ('wc' === $type) {
196
+ $args = array(
197
+ 'limit' => 2e3, // phpcs:ignore
198
+ 'status' => $this->post_status,
199
+ 'type' => ['simple', 'variable', 'grouped', 'external'],
200
+ 'orderby' => 'date',
201
+ 'order' => 'DESC',
202
+ 'return' => 'ids',
203
+ 'suppress_filters' => false,
204
+ );
205
+ }
206
+ if ('wp' === $type) {
207
+ $args = array(
208
+ 'posts_per_page' => 2e3, // phpcs:ignore
209
+ 'post_type' => 'product',
210
+ 'post_status' => 'publish',
211
+ 'order' => 'DESC',
212
+ 'fields' => 'ids',
213
+ 'cache_results' => false,
214
+ 'update_post_meta_cache' => false,
215
+ 'update_post_term_cache' => false,
216
+ 'suppress_filters' => false,
217
+ );
218
+ }
219
+ return $args;
220
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
+ /**
223
+ * Get Products using WC_Product_Query
224
+ *
225
+ * @return array
226
+ */
227
+ public function get_wc_query_products()
228
+ {
229
+ $args = $this->get_query_args('wc');
230
+ if (woo_feed_is_debugging_enabled()) {
231
+ 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
232
+ 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
233
+ }
234
+ $query = new WC_Product_Query($args);
235
+ if (woo_feed_is_debugging_enabled()) {
236
+ 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
237
  }
238
+ return $query->get_products();
239
+ }
240
 
241
+ /**
242
+ * Get Products using WP_Query
243
+ *
244
+ * @return array
245
+ */
246
+ public function get_wp_query_products()
247
+ {
248
+ $args = $this->get_query_args('wp');
249
+ $query = new WP_Query($args);
250
+ if (woo_feed_is_debugging_enabled()) {
251
+ 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
252
+ woo_feed_log_feed_process($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request));
253
+ 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
254
+ woo_feed_log($this->config['filename'], sprintf('WP_Query Request ::' . PHP_EOL . '%s', $query->request), 'info');
255
  }
256
+ return $query->get_posts();
257
+ }
258
 
259
+ /**
260
+ * Get products
261
+ *
262
+ * @return array
263
+ */
264
+ public function query_products()
265
+ {
266
+ $products = [];
267
+ if ('wc' == $this->queryType) {
268
+ $products = $this->get_wc_query_products();
269
+ } elseif ('wp' == $this->queryType) {
270
+ $products = $this->get_wp_query_products();
271
+ } elseif ('both' == $this->queryType) {
272
+ $wc = $this->get_wc_query_products();
273
+ $wp = $this->get_wp_query_products();
274
+ $products = array_unique(array_merge($wc, $wp));
275
+ }
276
 
277
+ return $products;
278
+ }
279
 
280
+ /**
281
+ * Organize Feed Attribute config
282
+ * @return array|bool
283
+ */
284
+ public function get_attribute_config()
285
+ {
286
+ if (empty($this->config)) {
287
+ return false;
288
+ }
289
 
290
+ $attributeConfig = array();
291
+ $merchantAttributes = $this->config['mattributes'];
292
+ if (!empty($merchantAttributes)) {
293
+ $i = 0;
294
+ foreach ($merchantAttributes as $key => $value) {
295
+ $attributeConfig[$i]['mattributes'] = $value;
296
+ $attributeConfig[$i]['prefix'] = $this->config['prefix'][$key];
297
+ $attributeConfig[$i]['type'] = $this->config['type'][$key];
298
+ $attributeConfig[$i]['attributes'] = $this->config['attributes'][$key];
299
+ $attributeConfig[$i]['default'] = $this->config['default'][$key];
300
+ $attributeConfig[$i]['suffix'] = $this->config['suffix'][$key];
301
+ $attributeConfig[$i]['output_type'] = $this->config['output_type'][$key];
302
+ $attributeConfig[$i]['limit'] = $this->config['limit'][$key];
303
+ $i++;
304
+ }
305
+ }
306
+
307
+ return $attributeConfig;
308
+ }
309
+
310
+ /**
311
+ * Get Product Information according to feed config
312
+ *
313
+ * @param int[] $productIds
314
+ *
315
+ * @return array
316
+ * @since 3.2.0
317
+ *
318
+ */
319
+ public function get_products($productIds)
320
+ {
321
+
322
+ if (empty($productIds)) {
323
+ return [];
324
+ }
325
+
326
+ /**
327
+ * Fires before looping through request product for getting product data
328
+ *
329
+ * @param int[] $productIds
330
+ * @param array $feedConfig
331
+ *
332
+ * @since 3.2.10
333
+ */
334
+ do_action('woo_feed_before_product_loop', $productIds, $this->config);
335
+
336
+ foreach ($productIds as $key => $pid) {
337
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Loading Product Data For %d.', $pid));
338
+ $product = wc_get_product($pid);
339
+
340
+ if ($this->exclude_from_loop($product)) {
341
+ continue;
342
+ }
343
+
344
+ if ($this->process_variation($product)) {
345
+ continue;
346
+ }
347
 
348
+ if (!$this->filter_product($product)) {
349
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Matched with filter conditions');
350
+ continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  }
352
 
353
+ woo_feed_log_feed_process($this->config['filename'], 'Formatting Feed Data...');
354
+
355
+ // Add Single item wrapper before product info loop start
356
+ if ('xml' == $this->config['feedType']) {
357
+ $this->feedBody .= "\n";
358
+ $this->feedBody .= '<' . $this->config['itemWrapper'] . '>';
359
+ $this->feedBody .= "\n";
360
  }
361
 
362
+ // reset processed attribute list before loop
363
+ $this->processed_merchant_attributes = [];
364
+ // Process attribute values
365
+ $this->process_attributes($product);
366
+
367
+ try {
368
+ woo_feed_log_feed_process($this->config['filename'], 'Processing Merchant Specific Fields');
369
+ // Process feed data for uncommon merchant feed like Google,Facebook,Pinterest
370
+ $this->process_for_merchant($product, $this->pi);
371
+ } catch (Exception $e) {
372
+ $message = 'Error Processing Merchant Specific Fields.' . PHP_EOL . 'Caught Exception :: ' . $e->getMessage();
373
+ woo_feed_log($this->config['filename'], $message, 'critical', $e, true);
374
+ woo_feed_log_fatal_error($message, $e);
375
  }
376
 
377
+ if ('xml' == $this->config['feedType']) {
378
+ if (empty($this->feedHeader)) {
379
+ $this->feedHeader = $this->process_xml_feed_header();
380
+ $this->feedFooter = $this->process_xml_feed_footer();
381
+
382
+ }
383
+
384
+ $this->feedBody .= '</' . $this->config['itemWrapper'] . '>';
385
+
386
+
387
+ } elseif ('txt' == $this->config['feedType']) {
388
+ if (empty($this->feedHeader)) {
389
+ $this->process_txt_feed_header();
390
+ }
391
+ $this->process_txt_feed_body();
392
+ } else {
393
+ if (empty($this->feedHeader)) {
394
+ $this->process_csv_feed_header();
395
+ }
396
+ $this->process_csv_feed_body();
397
  }
398
+ woo_feed_log_feed_process($this->config['filename'], 'Done Formatting...');
399
+ $this->pi++;
400
+ }
401
+
402
+ /**
403
+ * Fires after looping through request product for getting product data
404
+ *
405
+ * @param int[] $productIds
406
+ * @param array $feedConfig
407
+ *
408
+ * @since 3.2.10
409
+ */
410
+ do_action('woo_feed_after_product_loop', $productIds, $this->config);
411
+
412
+ return $this->products;
413
+ }
414
 
415
+ /**
416
+ * Process product variations
417
+ * @param WC_Abstract_Legacy_Product $product
418
+ *
419
+ * @return bool
420
+ * @since 3.3.9
421
+ */
422
+ protected function process_variation($product)
423
+ {
424
+ // Apply variable and variation settings
425
+ if ($product->is_type('variable') && $product->has_child()) {
426
+ $this->pi++;
427
+ $variations = $product->get_visible_children();
428
+ if (is_array($variations) && (sizeof($variations) > 0)) {
429
+ if (woo_feed_is_debugging_enabled()) {
430
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Getting Variation Product(s) :: %s', implode(', ', $variations)));
431
  }
432
+ $this->get_products($variations);
433
+ return false;
434
+ }
435
+ }
436
+ return false;
437
+ }
438
+
439
+ /**
440
+ * Process The Attributes and assign value to merchant attribute
441
+ *
442
+ * @param WC_Abstract_Legacy_Product $product
443
+ *
444
+ * @return void
445
+ * @since 3.3.9
446
+ */
447
+ protected function process_attributes($product)
448
+ {
449
+ // Get Product Attribute values by type and assign to product array
450
+ foreach ($this->config['attributes'] as $attr_key => $attribute) {
451
+
452
+ $merchant_attribute = $this->config['mattributes'][$attr_key];
453
+
454
+ if ($this->exclude_current_attribute($product, $merchant_attribute, $attribute)) {
455
+ continue;
456
  }
457
 
458
+ // Add Prefix and Suffix into Output
459
+ $prefix = $this->config['prefix'][$attr_key];
460
+ $suffix = $this->config['suffix'][$attr_key];
461
+ $merchant = $this->config['provider'];
462
+ $feedType = $this->config['feedType'];
463
+
464
+ if ('pattern' == $this->config['type'][$attr_key]) {
465
+ $attributeValue = $this->config['default'][$attr_key];
466
+ } else { // Get Pattern value
467
+ $attributeValue = $this->getAttributeValueByType($product, $attribute);
468
+ }
469
+
470
+ // Format Output according to Output Type config.
471
+ if (isset($this->config['output_type'][$attr_key])) {
472
+ $outputType = $this->config['output_type'][$attr_key];
473
+ $attributeValue = $this->format_output($attributeValue, $this->config['output_type'][$attr_key], $product, $attribute);
474
+ }
475
+
476
+ // Limit Output.
477
+ if (isset($this->config['limit'][$attr_key])) {
478
+ $attributeValue = $this->crop_string($attributeValue, 0, $this->config['limit'][$attr_key]);
479
+ }
480
+
481
+ // Process prefix and suffix.
482
+ $attributeValue = $this->process_prefix_suffix($attributeValue, $prefix, $suffix, $attribute);
483
+
484
+ if ('xml' == $feedType) {
485
+
486
+ // Replace XML Nodes according to merchant requirement.
487
+ $getReplacedAttribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
488
+
489
+ // XML does not support space in node. So replace Space with Underscore.
490
+ $getReplacedAttribute = str_replace(' ', '_', $getReplacedAttribute);
491
+
492
+ if (!empty($attributeValue)) {
493
+ $attributeValue = trim($attributeValue);
494
+ }
495
+
496
+ // Add closing XML node if value is empty
497
+ if ('' != $attributeValue) {
498
+ // Add CDATA wrapper for XML feed to prevent XML error.
499
+ $attributeValue = woo_feed_add_cdata($merchant_attribute, $attributeValue, $merchant);
500
+
501
+ // TODO Move to proper place
502
+ // Replace Google Color attribute value according to requirements
503
+ if ('g:color' == $getReplacedAttribute) {
504
+ $attributeValue = str_replace(', ', '/', $attributeValue);
505
+ }
506
+
507
+ // Strip slash from output
508
+ $attributeValue = stripslashes($attributeValue);
509
+
510
+ $this->feedBody .= '<' . $getReplacedAttribute . '>' . "$attributeValue" . '</' . $getReplacedAttribute . '>';
511
+ $this->feedBody .= "\n";
512
+
513
+ } else {
514
+ $this->feedBody .= '<' . $getReplacedAttribute . '/>';
515
+ $this->feedBody .= "\n";
516
  }
517
+ } elseif ('csv' == $feedType) {
518
+ $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
519
+ $merchant_attribute = $this->processStringForCSV($merchant_attribute);
520
+ $attributeValue = $this->processStringForCSV($attributeValue);
521
+ } elseif ('txt' == $feedType) {
522
+ $merchant_attribute = woo_feed_replace_to_merchant_attribute($merchant_attribute, $merchant, $feedType);
523
+ $merchant_attribute = $this->processStringForTXT($merchant_attribute);
524
+ $attributeValue = $this->processStringForTXT($attributeValue);
525
+ }
526
+
527
+ $this->products[$this->pi][$merchant_attribute] = $attributeValue;
528
+ }
529
+ }
530
+
531
+ /**
532
+ * Check if current product should be processed for feed
533
+ * This should be using by Woo_Feed_Products_v3::get_products()
534
+ *
535
+ * @param WC_Product $product
536
+ *
537
+ * @return bool
538
+ * @since 3.3.9
539
+ *
540
+ */
541
+ protected function exclude_from_loop($product)
542
+ {
543
+ // For WP_Query check available product types
544
+ if ('wp' == $this->queryType && !in_array($product->get_type(), $this->product_types)) {
545
+ woo_feed_log_feed_process($this->config['filename'], sprintf('Skipping Product :: Invalid Post/Product Type : %s.', $product->get_type()));
546
+ return true;
547
+ }
548
+
549
+ // Skip for invalid products
550
+ if (!is_object($product)) {
551
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product data is not a valid WC_Product object.');
552
+ return true;
553
+ }
554
+
555
+ // Skip for invisible products
556
+ if (!$product->is_visible()) {
557
+ woo_feed_log_feed_process($this->config['filename'], 'Skipping Product :: Product is not visible.');
558
+ return true;
559
+ }
560
+ return false;
561
+ }
562
+
563
+ /**
564
+ * Check if current attribute/merchant attribute should be processed for feed
565
+ * This should be using by Woo_Feed_Products_v3::get_products()
566
+ *
567
+ * @param WC_Product $product
568
+ * @param string $merchant_attribute
569
+ * @param string $product_attribute
570
+ * @param string $feedType
571
+ *
572
+ * @return bool
573
+ *
574
+ * @since 3.3.9
575
+ *
576
+ */
577
+ protected function exclude_current_attribute($product, $merchant_attribute, $product_attribute, $feedType = 'xml')
578
+ {
579
+ if (
580
+ $feedType == $this->config['feedType'] &&
581
+ in_array($this->config['provider'], array_keys($this->skipped_merchant_attributes)) &&
582
+ in_array($merchant_attribute, $this->skipped_merchant_attributes[$this->config['provider']])
583
+
584
+ ) {
585
+ return true;
586
+ }
587
+
588
+ if (in_array($merchant_attribute, $this->processed_merchant_attributes)) {
589
+ return true;
590
+ }
591
+
592
+ $this->processed_merchant_attributes[] = $merchant_attribute;
593
+
594
+ return false;
595
+ }
596
+
597
+ /**
598
+ * Wrapper for substr with <![CDATA[string]]> support
599
+ *
600
+ * @see substr
601
+ *
602
+ * @param string $string
603
+ * @param int $start
604
+ * @param int $limit
605
+ *
606
+ * @return string
607
+ */
608
+ protected function crop_string($string, $start = 0, $limit = null)
609
+ {
610
+ $limit = absint($limit);
611
+ if ($limit > 0) {
612
+ $start = absint($start);
613
+ if (strpos($string, '<![CDATA[') !== false) {
614
+ $string = str_replace(array('<![CDATA[', ']]>'), array('', ''), $string);
615
+ $string = substr($string, $start, $limit);
616
+ $string = '<![CDATA[' . $string . ']]>';
617
+ } else {
618
+ $string = substr($string, $start, $limit);
619
  }
620
+ }
621
+ return $string;
622
+ }
623
+
624
+ /**
625
+ * Process feed data according to merchant uncommon requirements like Google
626
+ *
627
+ * @param $productObj WC_Product
628
+ * @param $index | Product Index
629
+ *
630
+ * @since 3.2.0
631
+ *
632
+ */
633
+ protected function process_for_merchant($productObj, $index)
634
+ {
635
+ $product = $this->products[$index];
636
+ $merchantAttributes = $this->config['mattributes'];
637
+
638
+ // Format Shipping and Tax data for CSV and TXT feed only for google and facebook
639
+ if ('xml' != $this->config['feedType'] && in_array($this->config['provider'], ['google', 'facebook'])) {
640
+
641
+ $shipping = array();
642
+ $tax = array();
643
+ $installment = array();
644
+ $s = 0; // Shipping Index
645
+ $t = 0; // Tax Index
646
+ $i = 0; // Installment Index
647
+ $shippingAttr = array(
648
+ 'shipping_country',
649
+ 'shipping_service',
650
+ 'shipping_price',
651
+ 'shipping_region',
652
+ 'tax_country',
653
+ 'tax_region',
654
+ 'tax_rate',
655
+ 'tax_ship',
656
+ );
657
+ foreach ($this->products[$this->pi] as $attribute => $value) {
658
+ if (in_array($attribute, $shippingAttr)) {
659
+
660
+ if ('tax_country' == $attribute) {
661
+ $t++;
662
+ $tax[$t] .= $value . ':';
663
+ } elseif ('tax_region' == $attribute) {
664
+ $tax[$t] .= $value . ':';
665
+ } elseif ('tax_rate' == $attribute) {
666
+ $tax[$t] .= $value . ':';
667
+ } elseif ('tax_ship' == $attribute) {
668
+ $tax[$t] .= $value . ':';
669
+ }
670
+
671
+ if ('shipping_country' == $attribute) {
672
+ $s++;
673
+ $shipping[$s] .= $value . ':';
674
+ } elseif ('shipping_service' == $attribute) {
675
+ $shipping[$s] .= $value . ':';
676
+ } elseif ('shipping_price' == $attribute) {
677
+ $shipping[$s] .= $value . ':';
678
+ } elseif ('shipping_region' == $attribute) {
679
+ $shipping[$s] .= $value . ':';
680
+ }
681
 
682
+ unset($this->products[$this->pi][$attribute]);
 
 
 
 
683
  }
684
  }
685
 
686
+ foreach ($shipping as $key => $val) {
687
+ $this->products[$this->pi]['shipping(country:region:service:price)'] = $val;
688
+ }
689
+
690
+ foreach ($tax as $key => $val) {
691
+ $this->products[$this->pi]['tax(country:region:rate:tax_ship)'] = $val;
692
+ }
693
+ }
694
+
695
+ if ('google' == $this->config['provider']) {
696
+
697
+ // Reformat Shipping attributes for google, facebook
698
+ $s = 0;
699
+ $t = 0;
700
+ $tax = '';
701
+ $shipping = '';
702
+ if ('xml' == $this->config['feedType']) {
703
+ foreach ($merchantAttributes as $key => $value) {
704
+
705
+ if (!in_array($value, $this->google_shipping_tax)) {
706
+ continue;
707
+ }
708
+
709
+ $prefix = $this->config['prefix'][$key];
710
+ $suffix = $this->config['suffix'][$key];
711
+
712
+ if ('pattern' == $this->config['type'][$key]) {
713
+ $output = $this->config['default'][$key];
714
+ } else { // Get Pattern value.
715
+ $attribute = $this->config['attributes'][$key];
716
+ $output = $this->getAttributeValueByType($productObj, $attribute);
717
+ }
718
+
719
+ if (false !== strpos($value, 'price') || false !== strpos($value, 'rate')) {
720
+ $suffix = '' . $suffix;
721
  }
722
+
723
+
724
+ $output = $prefix . $output . $suffix;
725
+
726
+ if ('shipping_country' == $value) {
727
+ if (0 == $s) {
728
+ $shipping .= '<g:shipping>';
729
+ $s = 1;
730
+ } else {
731
+ $shipping .= '</g:shipping>' . "\n";
732
+ $shipping .= '<g:shipping>';
733
+ }
734
+ } elseif (!in_array('shipping_country', $merchantAttributes) && 'shipping_price' == $value) {
735
+ if (0 == $s) {
736
+ $shipping .= '<g:shipping>';
737
+ $s = 1;
738
+ } else {
739
+ $shipping .= '</g:shipping>' . "\n";
740
+ $shipping .= '<g:shipping>';
741
+ }
742
+ }
743
+
744
+ if ('shipping_country' == $value) {
745
+ $shipping .= '<g:country>' . $output . '</g:country>' . "\n";
746
+ } elseif ('shipping_region' == $value) {
747
+ $shipping .= '<g:region>' . $output . '</g:region>' . "\n";
748
+ } elseif ('shipping_service' == $value) {
749
+ $shipping .= '<g:service>' . $output . '</g:service>' . "\n";
750
+ } elseif ('shipping_price' == $value) {
751
+ $shipping .= '<g:price>' . $output . '</g:price>' . "\n";
752
+ } elseif ('tax_country' == $value) {
753
+ if (0 == $t) {
754
+ $tax .= '<g:tax>';
755
+ $t = 1;
756
+ } else {
757
+ $tax .= '</g:tax>' . "\n";
758
+ $tax .= '<g:tax>';
759
+ }
760
+ $tax .= '<g:country>' . $output . '</g:country>' . "\n";
761
+ } elseif ('tax_region' == $value) {
762
+ $tax .= '<g:region>' . $output . '</g:region>' . "\n";
763
+ } elseif ('tax_rate' == $value) {
764
+ $tax .= '<g:rate>' . $output . '</g:rate>' . "\n";
765
+ } elseif ('tax_ship' == $value) {
766
+ $tax .= '<g:tax_ship>' . $output . '</g:tax_ship>' . "\n";
767
+ }
768
+ }
769
+
770
+ if (1 == $s) {
771
+ $shipping .= '</g:shipping>';
772
+ }
773
+ if (1 == $t) {
774
+ $tax .= '</g:tax>';
775
  }
776
+
777
+ $this->feedBody .= $shipping;
778
+ $this->feedBody .= $tax;
779
  }
780
+ // ADD g:identifier_exists
781
+ $identifier = array('brand', 'upc', 'sku', 'mpn', 'gtin');
782
+ $countIdentifier = 0;
783
+ if (!in_array('identifier_exists', $merchantAttributes)) {
784
+ if (count(array_intersect_key(array_flip($identifier), $product)) >= 2) {
785
+ // Any 2 required keys exist!
786
+ // @TODO Refactor with OR
787
+ if (array_key_exists('brand', $product) && !empty($product['brand'])) {
788
+ $countIdentifier++;
789
+ }
790
+ if (array_key_exists('upc', $product) && !empty($product['upc'])) {
791
+ $countIdentifier++;
792
+ }
793
+ if (array_key_exists('sku', $product) && !empty($product['sku'])) {
794
+ $countIdentifier++;
795
+ }
796
+ if (array_key_exists('mpn', $product) && !empty($product['mpn'])) {
797
+ $countIdentifier++;
798
+ }
799
+ if (array_key_exists('gtin', $product) && !empty($product['gtin'])) {
800
+ $countIdentifier++;
801
+ }
802
+ }
803
 
804
+ if ('xml' == $this->config['feedType']) {
805
+ if ($countIdentifier >= 2) {
806
+ $this->feedBody .= '<g:identifier_exists>yes</g:identifier_exists>';
807
+ } else {
808
+ $this->feedBody .= '<g:identifier_exists>no</g:identifier_exists>';
809
+ }
810
+ } else {
811
+ if ($countIdentifier >= 2) {
812
+ $this->products[$this->pi]['identifier exists'] = 'yes';
813
+ } else {
814
+ $this->products[$this->pi]['identifier exists'] = 'no';
815
  }
816
  }
817
  }
818
+ }
819
+ }
820
+
821
+ /**
822
+ * Get Query Type Settings
823
+ * @return string
824
+ */
825
+ public function get_query_type()
826
+ {
827
+ return $this->queryType;
828
+ }
829
+
830
+ public function get_product_types()
831
+ {
832
+ return $this->product_types;
833
+ }
834
+
835
+ /**
836
+ * Generate TXT Feed Header
837
+ *
838
+ * @return string
839
+ * @since 3.2.0
840
+ *
841
+ */
842
+ protected function process_txt_feed_header()
843
+ {
844
+ // Set Delimiter
845
+ if ('tab' == $this->config['delimiter']) {
846
+ $this->delimiter = "\t";
847
+ } else {
848
+ $this->delimiter = $this->config['delimiter'];
849
+ }
850
+
851
+ // Set Enclosure
852
+ if (!empty($this->config['enclosure'])) {
853
+ $this->enclosure = $this->config['enclosure'];
854
+ if ('double' == $this->enclosure) {
855
+ $this->enclosure = '"';
856
+ } elseif ('single' == $this->enclosure) {
857
+ $this->enclosure = "'";
858
+ } else {
859
+ $this->enclosure = '';
860
+ }
861
+ } else {
862
+ $this->enclosure = '';
863
+ }
864
+
865
+ $eol = PHP_EOL;
866
+ if ('trovaprezzi' === $this->config['provider']) {
867
+ $eol = '<endrecord>' . PHP_EOL;
868
+ }
869
+
870
+ $product = $this->products[$this->pi];
871
+ $headers = array_keys($product);
872
+ $this->feedHeader .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $headers) . $this->enclosure . $eol;
873
+
874
+ return $this->feedHeader;
875
+ }
876
+
877
+ /**
878
+ * Generate TXT Feed Body
879
+ *
880
+ * @return string
881
+ * @since 3.2.0
882
+ *
883
+ */
884
+ protected function process_txt_feed_body()
885
+ {
886
+ $productInfo = array_values($this->products[$this->pi]);
887
+ $eol = PHP_EOL;
888
+ if ('trovaprezzi' === $this->config['provider']) {
889
+ $eol = '<endrecord>' . PHP_EOL;
890
+ }
891
+ $this->feedBody .= $this->enclosure . implode("$this->enclosure$this->delimiter$this->enclosure", $productInfo) . $this->enclosure . $eol;
892
+
893
+ return $this->feedBody;
894
+ }
895
+
896
+ /**
897
+ * Generate CSV Feed Header
898
+ *
899
+ * @return array
900
+ * @since 3.2.0
901
+ *
902
+ */
903
+ protected function process_csv_feed_header()
904
+ {
905
+ // Set Delimiter
906
+ if ('tab' == $this->config['delimiter']) {
907
+ $this->delimiter = "\t";
908
+ } else {
909
+ $this->delimiter = $this->config['delimiter'];
910
+ }
911
+
912
+ // Set Enclosure
913
+ if (!empty($this->config['enclosure'])) {
914
+ $this->enclosure = $this->config['enclosure'];
915
+ if ('double' == $this->enclosure) {
916
+ $this->enclosure = '"';
917
+ } elseif ('single' == $this->enclosure) {
918
+ $this->enclosure = "'";
919
+ } else {
920
+ $this->enclosure = '';
921
+ }
922
+ } else {
923
+ $this->enclosure = '';
924
+ }
925
+
926
+ $product = $this->products[$this->pi];
927
+ $this->feedHeader = array_keys($product);
928
+
929
+ return $this->feedHeader;
930
+ }
931
+
932
+ /**
933
+ * Generate CSV Feed Body
934
+ * @return array
935
+ * @since 3.2.0
936
+ */
937
+ protected function process_csv_feed_body()
938
+ {
939
+ $product = $this->products[$this->pi];
940
+ $this->feedBody[] = array_values($product);
941
+
942
+ return $this->feedBody;
943
+ }
944
+
945
+ protected function process_xml_wrapper()
946
+ {
947
+
948
+ $this->xml_wrapper = [
949
+ 'header' => '<?xml version="1.0" encoding="UTF-8" ?>' . PHP_EOL . '<' . $this->config['itemsWrapper'] . '>',
950
+ 'footer' => PHP_EOL . '</' . $this->config['itemsWrapper'] . '>',
951
+ ];
952
+ $this->config['itemWrapper'] = str_replace(' ', '_', $this->config['itemWrapper']);
953
+ $this->config['itemsWrapper'] = str_replace(' ', '_', $this->config['itemsWrapper']);
954
+
955
+ if (file_exists(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt')) {
956
+ $txt = file_get_contents(WOO_FEED_FREE_ADMIN_PATH . 'partials/templates/' . $this->config['provider'] . '.txt');
957
+ $txt = trim($txt);
958
+ $txt = explode('{separator}', $txt);
959
+ if (2 === count($txt)) {
960
+ $this->xml_wrapper['header'] = trim($txt[0]);
961
+ $this->xml_wrapper['footer'] = trim($txt[1]);
962
+ }
963
+ }
964
+
965
+ if (!empty($this->config['extraHeader'])) {
966
+ $this->xml_wrapper['header'] .= PHP_EOL . $this->config['extraHeader'];
967
+ }
968
+
969
+ // replace template variables.
970
+ $datetime_now = gmdate('Y-m-d H:i:s'); // {DateTimeNow}
971
+ $blog_name = get_bloginfo('name'); // {BlogName}
972
+ $blog_url = get_bloginfo('url'); // {BlogURL}
973
+ $blog_desc = get_bloginfo('description'); // {BlogDescription}
974
+ $blog_email = get_bloginfo('admin_email'); // {BlogEmail}
975
+
976
+ $this->xml_wrapper['header'] = str_replace(
977
+ ['{DateTimeNow}', '{BlogName}', '{BlogURL}', '{BlogDescription}', '{BlogEmail}'],
978
+ [$datetime_now, $blog_name, $blog_url, $blog_desc, $blog_email],
979
+ $this->xml_wrapper['header']
980
+ );
981
+ }
982
+
983
+ /**
984
+ * Make XML feed header
985
+ * @return string
986
+ * @since 3.2.0
987
+ */
988
+ protected function process_xml_feed_header()
989
+ {
990
+ return $this->xml_wrapper['header'];
991
+ }
992
+
993
+ /**
994
+ * Make XML feed header
995
+ * @return string
996
+ * @since 3.2.0
997
+ */
998
+ protected function process_xml_feed_footer()
999
+ {
1000
+ return $this->xml_wrapper['footer'];
1001
+ }
1002
+
1003
+ /**
1004
+ * Process string for TXT CSV Feed
1005
+ *
1006
+ * @param $string
1007
+ *
1008
+ * @return mixed|string
1009
+ * @since 3.2.0
1010
+ *
1011
+ */
1012
+ protected function processStringForTXT($string)
1013
+ {
1014
+ if (!empty($string)) {
1015
+ $string = html_entity_decode($string, ENT_HTML401 | ENT_QUOTES); // Convert any HTML entities
1016
+
1017
+ if (stristr($string, '"')) {
1018
+ $string = str_replace('"', '""', $string);
1019
+ }
1020
+ $string = str_replace("\n", ' ', $string);
1021
+ $string = str_replace("\r", ' ', $string);
1022
+ $string = str_replace("\t", ' ', $string);
1023
+ $string = trim($string);
1024
+ $string = stripslashes($string);
1025
+
1026
+ return $string;
1027
+ } elseif ('0' == $string) {
1028
+ return '0';
1029
+ } else {
1030
+ return '';
1031
+ }
1032
+ }
1033
+
1034
+ /**
1035
+ * Process string for CSV
1036
+ *
1037
+ * @param $string
1038
+ *
1039
+ * @return mixed|string
1040
+ * @since 3.2.0
1041
+ *
1042
+ */
1043
+ protected function processStringForCSV($string)
1044
+ {
1045
+ if (!empty($string)) {
1046
+ $string = str_replace("\n", ' ', $string);
1047
+ $string = str_replace("\r", ' ', $string);
1048
+ $string = trim($string);
1049
+ $string = stripslashes($string);
1050
+
1051
+ return $string;
1052
+ } elseif ('0' == $string) {
1053
+ return '0';
1054
+ } else {
1055
+ return '';
1056
+ }
1057
+ }
1058
+
1059
+ /**
1060
+ * Get Product Attribute Value by Type
1061
+ *
1062
+ * @param $product WC_Product
1063
+ * @param $attribute
1064
+ *
1065
+ * @return mixed|string
1066
+ * @since 3.2.0
1067
+ *
1068
+ */
1069
+ protected function getAttributeValueByType($product, $attribute)
1070
+ {
1071
+
1072
+ if (method_exists($this, $attribute)) {
1073
+ $output = call_user_func_array(array($this, $attribute), array($product));
1074
+ } elseif (false !== strpos($attribute, self::PRODUCT_ATTRIBUTE_PREFIX)) {
1075
+ $attribute = str_replace(self::PRODUCT_ATTRIBUTE_PREFIX, '', $attribute);
1076
+ $output = $this->getProductAttribute($product, $attribute);
1077
+ } elseif (false !== strpos($attribute, self::POST_META_PREFIX)) {
1078
+ $attribute = str_replace(self::POST_META_PREFIX, '', $attribute);
1079
+ $output = $this->getProductMeta($product, $attribute);
1080
+ } elseif (false !== strpos($attribute, self::PRODUCT_TAXONOMY_PREFIX)) {
1081
+ $attribute = str_replace(self::PRODUCT_TAXONOMY_PREFIX, '', $attribute);
1082
+ $output = $this->getProductTaxonomy($product, $attribute);
1083
+ } elseif ('image_' == substr($attribute, 0, 6)) {
1084
+ // For additional image method images() will be used with extra parameter - image number
1085
+ $imageKey = explode('_', $attribute);
1086
+ if (!isset($imageKey[1]) || (isset($imageKey[1]) && (empty($imageKey[1]) || !is_numeric($imageKey[1])))) {
1087
+ $imageKey[1] = '';
1088
+ }
1089
+ $output = call_user_func_array(array($this, 'images'), array($product, $imageKey[1]));
1090
+ } else {
1091
+ // return the attribute so multiple attribute can be join with separator to make custom attribute.
1092
+ $output = $attribute;
1093
+ }
1094
+
1095
+ // Json encode if value is an array
1096
+ if (is_array($output)) {
1097
+ $output = wp_json_encode($output);
1098
+ }
1099
+
1100
+ /**
1101
+ * Filter attribute value
1102
+ *
1103
+ * @param string $output the output
1104
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1105
+ * @param array feed config/rule
1106
+ *
1107
+ * @since 3.4.3
1108
+ *
1109
+ */
1110
+ $output = apply_filters('woo_feed_get_attribute', $output, $product, $this->config);
1111
+
1112
+ /**
1113
+ * Filter attribute value before return based on attribute name
1114
+ *
1115
+ * @param string $output the output
1116
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1117
+ * @param array feed config/rule
1118
+ *
1119
+ * @since 3.3.5
1120
+ *
1121
+ */
1122
+ $output = apply_filters("woo_feed_get_{$attribute}_attribute", $output, $product, $this->config);
1123
+
1124
+ /**
1125
+ * Filter attribute value before return based on merchant and attribute name
1126
+ *
1127
+ * @param string $output the output
1128
+ * @param WC_Abstract_Legacy_Product $product Product Object.
1129
+ * @param array feed config/rule
1130
+ *
1131
+ * @since 3.3.7
1132
+ *
1133
+ */
1134
+ $output = apply_filters("woo_feed_get_{$this->config['provider']}_{$attribute}_attribute", $output, $product, $this->config);
1135
+
1136
+ return $output;
1137
+ }
1138
+
1139
+ /**
1140
+ * Get Product Id
1141
+ *
1142
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1143
+ *
1144
+ * @return mixed
1145
+ * @since 3.2.0
1146
+ */
1147
+ protected function id($product)
1148
+ {
1149
+ return $product->get_id();
1150
+ }
1151
+
1152
+ /**
1153
+ * Get Product Title
1154
+ *
1155
+ * @param WC_Product $product
1156
+ *
1157
+ * @return mixed
1158
+ * @since 3.2.0
1159
+ *
1160
+ */
1161
+ protected function title($product)
1162
+ {
1163
+ return $product->get_name();
1164
+ }
1165
+
1166
+ /**
1167
+ * Get Yoast Product Title
1168
+ *
1169
+ * @param WC_Product $product
1170
+ *
1171
+ * @return mixed
1172
+ * @since 3.2.0
1173
+ *
1174
+ */
1175
+ protected function yoast_wpseo_title($product)
1176
+ {
1177
+ $yoast_title = get_post_meta($product->get_id(), '_yoast_wpseo_title', true);
1178
+ if (strpos($yoast_title, '%%') !== false) {
1179
+ $title = strstr($yoast_title, '%%', true);
1180
+ if (empty($title)) {
1181
+ $title = get_the_title($product->get_id());
1182
+ }
1183
+ $wpseo_titles = get_option('wpseo_titles');
1184
+
1185
+ $sep_options = WPSEO_Option_Titles::get_instance()->get_separator_options();
1186
+ if (isset($wpseo_titles['separator']) && isset($sep_options[$wpseo_titles['separator']])) {
1187
+ $sep = $sep_options[$wpseo_titles['separator']];
1188
+ } else {
1189
+ $sep = '-'; //setting default separator if Admin didn't set it from backed
1190
+ }
1191
+
1192
+ $site_title = get_bloginfo('name');
1193
+
1194
+ $meta_title = $title . ' ' . $sep . ' ' . $site_title;
1195
+
1196
+ if (!empty($meta_title)) {
1197
+ return $meta_title;
1198
+ }
1199
+ }elseif (!empty($yoast_title)){
1200
+ return $yoast_title;
1201
+ }
1202
+
1203
+ // $title = '';
1204
+ // if ( class_exists( 'WPSEO_Frontend' ) ) {
1205
+ // $title = WPSEO_Frontend::get_instance()->get_seo_title( get_post( $product->get_id() ) );
1206
+ // }
1207
+ // if ( ! empty( $title ) ) {
1208
+ // return $title;
1209
+ // }
1210
+
1211
+ return $this->title($product);
1212
+ }
1213
+
1214
+ /**
1215
+ * Get All In One Product Title
1216
+ *
1217
+ * @param WC_Product $product
1218
+ *
1219
+ * @return mixed
1220
+ * @since 3.2.0
1221
+ *
1222
+ */
1223
+ protected function _aioseop_title($product)
1224
+ {
1225
+ $title = '';
1226
+ if (class_exists('All_in_One_SEO_Pack')) {
1227
+ global $aioseop_options, $aiosp;
1228
+ if (!is_array($aioseop_options)) {
1229
+ $aioseop_options = get_option('aioseop_options');
1230
+ }
1231
+ if (!($aiosp instanceof All_in_One_SEO_Pack)) {
1232
+ $aiosp = new All_in_One_SEO_Pack();
1233
+ }
1234
+
1235
+ if (in_array('product', $aioseop_options['aiosp_cpostactive'], true)) {
1236
+ if (!empty($aioseop_options['aiosp_rewrite_titles'])) {
1237
+ $title = $aiosp->get_aioseop_title(get_post($product->get_id()));
1238
+ $title = $aiosp->apply_cf_fields($title);
1239
+ }
1240
+ $title = apply_filters('aioseop_title', $title);
1241
+ }
1242
+ }
1243
+ if (!empty($title)) {
1244
+ return $title;
1245
+ }
1246
+
1247
+ return $this->title($product);
1248
+ }
1249
+
1250
+ /**
1251
+ * Get Product Description
1252
+ *
1253
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1254
+ *
1255
+ * @return mixed|string
1256
+ * @since 3.2.0
1257
+ *
1258
+ */
1259
+ protected function description($product)
1260
+ {
1261
+
1262
+ $description = $product->get_description();
1263
+
1264
+ // Get Variation Description
1265
+ if ($product->is_type('variation') && empty($description)) {
1266
+ $parent = wc_get_product($product->get_parent_id());
1267
+ $description = $parent->get_description();
1268
+ }
1269
+ $description = $this->remove_short_codes($description);
1270
+
1271
+ // Add variations attributes after description to prevent Facebook error
1272
+ if ('facebook' == $this->config['provider']) {
1273
+ $variationInfo = explode('-', $product->get_name());
1274
+ if (isset($variationInfo[1])) {
1275
+ $extension = $variationInfo[1];
1276
+ } else {
1277
+ $extension = $product->get_id();
1278
+ }
1279
+ $description .= ' ' . $extension;
1280
+ }
1281
+
1282
+ return $description;
1283
+ }
1284
+
1285
+ /**
1286
+ * Get Yoast Product Description
1287
+ *
1288
+ * @param WC_Product $product
1289
+ *
1290
+ * @return mixed
1291
+ * @since 3.2.0
1292
+ *
1293
+ */
1294
+ protected function yoast_wpseo_metadesc($product)
1295
+ {
1296
+ $description = '';
1297
+ if (class_exists('WPSEO_Frontend')) {
1298
+ $description = wpseo_replace_vars(WPSEO_Meta::get_value('metadesc', $product->get_id()),
1299
+ get_post($product->get_id()));
1300
+ }
1301
+ if (!empty($description)) {
1302
+ return $description;
1303
+ }
1304
+
1305
+ return $this->description($product);
1306
+ }
1307
+
1308
+ /**
1309
+ * Get All In One Product Description
1310
+ *
1311
+ * @param WC_Product $product
1312
+ *
1313
+ * @return mixed
1314
+ * @since 3.2.0
1315
+ *
1316
+ */
1317
+ protected function _aioseop_description($product)
1318
+ {
1319
+ $description = '';
1320
+ if (class_exists('All_in_One_SEO_Pack')) {
1321
+ global $aioseop_options, $aiosp;
1322
+ if (!is_array($aioseop_options)) {
1323
+ $aioseop_options = get_option('aioseop_options');
1324
+ }
1325
+ if (!($aiosp instanceof All_in_One_SEO_Pack)) {
1326
+ $aiosp = new All_in_One_SEO_Pack();
1327
+ }
1328
+ if (in_array('product', $aioseop_options['aiosp_cpostactive'], true)) {
1329
+ $description = $aiosp->get_main_description(get_post($product->get_id())); // Get the description.
1330
+ $description = $aiosp->trim_description($description);
1331
+ $description = apply_filters('aioseop_description_full',
1332
+ $aiosp->apply_description_format($description, get_post($product->get_id())));
1333
+ }
1334
+ }
1335
+ if (!empty($description)) {
1336
+ return $description;
1337
+ }
1338
+
1339
+ return $this->description($product);
1340
+ }
1341
+
1342
+ /**
1343
+ * Get Product Short Description
1344
+ *
1345
+ * @param WC_Product $product
1346
+ *
1347
+ * @return mixed|string
1348
+ * @since 3.2.0
1349
+ *
1350
+ */
1351
+ protected function short_description($product)
1352
+ {
1353
+
1354
+ $short_description = $product->get_short_description();
1355
+
1356
+ // Get Variation Short Description
1357
+ if ($product->is_type('variation') && empty($short_description)) {
1358
+ $parent = wc_get_product($product->get_parent_id());
1359
+ $short_description = $parent->get_short_description();
1360
+ }
1361
+
1362
+
1363
+ $short_description = $this->remove_short_codes($short_description);
1364
+
1365
+ return $short_description;
1366
+ }
1367
+
1368
+
1369
+ /**
1370
+ * At First convert Short Codes and then Remove failed Short Codes from String
1371
+ *
1372
+ * @param $content
1373
+ *
1374
+ * @return mixed|string
1375
+ * @since 3.2.0
1376
+ *
1377
+ */
1378
+ protected function remove_short_codes($content)
1379
+ {
1380
+ if (empty($content)) {
1381
+ return '';
1382
+ }
1383
+
1384
+ // Remove DIVI Builder Short Codes
1385
+ if (class_exists('ET_Builder_Module') || defined('ET_BUILDER_PLUGIN_VERSION')) {
1386
+ /** @noinspection RegExpRedundantEscape */
1387
+ $content = preg_replace('/\[\/?et_pb.*?\]/', '', $content);
1388
+ }
1389
+
1390
+ $content = do_shortcode($content);
1391
+
1392
+ $content = woo_feed_stripInvalidXml($content);
1393
+
1394
+ return strip_shortcodes($content);
1395
+ }
1396
+
1397
+ /**
1398
+ * Get Product Main Category
1399
+ *
1400
+ * @param WC_Product $product
1401
+ *
1402
+ * @return string
1403
+ *
1404
+ */
1405
+ protected function primary_category($product)
1406
+ {
1407
+ $id = $product->get_id();
1408
+ if ($product->is_type('variation')) {
1409
+ $id = $product->get_parent_id();
1410
+ }
1411
+ $wpseo_primary_term = false;
1412
+ $main_category = '';
1413
+ if (class_exists('WPSEO_Primary_Term')) {
1414
+ $wpseo_primary_term = new WPSEO_Primary_Term('product_cat', $id);
1415
+ $main_category = $wpseo_primary_term->get_primary_term();
1416
+ $main_category = get_term($main_category, 'product_cat');
1417
+ }
1418
+ if (!($wpseo_primary_term instanceof WPSEO_Primary_Term) || empty($main_category)) {
1419
+ $term = wp_get_post_terms($id, 'product_cat');
1420
+ if (!is_wp_error($term) && !empty($term)) {
1421
+ $main_category = $term[0];
1422
+ }
1423
+ }
1424
+
1425
+ return $main_category instanceof WP_Term ? $main_category->name : '';
1426
+ }
1427
+
1428
+ /**
1429
+ * Get Product Categories
1430
+ *
1431
+ * @param WC_Product $product
1432
+ *
1433
+ * @return string
1434
+ * @since 3.2.0
1435
+ *
1436
+ */
1437
+ protected function product_type($product)
1438
+ {
1439
+ $id = $product->get_id();
1440
+ if ($product->is_type('variation')) {
1441
+ $id = $product->get_parent_id();
1442
+ }
1443
+
1444
+ $separator = apply_filters('woo_feed_product_type_separator', '>', $this->config, $product);
1445
+
1446
+ return wp_strip_all_tags(wc_get_product_category_list($id, $separator, ''));
1447
+ }
1448
+
1449
+ /**
1450
+ * Get Product URL
1451
+ *
1452
+ * @param WC_Product $product
1453
+ *
1454
+ * @return string
1455
+ * @since 3.2.0
1456
+ *
1457
+ */
1458
+ protected function link($product)
1459
+ {
1460
+ $utm = $this->config['campaign_parameters'];
1461
+ if (!empty($utm['utm_source']) && !empty($utm['utm_medium']) && !empty($utm['utm_campaign'])) {
1462
+ $utm = [
1463
+ 'utm_source' => $utm['utm_source'],
1464
+ 'utm_medium' => $utm['utm_medium'],
1465
+ 'utm_campaign' => $utm['utm_campaign'],
1466
+ 'utm_term' => $utm['utm_term'],
1467
+ 'utm_content' => $utm['utm_content'],
1468
+ ];
1469
+
1470
+ return add_query_arg(array_filter($utm), $product->get_permalink());
1471
+ }
1472
+
1473
+ return $product->get_permalink();
1474
+ }
1475
+
1476
+ /**
1477
+ * Get External Product URL
1478
+ *
1479
+ * @param WC_Product $product
1480
+ *
1481
+ * @return string
1482
+ * @since 3.2.0
1483
+ *
1484
+ */
1485
+ protected function ex_link($product)
1486
+ {
1487
+ if ($product->is_type('external')) {
1488
+ return $product->get_product_url();
1489
+ }
1490
+
1491
+ return '';
1492
+ }
1493
+
1494
+ /**
1495
+ * Get Product Image
1496
+ *
1497
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1498
+ *
1499
+ * @return mixed
1500
+ * @since 3.2.0
1501
+ *
1502
+ */
1503
+ protected function image($product)
1504
+ {
1505
+ if ($product->is_type('variation')) {
1506
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_id()),
1507
+ 'single-post-thumbnail');
1508
+ if (has_post_thumbnail($product->get_id()) && !empty($getImage[0])) :
1509
+ $image = woo_feed_get_formatted_url($getImage[0]);
1510
+ else :
1511
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_parent_id()),
1512
+ 'single-post-thumbnail');
1513
+ $image = woo_feed_get_formatted_url($getImage[0]);
1514
+ endif;
1515
+ } else {
1516
+ if (has_post_thumbnail($product->get_id())) :
1517
+ $getImage = wp_get_attachment_image_src(get_post_thumbnail_id($product->get_id()),
1518
+ 'single-post-thumbnail');
1519
+ $image = woo_feed_get_formatted_url($getImage[0]);
1520
+ else :
1521
+ $image = woo_feed_get_formatted_url(wp_get_attachment_url($product->get_id()));
1522
+ endif;
1523
+ }
1524
+
1525
+ return $image;
1526
+ }
1527
+
1528
+ /**
1529
+ * Get Product Featured Image
1530
+ *
1531
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1532
+ *
1533
+ * @return mixed
1534
+ * @since 3.2.0
1535
+ *
1536
+ */
1537
+ protected function feature_image($product)
1538
+ {
1539
+ return $this->image($product);
1540
+ }
1541
+
1542
+ /**
1543
+ * Get Comma Separated Product Images
1544
+ *
1545
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product Product Object.
1546
+ * @param string $additionalImg Specific Additional Image.
1547
+ *
1548
+ * @return mixed
1549
+ * @since 3.2.0
1550
+ *
1551
+ */
1552
+ protected function images($product, $additionalImg = '')
1553
+ {
1554
+ if ($product->is_type('variation')) {
1555
+ // TODO Test Variation Images
1556
+ $imgUrls = $this->get_product_gallery(wc_get_product($product->get_parent_id()));
1557
+ } else {
1558
+ $imgUrls = $this->get_product_gallery($product);
1559
+ }
1560
+
1561
+ // Return Specific Additional Image URL
1562
+ if ('' != $additionalImg) {
1563
+ if (array_key_exists($additionalImg, $imgUrls)) {
1564
+ return $imgUrls[$additionalImg];
1565
+ } else {
1566
+ return '';
1567
+ }
1568
+ }
1569
+
1570
+ return implode(',', array_filter($imgUrls));
1571
+ }
1572
+
1573
+ /**
1574
+ * Get Product Gallery Items (URL) array.
1575
+ * This can contains empty array values
1576
+ *
1577
+ * @param WC_Product|WC_Product_Variable|WC_Product_Variation|WC_Product_Grouped|WC_Product_External|WC_Product_Composite $product
1578
+ *
1579
+ * @return string[]
1580
+ * @since 3.2.6
1581
+ */
1582
+ protected function get_product_gallery($product)
1583
+ {
1584
+ $attachmentIds = $product->get_gallery_image_ids();
1585
+ $imgUrls = array();
1586
+ if ($attachmentIds && is_array($attachmentIds)) {
1587
+ $mKey = 1;
1588
+ foreach ($attachmentIds as $attachmentId) {
1589
+ $imgUrls[$mKey] = woo_feed_get_formatted_url(wp_get_attachment_url($attachmentId));
1590
+ $mKey++;
1591
+ }
1592
+ }
1593
+
1594
+ return $imgUrls;
1595
+ }
1596
+
1597
+ /**
1598
+ * Get Product Condition
1599
+ *
1600
+ * @param WC_Product $product
1601
+ *
1602
+ * @return mixed
1603
+ * @since 3.2.0
1604
+ *
1605
+ */
1606
+ protected function condition($product)
1607
+ {
1608
+ return apply_filters('woo_feed_product_condition', 'new', $product);
1609
+ }
1610
+
1611
+ /**
1612
+ * Get Product Type
1613
+ *
1614
+ * @param WC_Product $product
1615
+ *
1616
+ * @return mixed
1617
+ * @since 3.2.0
1618
+ *
1619
+ */
1620
+ protected function type($product)
1621
+ {
1622
+ return $product->get_type();
1623
+ }
1624
+
1625
+ /**
1626
+ * Get Product is a bundle product or not
1627
+ *
1628
+ * @param WC_Product $product
1629
+ *
1630
+ * @return mixed
1631
+ * @since 3.2.0
1632
+ *
1633
+ */
1634
+ protected function is_bundle($product)
1635
+ {
1636
+ if ($product->is_type('bundle') || $product->is_type('yith_bundle')) {
1637
+ return 'yes';
1638
+ }
1639
+
1640
+ return 'no';
1641
+ }
1642
+
1643
+ /**
1644
+ * Get Product is a multi-pack product or not
1645
+ *
1646
+ * @param WC_Product $product
1647
+ *
1648
+ * @return mixed
1649
+ * @since 3.2.0
1650
+ *
1651
+ */
1652
+ protected function multipack($product)
1653
+ {
1654
+ $multi_pack = '';
1655
+ if ($product->is_type('grouped')) {
1656
+ $multi_pack = (!empty($product->get_children())) ? count($product->get_children()) : '';
1657
+ }
1658
+
1659
+ return $multi_pack;
1660
+ }
1661
+
1662
+ /**
1663
+ * Get Product visibility status
1664
+ *
1665
+ * @param WC_Product $product
1666
+ *
1667
+ * @return mixed
1668
+ * @since 3.2.0
1669
+ *
1670
+ */
1671
+ protected function visibility($product)
1672
+ {
1673
+ return $product->get_catalog_visibility();
1674
+ }
1675
+
1676
+ /**
1677
+ * Get Product Total Rating
1678
+ *
1679
+ * @param WC_Product $product
1680
+ *
1681
+ * @return mixed
1682
+ * @since 3.2.0
1683
+ *
1684
+ */
1685
+ protected function rating_total($product)
1686
+ {
1687
+ return $product->get_rating_count();
1688
+ }
1689
+
1690
+ /**
1691
+ * Get Product average rating
1692
+ *
1693
+ * @param WC_Product $product
1694
+ *
1695
+ * @return mixed
1696
+ * @since 3.2.0
1697
+ *
1698
+ */
1699
+ protected function rating_average($product)
1700
+ {
1701
+ return $product->get_average_rating();
1702
+ }
1703
+
1704
+ /**
1705
+ * Get Product tags
1706
+ *
1707
+ * @param WC_Product $product
1708
+ *
1709
+ * @return string
1710
+ * @since 3.2.0
1711
+ *
1712
+ */
1713
+ protected function tags($product)
1714
+ {
1715
+ $id = $product->get_id();
1716
+ if ($product->is_type('variation')) {
1717
+ $id = $product->get_parent_id();
1718
+ }
1719
+
1720
+ /**
1721
+ * Separator for multiple tags
1722
+ * @param string $separator
1723
+ * @param array $config
1724
+ * @param WC_Abstract_Legacy_Product $product
1725
+ * @since 3.4.3
1726
+ */
1727
+ $separator = apply_filters('woo_feed_tags_separator', ',', $this->config, $product);
1728
+
1729
+ return wp_strip_all_tags(get_the_term_list($id, 'product_tag', '', $separator, ''));
1730
+ }
1731
+
1732
+ /**
1733
+ * Get Product Parent Id
1734
+ *
1735
+ * @param WC_Product $product
1736
+ *
1737
+ * @return mixed
1738
+ * @since 3.2.0
1739
+ *
1740
+ */
1741
+ protected function item_group_id($product)
1742
+ {
1743
+ $id = $product->get_id();
1744
+ if ($product->is_type('variation')) {
1745
+ $id = $product->get_parent_id();
1746
+ }
1747
+
1748
+ return $id;
1749
+ }
1750
+
1751
+ /**
1752
+ * Get Product SKU
1753
+ *
1754
+ * @param WC_Product $product
1755
+ *
1756
+ * @return mixed
1757
+ * @since 3.2.0
1758
+ *
1759
+ */
1760
+ protected function sku($product)
1761
+ {
1762
+ return $product->get_sku();
1763
+ }
1764
+
1765
+ /**
1766
+ * Get Product Parent SKU
1767
+ *
1768
+ * @param WC_Product $product
1769
+ *
1770
+ * @return mixed
1771
+ * @since 3.2.0
1772
+ *
1773
+ */
1774
+ protected function parent_sku($product)
1775
+ {
1776
+ if ($product->is_type('variation')) {
1777
+ $id = $product->get_parent_id();
1778
+ $parent = wc_get_product($id);
1779
+
1780
+ return $parent->get_sku();
1781
+ }
1782
+
1783
+ return $product->get_sku();
1784
+ }
1785
+
1786
+ /**
1787
+ * Get Product Availability Status
1788
+ *
1789
+ * @param WC_Product $product
1790
+ *
1791
+ * @return mixed
1792
+ * @since 3.2.0
1793
+ *
1794
+ */
1795
+ protected function availability($product)
1796
+ {
1797
+ $status = $product->get_stock_status();
1798
+ if ('instock' == $status) {
1799
+ return 'in stock';
1800
+ } elseif ('outofstock' == $status) {
1801
+ return 'out of stock';
1802
+ } elseif ('onbackorder' == $status) {
1803
+ return 'on backorder';
1804
+ } else {
1805
+ return 'in stock';
1806
+ }
1807
+ }
1808
+
1809
+ /**
1810
+ * Get Product Quantity
1811
+ *
1812
+ * @param WC_Product $product
1813
+ *
1814
+ * @return mixed
1815
+ * @since 3.2.0
1816
+ *
1817
+ */
1818
+ protected function quantity($product)
1819
+ {
1820
+ if ($product->is_type('variable') && $product->has_child()) {
1821
+ $visible_children = $product->get_visible_children();
1822
+ $qty = array();
1823
+ foreach ($visible_children as $key => $child) {
1824
+ $childQty = get_post_meta($child, '_stock', true);
1825
+ $qty[] = (int)$childQty + 0;
1826
+ }
1827
+
1828
+ if (isset($this->config['variable_quantity'])) {
1829
+ $vaQty = $this->config['variable_quantity'];
1830
+ if ('max' == $vaQty) {
1831
+ return max($qty);
1832
+ } elseif ('min' == $vaQty) {
1833
+ return min($qty);
1834
+ } elseif ('sum' == $vaQty) {
1835
+ return array_sum($qty);
1836
+ } elseif ('first' == $vaQty) {
1837
+ return ((int)$qty[0]);
1838
+ }
1839
+
1840
+ return array_sum($qty);
1841
+ }
1842
+ }
1843
+
1844
+ return $product->get_stock_quantity();
1845
+ }
1846
+
1847
+ /**
1848
+ * Get Product Sale Price Start Date
1849
+ *
1850
+ * @param WC_Product $product
1851
+ *
1852
+ * @return mixed
1853
+ * @since 3.2.0
1854
+ *
1855
+ */
1856
+ protected function sale_price_sdate($product)
1857
+ {
1858
+ $startDate = $product->get_date_on_sale_from();
1859
+ if (is_object($startDate)) {
1860
+ return $startDate->date_i18n();
1861
+ }
1862
+
1863
+ return '';
1864
+ }
1865
+
1866
+ /**
1867
+ * Get Product Sale Price End Date
1868
+ *
1869
+ * @param WC_Product $product
1870
+ *
1871
+ * @return mixed
1872
+ * @since 3.2.0
1873
+ *
1874
+ */
1875
+ protected function sale_price_edate($product)
1876
+ {
1877
+ $endDate = $product->get_date_on_sale_to();
1878
+ if (is_object($endDate)) {
1879
+ return $endDate->date_i18n();
1880
+ }
1881
+
1882
+ return '';
1883
+ }
1884
+
1885
+ /**
1886
+ * Get Product Regular Price
1887
+ *
1888
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
1889
+ *
1890
+ * @return mixed
1891
+ * @since 3.2.0
1892
+ *
1893
+ */
1894
+ protected function price($product)
1895
+ {
1896
+ if ($product->is_type('variable')) {
1897
+ return $this->getVariableProductPrice($product, 'regular_price');
1898
+ } elseif ($product->is_type('grouped')) {
1899
+ return $this->getGroupProductPrice($product,
1900
+ 'regular'); // this calls self::price() so no need to use self::getWPMLPrice()
1901
+ } else {
1902
+ return $product->get_regular_price();
1903
+ }
1904
+ }
1905
+
1906
+ /**
1907
+ * Get Product Price
1908
+ *
1909
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1910
+ *
1911
+ * @return int|float|double|mixed
1912
+ * @since 3.2.0
1913
+ *
1914
+ */
1915
+ protected function current_price($product)
1916
+ {
1917
+ if ($product->is_type('variable')) {
1918
+ return $this->getVariableProductPrice($product, 'price');
1919
+ } elseif ($product->is_type('grouped')) {
1920
+ return $this->getGroupProductPrice($product, 'current');
1921
+ } else {
1922
+ return $product->get_price();
1923
+ }
1924
+ }
1925
+
1926
+ /**
1927
+ * Get Product Sale Price
1928
+ *
1929
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1930
+ *
1931
+ * @return mixed
1932
+ * @since 3.2.0
1933
+ *
1934
+ */
1935
+ protected function sale_price($product)
1936
+ {
1937
+ if ($product->is_type('variable')) {
1938
+ return $this->getVariableProductPrice($product, 'sale_price');
1939
+ } elseif ($product->is_type('grouped')) {
1940
+ return $this->getGroupProductPrice($product, 'sale');
1941
+ } else {
1942
+ $price = $product->get_sale_price();
1943
+
1944
+ return $price > 0 ? $price : '';
1945
+ }
1946
+ }
1947
+
1948
+ /**
1949
+ * Get Product Regular Price with Tax
1950
+ *
1951
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product Product Object.
1952
+ *
1953
+ * @return mixed
1954
+ * @since 3.2.0
1955
+ *
1956
+ */
1957
+ protected function price_with_tax($product)
1958
+ {
1959
+ if ($product->is_type('variable')) {
1960
+ return $this->getVariableProductPrice($product, 'regular_price', true);
1961
+ } elseif ($product->is_type('grouped')) {
1962
+ return $this->getGroupProductPrice($product, 'regular', true);
1963
+ } else {
1964
+ $price = $this->price($product);
1965
+
1966
+ // Get price with tax.
1967
+ return ($product->is_taxable() && !empty($price)) ? $this->get_price_with_tax($product,
1968
+ $price) : $price;
1969
+ }
1970
+ }
1971
+
1972
+ /**
1973
+ * Get Product Regular Price with Tax
1974
+ *
1975
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
1976
+ *
1977
+ * @return mixed
1978
+ * @since 3.2.0
1979
+ *
1980
+ */
1981
+ protected function current_price_with_tax($product)
1982
+ {
1983
+ if ($product->is_type('variable')) {
1984
+ return $this->getVariableProductPrice($product, 'current_price', true);
1985
+ } elseif ($product->is_type('grouped')) {
1986
+ return $this->getGroupProductPrice($product, 'current', true);
1987
+ } else {
1988
+ $price = $this->current_price($product);
1989
+
1990
+ // Get price with tax
1991
+ return ($product->is_taxable() && !empty($price)) ? $this->get_price_with_tax($product,
1992
+ $price) : $price;
1993
+ }
1994
+ }
1995
+
1996
+ /**
1997
+ * Get Product Regular Price with Tax
1998
+ *
1999
+ * @param WC_Product|WC_Product_Variable|WC_Product_Grouped $product
2000
+ *
2001
+ * @return mixed
2002
+ * @since 3.2.0
2003
+ *
2004
+ */
2005
+ protected function sale_price_with_tax($product)
2006
+ {
2007
+ if ($product->is_type('variable')) {
2008
+ return $this->getVariableProductPrice($product, 'sale_price', true);
2009
+ } elseif ($product->is_type('grouped')) {
2010
+ return $this->getGroupProductPrice($product, 'sale', true);
2011
+ } else {
2012
+ $price = $this->sale_price($product);
2013
+ if ($product->is_taxable() && !empty($price)) {
2014
+ $price = $this->get_price_with_tax($product, $price);
2015
+ }
2016
+
2017
+ return $price > 0 ? $price : '';
2018
+ }
2019
+ }
2020
+
2021
+ /**
2022
+ * Get total price of grouped product
2023
+ *
2024
+ * @param WC_Product_Grouped $grouped
2025
+ * @param string $type
2026
+ * @param bool $tax
2027
+ *
2028
+ * @return int|string
2029
+ * @since 3.2.0
2030
+ *
2031
+ */
2032
+ protected function getGroupProductPrice($grouped, $type, $tax = false)
2033
+ {
2034
+ $groupProductIds = $grouped->get_children();
2035
+ $sum = 0;
2036
+ if (!empty($groupProductIds)) {
2037
+ foreach ($groupProductIds as $id) {
2038
+ $product = wc_get_product($id);
2039
+
2040
+ if (!is_object($product)) {
2041
+ continue; // make sure that the product exists..
2042
+ }
2043
+
2044
+ if ($tax) {
2045
+ if ('regular' == $type) {
2046
+ $regularPrice = $this->price_with_tax($product);
2047
+ $sum += (float)$regularPrice;
2048
+ } elseif ('current' == $type) {
2049
+ $currentPrice = $this->current_price_with_tax($product);
2050
+ $sum += (float)$currentPrice;
2051
+ } else {
2052
+ $salePrice = $this->sale_price_with_tax($product);
2053
+ $sum += (float)$salePrice;
2054
+ }
2055
+ } else {
2056
+ if ('regular' == $type) {
2057
+ $regularPrice = $this->price($product);
2058
+ $sum += (float)$regularPrice;
2059
+ } elseif ('current' == $type) {
2060
+ $currentPrice = $this->current_price($product);
2061
+ $sum += (float)$currentPrice;
2062
+ } else {
2063
+ $salePrice = $this->sale_price($product);
2064
+ $sum += (float)$salePrice;
2065
+ }
2066
+ }
2067
+ }
2068
+ }
2069
+
2070
+ if ('sale' == $type) {
2071
+ $sum = $sum > 0 ? $sum : '';
2072
+ }
2073
+
2074
+ return $sum;
2075
+ }
2076
+
2077
+ /**
2078
+ * Get total price of variable product
2079
+ *
2080
+ * @param WC_Product_Variable $variable
2081
+ * @param string $type regular_price, sale_price & current_price
2082
+ * @param bool $tax calculate tax
2083
+ *
2084
+ * @return int|string
2085
+ * @since 3.2.0
2086
+ *
2087
+ */
2088
+ protected function getVariableProductPrice($variable, $type, $tax = false)
2089
+ {
2090
+ $price = 0;
2091
+ if ('regular_price' == $type) {
2092
+ $price = $variable->get_variation_regular_price();
2093
+ } elseif ('sale_price' == $type) {
2094
+ $price = $variable->get_variation_sale_price();
2095
+ } else {
2096
+ $price = $variable->get_variation_price();
2097
+ }
2098
+ if (true === $tax && $variable->is_taxable()) {
2099
+ $price = $this->get_price_with_tax($variable, $price);
2100
+ }
2101
+ if ('sale_price' != $type) {
2102
+ $price = $price > 0 ? $price : '';
2103
+ }
2104
+
2105
+ return $price;
2106
+ }
2107
+
2108
+ /**
2109
+ * Return product price with tax
2110
+ *
2111
+ * @param WC_Product $product Product.
2112
+ * @param float $price Price.
2113
+ *
2114
+ * @return float|string
2115
+ * @since 3.2.0
2116
+ *
2117
+ */
2118
+ protected function get_price_with_tax($product, $price)
2119
+ {
2120
+ if (woo_feed_wc_version_check(3.0)) {
2121
+ return wc_get_price_including_tax($product, array('price' => $price));
2122
+ } else {
2123
+ return $product->get_price_including_tax(1, $price);
2124
+ }
2125
+ }
2126
+
2127
+ /**
2128
+ * Get Product Weight
2129
+ *
2130
+ * @param WC_Product $product
2131
+ *
2132
+ * @return mixed
2133
+ * @since 3.2.0
2134
+ *
2135
+ */
2136
+ protected function weight($product)
2137
+ {
2138
+ return $product->get_weight();
2139
+ }
2140
+
2141
+ /**
2142
+ * Get Product Width
2143
+ *
2144
+ * @param WC_Product $product
2145
+ *
2146
+ * @return mixed
2147
+ * @since 3.2.0
2148
+ *
2149
+ */
2150
+ protected function width($product)
2151
+ {
2152
+ return $product->get_width();
2153
+ }
2154
+
2155
+ /**
2156
+ * Get Product Height
2157
+ *
2158
+ * @param WC_Product $product
2159
+ *
2160
+ * @return mixed
2161
+ * @since 3.2.0
2162
+ *
2163
+ */
2164
+ protected function height($product)
2165
+ {
2166
+ return $product->get_height();
2167
+ }
2168
+
2169
+ /**
2170
+ * Get Product Length
2171
+ *
2172
+ * @param WC_Product $product
2173
+ *
2174
+ * @return mixed
2175
+ * @since 3.2.0
2176
+ *
2177
+ */
2178
+ protected function length($product)
2179
+ {
2180
+ return $product->get_length();
2181
+ }
2182
+
2183
+ /**
2184
+ * Get Product Shipping Class
2185
+ *
2186
+ * @param WC_Product $product
2187
+ *
2188
+ * @return mixed
2189
+ * @since 3.2.0
2190
+ *
2191
+ */
2192
+ protected function shipping_class($product)
2193
+ {
2194
+ return $product->get_shipping_class();
2195
+ }
2196
+
2197
+ /**
2198
+ * Get Product Author Name
2199
+ *
2200
+ * @param WC_Product $product
2201
+ *
2202
+ * @return mixed
2203
+ * @since 3.2.0
2204
+ *
2205
+ */
2206
+ protected function author_name($product)
2207
+ {
2208
+ $post = get_post($product->get_id());
2209
+
2210
+ return get_the_author_meta('user_login', $post->post_author);
2211
+ }
2212
+
2213
+ /**
2214
+ * Get Product Author Email
2215
+ *
2216
+ * @param WC_Product $product
2217
+ *
2218
+ * @return mixed
2219
+ * @since 3.2.0
2220
+ *
2221
+ */
2222
+ protected function author_email($product)
2223
+ {
2224
+ $post = get_post($product->get_id());
2225
+
2226
+ return get_the_author_meta('user_email', $post->post_author);
2227
+ }
2228
+
2229
+ /**
2230
+ * Get Product Created Date
2231
+ *
2232
+ * @param WC_Product $product
2233
+ *
2234
+ * @return mixed
2235
+ * @since 3.2.0
2236
+ *
2237
+ */
2238
+ protected function date_created($product)
2239
+ {
2240
+ return gmdate('Y-m-d', strtotime($product->get_date_created()));
2241
+ }
2242
+
2243
+ /**
2244
+ * Get Product Last Updated Date
2245
+ *
2246
+ * @param WC_Product $product
2247
+ *
2248
+ * @return mixed
2249
+ * @since 3.2.0
2250
+ *
2251
+ */
2252
+ protected function date_updated($product)
2253
+ {
2254
+ return gmdate('Y-m-d', strtotime($product->get_date_modified()));
2255
+ }
2256
+
2257
+ /**
2258
+ * Get Product Sale Price Effected Date for Google Shopping
2259
+ *
2260
+ * @param WC_Product $product
2261
+ *
2262
+ * @return string
2263
+ * @since 3.2.0
2264
+ *
2265
+ */
2266
+ protected function sale_price_effective_date($product)
2267
+ {
2268
+ $effective_date = '';
2269
+ $from = $this->sale_price_sdate($product);
2270
+ $to = $this->sale_price_edate($product);
2271
+ if (!empty($from) && !empty($to)) {
2272
+ $from = gmdate('c', strtotime($from));
2273
+ $to = gmdate('c', strtotime($to));
2274
+
2275
+ $effective_date = $from . '/' . $to;
2276
+ }
2277
+
2278
+ return $effective_date;
2279
+ }
2280
+
2281
+ /**
2282
+ * Ger Product Attribute
2283
+ *
2284
+ * @param WC_Product $product
2285
+ * @param $attr
2286
+ *
2287
+ * @return string
2288
+ * @since 2.2.3
2289
+ *
2290
+ */
2291
+ protected function getProductAttribute($product, $attr)
2292
+ {
2293
+ $id = $product->get_id();
2294
+
2295
+ if (woo_feed_wc_version_check(3.2)) {
2296
+ if (woo_feed_wc_version_check(3.6)) {
2297
+ $attr = str_replace('pa_', '', $attr);
2298
+ }
2299
+ $value = $product->get_attribute($attr);
2300
+
2301
+ return $value;
2302
+ } else {
2303
+ return implode(',', wc_get_product_terms($id, $attr, array('fields' => 'names')));
2304
+ }
2305
+ }
2306
+
2307
+ /**
2308
+ * Get Meta
2309
+ *
2310
+ * @param WC_Product $product
2311
+ * @param string $meta post meta key
2312
+ *
2313
+ * @return mixed|string
2314
+ * @since 2.2.3
2315
+ *
2316
+ */
2317
+ protected function getProductMeta($product, $meta)
2318
+ {
2319
+ $value = get_post_meta($product->get_id(), $meta, true);
2320
+ // if empty get meta value of parent post
2321
+ if ('' == $value && $product->get_parent_id()) {
2322
+ $value = get_post_meta($product->get_parent_id(), $meta, true);
2323
+ }
2324
+
2325
+ return $value;
2326
+ }
2327
+
2328
+ /**
2329
+ * Filter Products by Conditions
2330
+ *
2331
+ * @param WC_Product $product
2332
+ *
2333
+ * @return bool|array
2334
+ * @since 3.2.0
2335
+ *
2336
+ */
2337
+ public function filter_product($product)
2338
+ {
2339
+ return true;
2340
+ }
2341
+
2342
+ /**
2343
+ * Get Taxonomy
2344
+ *
2345
+ * @param WC_Product $product
2346
+ * @param $taxonomy
2347
+ *
2348
+ * @return string
2349
+ * @since 2.2.3
2350
+ *
2351
+ */
2352
+ protected function getProductTaxonomy($product, $taxonomy)
2353
+ {
2354
+ $id = $product->get_id();
2355
+ if ($product->is_type('variation')) {
2356
+ $id = $product->get_parent_id();
2357
+ }
2358
+
2359
+ $separator = apply_filters('woo_feed_product_taxonomy_term_list_separator', ',', $this->config, $product);
2360
+
2361
+ return wp_strip_all_tags(get_the_term_list($id, $taxonomy, '', $separator, ''));
2362
+ }
2363
+
2364
+ /**
2365
+ * Format price value
2366
+ *
2367
+ * @param string $name Attribute Name
2368
+ * @param int $conditionName condition
2369
+ * @param int $result price
2370
+ *
2371
+ * @return mixed
2372
+ * @since 3.2.0
2373
+ *
2374
+ */
2375
+ protected function price_format($name, $conditionName, $result)
2376
+ {
2377
+ $plus = '+';
2378
+ $minus = '-';
2379
+ $percent = '%';
2380
+
2381
+ if (strpos($name, 'price') !== false) {
2382
+ if (strpos($result, $plus) !== false && strpos($result, $percent) !== false) {
2383
+ $result = str_replace('+', '', $result);
2384
+ $result = str_replace('%', '', $result);
2385
+ if (is_numeric($result)) {
2386
+ $result = $conditionName + (($conditionName * $result) / 100);
2387
+ }
2388
+ } elseif (strpos($result, $minus) !== false && strpos($result, $percent) !== false) {
2389
+ $result = str_replace('-', '', $result);
2390
+ $result = str_replace('%', '', $result);
2391
+ if (is_numeric($result)) {
2392
+ $result = $conditionName - (($conditionName * $result) / 100);
2393
+ }
2394
+ } elseif (strpos($result, $plus) !== false) {
2395
+ $result = str_replace('+', '', $result);
2396
+ if (is_numeric($result)) {
2397
+ $result = ($conditionName + $result);
2398
+ }
2399
+ } elseif (strpos($result, $minus) !== false) {
2400
+ $result = str_replace('-', '', $result);
2401
+ if (is_numeric($result)) {
2402
+ $result = $conditionName - $result;
2403
+ }
2404
+ }
2405
+ }
2406
+
2407
+ return $result;
2408
+ }
2409
+
2410
+ /**
2411
+ * Format output According to Output Type config
2412
+ *
2413
+ * @param string $output
2414
+ * @param array $outputTypes
2415
+ * @param WC_Product $product
2416
+ * @param string $productAttribute
2417
+ *
2418
+ * @return float|int|string
2419
+ * @since 3.2.0
2420
+ *
2421
+ */
2422
+ protected function format_output($output, $outputTypes, $product, $productAttribute)
2423
+ {
2424
+ if (!empty($outputTypes) && is_array($outputTypes)) {
2425
+
2426
+ // Format Output According to output type
2427
+ if (in_array(2, $outputTypes)) { // Strip Tags
2428
+ $output = wp_strip_all_tags(html_entity_decode($output));
2429
+ }
2430
+
2431
+ if (in_array(3, $outputTypes)) { // UTF-8 Encode
2432
+ $output = utf8_encode($output);
2433
+ }
2434
+
2435
+ if (in_array(4, $outputTypes)) { // htmlentities
2436
+ $output = htmlentities($output, ENT_QUOTES, 'UTF-8');
2437
+ }
2438
+
2439
+ if (in_array(5, $outputTypes)) { // Integer
2440
+ $output = intval($output);
2441
+ }
2442
+
2443
+ if (in_array(6, $outputTypes)) { // Format Price
2444
+ if (!empty($output) && $output > 0) {
2445
+ $output = (float)$output;
2446
+ $output = number_format($output, 2, '.', '');
2447
+ }
2448
+ }
2449
+
2450
+ if (in_array(7, $outputTypes)) { // Delete Space
2451
+ $output = trim($output);
2452
+ $output = preg_replace('!\s+!', ' ', $output);
2453
+ }
2454
+
2455
+ if (in_array(9, $outputTypes)) { // Remove Invalid Character
2456
+ $output = woo_feed_stripInvalidXml($output);
2457
+ }
2458
+
2459
+ if (in_array(10, $outputTypes)) { // Remove ShortCodes
2460
+ $output = $this->remove_short_codes($output);
2461
+ }
2462
+
2463
+ if (in_array(11, $outputTypes)) {
2464
+ $output = ucwords(strtolower($output));
2465
+ }
2466
+
2467
+ if (in_array(12, $outputTypes)) {
2468
+ $output = ucfirst(strtolower($output));
2469
+ }
2470
+
2471
+ if (in_array(13, $outputTypes)) {
2472
+ $output = strtoupper(strtolower($output));
2473
+ }
2474
+
2475
+ if (in_array(14, $outputTypes)) {
2476
+ $output = strtolower($output);
2477
+ }
2478
+
2479
+ if (in_array(15, $outputTypes)) {
2480
+ if ('http' == substr($output, 0, 4)) {
2481
+ $output = str_replace('http://', 'https://', $output);
2482
+ }
2483
+ }
2484
+
2485
+ if (in_array(16, $outputTypes)) {
2486
+ if ('http' == substr($output, 0, 4)) {
2487
+ $output = str_replace('https://', 'http://', $output);
2488
+ }
2489
+ }
2490
+
2491
+ if (in_array(17, $outputTypes)) { // only parent
2492
+ if ($product->is_type('variation')) {
2493
+ $id = $product->get_parent_id();
2494
+ $parentProduct = wc_get_product($id);
2495
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute);
2496
+ }
2497
+ }
2498
+
2499
+ if (in_array(18, $outputTypes)) { // child if parent empty
2500
+ if ($product->is_type('variation')) {
2501
+ $id = $product->get_parent_id();
2502
+ $parentProduct = wc_get_product($id);
2503
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute);
2504
+ if (empty($output)) {
2505
+ $output = $this->getAttributeValueByType($product, $productAttribute);
2506
+ }
2507
+ }
2508
+ }
2509
+
2510
+ if (in_array(19, $outputTypes)) { // parent if child empty
2511
+ if ($product->is_type('variation')) {
2512
+ $output = $this->getAttributeValueByType($product, $productAttribute);
2513
+ if (empty($output)) {
2514
+ $id = $product->get_parent_id();
2515
+ $parentProduct = wc_get_product($id);
2516
+ $output = $this->getAttributeValueByType($parentProduct, $productAttribute);
2517
+ }
2518
+ }
2519
+ }
2520
+
2521
+ if (in_array(8, $outputTypes) && !empty($output)) { // Add CDATA
2522
+ $output = '<![CDATA[' . $output . ']]>';
2523
+ }
2524
+ }
2525
+
2526
+ return $output;
2527
+ }
2528
+
2529
+ /**
2530
+ * Add Prefix and Suffix with attribute value
2531
+ *
2532
+ * @param $output
2533
+ * @param $prefix
2534
+ * @param $suffix
2535
+ * @param $attribute
2536
+ *
2537
+ * @return string
2538
+ * @since 3.2.0
2539
+ *
2540
+ */
2541
+ public function process_prefix_suffix($output, $prefix, $suffix, $attribute = '')
2542
+ {
2543
+
2544
+ if ('' == $output) {
2545
+ return $output;
2546
+ }
2547
+
2548
+ // Add Prefix before Output
2549
+ if ('' != $prefix) {
2550
+ $output = "$prefix" . $output;
2551
+ }
2552
+
2553
+ // Add Suffix after Output
2554
+ if ('' !== $suffix) {
2555
+ if (
2556
+ 'price' == $attribute
2557
+ || 'sale_price' == $attribute
2558
+ || 'current_price' == $attribute
2559
+ || 'price_with_tax' == $attribute
2560
+ || 'current_price_with_tax' == $attribute
2561
+ || 'sale_price_with_tax' == $attribute
2562
+ || 'shipping_price' == $attribute
2563
+ || 'tax_rate' == $attribute
2564
+ ) { // Add space before suffix if attribute contain price.
2565
+ $output = $output . ' ' . $suffix;
2566
+ } elseif (substr($output, 0, 4) === 'http') {
2567
+ // Parse URL Parameters if available into suffix field
2568
+ $output = woo_feed_make_url_with_parameter($output, $suffix);
2569
+
2570
+ } else {
2571
+ $output = $output . "$suffix";
2572
+ }
2573
+ }
2574
 
2575
+ return "$output";
2576
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2577
  }
woo-feed.php CHANGED
@@ -11,7 +11,7 @@
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
  *
14
- * Version: 3.6.3
15
  * Author: WebAppick
16
  * Author URI: https://webappick.com/
17
  * License: GPL v2
@@ -39,7 +39,7 @@ if ( ! defined( 'WOO_FEED_FREE_VERSION' ) ) {
39
  * @var string
40
  * @since 3.1.6
41
  */
42
- define( 'WOO_FEED_FREE_VERSION', '3.6.3' );
43
  }
44
 
45
  if ( ! defined( 'WOO_FEED_FREE_FILE' ) ) {
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
  *
14
+ * Version: 3.6.4
15
  * Author: WebAppick
16
  * Author URI: https://webappick.com/
17
  * License: GPL v2
39
  * @var string
40
  * @since 3.1.6
41
  */
42
+ define( 'WOO_FEED_FREE_VERSION', '3.6.4' );
43
  }
44
 
45
  if ( ! defined( 'WOO_FEED_FREE_FILE' ) ) {